UNPKG

@fluent/langneg

Version:

Language Negotiation API for Fluent

72 lines (71 loc) 3 kB
/** * Negotiates the languages between the list of requested locales against * a list of available locales. * * The algorithm is based on the BCP4647 3.3.2 Extended Filtering algorithm, * with several modifications: * * 1) available locales are treated as ranges * * This change allows us to match a more specific request against * more generic available locale. * * For example, if the available locale list provides locale `en`, * and the requested locale is `en-US`, we treat the available locale as * a locale that matches all possible english requests. * * This means that we expect available locale ID to be as precize as * the matches they want to cover. * * For example, if there is only `sr` available, it's ok to list * it in available locales. But once the available locales has both, * Cyrl and Latn variants, the locale IDs should be `sr-Cyrl` and `sr-Latn` * to avoid any `sr-*` request to match against whole `sr` range. * * What it does ([requested] * [available] = [supported]): * * ['en-US'] * ['en'] = ['en'] * * 2) likely subtags from LDML 4.3 Likely Subtags has been added * * The most obvious likely subtag that can be computed is a duplication * of the language field onto region field (`fr` => `fr-FR`). * * On top of that, likely subtags may use a list of mappings, that * allow the algorithm to handle non-obvious matches. * For example, making sure that we match `en` to `en-US` or `sr` to * `sr-Cyrl`, while `sr-RU` to `sr-Latn-RU`. * * This list can be taken directly from CLDR Supplemental Data. * * What it does ([requested] * [available] = [supported]): * * ['fr'] * ['fr-FR'] = ['fr-FR'] * ['en'] * ['en-US'] = ['en-US'] * ['sr'] * ['sr-Latn', 'sr-Cyrl'] = ['sr-Cyrl'] * * 3) variant/region range check has been added * * Lastly, the last form of check is against the requested locale ID * but with the variant/region field replaced with a `*` range. * * The rationale here laid out in LDML 4.4 Language Matching: * "(...) normally the fall-off between the user's languages is * substantially greated than regional variants." * * In other words, if we can't match for the given region, maybe * we can match for the same language/script but other region, and * it will in most cases be preferred over falling back on the next * language. * * What it does ([requested] * [available] = [supported]): * * ['en-AU'] * ['en-US'] = ['en-US'] * ['sr-RU'] * ['sr-Latn-RO'] = ['sr-Latn-RO'] // sr-RU -> sr-Latn-RU * * It works similarly to getParentLocales algo, except that we stop * after matching against variant/region ranges and don't try to match * ignoring script ranges. That means that `sr-Cyrl` will never match * against `sr-Latn`. */ export declare function filterMatches(requestedLocales: Array<string>, availableLocales: Array<string>, strategy: string): Array<string>;