i18n-supported websites often get a list of preferred locales via Accept-Language
header or navigator.languages
. They then try to determine the best available locale based on the set of locales that they support (and have translations for).
This operation currently exists within ECMA-402 but is only available as an abstract operation. Surfacing this functionality as a top level API would improve locale negotiation correctness and developer productivity as sites will be able to reliably handle not only matching, but also aliases, fallbacks and such.
- Given a set of locales an application has translations for and the set of locales a user requests, find the best matching locales.
- JS runtimes (& polyfills) are not required to guarantee supporting all locales. Given a set of locales it supports and what the user requests, find the best matching locales.
- An application can also provide different "tones" of the same locales (e.g casual, formal), utilizing
-x-
private tag. Given a set of locales with extensions and what the user preference might be, find the best matching locales.
Stage 1
Ponyfill: https://formatjs.io/docs/polyfills/intl-localematcher
interface Options {
algorithm: 'lookup' | 'best fit'
}
Intl.LocaleMatcher.match(
requestedLocales: string[],
availableLocales: string[],
defaultLocale: string,
options?: Options
): string
lookup
would continue to be the existingLookupMatcher
implementation within ECMA-402.best fit
would be implementation-dependent.
Intl.LocaleMatcher.match(["fr-XX", "en"], ["fr", "en"], "en"); // 'fr'
This is the core of hapijs header parsing with quality preferences. This however does a naive hierarchy with exact matches only. For example:
Accept.language("en;q=0.7, fr-XX;q=0.8", ["fr", "en"]); // language === "en"
which would not be accurate.
Similarly, Koa's request.acceptsLanguages
follow similar exact match algorithm.
This details a more sophisticated locale negotiation algorithm that is more accurate than hapi
/koa
This is the lookup
algorithm in ECMA-402.
Similar to UTS35 LanguageMatching.