Managing regional language variants
English is not one language for translation purposes. "Sign up" becomes "Register" in formal British English. "Billing" may need to surface as "Billing (USD)" for US users and "Billing (GBP)" for UK users. "Authorize" is spelled "Authorise" in Commonwealth English. Dates format as MM/DD/YYYY in the US and DD/MM/YYYY in the UK. Currency symbols differ. Tax terminology differs.
Maintaining a completely separate translation file per regional variant is expensive: you replicate every string, and any change to the shared base has to be applied manually to every variant. Messagevisor's locale inheritance model solves this by letting regional locales override only the strings and formats that actually differ while inheriting everything else from a base locale.
The inheritance model#
A locale can declare inheritTranslationsFrom and inheritFormatsFrom. At build time, Messagevisor walks the inheritance chain to resolve each message and format preset. You author the difference, not the duplicate.
The resolution order for translations is:
- The regional locale's own authored translation for this message
- If missing, follow the
inheritTranslationsFromchain - If nothing is found in the chain, that message key is omitted from the datafile for this locale
The resolution order for formats is a deep merge: start with the inherited locale's formats, then layer the regional locale's own format declarations on top.
Structuring a locale hierarchy#
description: English baseformats: number: decimal: maximumFractionDigits: 2 money: style: currency currency: USD currencyDisplay: symbol date: long: year: numeric month: long day: numeric time: short: hour: numeric minute: 2-digitdescription: English (United States)direction: ltrinheritTranslationsFrom: eninheritFormatsFrom: endescription: English (United Kingdom)direction: ltrinheritTranslationsFrom: eninheritFormatsFrom: enformats: number: money: style: currency currency: GBP currencyDisplay: symbol date: long: year: numeric month: long day: numericdescription: English (Australia)direction: ltrinheritTranslationsFrom: eninheritFormatsFrom: enformats: number: money: style: currency currency: AUD currencyDisplay: symbolen-US, en-GB, and en-AU all inherit from en. Only en-GB and en-AU need to override the money format because their currency differs. The rest of the formatting presets are inherited unchanged.
Authoring only the strings that differ#
For most messages, the en base translation is correct for all regional variants. You only need to author a regional translation when the text genuinely differs:
description: Registration action labeltranslations: en: Sign up en-GB: Register nl: RegistrerenAt build time, a datafile for en-US will inherit the en translation ("Sign up"). A datafile for en-GB will use its own authored translation ("Register"). You do not need to repeat "Sign up" for en-US explicitly.
description: Label for the tax line item on invoicestranslations: en: Tax en-GB: VAT en-AU: GSTdescription: Generic colour label used in product settingstranslations: en: Color en-GB: Colour en-AU: ColourMessages that are truly the same across all English variants require no regional entries at all. The base en translation is resolved for every inheriting locale.
Multi-level chains#
Inheritance chains can span more than one level. A locale that represents a market-specific variant of a regional variant can chain through both:
description: English for Netherlands marketdirection: ltrinheritTranslationsFrom: en-GBinheritFormatsFrom: en-GBformats: number: money: style: currency currency: EUR currencyDisplay: symbolen-NL inherits translations from en-GB, which itself inherits from en. Messagevisor walks the full chain until it finds a translation. The currency format is overridden to EUR since this locale is used in the Netherlands.
Merging examples across the chain#
Use mergeExamplesFrom when you want a regional locale to include the base locale's examples in the generated Catalog and CLI examples command output:
description: English (United Kingdom)direction: ltrinheritTranslationsFrom: eninheritFormatsFrom: enmergeExamplesFrom: enformats: number: money: style: currency currency: GBPThis is useful when the base en locale has a thorough set of format examples covering number, date, and time presets, and you want those documented for en-GB without re-authoring them.
Target-level locale filtering#
Not every locale needs to be included in every datafile. Targets control which locales are emitted, so you can build a web datafile that includes only the locales your web app actually supports:
description: Web application datafileincludeMessages: - auth* - nav* - billing* - common*locales: - en - en-US - en-GB - en-AU - nl-NLcontext: platform: webA separate mobile target might cover a different locale set, or the same one with different format presets for the platform.
Testing regional variants#
Test each regional locale's translations and format resolutions explicitly to catch cases where the inheritance chain is not working as expected:
message: billing.taxLabelassertions: - description: Generic English uses Tax locale: en target: web expectedTranslation: Tax - description: British English uses VAT locale: en-GB target: web expectedTranslation: VAT - description: Australian English uses GST locale: en-AU target: web expectedTranslation: GST - description: US English inherits from en locale: en-US target: web expectedTranslation: TaxTest locale format inheritance separately using locale tests:
locale: en-GBassertions: - description: GBP money format is resolved expectedFormats: number: money: currency: GBP currencyDisplay: symbol - description: en-GB inherits date long format from en expectedFormats: date: long: year: numeric month: longCLI evaluation for a specific locale#
Quickly verify what a message resolves to for a regional locale before committing a test:
$ npx messagevisor evaluate --message=billing.taxLabel --locale=en-GB --target=web$ npx messagevisor evaluate --message=billing.taxLabel --locale=en-AU --target=web
