PPayNow Docs
Menu — Localization

Integration Guide

Localization

Two languages today (English, Nepali). Add yours with one map entry.

The gateway picks up the customer's language from the ?locale= query param on the redirect URL.

Supported locales

Code Language
en English (default)
ne Nepali

How the merchant passes it

Append locale to the gateway redirect URL:

https://checkout.paynow.ma/?merchant_id=...&reference=...&locale=ne
            

If you're using the merchant demo's merchantInitiateMiddleware, the locale comes from the request body and is appended automatically.

What gets translated

  • All copy on the QR, account, OTP, and receipt screens.
  • Error messages surfaced from _getUserFriendlyErrorMessage.
  • Stage labels in the sidebar / progress indicator.

What's not translated:

  • Currency formatting (uses ISO codes — LYD 25.900).
  • Backend-supplied messages (those come from OnePay, not the SDK).

Adding a locale

Translations live in packages/paynow_core/lib/src/checkout_localization.dart. Adding a new locale is two steps:

  1. Add a translated string set (one entry per PayNowCheckoutCopy field).
  2. Register it in the resolveGatewayLocalization lookup.
// 1. New copy set
            const _ar = PayNowCheckoutCopy(
              checkoutTitle: 'الدفع',
              checkoutSubtitle: '...',
              // ...
            );
            
            // 2. Lookup
            PayNowCheckoutLocalization resolveGatewayLocalization(String code) {
              switch (code.toLowerCase()) {
                case 'ar': return PayNowCheckoutLocalization(localeCode: 'ar', checkoutCopy: _ar, ...);
                case 'ne': return ...;
                default:   return english;
              }
            }
            

Then write a test under packages/paynow_core/test/ that pins the new copy set so it doesn't drift.

RTL languages

For Arabic / Hebrew / etc., set the document direction at the gateway level. The merchant demo already handles this:

Document(
              htmlAttributes: {'dir': isRtl ? 'rtl' : 'ltr', 'lang': locale},
              // ...
            )
            

The brand stylesheet uses logical CSS properties where possible (padding-inline-start, border-inline-end) so most layout flips correctly under dir="rtl". Test before shipping an RTL locale — some hand-tuned layout pieces may need attention.