pattern

Locale Fallback Chain

also called Language Negotiation Chain, Locale Resolution Order

The declared order in which a system degrades from a requested locale to one it can actually serve - and the decision about which values are allowed to degrade at all.

i18nlocalefallbacksilent failurepricing

A release adds Portuguese for Angola with 60% of the strings translated. Within half an hour, customers in Luanda are being shown prices in Brazilian reais with Brazilian tax wording, in fluent Portuguese. Nothing errored. Every response was HTTP 200.

The resolver did exactly what the standards describe: the requested tag pt-AO had no catalogue, so it was truncated and matched the only Portuguese catalogue present. The defect is that the resolved tag was then used for three unrelated decisions — which strings to render, how to format numbers, and which commercial and legal text applies.

Why it matters

A fallback chain is an availability mechanism. Pointed at text it degrades gracefully and users are grateful: a Brazilian phrasing beats a raw message key. Pointed at money or law it turns a missing translation into a confident false statement, and that failure is invisible to every monitor a team usually has, because the page is complete and the status code is 200.

The cost asymmetry decides the design. A wrong phrasing is a support ticket. A wrong currency or a wrong tax disclosure is a refund, a regulator, or a mispriced order book.

Implementation patterns

  • Two chains, two policies. A translation chain that may degrade (pt-AO → pt-BR → pt → en), declared explicitly per locale rather than derived by truncation. A commercial chain that may not.
  • Resolve commercial values from a market record keyed by country, never from the language tag. Currency, tax wording, legal copy, measurement units, address format and name order belong to the market.
  • Hard-fail on a commercial miss. Render a placeholder, block the priced component, raise an alert. A missing price must not be replaced by a neighbour's price.
  • Per-namespace fallback policy. Interface chrome falls back silently; namespaces marked priced or legal do not render on a miss.
  • Declare the chain as data and review it, so adding a market is a configuration change someone approves rather than an emergent consequence of which files exist.
  • Log the resolved tag next to the requested tag on every render, and alert when they differ for a market configured as launched. This is the one-counter detection that turns a 30-minute incident into a 2-minute one.
  • Separate the display locale from the formatting locale in the API you expose to product code, so a developer cannot accidentally pass one where the other is meant.

Industry example

The mechanism is standardised: BCP 47 defines the tags and RFC 4647 defines matching, including the lookup scheme that progressively truncates subtags — exactly the behaviour that resolves pt-AO to pt. Platform libraries implement it faithfully, including Intl.NumberFormat in the browser, which will happily format with whatever tag it is handed. The standard is doing its job; the architecture decides what that job is allowed to touch. Teams that run pseudo-locale testing still miss this class, because a pseudo-locale is always present and therefore never exercises resolution.

Failure scenarios

  • Currency inherited from a language neighbour, as above.
  • Mixed-language pages, where one namespace falls through to the default locale and another does not.
  • Right-to-left inherited by a fallback, so an Arabic fallback flips the layout of a page displaying English.
  • A new market launching with a silent fallback nobody declared, discovered by customers.
  • Plural rules from the wrong language, which is a correctness bug in counts, not a style issue.
  • A cached response keyed on the requested tag but rendered from the resolved tag, so two markets share one cache entry.

Trade-offs

Declaring and enforcing two chains costs configuration, a review step per market, and a class of hard failures that a silent fallback would have hidden — which means more alerts and occasional blocked components in production. The alternative is cheaper to build and fails in the direction of confident wrongness.

A reasonable middle position for a pre-revenue product: one chain, plus a test that asserts no priced namespace ever resolves to a tag whose region differs from the request's market. The tag machinery itself is standardised rather than invented per product: BCP 47 (RFC 5646, 2009) defines the subtag structure the chain walks, and the Unicode CLDR likely-subtags data is what most libraries use to decide that pt-AO should reach for pt-PT before pt-BR, so the work is declaring policy rather than writing resolution code.

When not to use it

For a single-market, single-currency product, splitting the chains is ceremony. Language is the only axis that varies, one tag is honest, and the extra configuration earns nothing. The split pays for itself at the second market — which is also the point at which retrofitting it costs weeks, so the trigger to watch for is the first commercial conversation about a second country, not the first translation request.

Interview question

Q: We are launching in four new countries that share two languages. Design locale resolution so that a missing translation never changes what a customer is charged, and tell me how you would prove it in CI.

What a strong answer covers: two resolution paths with different failure modes; the market record as the authority for currency, tax and legal text; a hard failure on commercial misses; the resolved-versus-requested telemetry; and a CI test that enumerates every launched market against every priced namespace and asserts an exact match rather than a fallback.

Quick check

Quiz: Which three classes of value must never follow a language fallback? Currency and price, tax or legal wording, and units of measurement — they belong to the market, not the language.

Flashcard: Why does this failure class never page anyone? — Every response is a complete HTTP 200 page, so error-rate and synthetic monitoring stay green.