Locale Fallback Chain: How Browsers Resolve Locale Requests
Understand how the Intl API resolves locale requests through fallback chains. Learn about BCP 47 subtags, the locale negotiation algorithm, and best practices for locale specification.
Detailed Explanation
Locale Fallback Chain
When you request a locale that is not fully supported, the Intl API uses a fallback chain to find the best available match. Understanding this mechanism is essential for predictable internationalization behavior.
BCP 47 Locale Tags
A full locale tag has multiple subtags:
language-script-region-extensions
zh-Hans-CN-u-ca-chinese
language: zh (Chinese)
script: Hans (Simplified Han)
region: CN (China)
extension: u-ca-chinese (Chinese calendar)
The Fallback Algorithm
When you request zh-Hans-CN, the browser looks for:
zh-Hans-CN(exact match)zh-Hans(drop region)zh(drop script)- Default locale (typically
en)
// All of these may produce the same result
// if only "zh" data is available:
new Intl.NumberFormat('zh-Hans-CN').format(1234);
new Intl.NumberFormat('zh-Hans').format(1234);
new Intl.NumberFormat('zh').format(1234);
// All: "1,234"
Checking Supported Locales
// Check if a locale is supported
Intl.NumberFormat.supportedLocalesOf(['zh-Hans-CN', 'xyz-ZZ']);
// ["zh-Hans-CN"] -- xyz-ZZ is unsupported
// Check with lookup algorithm (stricter)
Intl.NumberFormat.supportedLocalesOf(
['zh-Hans-CN'],
{ localeMatcher: 'lookup' }
);
Locale Matcher Algorithms
- "best fit" (default): Uses a sophisticated algorithm to find the best available locale. May match
pt-BRtopteven ifpt-PTis available. - "lookup": Uses a simple subtag-removal algorithm. More predictable but potentially less optimal.
Unicode Extensions
Extensions (after -u-) customize behavior without changing the base locale:
// Calendar system
'ja-JP-u-ca-japanese' // Japanese Imperial era
'ar-SA-u-ca-islamic' // Islamic (Hijri) calendar
// Numbering system
'ar-SA-u-nu-latn' // Arabic locale with Latin digits
// Collation
'de-DE-u-co-phonebk' // German phonebook sort order
// Hour cycle
'en-US-u-hc-h23' // 24-hour time in US English
Practical Recommendations
- Always specify region when formatting currencies:
en-USnot justen - Use extensions for specific needs:
ja-JP-u-ca-japanesefor era dates - Check supportedLocalesOf in tests to verify locale availability
- Accept user-specified locales but validate with
Intl.getCanonicalLocales()
try {
Intl.getCanonicalLocales('en-us'); // ["en-US"]
Intl.getCanonicalLocales('invalid'); // throws RangeError
} catch (e) {
// Invalid locale
}
Use Case
Understanding locale fallback is critical for i18n architects and developers building locale-aware applications. When a user's browser reports 'en-AU' but the app only has 'en-US' and 'en-GB' data, the fallback chain determines which is used. When building locale selectors, knowing which locales are actually supported prevents offering options that silently fall back. This knowledge helps debug issues where formatting does not match expectations because a locale subtag was dropped during resolution.
Try It — Locale String Tester
Related Topics
Intl.DisplayNames API: Language, Region, Script, and Currency Names
Intl.DisplayNames
Japanese Era Calendar Dates with Intl.DateTimeFormat
Intl.DateTimeFormat
Arabic and Hebrew RTL Number Formatting with Intl
Intl.NumberFormat
Plural Rules by Language with Intl.PluralRules
Intl.PluralRules
Collation and Sorting by Locale with Intl.Collator
Intl.Collator