Customize checkout form text to match your brand voice, provide clearer user guidance, and support international customers. Text customization helps create a cohesive experience that aligns with your existing user interface patterns.
Complete Control
Override labels, buttons, validation messages, and status notifications.
Multi-Language Support
30+ built-in translations with automatic browser language detection.
RTL Language Support
Automatic right-to-left layout adjustment for Arabic and other RTL languages.
Partial Overrides
Change only specific text elements while keeping default translations for others.
The PayNext SDK automatically detects the user’s preferred language from browser settings:
Provide the locale and translate properties on the object you pass into checkout.mount('element-id', { ...config }) after creating the instance with new PayNextCheckout(), as shown in Mount the Checkout. The snippets below focus on those configuration objects.
The SDK reads errorMessageText from the same configuration object you pass into checkout.mount(...). That value flows straight into the checkout state and overrides the localized fallback string shown in the global error banner.
import { PayNextCheckout, type PayNextConfig, type CheckoutTranslate, type DeepPartial } from '@paynext/sdk'const customTranslations: DeepPartial<CheckoutTranslate> = { card: { required: 'Please fill in every required field.', pay: { button: 'Complete purchase' }, compact: { button: 'Pay with card' } }, status: { error: 'Unable to process payment. Please try again.', invalidSession: 'Your session expired. Refresh and try again.', authenticationFailed: 'Your payment method authentication was unsuccessful. Please try submitting the payment again and complete the authentication process, or use a different payment method.' }}export async function mountCustomTranslations( containerId: string, baseConfig: PayNextConfig) { const checkout = new PayNextCheckout() await checkout.mount(containerId, { ...baseConfig, translate: customTranslations, }) return checkout}
You can pass a partial object. Any missing strings fall back to built-in translations.
Copy
Ask AI
import { type CheckoutTranslate } from '@paynext/sdk'const completeCustomTranslations: CheckoutTranslate = { card: { required: 'Please complete every field before continuing.', // Card number field number: { label: 'Credit Card Number', error: { invalid: 'Enter a valid card number.', incomplete: 'Your card number is incomplete.', unsupported: 'This card type is not accepted.' } }, // Expiry date field expiry: { label: 'Expiration Date', placeholder: 'MM/YY', error: { invalid: 'Enter a valid expiry date.', incomplete: 'The expiry date is incomplete.', expired: 'This card has expired.', tooFarInFuture: 'The expiry date looks too far in the future.' } }, // Security code field cvc: { label: 'Security Code', placeholder: 'CVC', error: { incomplete: 'The security code is incomplete.' } }, // Cardholder name field name: { label: 'Cardholder Name', placeholder: 'Full name as shown on card' }, // Payment buttons pay: { button: 'Complete Payment' }, compact: { button: 'Credit or Debit Card' } }, // Status messages status: { error: 'We couldn\'t process your payment. Please check your information and try again.', invalidSession: 'Your payment session expired. Refresh to continue.', authenticationFailed: 'Your payment method authentication was unsuccessful. Please try submitting the payment again and complete the authentication process, or use a different payment method.' }, // Optional processor error overrides errors: { doNotHonor: 'Your bank declined the payment.', insufficientFunds: 'There are insufficient funds to complete the payment.', limitExceeded: 'This payment exceeds the card limit.', expiredCard: 'This card has expired.', invalidCreditCardNumber: 'Enter a valid card number.', processorDeclinedFraudSuspected: 'The transaction was declined for security reasons.', cardholderAuthenticationRequired: 'Additional verification is required to complete the payment.', offlineIssuerDeclined: 'The issuer was unreachable to approve the transaction.', cardReportedAsLostOrStolen: 'This card has been reported lost or stolen.', invalidSecurePaymentData: 'Secure payment data was invalid.', declined: 'The payment was declined.' }}// When mounting (see Getting Started "Mount the Checkout" section):// const checkout = new PayNextCheckout()// await checkout.mount('checkout-container', {// ...baseConfig,// translate: completeCustomTranslations,// })
import { type CheckoutTranslate, type DeepPartial } from '@paynext/sdk'const helpfulValidations: DeepPartial<CheckoutTranslate> = { card: { number: { error: { required: 'Please enter your card number', invalid: 'This doesn\'t look like a valid card number', incomplete: 'Please enter your complete card number', unsupported: 'We don\'t accept this card type. Try Visa or Mastercard.' } }, expiry: { error: { required: 'When does your card expire?', invalid: 'Please check your card\'s expiry date', incomplete: 'Please enter the full expiry date', expired: 'This card has expired. Please use a different card.' } }, cvc: { error: { required: 'Please enter your card\'s security code', invalid: 'Please check the security code', incomplete: 'Please enter the complete security code (usually 3-4 digits)' } }, name: { error: { required: 'Please enter the name on your card', invalid: 'Please enter the full name exactly as it appears on your card' } } }}// When mounting (see Getting Started "Mount the Checkout" section):// const checkout = new PayNextCheckout()// await checkout.mount('checkout-container', {// ...baseConfig,// translate: helpfulValidations,// })
When the 3DS (3D Secure) authentication flow encounters an error, the checkout surfaces the authenticationFailed status message. The payment status payload contains a decline_code that distinguishes between:
payment_attempt_authentication_cancelled: Customer explicitly closed the challenge window, abandoned it before timeout, or the challenge window was left open beyond the 10-minute timeout
Use the status_reason.decline_code in your payment status callbacks to customize messaging based on the failure type. See the 3D Secure guide for complete API response examples and detailed explanations of each scenario.
Workflows can still block a payment after 3DS. In that case the SDK receives status: "blocked" with the default “The payment was blocked by the workflow settings.” copy—branch on this separately from regular declined/failed outcomes.
RTL languages automatically receive proper layout and text direction:
Copy
Ask AI
// When mounting (see Getting Started "Mount the Checkout" section):const checkout = new PayNextCheckout()await checkout.mount('checkout-container', { ...config, locale: 'ar', // Arabic})