Localized Error Messages
Tell customers why a payment failed, in their language.
Providers write error messages in their own words and language, often in technical terms ("Do not honour", "Invalid merchant"). The localizedErrors plugin replaces the errorMessage of failed results with a message for the customer, chosen by the normalized error code. English, Turkish, German, Russian, and Arabic messages are included.
Built-in languages: English and Turkish Added in 0.5.0, German Added in 0.5.1, Russian Added in 0.5.2, and Arabic Not released yet.
Setup
import { betterPayment, iyzico } from 'better-payment';
import { localizedErrors } from 'better-payment/plugins';
const payment = betterPayment({
providers: { iyzico: iyzico({ /* ... */ }) },
plugins: [localizedErrors({ locale: 'tr' })],
});
const result = await payment.createPayment(request);
result.code; // 'INSUFFICIENT_FUNDS'
result.errorMessage; // 'Kartınızın bakiyesi veya limiti yetersiz. Başka bir kart deneyin.'
result.providerMessage; // the provider's own message, for your logsOnly results with a code change: failures, and pending results with NETWORK_ERROR. The provider's text stays in providerMessage, for your logs and your support team.
Options
| Option | Default | Description |
|---|---|---|
locale | 'en' | Default language |
fallbackLocale | 'en' | Language used for codes missing in a language |
messages | — | More languages, or your own wording, by language |
detectLocale | true | Choose the language of each HTTP handler response from the request |
Your own wording and more languages
localizedErrors({
locale: 'tr',
messages: {
tr: { INSUFFICIENT_FUNDS: 'Bakiyeniz yetersiz, lütfen başka bir kart deneyin.' },
es: {
INSUFFICIENT_FUNDS: 'Fondos insuficientes. Intente con otra tarjeta.',
CARD_DECLINED: 'Su banco rechazó el pago.',
},
},
});A code missing in a language falls back to fallbackLocale. A locale without messages throws a ConfigurationError.
Per request in the HTTP handler
The HTTP handler translates each response for its request, from the Accept-Language header by default: tr-TR,tr;q=0.9 gets Turkish, an unsupported language gets locale. Responses replayed for an Idempotency-Key are translated for the new request too. Choose the language another way with a function, or turn detection off:
// Language from a query parameter: /api/pay/iyzico/payment?lang=tr
localizedErrors({
detectLocale: (request) => new URL(request.url, 'http://localhost').searchParams.get('lang') ?? undefined,
});
// Always Turkish
localizedErrors({ locale: 'tr', detectLocale: false });The handler's own error responses (404, 403, an invalid body) are meant for developers and stay in English.
In your code
Operations you call in code use locale. For another language, or for results of provider-specific methods (the iyzico checkout form, subscriptions), which run without plugin hooks, use payment.errors:
payment.errors.message('EXPIRED_CARD', 'en'); // "Check your card's expiry date."
payment.errors.translate(checkoutResult, 'tr'); // the result, with errorMessage in Turkish
payment.errors.locales; // ['en', 'tr', ...]Error codes of other plugins
Codes that other plugins declare in $ERROR_CODES are translated too. The plugin's own message is the default; add translations in messages:
plugins: [
blockList({ bins: ['400000'] }), // declares BLOCKED_BIN in $ERROR_CODES
localizedErrors({
locale: 'tr',
messages: { tr: { BLOCKED_BIN: 'Bu kart kullanılamaz.' } },
}),
],The plugin's code (in errorCode) is looked up first, then the normalized code.
Add a language to better-payment
The built-in messages are in packages/better-payment/src/plugins/localized-errors/, one file per language, typed as Record<PaymentErrorCode, string>: a file that misses a code does not compile.
- Copy
en.tsto a file named after the language (fr.ts) and translate the messages. Write them for customers, in words that read naturally in that language, without technical details. Don't shorten them to fit the bundle size check; if the new language goes over the budget, say so in the pull request. - Add the language to
errorMessagesinlocalized-errors/index.ts. - Open a pull request. The existing test checks that every language has a message for every code.