Localization and currencies
Two distinct concerns:
- Localization — the language of human-readable strings
(
messagefields in errors, “Please enter your PIN” in the SDK widget). - Currency — the unit the customer is charged in. Sometimes different from the unit the merchant priced in.
Localization
Section titled “Localization”Supported languages
Section titled “Supported languages”Six built-in locales:
| Code | Language |
|---|---|
en | English |
fr | French (default) |
es | Spanish |
ru | Russian |
zh | Chinese (Mandarin) |
ln | Lingala |
Both SDKs default to French (fr). Override per checkout via
acceptLanguage (config) or the language widget input.
How it works
Section titled “How it works”Send Accept-Language: <code> on every request. The gateway
translates the message field on error responses and any
human-readable string in the response body.
error_code values are never localised — they are stable
identifiers, not display text.
curl https://app.api.gtwy.pdirect.com/api/v1/payments/health \ -H "Accept-Language: en"curl https://app.api.gtwy.pdirect.com/api/v1/payments/health \ -H "Accept-Language: fr"SDK propagation
Section titled “SDK propagation”// Flutter — process-wide defaultPdirectPay.init(const PdirectPayConfig( environment: PdirectPayEnvironment.production, defaultLocale: 'en',));
// Per-checkout overridePdirectPayCheckout( configs: PdirectPayConfigs( sessionToken: token, acceptLanguage: 'fr', // overrides defaultLocale for this checkout ), language: PdirectPayLanguage.french, // also overrides UI strings // ...);// Angular — process-wide default{ provide: PDIRECT_PAY_CONFIG, useValue: { acceptLanguage: "en", isProduction: true },}
// Per-checkout overrideconfigs: PdirectPayConfig = { token: "merchant-app-key", acceptLanguage: "fr",};The Angular SDK exposes PdirectLocalizationService if you need to
swap the entire UI language at runtime:
import { PdirectLocalizationService, PdirectPayLanguage } from "@mms/pdirect-pay";
constructor(private i18n: PdirectLocalizationService) {}
ngOnInit() { this.i18n.setLanguage(PdirectPayLanguage.French); // ... this.i18n.translations$.subscribe(t => { // t is the active translation table });}Adding strings
Section titled “Adding strings”PdirectLocalizationService.addTranslations(language, partial) lets
you extend or override the built-in tables for a language. The
Flutter SDK uses Flutter’s intl package and accepts custom
delegates.
For full UX customisation (different copy than what the SDK ships), override the relevant Starlight content rather than adding translations to the SDK — the SDK’s surface is intentionally narrow.
Currencies
Section titled “Currencies”Supported
Section titled “Supported”Three currencies in v1:
| Code | Currency |
|---|---|
usd | US Dollar |
cdf | Congolese Franc |
xof | West African CFA Franc |
Lowercase ISO 4217. The gateway rejects uppercase or alternative
forms (USD, dollar) with error_code: "1102".
More currencies are on the roadmap; track the changelog.
Pricing currency vs transactional currency
Section titled “Pricing currency vs transactional currency”The currency field on /payments/collect is the pricing
currency — what your books say the customer owes. The
transactional_currency field is the transactional currency —
what the customer actually gets debited in.
Most of the time these are the same:
{ "amount": "12.50", "currency": "usd" }But you can override:
{ "amount": "12.50", "currency": "usd", "transactional_currency": "cdf"}Effect: the gateway displays a CDF-equivalent amount to the customer (at the FX rate active at session-mint time), debits in CDF, and settles to your account in USD.
When to use this:
- The customer’s wallet is denominated in
cdfbut you price inusd. The customer sees a familiar local-currency total while your accounting stays in dollars. - You’re running a cross-border B2C payout and the beneficiary receives in their local currency.
When not to use it:
- For card payments where Mastercard handles FX server-side. Set
currencyonly.
FX timing
Section titled “FX timing”The rate locks at session-mint time. The customer sees the rate at
session-mint; if FX moves between session-mint and /submit, you
do not get re-quoted.
This means a stale session (a customer who walks away and returns 20 minutes later) may now have an out-of-date rate. The session TTL of 30 minutes (configurable up to 60) is your guard against this.
Number formatting
Section titled “Number formatting”amount is a positive decimal string ("12.50", not 12.50 or
1250). Decimal places match the currency’s standard:
| Currency | Decimals |
|---|---|
usd | 2 ("12.50") |
cdf | 2 |
xof | 0 ("5000" — no decimals) |
The gateway accepts "5000.00" for XOF too, but settlement is in
whole units.
For display, use the customer’s locale’s formatting (1,000.50 vs 1.000,50). For storage and gateway calls, use the canonical unformatted string.
See also
Section titled “See also”- Concepts → Requests and responses — encoding rules
- Payment methods —
transactional_currencyper method - Errors —
1102 INVALID_CURRENCY