@formatjs/intl-localematcher
Advanced tools
| /** | ||
| * https://tc39.es/ecma402/#sec-bestavailablelocale | ||
| * @param availableLocales | ||
| * @param locale | ||
| */ | ||
| * https://tc39.es/ecma402/#sec-bestavailablelocale | ||
| * @param availableLocales | ||
| * @param locale | ||
| */ | ||
| export declare function BestAvailableLocale(availableLocales: readonly string[], locale: string): string | undefined; |
| // Cache for Set conversions to avoid repeated array->Set conversions | ||
| var availableLocalesSetCache = new WeakMap(); | ||
| const availableLocalesSetCache = new WeakMap(); | ||
| /** | ||
| * https://tc39.es/ecma402/#sec-bestavailablelocale | ||
| * @param availableLocales | ||
| * @param locale | ||
| */ | ||
| * https://tc39.es/ecma402/#sec-bestavailablelocale | ||
| * @param availableLocales | ||
| * @param locale | ||
| */ | ||
| export function BestAvailableLocale(availableLocales, locale) { | ||
| // Fast path: use Set for O(1) lookups instead of O(n) indexOf | ||
| var availableSet = availableLocalesSetCache.get(availableLocales); | ||
| if (!availableSet) { | ||
| availableSet = new Set(availableLocales); | ||
| availableLocalesSetCache.set(availableLocales, availableSet); | ||
| } | ||
| var candidate = locale; | ||
| while (true) { | ||
| if (availableSet.has(candidate)) { | ||
| return candidate; | ||
| } | ||
| var pos = candidate.lastIndexOf('-'); | ||
| if (!~pos) { | ||
| return undefined; | ||
| } | ||
| if (pos >= 2 && candidate[pos - 2] === '-') { | ||
| pos -= 2; | ||
| } | ||
| candidate = candidate.slice(0, pos); | ||
| } | ||
| // Fast path: use Set for O(1) lookups instead of O(n) indexOf | ||
| let availableSet = availableLocalesSetCache.get(availableLocales); | ||
| if (!availableSet) { | ||
| availableSet = new Set(availableLocales); | ||
| availableLocalesSetCache.set(availableLocales, availableSet); | ||
| } | ||
| let candidate = locale; | ||
| while (true) { | ||
| if (availableSet.has(candidate)) { | ||
| return candidate; | ||
| } | ||
| let pos = candidate.lastIndexOf("-"); | ||
| if (!~pos) { | ||
| return undefined; | ||
| } | ||
| if (pos >= 2 && candidate[pos - 2] === "-") { | ||
| pos -= 2; | ||
| } | ||
| candidate = candidate.slice(0, pos); | ||
| } | ||
| } |
@@ -1,8 +0,8 @@ | ||
| import { LookupMatcherResult } from './types.js'; | ||
| import type { LookupMatcherResult } from "./types.js"; | ||
| /** | ||
| * https://tc39.es/ecma402/#sec-bestfitmatcher | ||
| * @param availableLocales | ||
| * @param requestedLocales | ||
| * @param getDefaultLocale | ||
| */ | ||
| * https://tc39.es/ecma402/#sec-bestfitmatcher | ||
| * @param availableLocales | ||
| * @param requestedLocales | ||
| * @param getDefaultLocale | ||
| */ | ||
| export declare function BestFitMatcher(availableLocales: readonly string[], requestedLocales: readonly string[], getDefaultLocale: () => string): LookupMatcherResult; |
@@ -1,31 +0,30 @@ | ||
| import { UNICODE_EXTENSION_SEQUENCE_REGEX, findBestMatch } from './utils.js'; | ||
| import { UNICODE_EXTENSION_SEQUENCE_REGEX, findBestMatch } from "./utils.js"; | ||
| /** | ||
| * https://tc39.es/ecma402/#sec-bestfitmatcher | ||
| * @param availableLocales | ||
| * @param requestedLocales | ||
| * @param getDefaultLocale | ||
| */ | ||
| * https://tc39.es/ecma402/#sec-bestfitmatcher | ||
| * @param availableLocales | ||
| * @param requestedLocales | ||
| * @param getDefaultLocale | ||
| */ | ||
| export function BestFitMatcher(availableLocales, requestedLocales, getDefaultLocale) { | ||
| var foundLocale; | ||
| var extension; | ||
| var noExtensionLocales = []; | ||
| var noExtensionLocaleMap = requestedLocales.reduce(function (all, l) { | ||
| var noExtensionLocale = l.replace(UNICODE_EXTENSION_SEQUENCE_REGEX, ''); | ||
| noExtensionLocales.push(noExtensionLocale); | ||
| all[noExtensionLocale] = l; | ||
| return all; | ||
| }, {}); | ||
| var result = findBestMatch(noExtensionLocales, availableLocales); | ||
| if (result.matchedSupportedLocale && result.matchedDesiredLocale) { | ||
| foundLocale = result.matchedSupportedLocale; | ||
| extension = | ||
| noExtensionLocaleMap[result.matchedDesiredLocale].slice(result.matchedDesiredLocale.length) || undefined; | ||
| } | ||
| if (!foundLocale) { | ||
| return { locale: getDefaultLocale() }; | ||
| } | ||
| return { | ||
| locale: foundLocale, | ||
| extension: extension, | ||
| }; | ||
| let foundLocale; | ||
| let extension; | ||
| const noExtensionLocales = []; | ||
| const noExtensionLocaleMap = requestedLocales.reduce((all, l) => { | ||
| const noExtensionLocale = l.replace(UNICODE_EXTENSION_SEQUENCE_REGEX, ""); | ||
| noExtensionLocales.push(noExtensionLocale); | ||
| all[noExtensionLocale] = l; | ||
| return all; | ||
| }, {}); | ||
| const result = findBestMatch(noExtensionLocales, availableLocales); | ||
| if (result.matchedSupportedLocale && result.matchedDesiredLocale) { | ||
| foundLocale = result.matchedSupportedLocale; | ||
| extension = noExtensionLocaleMap[result.matchedDesiredLocale].slice(result.matchedDesiredLocale.length) || undefined; | ||
| } | ||
| if (!foundLocale) { | ||
| return { locale: getDefaultLocale() }; | ||
| } | ||
| return { | ||
| locale: foundLocale, | ||
| extension | ||
| }; | ||
| } |
| /** | ||
| * http://ecma-international.org/ecma-402/7.0/index.html#sec-canonicalizelocalelist | ||
| * @param locales | ||
| */ | ||
| * http://ecma-international.org/ecma-402/7.0/index.html#sec-canonicalizelocalelist | ||
| * @param locales | ||
| */ | ||
| export declare function CanonicalizeLocaleList(locales?: string | readonly string[]): string[]; |
| /** | ||
| * http://ecma-international.org/ecma-402/7.0/index.html#sec-canonicalizelocalelist | ||
| * @param locales | ||
| */ | ||
| * http://ecma-international.org/ecma-402/7.0/index.html#sec-canonicalizelocalelist | ||
| * @param locales | ||
| */ | ||
| export function CanonicalizeLocaleList(locales) { | ||
| return Intl.getCanonicalLocales(locales); | ||
| return Intl.getCanonicalLocales(locales); | ||
| } |
| export function CanonicalizeUnicodeLocaleId(locale) { | ||
| return Intl.getCanonicalLocales(locale)[0]; | ||
| return Intl.getCanonicalLocales(locale)[0]; | ||
| } |
@@ -1,8 +0,8 @@ | ||
| import { invariant } from './utils.js'; | ||
| import { invariant } from "./utils.js"; | ||
| export function CanonicalizeUValue(ukey, uvalue) { | ||
| // TODO: Implement algorithm for CanonicalizeUValue per https://tc39.es/ecma402/#sec-canonicalizeuvalue | ||
| var lowerValue = uvalue.toLowerCase(); | ||
| invariant(ukey !== undefined, "ukey must be defined"); | ||
| var canonicalized = lowerValue; | ||
| return canonicalized; | ||
| // TODO: Implement algorithm for CanonicalizeUValue per https://tc39.es/ecma402/#sec-canonicalizeuvalue | ||
| let lowerValue = uvalue.toLowerCase(); | ||
| invariant(ukey !== undefined, `ukey must be defined`); | ||
| let canonicalized = lowerValue; | ||
| return canonicalized; | ||
| } |
@@ -1,2 +0,2 @@ | ||
| import { Keyword } from './types.js'; | ||
| import type { Keyword } from "./types.js"; | ||
| export declare function InsertUnicodeExtensionAndCanonicalize(locale: string, attributes: string[], keywords: Array<Keyword>): string; |
@@ -1,32 +0,29 @@ | ||
| import { CanonicalizeUnicodeLocaleId } from './CanonicalizeUnicodeLocaleId.js'; | ||
| import { invariant } from './utils.js'; | ||
| import { CanonicalizeUnicodeLocaleId } from "./CanonicalizeUnicodeLocaleId.js"; | ||
| import { invariant } from "./utils.js"; | ||
| export function InsertUnicodeExtensionAndCanonicalize(locale, attributes, keywords) { | ||
| invariant(locale.indexOf('-u-') === -1, 'Expected locale to not have a Unicode locale extension'); | ||
| var extension = '-u'; | ||
| for (var _i = 0, attributes_1 = attributes; _i < attributes_1.length; _i++) { | ||
| var attr = attributes_1[_i]; | ||
| extension += "-".concat(attr); | ||
| } | ||
| for (var _a = 0, keywords_1 = keywords; _a < keywords_1.length; _a++) { | ||
| var kw = keywords_1[_a]; | ||
| var key = kw.key, value = kw.value; | ||
| extension += "-".concat(key); | ||
| if (value !== '') { | ||
| extension += "-".concat(value); | ||
| } | ||
| } | ||
| if (extension === '-u') { | ||
| return CanonicalizeUnicodeLocaleId(locale); | ||
| } | ||
| var privateIndex = locale.indexOf('-x-'); | ||
| var newLocale; | ||
| if (privateIndex === -1) { | ||
| newLocale = locale + extension; | ||
| } | ||
| else { | ||
| var preExtension = locale.slice(0, privateIndex); | ||
| var postExtension = locale.slice(privateIndex); | ||
| newLocale = preExtension + extension + postExtension; | ||
| } | ||
| return CanonicalizeUnicodeLocaleId(newLocale); | ||
| invariant(locale.indexOf("-u-") === -1, "Expected locale to not have a Unicode locale extension"); | ||
| let extension = "-u"; | ||
| for (const attr of attributes) { | ||
| extension += `-${attr}`; | ||
| } | ||
| for (const kw of keywords) { | ||
| const { key, value } = kw; | ||
| extension += `-${key}`; | ||
| if (value !== "") { | ||
| extension += `-${value}`; | ||
| } | ||
| } | ||
| if (extension === "-u") { | ||
| return CanonicalizeUnicodeLocaleId(locale); | ||
| } | ||
| let privateIndex = locale.indexOf("-x-"); | ||
| let newLocale; | ||
| if (privateIndex === -1) { | ||
| newLocale = locale + extension; | ||
| } else { | ||
| let preExtension = locale.slice(0, privateIndex); | ||
| let postExtension = locale.slice(privateIndex); | ||
| newLocale = preExtension + extension + postExtension; | ||
| } | ||
| return CanonicalizeUnicodeLocaleId(newLocale); | ||
| } |
@@ -1,8 +0,8 @@ | ||
| import { LookupMatcherResult } from './types.js'; | ||
| import type { LookupMatcherResult } from "./types.js"; | ||
| /** | ||
| * https://tc39.es/ecma402/#sec-lookupmatcher | ||
| * @param availableLocales | ||
| * @param requestedLocales | ||
| * @param getDefaultLocale | ||
| */ | ||
| * https://tc39.es/ecma402/#sec-lookupmatcher | ||
| * @param availableLocales | ||
| * @param requestedLocales | ||
| * @param getDefaultLocale | ||
| */ | ||
| export declare function LookupMatcher(availableLocales: readonly string[], requestedLocales: readonly string[], getDefaultLocale: () => string): LookupMatcherResult; |
@@ -1,25 +0,24 @@ | ||
| import { BestAvailableLocale } from './BestAvailableLocale.js'; | ||
| import { UNICODE_EXTENSION_SEQUENCE_REGEX } from './utils.js'; | ||
| import { BestAvailableLocale } from "./BestAvailableLocale.js"; | ||
| import { UNICODE_EXTENSION_SEQUENCE_REGEX } from "./utils.js"; | ||
| /** | ||
| * https://tc39.es/ecma402/#sec-lookupmatcher | ||
| * @param availableLocales | ||
| * @param requestedLocales | ||
| * @param getDefaultLocale | ||
| */ | ||
| * https://tc39.es/ecma402/#sec-lookupmatcher | ||
| * @param availableLocales | ||
| * @param requestedLocales | ||
| * @param getDefaultLocale | ||
| */ | ||
| export function LookupMatcher(availableLocales, requestedLocales, getDefaultLocale) { | ||
| var result = { locale: '' }; | ||
| for (var _i = 0, requestedLocales_1 = requestedLocales; _i < requestedLocales_1.length; _i++) { | ||
| var locale = requestedLocales_1[_i]; | ||
| var noExtensionLocale = locale.replace(UNICODE_EXTENSION_SEQUENCE_REGEX, ''); | ||
| var availableLocale = BestAvailableLocale(availableLocales, noExtensionLocale); | ||
| if (availableLocale) { | ||
| result.locale = availableLocale; | ||
| if (locale !== noExtensionLocale) { | ||
| result.extension = locale.slice(noExtensionLocale.length, locale.length); | ||
| } | ||
| return result; | ||
| } | ||
| } | ||
| result.locale = getDefaultLocale(); | ||
| return result; | ||
| const result = { locale: "" }; | ||
| for (const locale of requestedLocales) { | ||
| const noExtensionLocale = locale.replace(UNICODE_EXTENSION_SEQUENCE_REGEX, ""); | ||
| const availableLocale = BestAvailableLocale(availableLocales, noExtensionLocale); | ||
| if (availableLocale) { | ||
| result.locale = availableLocale; | ||
| if (locale !== noExtensionLocale) { | ||
| result.extension = locale.slice(noExtensionLocale.length, locale.length); | ||
| } | ||
| return result; | ||
| } | ||
| } | ||
| result.locale = getDefaultLocale(); | ||
| return result; | ||
| } |
| /** | ||
| * https://tc39.es/ecma402/#sec-lookupsupportedlocales | ||
| * @param availableLocales | ||
| * @param requestedLocales | ||
| */ | ||
| * https://tc39.es/ecma402/#sec-lookupsupportedlocales | ||
| * @param availableLocales | ||
| * @param requestedLocales | ||
| */ | ||
| export declare function LookupSupportedLocales(availableLocales: string[], requestedLocales: string[]): string[]; |
@@ -1,19 +0,18 @@ | ||
| import { BestAvailableLocale } from './BestAvailableLocale.js'; | ||
| import { UNICODE_EXTENSION_SEQUENCE_REGEX } from './utils.js'; | ||
| import { BestAvailableLocale } from "./BestAvailableLocale.js"; | ||
| import { UNICODE_EXTENSION_SEQUENCE_REGEX } from "./utils.js"; | ||
| /** | ||
| * https://tc39.es/ecma402/#sec-lookupsupportedlocales | ||
| * @param availableLocales | ||
| * @param requestedLocales | ||
| */ | ||
| * https://tc39.es/ecma402/#sec-lookupsupportedlocales | ||
| * @param availableLocales | ||
| * @param requestedLocales | ||
| */ | ||
| export function LookupSupportedLocales(availableLocales, requestedLocales) { | ||
| var subset = []; | ||
| for (var _i = 0, requestedLocales_1 = requestedLocales; _i < requestedLocales_1.length; _i++) { | ||
| var locale = requestedLocales_1[_i]; | ||
| var noExtensionLocale = locale.replace(UNICODE_EXTENSION_SEQUENCE_REGEX, ''); | ||
| var availableLocale = BestAvailableLocale(availableLocales, noExtensionLocale); | ||
| if (availableLocale) { | ||
| subset.push(availableLocale); | ||
| } | ||
| } | ||
| return subset; | ||
| const subset = []; | ||
| for (const locale of requestedLocales) { | ||
| const noExtensionLocale = locale.replace(UNICODE_EXTENSION_SEQUENCE_REGEX, ""); | ||
| const availableLocale = BestAvailableLocale(availableLocales, noExtensionLocale); | ||
| if (availableLocale) { | ||
| subset.push(availableLocale); | ||
| } | ||
| } | ||
| return subset; | ||
| } |
@@ -0,1 +1,2 @@ | ||
| // This file is generated from regions-gen.ts | ||
| export declare const regions: Record<string, string[]>; |
+1332
-1191
| // This file is generated from regions-gen.ts | ||
| export var regions = { | ||
| '001': [ | ||
| '001', | ||
| '001-status-grouping', | ||
| '002', | ||
| '005', | ||
| '009', | ||
| '011', | ||
| '013', | ||
| '014', | ||
| '015', | ||
| '017', | ||
| '018', | ||
| '019', | ||
| '021', | ||
| '029', | ||
| '030', | ||
| '034', | ||
| '035', | ||
| '039', | ||
| '053', | ||
| '054', | ||
| '057', | ||
| '061', | ||
| '142', | ||
| '143', | ||
| '145', | ||
| '150', | ||
| '151', | ||
| '154', | ||
| '155', | ||
| 'AC', | ||
| 'AD', | ||
| 'AE', | ||
| 'AF', | ||
| 'AG', | ||
| 'AI', | ||
| 'AL', | ||
| 'AM', | ||
| 'AO', | ||
| 'AQ', | ||
| 'AR', | ||
| 'AS', | ||
| 'AT', | ||
| 'AU', | ||
| 'AW', | ||
| 'AX', | ||
| 'AZ', | ||
| 'BA', | ||
| 'BB', | ||
| 'BD', | ||
| 'BE', | ||
| 'BF', | ||
| 'BG', | ||
| 'BH', | ||
| 'BI', | ||
| 'BJ', | ||
| 'BL', | ||
| 'BM', | ||
| 'BN', | ||
| 'BO', | ||
| 'BQ', | ||
| 'BR', | ||
| 'BS', | ||
| 'BT', | ||
| 'BV', | ||
| 'BW', | ||
| 'BY', | ||
| 'BZ', | ||
| 'CA', | ||
| 'CC', | ||
| 'CD', | ||
| 'CF', | ||
| 'CG', | ||
| 'CH', | ||
| 'CI', | ||
| 'CK', | ||
| 'CL', | ||
| 'CM', | ||
| 'CN', | ||
| 'CO', | ||
| 'CP', | ||
| 'CQ', | ||
| 'CR', | ||
| 'CU', | ||
| 'CV', | ||
| 'CW', | ||
| 'CX', | ||
| 'CY', | ||
| 'CZ', | ||
| 'DE', | ||
| 'DG', | ||
| 'DJ', | ||
| 'DK', | ||
| 'DM', | ||
| 'DO', | ||
| 'DZ', | ||
| 'EA', | ||
| 'EC', | ||
| 'EE', | ||
| 'EG', | ||
| 'EH', | ||
| 'ER', | ||
| 'ES', | ||
| 'ET', | ||
| 'EU', | ||
| 'EZ', | ||
| 'FI', | ||
| 'FJ', | ||
| 'FK', | ||
| 'FM', | ||
| 'FO', | ||
| 'FR', | ||
| 'GA', | ||
| 'GB', | ||
| 'GD', | ||
| 'GE', | ||
| 'GF', | ||
| 'GG', | ||
| 'GH', | ||
| 'GI', | ||
| 'GL', | ||
| 'GM', | ||
| 'GN', | ||
| 'GP', | ||
| 'GQ', | ||
| 'GR', | ||
| 'GS', | ||
| 'GT', | ||
| 'GU', | ||
| 'GW', | ||
| 'GY', | ||
| 'HK', | ||
| 'HM', | ||
| 'HN', | ||
| 'HR', | ||
| 'HT', | ||
| 'HU', | ||
| 'IC', | ||
| 'ID', | ||
| 'IE', | ||
| 'IL', | ||
| 'IM', | ||
| 'IN', | ||
| 'IO', | ||
| 'IQ', | ||
| 'IR', | ||
| 'IS', | ||
| 'IT', | ||
| 'JE', | ||
| 'JM', | ||
| 'JO', | ||
| 'JP', | ||
| 'KE', | ||
| 'KG', | ||
| 'KH', | ||
| 'KI', | ||
| 'KM', | ||
| 'KN', | ||
| 'KP', | ||
| 'KR', | ||
| 'KW', | ||
| 'KY', | ||
| 'KZ', | ||
| 'LA', | ||
| 'LB', | ||
| 'LC', | ||
| 'LI', | ||
| 'LK', | ||
| 'LR', | ||
| 'LS', | ||
| 'LT', | ||
| 'LU', | ||
| 'LV', | ||
| 'LY', | ||
| 'MA', | ||
| 'MC', | ||
| 'MD', | ||
| 'ME', | ||
| 'MF', | ||
| 'MG', | ||
| 'MH', | ||
| 'MK', | ||
| 'ML', | ||
| 'MM', | ||
| 'MN', | ||
| 'MO', | ||
| 'MP', | ||
| 'MQ', | ||
| 'MR', | ||
| 'MS', | ||
| 'MT', | ||
| 'MU', | ||
| 'MV', | ||
| 'MW', | ||
| 'MX', | ||
| 'MY', | ||
| 'MZ', | ||
| 'NA', | ||
| 'NC', | ||
| 'NE', | ||
| 'NF', | ||
| 'NG', | ||
| 'NI', | ||
| 'NL', | ||
| 'NO', | ||
| 'NP', | ||
| 'NR', | ||
| 'NU', | ||
| 'NZ', | ||
| 'OM', | ||
| 'PA', | ||
| 'PE', | ||
| 'PF', | ||
| 'PG', | ||
| 'PH', | ||
| 'PK', | ||
| 'PL', | ||
| 'PM', | ||
| 'PN', | ||
| 'PR', | ||
| 'PS', | ||
| 'PT', | ||
| 'PW', | ||
| 'PY', | ||
| 'QA', | ||
| 'QO', | ||
| 'RE', | ||
| 'RO', | ||
| 'RS', | ||
| 'RU', | ||
| 'RW', | ||
| 'SA', | ||
| 'SB', | ||
| 'SC', | ||
| 'SD', | ||
| 'SE', | ||
| 'SG', | ||
| 'SH', | ||
| 'SI', | ||
| 'SJ', | ||
| 'SK', | ||
| 'SL', | ||
| 'SM', | ||
| 'SN', | ||
| 'SO', | ||
| 'SR', | ||
| 'SS', | ||
| 'ST', | ||
| 'SV', | ||
| 'SX', | ||
| 'SY', | ||
| 'SZ', | ||
| 'TA', | ||
| 'TC', | ||
| 'TD', | ||
| 'TF', | ||
| 'TG', | ||
| 'TH', | ||
| 'TJ', | ||
| 'TK', | ||
| 'TL', | ||
| 'TM', | ||
| 'TN', | ||
| 'TO', | ||
| 'TR', | ||
| 'TT', | ||
| 'TV', | ||
| 'TW', | ||
| 'TZ', | ||
| 'UA', | ||
| 'UG', | ||
| 'UM', | ||
| 'UN', | ||
| 'US', | ||
| 'UY', | ||
| 'UZ', | ||
| 'VA', | ||
| 'VC', | ||
| 'VE', | ||
| 'VG', | ||
| 'VI', | ||
| 'VN', | ||
| 'VU', | ||
| 'WF', | ||
| 'WS', | ||
| 'XK', | ||
| 'YE', | ||
| 'YT', | ||
| 'ZA', | ||
| 'ZM', | ||
| 'ZW', | ||
| ], | ||
| '002': [ | ||
| '002', | ||
| '002-status-grouping', | ||
| '011', | ||
| '014', | ||
| '015', | ||
| '017', | ||
| '018', | ||
| '202', | ||
| 'AO', | ||
| 'BF', | ||
| 'BI', | ||
| 'BJ', | ||
| 'BW', | ||
| 'CD', | ||
| 'CF', | ||
| 'CG', | ||
| 'CI', | ||
| 'CM', | ||
| 'CV', | ||
| 'DJ', | ||
| 'DZ', | ||
| 'EA', | ||
| 'EG', | ||
| 'EH', | ||
| 'ER', | ||
| 'ET', | ||
| 'GA', | ||
| 'GH', | ||
| 'GM', | ||
| 'GN', | ||
| 'GQ', | ||
| 'GW', | ||
| 'IC', | ||
| 'IO', | ||
| 'KE', | ||
| 'KM', | ||
| 'LR', | ||
| 'LS', | ||
| 'LY', | ||
| 'MA', | ||
| 'MG', | ||
| 'ML', | ||
| 'MR', | ||
| 'MU', | ||
| 'MW', | ||
| 'MZ', | ||
| 'NA', | ||
| 'NE', | ||
| 'NG', | ||
| 'RE', | ||
| 'RW', | ||
| 'SC', | ||
| 'SD', | ||
| 'SH', | ||
| 'SL', | ||
| 'SN', | ||
| 'SO', | ||
| 'SS', | ||
| 'ST', | ||
| 'SZ', | ||
| 'TD', | ||
| 'TF', | ||
| 'TG', | ||
| 'TN', | ||
| 'TZ', | ||
| 'UG', | ||
| 'YT', | ||
| 'ZA', | ||
| 'ZM', | ||
| 'ZW', | ||
| ], | ||
| '003': [ | ||
| '003', | ||
| '013', | ||
| '021', | ||
| '029', | ||
| 'AG', | ||
| 'AI', | ||
| 'AW', | ||
| 'BB', | ||
| 'BL', | ||
| 'BM', | ||
| 'BQ', | ||
| 'BS', | ||
| 'BZ', | ||
| 'CA', | ||
| 'CR', | ||
| 'CU', | ||
| 'CW', | ||
| 'DM', | ||
| 'DO', | ||
| 'GD', | ||
| 'GL', | ||
| 'GP', | ||
| 'GT', | ||
| 'HN', | ||
| 'HT', | ||
| 'JM', | ||
| 'KN', | ||
| 'KY', | ||
| 'LC', | ||
| 'MF', | ||
| 'MQ', | ||
| 'MS', | ||
| 'MX', | ||
| 'NI', | ||
| 'PA', | ||
| 'PM', | ||
| 'PR', | ||
| 'SV', | ||
| 'SX', | ||
| 'TC', | ||
| 'TT', | ||
| 'US', | ||
| 'VC', | ||
| 'VG', | ||
| 'VI', | ||
| ], | ||
| '005': [ | ||
| '005', | ||
| 'AR', | ||
| 'BO', | ||
| 'BR', | ||
| 'BV', | ||
| 'CL', | ||
| 'CO', | ||
| 'EC', | ||
| 'FK', | ||
| 'GF', | ||
| 'GS', | ||
| 'GY', | ||
| 'PE', | ||
| 'PY', | ||
| 'SR', | ||
| 'UY', | ||
| 'VE', | ||
| ], | ||
| '009': [ | ||
| '009', | ||
| '053', | ||
| '054', | ||
| '057', | ||
| '061', | ||
| 'AC', | ||
| 'AQ', | ||
| 'AS', | ||
| 'AU', | ||
| 'CC', | ||
| 'CK', | ||
| 'CP', | ||
| 'CX', | ||
| 'DG', | ||
| 'FJ', | ||
| 'FM', | ||
| 'GU', | ||
| 'HM', | ||
| 'KI', | ||
| 'MH', | ||
| 'MP', | ||
| 'NC', | ||
| 'NF', | ||
| 'NR', | ||
| 'NU', | ||
| 'NZ', | ||
| 'PF', | ||
| 'PG', | ||
| 'PN', | ||
| 'PW', | ||
| 'QO', | ||
| 'SB', | ||
| 'TA', | ||
| 'TK', | ||
| 'TO', | ||
| 'TV', | ||
| 'UM', | ||
| 'VU', | ||
| 'WF', | ||
| 'WS', | ||
| ], | ||
| '011': [ | ||
| '011', | ||
| 'BF', | ||
| 'BJ', | ||
| 'CI', | ||
| 'CV', | ||
| 'GH', | ||
| 'GM', | ||
| 'GN', | ||
| 'GW', | ||
| 'LR', | ||
| 'ML', | ||
| 'MR', | ||
| 'NE', | ||
| 'NG', | ||
| 'SH', | ||
| 'SL', | ||
| 'SN', | ||
| 'TG', | ||
| ], | ||
| '013': ['013', 'BZ', 'CR', 'GT', 'HN', 'MX', 'NI', 'PA', 'SV'], | ||
| '014': [ | ||
| '014', | ||
| 'BI', | ||
| 'DJ', | ||
| 'ER', | ||
| 'ET', | ||
| 'IO', | ||
| 'KE', | ||
| 'KM', | ||
| 'MG', | ||
| 'MU', | ||
| 'MW', | ||
| 'MZ', | ||
| 'RE', | ||
| 'RW', | ||
| 'SC', | ||
| 'SO', | ||
| 'SS', | ||
| 'TF', | ||
| 'TZ', | ||
| 'UG', | ||
| 'YT', | ||
| 'ZM', | ||
| 'ZW', | ||
| ], | ||
| '015': ['015', 'DZ', 'EA', 'EG', 'EH', 'IC', 'LY', 'MA', 'SD', 'TN'], | ||
| '017': ['017', 'AO', 'CD', 'CF', 'CG', 'CM', 'GA', 'GQ', 'ST', 'TD'], | ||
| '018': ['018', 'BW', 'LS', 'NA', 'SZ', 'ZA'], | ||
| '019': [ | ||
| '003', | ||
| '005', | ||
| '013', | ||
| '019', | ||
| '019-status-grouping', | ||
| '021', | ||
| '029', | ||
| '419', | ||
| 'AG', | ||
| 'AI', | ||
| 'AR', | ||
| 'AW', | ||
| 'BB', | ||
| 'BL', | ||
| 'BM', | ||
| 'BO', | ||
| 'BQ', | ||
| 'BR', | ||
| 'BS', | ||
| 'BV', | ||
| 'BZ', | ||
| 'CA', | ||
| 'CL', | ||
| 'CO', | ||
| 'CR', | ||
| 'CU', | ||
| 'CW', | ||
| 'DM', | ||
| 'DO', | ||
| 'EC', | ||
| 'FK', | ||
| 'GD', | ||
| 'GF', | ||
| 'GL', | ||
| 'GP', | ||
| 'GS', | ||
| 'GT', | ||
| 'GY', | ||
| 'HN', | ||
| 'HT', | ||
| 'JM', | ||
| 'KN', | ||
| 'KY', | ||
| 'LC', | ||
| 'MF', | ||
| 'MQ', | ||
| 'MS', | ||
| 'MX', | ||
| 'NI', | ||
| 'PA', | ||
| 'PE', | ||
| 'PM', | ||
| 'PR', | ||
| 'PY', | ||
| 'SR', | ||
| 'SV', | ||
| 'SX', | ||
| 'TC', | ||
| 'TT', | ||
| 'US', | ||
| 'UY', | ||
| 'VC', | ||
| 'VE', | ||
| 'VG', | ||
| 'VI', | ||
| ], | ||
| '021': ['021', 'BM', 'CA', 'GL', 'PM', 'US'], | ||
| '029': [ | ||
| '029', | ||
| 'AG', | ||
| 'AI', | ||
| 'AW', | ||
| 'BB', | ||
| 'BL', | ||
| 'BQ', | ||
| 'BS', | ||
| 'CU', | ||
| 'CW', | ||
| 'DM', | ||
| 'DO', | ||
| 'GD', | ||
| 'GP', | ||
| 'HT', | ||
| 'JM', | ||
| 'KN', | ||
| 'KY', | ||
| 'LC', | ||
| 'MF', | ||
| 'MQ', | ||
| 'MS', | ||
| 'PR', | ||
| 'SX', | ||
| 'TC', | ||
| 'TT', | ||
| 'VC', | ||
| 'VG', | ||
| 'VI', | ||
| ], | ||
| '030': ['030', 'CN', 'HK', 'JP', 'KP', 'KR', 'MN', 'MO', 'TW'], | ||
| '034': ['034', 'AF', 'BD', 'BT', 'IN', 'IR', 'LK', 'MV', 'NP', 'PK'], | ||
| '035': [ | ||
| '035', | ||
| 'BN', | ||
| 'ID', | ||
| 'KH', | ||
| 'LA', | ||
| 'MM', | ||
| 'MY', | ||
| 'PH', | ||
| 'SG', | ||
| 'TH', | ||
| 'TL', | ||
| 'VN', | ||
| ], | ||
| '039': [ | ||
| '039', | ||
| 'AD', | ||
| 'AL', | ||
| 'BA', | ||
| 'ES', | ||
| 'GI', | ||
| 'GR', | ||
| 'HR', | ||
| 'IT', | ||
| 'ME', | ||
| 'MK', | ||
| 'MT', | ||
| 'PT', | ||
| 'RS', | ||
| 'SI', | ||
| 'SM', | ||
| 'VA', | ||
| 'XK', | ||
| ], | ||
| '053': ['053', 'AU', 'CC', 'CX', 'HM', 'NF', 'NZ'], | ||
| '054': ['054', 'FJ', 'NC', 'PG', 'SB', 'VU'], | ||
| '057': ['057', 'FM', 'GU', 'KI', 'MH', 'MP', 'NR', 'PW', 'UM'], | ||
| '061': ['061', 'AS', 'CK', 'NU', 'PF', 'PN', 'TK', 'TO', 'TV', 'WF', 'WS'], | ||
| '142': [ | ||
| '030', | ||
| '034', | ||
| '035', | ||
| '142', | ||
| '143', | ||
| '145', | ||
| 'AE', | ||
| 'AF', | ||
| 'AM', | ||
| 'AZ', | ||
| 'BD', | ||
| 'BH', | ||
| 'BN', | ||
| 'BT', | ||
| 'CN', | ||
| 'CY', | ||
| 'GE', | ||
| 'HK', | ||
| 'ID', | ||
| 'IL', | ||
| 'IN', | ||
| 'IQ', | ||
| 'IR', | ||
| 'JO', | ||
| 'JP', | ||
| 'KG', | ||
| 'KH', | ||
| 'KP', | ||
| 'KR', | ||
| 'KW', | ||
| 'KZ', | ||
| 'LA', | ||
| 'LB', | ||
| 'LK', | ||
| 'MM', | ||
| 'MN', | ||
| 'MO', | ||
| 'MV', | ||
| 'MY', | ||
| 'NP', | ||
| 'OM', | ||
| 'PH', | ||
| 'PK', | ||
| 'PS', | ||
| 'QA', | ||
| 'SA', | ||
| 'SG', | ||
| 'SY', | ||
| 'TH', | ||
| 'TJ', | ||
| 'TL', | ||
| 'TM', | ||
| 'TR', | ||
| 'TW', | ||
| 'UZ', | ||
| 'VN', | ||
| 'YE', | ||
| ], | ||
| '143': ['143', 'KG', 'KZ', 'TJ', 'TM', 'UZ'], | ||
| '145': [ | ||
| '145', | ||
| 'AE', | ||
| 'AM', | ||
| 'AZ', | ||
| 'BH', | ||
| 'CY', | ||
| 'GE', | ||
| 'IL', | ||
| 'IQ', | ||
| 'JO', | ||
| 'KW', | ||
| 'LB', | ||
| 'OM', | ||
| 'PS', | ||
| 'QA', | ||
| 'SA', | ||
| 'SY', | ||
| 'TR', | ||
| 'YE', | ||
| ], | ||
| '150': [ | ||
| '039', | ||
| '150', | ||
| '151', | ||
| '154', | ||
| '155', | ||
| 'AD', | ||
| 'AL', | ||
| 'AT', | ||
| 'AX', | ||
| 'BA', | ||
| 'BE', | ||
| 'BG', | ||
| 'BY', | ||
| 'CH', | ||
| 'CQ', | ||
| 'CZ', | ||
| 'DE', | ||
| 'DK', | ||
| 'EE', | ||
| 'ES', | ||
| 'FI', | ||
| 'FO', | ||
| 'FR', | ||
| 'GB', | ||
| 'GG', | ||
| 'GI', | ||
| 'GR', | ||
| 'HR', | ||
| 'HU', | ||
| 'IE', | ||
| 'IM', | ||
| 'IS', | ||
| 'IT', | ||
| 'JE', | ||
| 'LI', | ||
| 'LT', | ||
| 'LU', | ||
| 'LV', | ||
| 'MC', | ||
| 'MD', | ||
| 'ME', | ||
| 'MK', | ||
| 'MT', | ||
| 'NL', | ||
| 'NO', | ||
| 'PL', | ||
| 'PT', | ||
| 'RO', | ||
| 'RS', | ||
| 'RU', | ||
| 'SE', | ||
| 'SI', | ||
| 'SJ', | ||
| 'SK', | ||
| 'SM', | ||
| 'UA', | ||
| 'VA', | ||
| 'XK', | ||
| ], | ||
| '151': ['151', 'BG', 'BY', 'CZ', 'HU', 'MD', 'PL', 'RO', 'RU', 'SK', 'UA'], | ||
| '154': [ | ||
| '154', | ||
| 'AX', | ||
| 'CQ', | ||
| 'DK', | ||
| 'EE', | ||
| 'FI', | ||
| 'FO', | ||
| 'GB', | ||
| 'GG', | ||
| 'IE', | ||
| 'IM', | ||
| 'IS', | ||
| 'JE', | ||
| 'LT', | ||
| 'LV', | ||
| 'NO', | ||
| 'SE', | ||
| 'SJ', | ||
| ], | ||
| '155': ['155', 'AT', 'BE', 'CH', 'DE', 'FR', 'LI', 'LU', 'MC', 'NL'], | ||
| '202': [ | ||
| '011', | ||
| '014', | ||
| '017', | ||
| '018', | ||
| '202', | ||
| 'AO', | ||
| 'BF', | ||
| 'BI', | ||
| 'BJ', | ||
| 'BW', | ||
| 'CD', | ||
| 'CF', | ||
| 'CG', | ||
| 'CI', | ||
| 'CM', | ||
| 'CV', | ||
| 'DJ', | ||
| 'ER', | ||
| 'ET', | ||
| 'GA', | ||
| 'GH', | ||
| 'GM', | ||
| 'GN', | ||
| 'GQ', | ||
| 'GW', | ||
| 'IO', | ||
| 'KE', | ||
| 'KM', | ||
| 'LR', | ||
| 'LS', | ||
| 'MG', | ||
| 'ML', | ||
| 'MR', | ||
| 'MU', | ||
| 'MW', | ||
| 'MZ', | ||
| 'NA', | ||
| 'NE', | ||
| 'NG', | ||
| 'RE', | ||
| 'RW', | ||
| 'SC', | ||
| 'SH', | ||
| 'SL', | ||
| 'SN', | ||
| 'SO', | ||
| 'SS', | ||
| 'ST', | ||
| 'SZ', | ||
| 'TD', | ||
| 'TF', | ||
| 'TG', | ||
| 'TZ', | ||
| 'UG', | ||
| 'YT', | ||
| 'ZA', | ||
| 'ZM', | ||
| 'ZW', | ||
| ], | ||
| '419': [ | ||
| '005', | ||
| '013', | ||
| '029', | ||
| '419', | ||
| 'AG', | ||
| 'AI', | ||
| 'AR', | ||
| 'AW', | ||
| 'BB', | ||
| 'BL', | ||
| 'BO', | ||
| 'BQ', | ||
| 'BR', | ||
| 'BS', | ||
| 'BV', | ||
| 'BZ', | ||
| 'CL', | ||
| 'CO', | ||
| 'CR', | ||
| 'CU', | ||
| 'CW', | ||
| 'DM', | ||
| 'DO', | ||
| 'EC', | ||
| 'FK', | ||
| 'GD', | ||
| 'GF', | ||
| 'GP', | ||
| 'GS', | ||
| 'GT', | ||
| 'GY', | ||
| 'HN', | ||
| 'HT', | ||
| 'JM', | ||
| 'KN', | ||
| 'KY', | ||
| 'LC', | ||
| 'MF', | ||
| 'MQ', | ||
| 'MS', | ||
| 'MX', | ||
| 'NI', | ||
| 'PA', | ||
| 'PE', | ||
| 'PR', | ||
| 'PY', | ||
| 'SR', | ||
| 'SV', | ||
| 'SX', | ||
| 'TC', | ||
| 'TT', | ||
| 'UY', | ||
| 'VC', | ||
| 'VE', | ||
| 'VG', | ||
| 'VI', | ||
| ], | ||
| EU: [ | ||
| 'AT', | ||
| 'BE', | ||
| 'BG', | ||
| 'CY', | ||
| 'CZ', | ||
| 'DE', | ||
| 'DK', | ||
| 'EE', | ||
| 'ES', | ||
| 'EU', | ||
| 'FI', | ||
| 'FR', | ||
| 'GR', | ||
| 'HR', | ||
| 'HU', | ||
| 'IE', | ||
| 'IT', | ||
| 'LT', | ||
| 'LU', | ||
| 'LV', | ||
| 'MT', | ||
| 'NL', | ||
| 'PL', | ||
| 'PT', | ||
| 'RO', | ||
| 'SE', | ||
| 'SI', | ||
| 'SK', | ||
| ], | ||
| EZ: [ | ||
| 'AT', | ||
| 'BE', | ||
| 'CY', | ||
| 'DE', | ||
| 'EE', | ||
| 'ES', | ||
| 'EZ', | ||
| 'FI', | ||
| 'FR', | ||
| 'GR', | ||
| 'IE', | ||
| 'IT', | ||
| 'LT', | ||
| 'LU', | ||
| 'LV', | ||
| 'MT', | ||
| 'NL', | ||
| 'PT', | ||
| 'SI', | ||
| 'SK', | ||
| ], | ||
| QO: ['AC', 'AQ', 'CP', 'DG', 'QO', 'TA'], | ||
| UN: [ | ||
| 'AD', | ||
| 'AE', | ||
| 'AF', | ||
| 'AG', | ||
| 'AL', | ||
| 'AM', | ||
| 'AO', | ||
| 'AR', | ||
| 'AT', | ||
| 'AU', | ||
| 'AZ', | ||
| 'BA', | ||
| 'BB', | ||
| 'BD', | ||
| 'BE', | ||
| 'BF', | ||
| 'BG', | ||
| 'BH', | ||
| 'BI', | ||
| 'BJ', | ||
| 'BN', | ||
| 'BO', | ||
| 'BR', | ||
| 'BS', | ||
| 'BT', | ||
| 'BW', | ||
| 'BY', | ||
| 'BZ', | ||
| 'CA', | ||
| 'CD', | ||
| 'CF', | ||
| 'CG', | ||
| 'CH', | ||
| 'CI', | ||
| 'CL', | ||
| 'CM', | ||
| 'CN', | ||
| 'CO', | ||
| 'CR', | ||
| 'CU', | ||
| 'CV', | ||
| 'CY', | ||
| 'CZ', | ||
| 'DE', | ||
| 'DJ', | ||
| 'DK', | ||
| 'DM', | ||
| 'DO', | ||
| 'DZ', | ||
| 'EC', | ||
| 'EE', | ||
| 'EG', | ||
| 'ER', | ||
| 'ES', | ||
| 'ET', | ||
| 'FI', | ||
| 'FJ', | ||
| 'FM', | ||
| 'FR', | ||
| 'GA', | ||
| 'GB', | ||
| 'GD', | ||
| 'GE', | ||
| 'GH', | ||
| 'GM', | ||
| 'GN', | ||
| 'GQ', | ||
| 'GR', | ||
| 'GT', | ||
| 'GW', | ||
| 'GY', | ||
| 'HN', | ||
| 'HR', | ||
| 'HT', | ||
| 'HU', | ||
| 'ID', | ||
| 'IE', | ||
| 'IL', | ||
| 'IN', | ||
| 'IQ', | ||
| 'IR', | ||
| 'IS', | ||
| 'IT', | ||
| 'JM', | ||
| 'JO', | ||
| 'JP', | ||
| 'KE', | ||
| 'KG', | ||
| 'KH', | ||
| 'KI', | ||
| 'KM', | ||
| 'KN', | ||
| 'KP', | ||
| 'KR', | ||
| 'KW', | ||
| 'KZ', | ||
| 'LA', | ||
| 'LB', | ||
| 'LC', | ||
| 'LI', | ||
| 'LK', | ||
| 'LR', | ||
| 'LS', | ||
| 'LT', | ||
| 'LU', | ||
| 'LV', | ||
| 'LY', | ||
| 'MA', | ||
| 'MC', | ||
| 'MD', | ||
| 'ME', | ||
| 'MG', | ||
| 'MH', | ||
| 'MK', | ||
| 'ML', | ||
| 'MM', | ||
| 'MN', | ||
| 'MR', | ||
| 'MT', | ||
| 'MU', | ||
| 'MV', | ||
| 'MW', | ||
| 'MX', | ||
| 'MY', | ||
| 'MZ', | ||
| 'NA', | ||
| 'NE', | ||
| 'NG', | ||
| 'NI', | ||
| 'NL', | ||
| 'NO', | ||
| 'NP', | ||
| 'NR', | ||
| 'NZ', | ||
| 'OM', | ||
| 'PA', | ||
| 'PE', | ||
| 'PG', | ||
| 'PH', | ||
| 'PK', | ||
| 'PL', | ||
| 'PT', | ||
| 'PW', | ||
| 'PY', | ||
| 'QA', | ||
| 'RO', | ||
| 'RS', | ||
| 'RU', | ||
| 'RW', | ||
| 'SA', | ||
| 'SB', | ||
| 'SC', | ||
| 'SD', | ||
| 'SE', | ||
| 'SG', | ||
| 'SI', | ||
| 'SK', | ||
| 'SL', | ||
| 'SM', | ||
| 'SN', | ||
| 'SO', | ||
| 'SR', | ||
| 'SS', | ||
| 'ST', | ||
| 'SV', | ||
| 'SY', | ||
| 'SZ', | ||
| 'TD', | ||
| 'TG', | ||
| 'TH', | ||
| 'TJ', | ||
| 'TL', | ||
| 'TM', | ||
| 'TN', | ||
| 'TO', | ||
| 'TR', | ||
| 'TT', | ||
| 'TV', | ||
| 'TZ', | ||
| 'UA', | ||
| 'UG', | ||
| 'UN', | ||
| 'US', | ||
| 'UY', | ||
| 'UZ', | ||
| 'VC', | ||
| 'VE', | ||
| 'VN', | ||
| 'VU', | ||
| 'WS', | ||
| 'YE', | ||
| 'ZA', | ||
| 'ZM', | ||
| 'ZW', | ||
| ], | ||
| export const regions = { | ||
| "001": [ | ||
| "001", | ||
| "001-status-grouping", | ||
| "002", | ||
| "005", | ||
| "009", | ||
| "011", | ||
| "013", | ||
| "014", | ||
| "015", | ||
| "017", | ||
| "018", | ||
| "019", | ||
| "021", | ||
| "029", | ||
| "030", | ||
| "034", | ||
| "035", | ||
| "039", | ||
| "053", | ||
| "054", | ||
| "057", | ||
| "061", | ||
| "142", | ||
| "143", | ||
| "145", | ||
| "150", | ||
| "151", | ||
| "154", | ||
| "155", | ||
| "AC", | ||
| "AD", | ||
| "AE", | ||
| "AF", | ||
| "AG", | ||
| "AI", | ||
| "AL", | ||
| "AM", | ||
| "AO", | ||
| "AQ", | ||
| "AR", | ||
| "AS", | ||
| "AT", | ||
| "AU", | ||
| "AW", | ||
| "AX", | ||
| "AZ", | ||
| "BA", | ||
| "BB", | ||
| "BD", | ||
| "BE", | ||
| "BF", | ||
| "BG", | ||
| "BH", | ||
| "BI", | ||
| "BJ", | ||
| "BL", | ||
| "BM", | ||
| "BN", | ||
| "BO", | ||
| "BQ", | ||
| "BR", | ||
| "BS", | ||
| "BT", | ||
| "BV", | ||
| "BW", | ||
| "BY", | ||
| "BZ", | ||
| "CA", | ||
| "CC", | ||
| "CD", | ||
| "CF", | ||
| "CG", | ||
| "CH", | ||
| "CI", | ||
| "CK", | ||
| "CL", | ||
| "CM", | ||
| "CN", | ||
| "CO", | ||
| "CP", | ||
| "CQ", | ||
| "CR", | ||
| "CU", | ||
| "CV", | ||
| "CW", | ||
| "CX", | ||
| "CY", | ||
| "CZ", | ||
| "DE", | ||
| "DG", | ||
| "DJ", | ||
| "DK", | ||
| "DM", | ||
| "DO", | ||
| "DZ", | ||
| "EA", | ||
| "EC", | ||
| "EE", | ||
| "EG", | ||
| "EH", | ||
| "ER", | ||
| "ES", | ||
| "ET", | ||
| "EU", | ||
| "EZ", | ||
| "FI", | ||
| "FJ", | ||
| "FK", | ||
| "FM", | ||
| "FO", | ||
| "FR", | ||
| "GA", | ||
| "GB", | ||
| "GD", | ||
| "GE", | ||
| "GF", | ||
| "GG", | ||
| "GH", | ||
| "GI", | ||
| "GL", | ||
| "GM", | ||
| "GN", | ||
| "GP", | ||
| "GQ", | ||
| "GR", | ||
| "GS", | ||
| "GT", | ||
| "GU", | ||
| "GW", | ||
| "GY", | ||
| "HK", | ||
| "HM", | ||
| "HN", | ||
| "HR", | ||
| "HT", | ||
| "HU", | ||
| "IC", | ||
| "ID", | ||
| "IE", | ||
| "IL", | ||
| "IM", | ||
| "IN", | ||
| "IO", | ||
| "IQ", | ||
| "IR", | ||
| "IS", | ||
| "IT", | ||
| "JE", | ||
| "JM", | ||
| "JO", | ||
| "JP", | ||
| "KE", | ||
| "KG", | ||
| "KH", | ||
| "KI", | ||
| "KM", | ||
| "KN", | ||
| "KP", | ||
| "KR", | ||
| "KW", | ||
| "KY", | ||
| "KZ", | ||
| "LA", | ||
| "LB", | ||
| "LC", | ||
| "LI", | ||
| "LK", | ||
| "LR", | ||
| "LS", | ||
| "LT", | ||
| "LU", | ||
| "LV", | ||
| "LY", | ||
| "MA", | ||
| "MC", | ||
| "MD", | ||
| "ME", | ||
| "MF", | ||
| "MG", | ||
| "MH", | ||
| "MK", | ||
| "ML", | ||
| "MM", | ||
| "MN", | ||
| "MO", | ||
| "MP", | ||
| "MQ", | ||
| "MR", | ||
| "MS", | ||
| "MT", | ||
| "MU", | ||
| "MV", | ||
| "MW", | ||
| "MX", | ||
| "MY", | ||
| "MZ", | ||
| "NA", | ||
| "NC", | ||
| "NE", | ||
| "NF", | ||
| "NG", | ||
| "NI", | ||
| "NL", | ||
| "NO", | ||
| "NP", | ||
| "NR", | ||
| "NU", | ||
| "NZ", | ||
| "OM", | ||
| "PA", | ||
| "PE", | ||
| "PF", | ||
| "PG", | ||
| "PH", | ||
| "PK", | ||
| "PL", | ||
| "PM", | ||
| "PN", | ||
| "PR", | ||
| "PS", | ||
| "PT", | ||
| "PW", | ||
| "PY", | ||
| "QA", | ||
| "QO", | ||
| "RE", | ||
| "RO", | ||
| "RS", | ||
| "RU", | ||
| "RW", | ||
| "SA", | ||
| "SB", | ||
| "SC", | ||
| "SD", | ||
| "SE", | ||
| "SG", | ||
| "SH", | ||
| "SI", | ||
| "SJ", | ||
| "SK", | ||
| "SL", | ||
| "SM", | ||
| "SN", | ||
| "SO", | ||
| "SR", | ||
| "SS", | ||
| "ST", | ||
| "SV", | ||
| "SX", | ||
| "SY", | ||
| "SZ", | ||
| "TA", | ||
| "TC", | ||
| "TD", | ||
| "TF", | ||
| "TG", | ||
| "TH", | ||
| "TJ", | ||
| "TK", | ||
| "TL", | ||
| "TM", | ||
| "TN", | ||
| "TO", | ||
| "TR", | ||
| "TT", | ||
| "TV", | ||
| "TW", | ||
| "TZ", | ||
| "UA", | ||
| "UG", | ||
| "UM", | ||
| "UN", | ||
| "US", | ||
| "UY", | ||
| "UZ", | ||
| "VA", | ||
| "VC", | ||
| "VE", | ||
| "VG", | ||
| "VI", | ||
| "VN", | ||
| "VU", | ||
| "WF", | ||
| "WS", | ||
| "XK", | ||
| "YE", | ||
| "YT", | ||
| "ZA", | ||
| "ZM", | ||
| "ZW" | ||
| ], | ||
| "002": [ | ||
| "002", | ||
| "002-status-grouping", | ||
| "011", | ||
| "014", | ||
| "015", | ||
| "017", | ||
| "018", | ||
| "202", | ||
| "AO", | ||
| "BF", | ||
| "BI", | ||
| "BJ", | ||
| "BW", | ||
| "CD", | ||
| "CF", | ||
| "CG", | ||
| "CI", | ||
| "CM", | ||
| "CV", | ||
| "DJ", | ||
| "DZ", | ||
| "EA", | ||
| "EG", | ||
| "EH", | ||
| "ER", | ||
| "ET", | ||
| "GA", | ||
| "GH", | ||
| "GM", | ||
| "GN", | ||
| "GQ", | ||
| "GW", | ||
| "IC", | ||
| "IO", | ||
| "KE", | ||
| "KM", | ||
| "LR", | ||
| "LS", | ||
| "LY", | ||
| "MA", | ||
| "MG", | ||
| "ML", | ||
| "MR", | ||
| "MU", | ||
| "MW", | ||
| "MZ", | ||
| "NA", | ||
| "NE", | ||
| "NG", | ||
| "RE", | ||
| "RW", | ||
| "SC", | ||
| "SD", | ||
| "SH", | ||
| "SL", | ||
| "SN", | ||
| "SO", | ||
| "SS", | ||
| "ST", | ||
| "SZ", | ||
| "TD", | ||
| "TF", | ||
| "TG", | ||
| "TN", | ||
| "TZ", | ||
| "UG", | ||
| "YT", | ||
| "ZA", | ||
| "ZM", | ||
| "ZW" | ||
| ], | ||
| "003": [ | ||
| "003", | ||
| "013", | ||
| "021", | ||
| "029", | ||
| "AG", | ||
| "AI", | ||
| "AW", | ||
| "BB", | ||
| "BL", | ||
| "BM", | ||
| "BQ", | ||
| "BS", | ||
| "BZ", | ||
| "CA", | ||
| "CR", | ||
| "CU", | ||
| "CW", | ||
| "DM", | ||
| "DO", | ||
| "GD", | ||
| "GL", | ||
| "GP", | ||
| "GT", | ||
| "HN", | ||
| "HT", | ||
| "JM", | ||
| "KN", | ||
| "KY", | ||
| "LC", | ||
| "MF", | ||
| "MQ", | ||
| "MS", | ||
| "MX", | ||
| "NI", | ||
| "PA", | ||
| "PM", | ||
| "PR", | ||
| "SV", | ||
| "SX", | ||
| "TC", | ||
| "TT", | ||
| "US", | ||
| "VC", | ||
| "VG", | ||
| "VI" | ||
| ], | ||
| "005": [ | ||
| "005", | ||
| "AR", | ||
| "BO", | ||
| "BR", | ||
| "BV", | ||
| "CL", | ||
| "CO", | ||
| "EC", | ||
| "FK", | ||
| "GF", | ||
| "GS", | ||
| "GY", | ||
| "PE", | ||
| "PY", | ||
| "SR", | ||
| "UY", | ||
| "VE" | ||
| ], | ||
| "009": [ | ||
| "009", | ||
| "053", | ||
| "054", | ||
| "057", | ||
| "061", | ||
| "AC", | ||
| "AQ", | ||
| "AS", | ||
| "AU", | ||
| "CC", | ||
| "CK", | ||
| "CP", | ||
| "CX", | ||
| "DG", | ||
| "FJ", | ||
| "FM", | ||
| "GU", | ||
| "HM", | ||
| "KI", | ||
| "MH", | ||
| "MP", | ||
| "NC", | ||
| "NF", | ||
| "NR", | ||
| "NU", | ||
| "NZ", | ||
| "PF", | ||
| "PG", | ||
| "PN", | ||
| "PW", | ||
| "QO", | ||
| "SB", | ||
| "TA", | ||
| "TK", | ||
| "TO", | ||
| "TV", | ||
| "UM", | ||
| "VU", | ||
| "WF", | ||
| "WS" | ||
| ], | ||
| "011": [ | ||
| "011", | ||
| "BF", | ||
| "BJ", | ||
| "CI", | ||
| "CV", | ||
| "GH", | ||
| "GM", | ||
| "GN", | ||
| "GW", | ||
| "LR", | ||
| "ML", | ||
| "MR", | ||
| "NE", | ||
| "NG", | ||
| "SH", | ||
| "SL", | ||
| "SN", | ||
| "TG" | ||
| ], | ||
| "013": [ | ||
| "013", | ||
| "BZ", | ||
| "CR", | ||
| "GT", | ||
| "HN", | ||
| "MX", | ||
| "NI", | ||
| "PA", | ||
| "SV" | ||
| ], | ||
| "014": [ | ||
| "014", | ||
| "BI", | ||
| "DJ", | ||
| "ER", | ||
| "ET", | ||
| "IO", | ||
| "KE", | ||
| "KM", | ||
| "MG", | ||
| "MU", | ||
| "MW", | ||
| "MZ", | ||
| "RE", | ||
| "RW", | ||
| "SC", | ||
| "SO", | ||
| "SS", | ||
| "TF", | ||
| "TZ", | ||
| "UG", | ||
| "YT", | ||
| "ZM", | ||
| "ZW" | ||
| ], | ||
| "015": [ | ||
| "015", | ||
| "DZ", | ||
| "EA", | ||
| "EG", | ||
| "EH", | ||
| "IC", | ||
| "LY", | ||
| "MA", | ||
| "SD", | ||
| "TN" | ||
| ], | ||
| "017": [ | ||
| "017", | ||
| "AO", | ||
| "CD", | ||
| "CF", | ||
| "CG", | ||
| "CM", | ||
| "GA", | ||
| "GQ", | ||
| "ST", | ||
| "TD" | ||
| ], | ||
| "018": [ | ||
| "018", | ||
| "BW", | ||
| "LS", | ||
| "NA", | ||
| "SZ", | ||
| "ZA" | ||
| ], | ||
| "019": [ | ||
| "003", | ||
| "005", | ||
| "013", | ||
| "019", | ||
| "019-status-grouping", | ||
| "021", | ||
| "029", | ||
| "419", | ||
| "AG", | ||
| "AI", | ||
| "AR", | ||
| "AW", | ||
| "BB", | ||
| "BL", | ||
| "BM", | ||
| "BO", | ||
| "BQ", | ||
| "BR", | ||
| "BS", | ||
| "BV", | ||
| "BZ", | ||
| "CA", | ||
| "CL", | ||
| "CO", | ||
| "CR", | ||
| "CU", | ||
| "CW", | ||
| "DM", | ||
| "DO", | ||
| "EC", | ||
| "FK", | ||
| "GD", | ||
| "GF", | ||
| "GL", | ||
| "GP", | ||
| "GS", | ||
| "GT", | ||
| "GY", | ||
| "HN", | ||
| "HT", | ||
| "JM", | ||
| "KN", | ||
| "KY", | ||
| "LC", | ||
| "MF", | ||
| "MQ", | ||
| "MS", | ||
| "MX", | ||
| "NI", | ||
| "PA", | ||
| "PE", | ||
| "PM", | ||
| "PR", | ||
| "PY", | ||
| "SR", | ||
| "SV", | ||
| "SX", | ||
| "TC", | ||
| "TT", | ||
| "US", | ||
| "UY", | ||
| "VC", | ||
| "VE", | ||
| "VG", | ||
| "VI" | ||
| ], | ||
| "021": [ | ||
| "021", | ||
| "BM", | ||
| "CA", | ||
| "GL", | ||
| "PM", | ||
| "US" | ||
| ], | ||
| "029": [ | ||
| "029", | ||
| "AG", | ||
| "AI", | ||
| "AW", | ||
| "BB", | ||
| "BL", | ||
| "BQ", | ||
| "BS", | ||
| "CU", | ||
| "CW", | ||
| "DM", | ||
| "DO", | ||
| "GD", | ||
| "GP", | ||
| "HT", | ||
| "JM", | ||
| "KN", | ||
| "KY", | ||
| "LC", | ||
| "MF", | ||
| "MQ", | ||
| "MS", | ||
| "PR", | ||
| "SX", | ||
| "TC", | ||
| "TT", | ||
| "VC", | ||
| "VG", | ||
| "VI" | ||
| ], | ||
| "030": [ | ||
| "030", | ||
| "CN", | ||
| "HK", | ||
| "JP", | ||
| "KP", | ||
| "KR", | ||
| "MN", | ||
| "MO", | ||
| "TW" | ||
| ], | ||
| "034": [ | ||
| "034", | ||
| "AF", | ||
| "BD", | ||
| "BT", | ||
| "IN", | ||
| "IR", | ||
| "LK", | ||
| "MV", | ||
| "NP", | ||
| "PK" | ||
| ], | ||
| "035": [ | ||
| "035", | ||
| "BN", | ||
| "ID", | ||
| "KH", | ||
| "LA", | ||
| "MM", | ||
| "MY", | ||
| "PH", | ||
| "SG", | ||
| "TH", | ||
| "TL", | ||
| "VN" | ||
| ], | ||
| "039": [ | ||
| "039", | ||
| "AD", | ||
| "AL", | ||
| "BA", | ||
| "ES", | ||
| "GI", | ||
| "GR", | ||
| "HR", | ||
| "IT", | ||
| "ME", | ||
| "MK", | ||
| "MT", | ||
| "PT", | ||
| "RS", | ||
| "SI", | ||
| "SM", | ||
| "VA", | ||
| "XK" | ||
| ], | ||
| "053": [ | ||
| "053", | ||
| "AU", | ||
| "CC", | ||
| "CX", | ||
| "HM", | ||
| "NF", | ||
| "NZ" | ||
| ], | ||
| "054": [ | ||
| "054", | ||
| "FJ", | ||
| "NC", | ||
| "PG", | ||
| "SB", | ||
| "VU" | ||
| ], | ||
| "057": [ | ||
| "057", | ||
| "FM", | ||
| "GU", | ||
| "KI", | ||
| "MH", | ||
| "MP", | ||
| "NR", | ||
| "PW", | ||
| "UM" | ||
| ], | ||
| "061": [ | ||
| "061", | ||
| "AS", | ||
| "CK", | ||
| "NU", | ||
| "PF", | ||
| "PN", | ||
| "TK", | ||
| "TO", | ||
| "TV", | ||
| "WF", | ||
| "WS" | ||
| ], | ||
| "142": [ | ||
| "030", | ||
| "034", | ||
| "035", | ||
| "142", | ||
| "143", | ||
| "145", | ||
| "AE", | ||
| "AF", | ||
| "AM", | ||
| "AZ", | ||
| "BD", | ||
| "BH", | ||
| "BN", | ||
| "BT", | ||
| "CN", | ||
| "CY", | ||
| "GE", | ||
| "HK", | ||
| "ID", | ||
| "IL", | ||
| "IN", | ||
| "IQ", | ||
| "IR", | ||
| "JO", | ||
| "JP", | ||
| "KG", | ||
| "KH", | ||
| "KP", | ||
| "KR", | ||
| "KW", | ||
| "KZ", | ||
| "LA", | ||
| "LB", | ||
| "LK", | ||
| "MM", | ||
| "MN", | ||
| "MO", | ||
| "MV", | ||
| "MY", | ||
| "NP", | ||
| "OM", | ||
| "PH", | ||
| "PK", | ||
| "PS", | ||
| "QA", | ||
| "SA", | ||
| "SG", | ||
| "SY", | ||
| "TH", | ||
| "TJ", | ||
| "TL", | ||
| "TM", | ||
| "TR", | ||
| "TW", | ||
| "UZ", | ||
| "VN", | ||
| "YE" | ||
| ], | ||
| "143": [ | ||
| "143", | ||
| "KG", | ||
| "KZ", | ||
| "TJ", | ||
| "TM", | ||
| "UZ" | ||
| ], | ||
| "145": [ | ||
| "145", | ||
| "AE", | ||
| "AM", | ||
| "AZ", | ||
| "BH", | ||
| "CY", | ||
| "GE", | ||
| "IL", | ||
| "IQ", | ||
| "JO", | ||
| "KW", | ||
| "LB", | ||
| "OM", | ||
| "PS", | ||
| "QA", | ||
| "SA", | ||
| "SY", | ||
| "TR", | ||
| "YE" | ||
| ], | ||
| "150": [ | ||
| "039", | ||
| "150", | ||
| "151", | ||
| "154", | ||
| "155", | ||
| "AD", | ||
| "AL", | ||
| "AT", | ||
| "AX", | ||
| "BA", | ||
| "BE", | ||
| "BG", | ||
| "BY", | ||
| "CH", | ||
| "CQ", | ||
| "CZ", | ||
| "DE", | ||
| "DK", | ||
| "EE", | ||
| "ES", | ||
| "FI", | ||
| "FO", | ||
| "FR", | ||
| "GB", | ||
| "GG", | ||
| "GI", | ||
| "GR", | ||
| "HR", | ||
| "HU", | ||
| "IE", | ||
| "IM", | ||
| "IS", | ||
| "IT", | ||
| "JE", | ||
| "LI", | ||
| "LT", | ||
| "LU", | ||
| "LV", | ||
| "MC", | ||
| "MD", | ||
| "ME", | ||
| "MK", | ||
| "MT", | ||
| "NL", | ||
| "NO", | ||
| "PL", | ||
| "PT", | ||
| "RO", | ||
| "RS", | ||
| "RU", | ||
| "SE", | ||
| "SI", | ||
| "SJ", | ||
| "SK", | ||
| "SM", | ||
| "UA", | ||
| "VA", | ||
| "XK" | ||
| ], | ||
| "151": [ | ||
| "151", | ||
| "BG", | ||
| "BY", | ||
| "CZ", | ||
| "HU", | ||
| "MD", | ||
| "PL", | ||
| "RO", | ||
| "RU", | ||
| "SK", | ||
| "UA" | ||
| ], | ||
| "154": [ | ||
| "154", | ||
| "AX", | ||
| "CQ", | ||
| "DK", | ||
| "EE", | ||
| "FI", | ||
| "FO", | ||
| "GB", | ||
| "GG", | ||
| "IE", | ||
| "IM", | ||
| "IS", | ||
| "JE", | ||
| "LT", | ||
| "LV", | ||
| "NO", | ||
| "SE", | ||
| "SJ" | ||
| ], | ||
| "155": [ | ||
| "155", | ||
| "AT", | ||
| "BE", | ||
| "CH", | ||
| "DE", | ||
| "FR", | ||
| "LI", | ||
| "LU", | ||
| "MC", | ||
| "NL" | ||
| ], | ||
| "202": [ | ||
| "011", | ||
| "014", | ||
| "017", | ||
| "018", | ||
| "202", | ||
| "AO", | ||
| "BF", | ||
| "BI", | ||
| "BJ", | ||
| "BW", | ||
| "CD", | ||
| "CF", | ||
| "CG", | ||
| "CI", | ||
| "CM", | ||
| "CV", | ||
| "DJ", | ||
| "ER", | ||
| "ET", | ||
| "GA", | ||
| "GH", | ||
| "GM", | ||
| "GN", | ||
| "GQ", | ||
| "GW", | ||
| "IO", | ||
| "KE", | ||
| "KM", | ||
| "LR", | ||
| "LS", | ||
| "MG", | ||
| "ML", | ||
| "MR", | ||
| "MU", | ||
| "MW", | ||
| "MZ", | ||
| "NA", | ||
| "NE", | ||
| "NG", | ||
| "RE", | ||
| "RW", | ||
| "SC", | ||
| "SH", | ||
| "SL", | ||
| "SN", | ||
| "SO", | ||
| "SS", | ||
| "ST", | ||
| "SZ", | ||
| "TD", | ||
| "TF", | ||
| "TG", | ||
| "TZ", | ||
| "UG", | ||
| "YT", | ||
| "ZA", | ||
| "ZM", | ||
| "ZW" | ||
| ], | ||
| "419": [ | ||
| "005", | ||
| "013", | ||
| "029", | ||
| "419", | ||
| "AG", | ||
| "AI", | ||
| "AR", | ||
| "AW", | ||
| "BB", | ||
| "BL", | ||
| "BO", | ||
| "BQ", | ||
| "BR", | ||
| "BS", | ||
| "BV", | ||
| "BZ", | ||
| "CL", | ||
| "CO", | ||
| "CR", | ||
| "CU", | ||
| "CW", | ||
| "DM", | ||
| "DO", | ||
| "EC", | ||
| "FK", | ||
| "GD", | ||
| "GF", | ||
| "GP", | ||
| "GS", | ||
| "GT", | ||
| "GY", | ||
| "HN", | ||
| "HT", | ||
| "JM", | ||
| "KN", | ||
| "KY", | ||
| "LC", | ||
| "MF", | ||
| "MQ", | ||
| "MS", | ||
| "MX", | ||
| "NI", | ||
| "PA", | ||
| "PE", | ||
| "PR", | ||
| "PY", | ||
| "SR", | ||
| "SV", | ||
| "SX", | ||
| "TC", | ||
| "TT", | ||
| "UY", | ||
| "VC", | ||
| "VE", | ||
| "VG", | ||
| "VI" | ||
| ], | ||
| EU: [ | ||
| "AT", | ||
| "BE", | ||
| "BG", | ||
| "CY", | ||
| "CZ", | ||
| "DE", | ||
| "DK", | ||
| "EE", | ||
| "ES", | ||
| "EU", | ||
| "FI", | ||
| "FR", | ||
| "GR", | ||
| "HR", | ||
| "HU", | ||
| "IE", | ||
| "IT", | ||
| "LT", | ||
| "LU", | ||
| "LV", | ||
| "MT", | ||
| "NL", | ||
| "PL", | ||
| "PT", | ||
| "RO", | ||
| "SE", | ||
| "SI", | ||
| "SK" | ||
| ], | ||
| EZ: [ | ||
| "AT", | ||
| "BE", | ||
| "CY", | ||
| "DE", | ||
| "EE", | ||
| "ES", | ||
| "EZ", | ||
| "FI", | ||
| "FR", | ||
| "GR", | ||
| "IE", | ||
| "IT", | ||
| "LT", | ||
| "LU", | ||
| "LV", | ||
| "MT", | ||
| "NL", | ||
| "PT", | ||
| "SI", | ||
| "SK" | ||
| ], | ||
| QO: [ | ||
| "AC", | ||
| "AQ", | ||
| "CP", | ||
| "DG", | ||
| "QO", | ||
| "TA" | ||
| ], | ||
| UN: [ | ||
| "AD", | ||
| "AE", | ||
| "AF", | ||
| "AG", | ||
| "AL", | ||
| "AM", | ||
| "AO", | ||
| "AR", | ||
| "AT", | ||
| "AU", | ||
| "AZ", | ||
| "BA", | ||
| "BB", | ||
| "BD", | ||
| "BE", | ||
| "BF", | ||
| "BG", | ||
| "BH", | ||
| "BI", | ||
| "BJ", | ||
| "BN", | ||
| "BO", | ||
| "BR", | ||
| "BS", | ||
| "BT", | ||
| "BW", | ||
| "BY", | ||
| "BZ", | ||
| "CA", | ||
| "CD", | ||
| "CF", | ||
| "CG", | ||
| "CH", | ||
| "CI", | ||
| "CL", | ||
| "CM", | ||
| "CN", | ||
| "CO", | ||
| "CR", | ||
| "CU", | ||
| "CV", | ||
| "CY", | ||
| "CZ", | ||
| "DE", | ||
| "DJ", | ||
| "DK", | ||
| "DM", | ||
| "DO", | ||
| "DZ", | ||
| "EC", | ||
| "EE", | ||
| "EG", | ||
| "ER", | ||
| "ES", | ||
| "ET", | ||
| "FI", | ||
| "FJ", | ||
| "FM", | ||
| "FR", | ||
| "GA", | ||
| "GB", | ||
| "GD", | ||
| "GE", | ||
| "GH", | ||
| "GM", | ||
| "GN", | ||
| "GQ", | ||
| "GR", | ||
| "GT", | ||
| "GW", | ||
| "GY", | ||
| "HN", | ||
| "HR", | ||
| "HT", | ||
| "HU", | ||
| "ID", | ||
| "IE", | ||
| "IL", | ||
| "IN", | ||
| "IQ", | ||
| "IR", | ||
| "IS", | ||
| "IT", | ||
| "JM", | ||
| "JO", | ||
| "JP", | ||
| "KE", | ||
| "KG", | ||
| "KH", | ||
| "KI", | ||
| "KM", | ||
| "KN", | ||
| "KP", | ||
| "KR", | ||
| "KW", | ||
| "KZ", | ||
| "LA", | ||
| "LB", | ||
| "LC", | ||
| "LI", | ||
| "LK", | ||
| "LR", | ||
| "LS", | ||
| "LT", | ||
| "LU", | ||
| "LV", | ||
| "LY", | ||
| "MA", | ||
| "MC", | ||
| "MD", | ||
| "ME", | ||
| "MG", | ||
| "MH", | ||
| "MK", | ||
| "ML", | ||
| "MM", | ||
| "MN", | ||
| "MR", | ||
| "MT", | ||
| "MU", | ||
| "MV", | ||
| "MW", | ||
| "MX", | ||
| "MY", | ||
| "MZ", | ||
| "NA", | ||
| "NE", | ||
| "NG", | ||
| "NI", | ||
| "NL", | ||
| "NO", | ||
| "NP", | ||
| "NR", | ||
| "NZ", | ||
| "OM", | ||
| "PA", | ||
| "PE", | ||
| "PG", | ||
| "PH", | ||
| "PK", | ||
| "PL", | ||
| "PT", | ||
| "PW", | ||
| "PY", | ||
| "QA", | ||
| "RO", | ||
| "RS", | ||
| "RU", | ||
| "RW", | ||
| "SA", | ||
| "SB", | ||
| "SC", | ||
| "SD", | ||
| "SE", | ||
| "SG", | ||
| "SI", | ||
| "SK", | ||
| "SL", | ||
| "SM", | ||
| "SN", | ||
| "SO", | ||
| "SR", | ||
| "SS", | ||
| "ST", | ||
| "SV", | ||
| "SY", | ||
| "SZ", | ||
| "TD", | ||
| "TG", | ||
| "TH", | ||
| "TJ", | ||
| "TL", | ||
| "TM", | ||
| "TN", | ||
| "TO", | ||
| "TR", | ||
| "TT", | ||
| "TV", | ||
| "TZ", | ||
| "UA", | ||
| "UG", | ||
| "UN", | ||
| "US", | ||
| "UY", | ||
| "UZ", | ||
| "VC", | ||
| "VE", | ||
| "VN", | ||
| "VU", | ||
| "WS", | ||
| "YE", | ||
| "ZA", | ||
| "ZM", | ||
| "ZW" | ||
| ] | ||
| }; |
| export interface ResolveLocaleResult { | ||
| locale: string; | ||
| dataLocale: string; | ||
| [k: string]: any; | ||
| locale: string; | ||
| dataLocale: string; | ||
| [k: string]: any; | ||
| } | ||
| /** | ||
| * https://tc39.es/ecma402/#sec-resolvelocale | ||
| */ | ||
| export declare function ResolveLocale<K extends string, D extends { | ||
| [k in K]: any; | ||
| }>(availableLocales: Set<string> | readonly string[], requestedLocales: readonly string[], options: { | ||
| localeMatcher: string; | ||
| [k: string]: string; | ||
| * https://tc39.es/ecma402/#sec-resolvelocale | ||
| */ | ||
| export declare function ResolveLocale< | ||
| K extends string, | ||
| D extends { [k in K] : any } | ||
| >(availableLocales: Set<string> | readonly string[], requestedLocales: readonly string[], options: { | ||
| localeMatcher: string; | ||
| [k: string]: string; | ||
| }, relevantExtensionKeys: K[], localeData: Record<string, D | undefined>, getDefaultLocale: () => string): ResolveLocaleResult; |
@@ -1,100 +0,95 @@ | ||
| import { BestFitMatcher } from './BestFitMatcher.js'; | ||
| import { CanonicalizeUValue } from './CanonicalizeUValue.js'; | ||
| import { InsertUnicodeExtensionAndCanonicalize } from './InsertUnicodeExtensionAndCanonicalize.js'; | ||
| import { LookupMatcher } from './LookupMatcher.js'; | ||
| import { UnicodeExtensionComponents } from './UnicodeExtensionComponents.js'; | ||
| import { invariant } from './utils.js'; | ||
| import { BestFitMatcher } from "./BestFitMatcher.js"; | ||
| import { CanonicalizeUValue } from "./CanonicalizeUValue.js"; | ||
| import { InsertUnicodeExtensionAndCanonicalize } from "./InsertUnicodeExtensionAndCanonicalize.js"; | ||
| import { LookupMatcher } from "./LookupMatcher.js"; | ||
| import { UnicodeExtensionComponents } from "./UnicodeExtensionComponents.js"; | ||
| import { invariant } from "./utils.js"; | ||
| /** | ||
| * https://tc39.es/ecma402/#sec-resolvelocale | ||
| */ | ||
| * https://tc39.es/ecma402/#sec-resolvelocale | ||
| */ | ||
| export function ResolveLocale(availableLocales, requestedLocales, options, relevantExtensionKeys, localeData, getDefaultLocale) { | ||
| var _a; | ||
| var matcher = options.localeMatcher; | ||
| var r; | ||
| if (matcher === 'lookup') { | ||
| r = LookupMatcher(Array.from(availableLocales), requestedLocales, getDefaultLocale); | ||
| } | ||
| else { | ||
| r = BestFitMatcher(Array.from(availableLocales), requestedLocales, getDefaultLocale); | ||
| } | ||
| if (r == null) { | ||
| r = { | ||
| locale: getDefaultLocale(), | ||
| extension: '', | ||
| }; | ||
| } | ||
| var foundLocale = r.locale; | ||
| var foundLocaleData = localeData[foundLocale]; | ||
| // TODO: We can't really guarantee that the locale data is available | ||
| // invariant( | ||
| // foundLocaleData !== undefined, | ||
| // `Missing locale data for ${foundLocale}` | ||
| // ) | ||
| var result = { locale: 'en', dataLocale: foundLocale }; | ||
| var components; | ||
| var keywords; | ||
| if (r.extension) { | ||
| components = UnicodeExtensionComponents(r.extension); | ||
| keywords = components.keywords; | ||
| } | ||
| else { | ||
| keywords = []; | ||
| } | ||
| var supportedKeywords = []; | ||
| var _loop_1 = function (key) { | ||
| // TODO: Shouldn't default to empty array, see TODO above | ||
| var keyLocaleData = (_a = foundLocaleData === null || foundLocaleData === void 0 ? void 0 : foundLocaleData[key]) !== null && _a !== void 0 ? _a : []; | ||
| invariant(Array.isArray(keyLocaleData), "keyLocaleData for ".concat(key, " must be an array")); | ||
| var value = keyLocaleData[0]; | ||
| invariant(value === undefined || typeof value === 'string', "value must be a string or undefined"); | ||
| var supportedKeyword = void 0; | ||
| var entry = keywords.find(function (k) { return k.key === key; }); | ||
| if (entry) { | ||
| var requestedValue = entry.value; | ||
| if (requestedValue !== '') { | ||
| if (keyLocaleData.indexOf(requestedValue) > -1) { | ||
| value = requestedValue; | ||
| supportedKeyword = { | ||
| key: key, | ||
| value: value, | ||
| }; | ||
| } | ||
| } | ||
| else if (keyLocaleData.indexOf('true') > -1) { | ||
| value = 'true'; | ||
| supportedKeyword = { | ||
| key: key, | ||
| value: value, | ||
| }; | ||
| } | ||
| } | ||
| var optionsValue = options[key]; | ||
| invariant(optionsValue == null || typeof optionsValue === 'string', "optionsValue must be a string or undefined"); | ||
| if (typeof optionsValue === 'string') { | ||
| var ukey = key.toLowerCase(); | ||
| optionsValue = CanonicalizeUValue(ukey, optionsValue); | ||
| if (optionsValue === '') { | ||
| optionsValue = 'true'; | ||
| } | ||
| } | ||
| if (optionsValue !== value && keyLocaleData.indexOf(optionsValue) > -1) { | ||
| value = optionsValue; | ||
| supportedKeyword = undefined; | ||
| } | ||
| if (supportedKeyword) { | ||
| supportedKeywords.push(supportedKeyword); | ||
| } | ||
| result[key] = value; | ||
| }; | ||
| for (var _i = 0, relevantExtensionKeys_1 = relevantExtensionKeys; _i < relevantExtensionKeys_1.length; _i++) { | ||
| var key = relevantExtensionKeys_1[_i]; | ||
| _loop_1(key); | ||
| } | ||
| var supportedAttributes = []; | ||
| if (supportedKeywords.length > 0) { | ||
| supportedAttributes = []; | ||
| foundLocale = InsertUnicodeExtensionAndCanonicalize(foundLocale, supportedAttributes, supportedKeywords); | ||
| } | ||
| result.locale = foundLocale; | ||
| return result; | ||
| const matcher = options.localeMatcher; | ||
| let r; | ||
| if (matcher === "lookup") { | ||
| r = LookupMatcher(Array.from(availableLocales), requestedLocales, getDefaultLocale); | ||
| } else { | ||
| r = BestFitMatcher(Array.from(availableLocales), requestedLocales, getDefaultLocale); | ||
| } | ||
| if (r == null) { | ||
| r = { | ||
| locale: getDefaultLocale(), | ||
| extension: "" | ||
| }; | ||
| } | ||
| let foundLocale = r.locale; | ||
| let foundLocaleData = localeData[foundLocale]; | ||
| // TODO: We can't really guarantee that the locale data is available | ||
| // invariant( | ||
| // foundLocaleData !== undefined, | ||
| // `Missing locale data for ${foundLocale}` | ||
| // ) | ||
| const result = { | ||
| locale: "en", | ||
| dataLocale: foundLocale | ||
| }; | ||
| let components; | ||
| let keywords; | ||
| if (r.extension) { | ||
| components = UnicodeExtensionComponents(r.extension); | ||
| keywords = components.keywords; | ||
| } else { | ||
| keywords = []; | ||
| } | ||
| let supportedKeywords = []; | ||
| for (const key of relevantExtensionKeys) { | ||
| // TODO: Shouldn't default to empty array, see TODO above | ||
| let keyLocaleData = foundLocaleData?.[key] ?? []; | ||
| invariant(Array.isArray(keyLocaleData), `keyLocaleData for ${key} must be an array`); | ||
| let value = keyLocaleData[0]; | ||
| invariant(value === undefined || typeof value === "string", `value must be a string or undefined`); | ||
| let supportedKeyword; | ||
| let entry = keywords.find((k) => k.key === key); | ||
| if (entry) { | ||
| let requestedValue = entry.value; | ||
| if (requestedValue !== "") { | ||
| if (keyLocaleData.indexOf(requestedValue) > -1) { | ||
| value = requestedValue; | ||
| supportedKeyword = { | ||
| key, | ||
| value | ||
| }; | ||
| } | ||
| } else if (keyLocaleData.indexOf("true") > -1) { | ||
| value = "true"; | ||
| supportedKeyword = { | ||
| key, | ||
| value | ||
| }; | ||
| } | ||
| } | ||
| let optionsValue = options[key]; | ||
| invariant(optionsValue == null || typeof optionsValue === "string", `optionsValue must be a string or undefined`); | ||
| if (typeof optionsValue === "string") { | ||
| let ukey = key.toLowerCase(); | ||
| optionsValue = CanonicalizeUValue(ukey, optionsValue); | ||
| if (optionsValue === "") { | ||
| optionsValue = "true"; | ||
| } | ||
| } | ||
| if (optionsValue !== value && keyLocaleData.indexOf(optionsValue) > -1) { | ||
| value = optionsValue; | ||
| supportedKeyword = undefined; | ||
| } | ||
| if (supportedKeyword) { | ||
| supportedKeywords.push(supportedKeyword); | ||
| } | ||
| result[key] = value; | ||
| } | ||
| let supportedAttributes = []; | ||
| if (supportedKeywords.length > 0) { | ||
| supportedAttributes = []; | ||
| foundLocale = InsertUnicodeExtensionAndCanonicalize(foundLocale, supportedAttributes, supportedKeywords); | ||
| } | ||
| result.locale = foundLocale; | ||
| return result; | ||
| } |
| export interface LookupMatcherResult { | ||
| locale: string; | ||
| extension?: string; | ||
| nu?: string; | ||
| locale: string; | ||
| extension?: string; | ||
| nu?: string; | ||
| } | ||
| export interface Keyword { | ||
| key: string; | ||
| value: string; | ||
| key: string; | ||
| value: string; | ||
| } |
@@ -1,5 +0,5 @@ | ||
| import { Keyword } from './types.js'; | ||
| import type { Keyword } from "./types.js"; | ||
| export declare function UnicodeExtensionComponents(extension: string): { | ||
| attributes: string[]; | ||
| keywords: Array<Keyword>; | ||
| attributes: string[]; | ||
| keywords: Array<Keyword>; | ||
| }; |
@@ -1,42 +0,44 @@ | ||
| import { invariant } from './utils.js'; | ||
| import { invariant } from "./utils.js"; | ||
| export function UnicodeExtensionComponents(extension) { | ||
| invariant(extension === extension.toLowerCase(), 'Expected extension to be lowercase'); | ||
| invariant(extension.slice(0, 3) === '-u-', 'Expected extension to be a Unicode locale extension'); | ||
| var attributes = []; | ||
| var keywords = []; | ||
| var keyword; | ||
| var size = extension.length; | ||
| var k = 3; | ||
| while (k < size) { | ||
| var e = extension.indexOf('-', k); | ||
| var len = void 0; | ||
| if (e === -1) { | ||
| len = size - k; | ||
| } | ||
| else { | ||
| len = e - k; | ||
| } | ||
| var subtag = extension.slice(k, k + len); | ||
| invariant(len >= 2, 'Expected a subtag to have at least 2 characters'); | ||
| if (keyword === undefined && len != 2) { | ||
| if (attributes.indexOf(subtag) === -1) { | ||
| attributes.push(subtag); | ||
| } | ||
| } | ||
| else if (len === 2) { | ||
| keyword = { key: subtag, value: '' }; | ||
| if (keywords.find(function (k) { return k.key === (keyword === null || keyword === void 0 ? void 0 : keyword.key); }) === undefined) { | ||
| keywords.push(keyword); | ||
| } | ||
| } | ||
| else if ((keyword === null || keyword === void 0 ? void 0 : keyword.value) === '') { | ||
| keyword.value = subtag; | ||
| } | ||
| else { | ||
| invariant(keyword !== undefined, 'Expected keyword to be defined'); | ||
| keyword.value += '-' + subtag; | ||
| } | ||
| k += len + 1; | ||
| } | ||
| return { attributes: attributes, keywords: keywords }; | ||
| invariant(extension === extension.toLowerCase(), "Expected extension to be lowercase"); | ||
| invariant(extension.slice(0, 3) === "-u-", "Expected extension to be a Unicode locale extension"); | ||
| const attributes = []; | ||
| const keywords = []; | ||
| let keyword; | ||
| let size = extension.length; | ||
| let k = 3; | ||
| while (k < size) { | ||
| let e = extension.indexOf("-", k); | ||
| let len; | ||
| if (e === -1) { | ||
| len = size - k; | ||
| } else { | ||
| len = e - k; | ||
| } | ||
| let subtag = extension.slice(k, k + len); | ||
| invariant(len >= 2, "Expected a subtag to have at least 2 characters"); | ||
| if (keyword === undefined && len != 2) { | ||
| if (attributes.indexOf(subtag) === -1) { | ||
| attributes.push(subtag); | ||
| } | ||
| } else if (len === 2) { | ||
| keyword = { | ||
| key: subtag, | ||
| value: "" | ||
| }; | ||
| if (keywords.find((k) => k.key === keyword?.key) === undefined) { | ||
| keywords.push(keyword); | ||
| } | ||
| } else if (keyword?.value === "") { | ||
| keyword.value = subtag; | ||
| } else { | ||
| invariant(keyword !== undefined, "Expected keyword to be defined"); | ||
| keyword.value += "-" + subtag; | ||
| } | ||
| k += len + 1; | ||
| } | ||
| return { | ||
| attributes, | ||
| keywords | ||
| }; | ||
| } |
| /** | ||
| * https://tc39.es/ecma402/#sec-unicodeextensionvalue | ||
| * @param extension | ||
| * @param key | ||
| */ | ||
| * https://tc39.es/ecma402/#sec-unicodeextensionvalue | ||
| * @param extension | ||
| * @param key | ||
| */ | ||
| export declare function UnicodeExtensionValue(extension: string, key: string): string | undefined; |
@@ -1,46 +0,43 @@ | ||
| import { invariant } from './utils.js'; | ||
| import { invariant } from "./utils.js"; | ||
| /** | ||
| * https://tc39.es/ecma402/#sec-unicodeextensionvalue | ||
| * @param extension | ||
| * @param key | ||
| */ | ||
| * https://tc39.es/ecma402/#sec-unicodeextensionvalue | ||
| * @param extension | ||
| * @param key | ||
| */ | ||
| export function UnicodeExtensionValue(extension, key) { | ||
| invariant(key.length === 2, 'key must have 2 elements'); | ||
| var size = extension.length; | ||
| var searchValue = "-".concat(key, "-"); | ||
| var pos = extension.indexOf(searchValue); | ||
| if (pos !== -1) { | ||
| var start = pos + 4; | ||
| var end = start; | ||
| var k = start; | ||
| var done = false; | ||
| while (!done) { | ||
| var e = extension.indexOf('-', k); | ||
| var len = void 0; | ||
| if (e === -1) { | ||
| len = size - k; | ||
| } | ||
| else { | ||
| len = e - k; | ||
| } | ||
| if (len === 2) { | ||
| done = true; | ||
| } | ||
| else if (e === -1) { | ||
| end = size; | ||
| done = true; | ||
| } | ||
| else { | ||
| end = e; | ||
| k = e + 1; | ||
| } | ||
| } | ||
| return extension.slice(start, end); | ||
| } | ||
| searchValue = "-".concat(key); | ||
| pos = extension.indexOf(searchValue); | ||
| if (pos !== -1 && pos + 3 === size) { | ||
| return ''; | ||
| } | ||
| return undefined; | ||
| invariant(key.length === 2, "key must have 2 elements"); | ||
| const size = extension.length; | ||
| let searchValue = `-${key}-`; | ||
| let pos = extension.indexOf(searchValue); | ||
| if (pos !== -1) { | ||
| const start = pos + 4; | ||
| let end = start; | ||
| let k = start; | ||
| let done = false; | ||
| while (!done) { | ||
| const e = extension.indexOf("-", k); | ||
| let len; | ||
| if (e === -1) { | ||
| len = size - k; | ||
| } else { | ||
| len = e - k; | ||
| } | ||
| if (len === 2) { | ||
| done = true; | ||
| } else if (e === -1) { | ||
| end = size; | ||
| done = true; | ||
| } else { | ||
| end = e; | ||
| k = e + 1; | ||
| } | ||
| } | ||
| return extension.slice(start, end); | ||
| } | ||
| searchValue = `-${key}`; | ||
| pos = extension.indexOf(searchValue); | ||
| if (pos !== -1 && pos + 3 === size) { | ||
| return ""; | ||
| } | ||
| return undefined; | ||
| } |
+37
-37
| export declare const UNICODE_EXTENSION_SEQUENCE_REGEX: RegExp; | ||
| /** | ||
| * Asserts that a condition is true, throwing an error if it is not. | ||
| * Used for runtime validation and type narrowing. | ||
| * | ||
| * @param condition - The condition to check | ||
| * @param message - Error message if condition is false | ||
| * @param Err - Error constructor to use (defaults to Error) | ||
| * @throws {Error} When condition is false | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * invariant(locale !== undefined, 'Locale must be defined') | ||
| * // locale is now narrowed to non-undefined type | ||
| * ``` | ||
| */ | ||
| * Asserts that a condition is true, throwing an error if it is not. | ||
| * Used for runtime validation and type narrowing. | ||
| * | ||
| * @param condition - The condition to check | ||
| * @param message - Error message if condition is false | ||
| * @param Err - Error constructor to use (defaults to Error) | ||
| * @throws {Error} When condition is false | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * invariant(locale !== undefined, 'Locale must be defined') | ||
| * // locale is now narrowed to non-undefined type | ||
| * ``` | ||
| */ | ||
| export declare function invariant(condition: boolean, message: string, Err?: any): asserts condition; | ||
| /** | ||
| * Calculates the matching distance between two locales using the CLDR Enhanced Language Matching algorithm. | ||
| * This function is memoized for performance, as distance calculations are expensive. | ||
| * | ||
| * The distance represents how "far apart" two locales are, with 0 being identical (after maximization). | ||
| * Distances are calculated based on Language-Script-Region (LSR) differences using CLDR data. | ||
| * | ||
| * @param desired - The desired locale (e.g., "en-US") | ||
| * @param supported - The supported locale to compare against (e.g., "en-GB") | ||
| * @returns The calculated distance between the locales | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * findMatchingDistance('en-US', 'en-US') // 0 - identical | ||
| * findMatchingDistance('en-US', 'en-GB') // 40 - same language/script, different region | ||
| * findMatchingDistance('es-CO', 'es-419') // 39 - regional variant | ||
| * findMatchingDistance('en', 'fr') // 840 - completely different languages | ||
| * ``` | ||
| * | ||
| * @see https://unicode.org/reports/tr35/#EnhancedLanguageMatching | ||
| */ | ||
| * Calculates the matching distance between two locales using the CLDR Enhanced Language Matching algorithm. | ||
| * This function is memoized for performance, as distance calculations are expensive. | ||
| * | ||
| * The distance represents how "far apart" two locales are, with 0 being identical (after maximization). | ||
| * Distances are calculated based on Language-Script-Region (LSR) differences using CLDR data. | ||
| * | ||
| * @param desired - The desired locale (e.g., "en-US") | ||
| * @param supported - The supported locale to compare against (e.g., "en-GB") | ||
| * @returns The calculated distance between the locales | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * findMatchingDistance('en-US', 'en-US') // 0 - identical | ||
| * findMatchingDistance('en-US', 'en-GB') // 40 - same language/script, different region | ||
| * findMatchingDistance('es-CO', 'es-419') // 39 - regional variant | ||
| * findMatchingDistance('en', 'fr') // 840 - completely different languages | ||
| * ``` | ||
| * | ||
| * @see https://unicode.org/reports/tr35/#EnhancedLanguageMatching | ||
| */ | ||
| export declare const findMatchingDistance: (desired: string, supported: string) => number; | ||
| interface LocaleMatchingResult { | ||
| distances: Record<string, Record<string, number>>; | ||
| matchedSupportedLocale?: string; | ||
| matchedDesiredLocale?: string; | ||
| distances: Record<string, Record<string, number>>; | ||
| matchedSupportedLocale?: string; | ||
| matchedDesiredLocale?: string; | ||
| } | ||
| export declare function findBestMatch(requestedLocales: readonly string[], supportedLocales: readonly string[], threshold?: number): LocaleMatchingResult; | ||
| export {}; |
+329
-359
@@ -1,379 +0,349 @@ | ||
| import { __spreadArray } from "tslib"; | ||
| import { memoize } from '@formatjs/fast-memoize'; | ||
| import { data as jsonData } from './languageMatching.js'; | ||
| import { regions } from './regions.generated.js'; | ||
| export var UNICODE_EXTENSION_SEQUENCE_REGEX = /-u(?:-[0-9a-z]{2,8})+/gi; | ||
| import { memoize } from "@formatjs/fast-memoize"; | ||
| import { data as jsonData } from "./languageMatching.js"; | ||
| import { regions } from "./regions.generated.js"; | ||
| export const UNICODE_EXTENSION_SEQUENCE_REGEX = /-u(?:-[0-9a-z]{2,8})+/gi; | ||
| /** | ||
| * Asserts that a condition is true, throwing an error if it is not. | ||
| * Used for runtime validation and type narrowing. | ||
| * | ||
| * @param condition - The condition to check | ||
| * @param message - Error message if condition is false | ||
| * @param Err - Error constructor to use (defaults to Error) | ||
| * @throws {Error} When condition is false | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * invariant(locale !== undefined, 'Locale must be defined') | ||
| * // locale is now narrowed to non-undefined type | ||
| * ``` | ||
| */ | ||
| export function invariant(condition, message, Err) { | ||
| if (Err === void 0) { Err = Error; } | ||
| if (!condition) { | ||
| throw new Err(message); | ||
| } | ||
| * Asserts that a condition is true, throwing an error if it is not. | ||
| * Used for runtime validation and type narrowing. | ||
| * | ||
| * @param condition - The condition to check | ||
| * @param message - Error message if condition is false | ||
| * @param Err - Error constructor to use (defaults to Error) | ||
| * @throws {Error} When condition is false | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * invariant(locale !== undefined, 'Locale must be defined') | ||
| * // locale is now narrowed to non-undefined type | ||
| * ``` | ||
| */ | ||
| export function invariant(condition, message, Err = Error) { | ||
| if (!condition) { | ||
| throw new Err(message); | ||
| } | ||
| } | ||
| // This is effectively 2 languages in 2 different regions in the same cluster | ||
| var DEFAULT_MATCHING_THRESHOLD = 838; | ||
| var PROCESSED_DATA; | ||
| const DEFAULT_MATCHING_THRESHOLD = 838; | ||
| let PROCESSED_DATA; | ||
| function processData() { | ||
| var _a, _b; | ||
| if (!PROCESSED_DATA) { | ||
| var paradigmLocales = (_b = (_a = jsonData.supplemental.languageMatching['written-new'][0]) === null || _a === void 0 ? void 0 : _a.paradigmLocales) === null || _b === void 0 ? void 0 : _b._locales.split(' '); | ||
| var matchVariables = jsonData.supplemental.languageMatching['written-new'].slice(1, 5); | ||
| var data = jsonData.supplemental.languageMatching['written-new'].slice(5); | ||
| var matches = data.map(function (d) { | ||
| var key = Object.keys(d)[0]; | ||
| var value = d[key]; | ||
| return { | ||
| supported: key, | ||
| desired: value._desired, | ||
| distance: +value._distance, | ||
| oneway: value.oneway === 'true' ? true : false, | ||
| }; | ||
| }, {}); | ||
| PROCESSED_DATA = { | ||
| matches: matches, | ||
| matchVariables: matchVariables.reduce(function (all, d) { | ||
| var key = Object.keys(d)[0]; | ||
| var value = d[key]; | ||
| all[key.slice(1)] = value._value.split('+'); | ||
| return all; | ||
| }, {}), | ||
| paradigmLocales: __spreadArray(__spreadArray([], paradigmLocales, true), paradigmLocales.map(function (l) { | ||
| return new Intl.Locale(l.replace(/_/g, '-')).maximize().toString(); | ||
| }), true), | ||
| }; | ||
| } | ||
| return PROCESSED_DATA; | ||
| if (!PROCESSED_DATA) { | ||
| const paradigmLocales = jsonData.supplemental.languageMatching["written-new"][0]?.paradigmLocales?._locales.split(" "); | ||
| const matchVariables = jsonData.supplemental.languageMatching["written-new"].slice(1, 5); | ||
| const data = jsonData.supplemental.languageMatching["written-new"].slice(5); | ||
| const matches = data.map((d) => { | ||
| const key = Object.keys(d)[0]; | ||
| const value = d[key]; | ||
| return { | ||
| supported: key, | ||
| desired: value._desired, | ||
| distance: +value._distance, | ||
| oneway: value.oneway === "true" ? true : false | ||
| }; | ||
| }, {}); | ||
| PROCESSED_DATA = { | ||
| matches, | ||
| matchVariables: matchVariables.reduce((all, d) => { | ||
| const key = Object.keys(d)[0]; | ||
| const value = d[key]; | ||
| all[key.slice(1)] = value._value.split("+"); | ||
| return all; | ||
| }, {}), | ||
| paradigmLocales: [...paradigmLocales, ...paradigmLocales.map((l) => new Intl.Locale(l.replace(/_/g, "-")).maximize().toString())] | ||
| }; | ||
| } | ||
| return PROCESSED_DATA; | ||
| } | ||
| function isMatched(locale, languageMatchInfoLocale, matchVariables) { | ||
| var _a = languageMatchInfoLocale.split('-'), language = _a[0], script = _a[1], region = _a[2]; | ||
| var matches = true; | ||
| if (region && region[0] === '$') { | ||
| var shouldInclude = region[1] !== '!'; | ||
| var matchRegions = shouldInclude | ||
| ? matchVariables[region.slice(1)] | ||
| : matchVariables[region.slice(2)]; | ||
| var expandedMatchedRegions = matchRegions | ||
| .map(function (r) { return regions[r] || [r]; }) | ||
| .reduce(function (all, list) { return __spreadArray(__spreadArray([], all, true), list, true); }, []); | ||
| matches && (matches = !(expandedMatchedRegions.indexOf(locale.region || '') > -1 != | ||
| shouldInclude)); | ||
| } | ||
| else { | ||
| matches && (matches = locale.region | ||
| ? region === '*' || region === locale.region | ||
| : true); | ||
| } | ||
| matches && (matches = locale.script ? script === '*' || script === locale.script : true); | ||
| matches && (matches = locale.language | ||
| ? language === '*' || language === locale.language | ||
| : true); | ||
| return matches; | ||
| const [language, script, region] = languageMatchInfoLocale.split("-"); | ||
| let matches = true; | ||
| if (region && region[0] === "$") { | ||
| const shouldInclude = region[1] !== "!"; | ||
| const matchRegions = shouldInclude ? matchVariables[region.slice(1)] : matchVariables[region.slice(2)]; | ||
| const expandedMatchedRegions = matchRegions.map((r) => regions[r] || [r]).reduce((all, list) => [...all, ...list], []); | ||
| matches &&= !(expandedMatchedRegions.indexOf(locale.region || "") > -1 != shouldInclude); | ||
| } else { | ||
| matches &&= locale.region ? region === "*" || region === locale.region : true; | ||
| } | ||
| matches &&= locale.script ? script === "*" || script === locale.script : true; | ||
| matches &&= locale.language ? language === "*" || language === locale.language : true; | ||
| return matches; | ||
| } | ||
| function serializeLSR(lsr) { | ||
| return [lsr.language, lsr.script, lsr.region].filter(Boolean).join('-'); | ||
| return [ | ||
| lsr.language, | ||
| lsr.script, | ||
| lsr.region | ||
| ].filter(Boolean).join("-"); | ||
| } | ||
| function findMatchingDistanceForLSR(desired, supported, data) { | ||
| for (var _i = 0, _a = data.matches; _i < _a.length; _i++) { | ||
| var d = _a[_i]; | ||
| var matches = isMatched(desired, d.desired, data.matchVariables) && | ||
| isMatched(supported, d.supported, data.matchVariables); | ||
| if (!d.oneway && !matches) { | ||
| matches = | ||
| isMatched(desired, d.supported, data.matchVariables) && | ||
| isMatched(supported, d.desired, data.matchVariables); | ||
| } | ||
| if (matches) { | ||
| var distance = d.distance * 10; | ||
| if (data.paradigmLocales.indexOf(serializeLSR(desired)) > -1 != | ||
| data.paradigmLocales.indexOf(serializeLSR(supported)) > -1) { | ||
| return distance - 1; | ||
| } | ||
| return distance; | ||
| } | ||
| } | ||
| throw new Error('No matching distance found'); | ||
| for (const d of data.matches) { | ||
| let matches = isMatched(desired, d.desired, data.matchVariables) && isMatched(supported, d.supported, data.matchVariables); | ||
| if (!d.oneway && !matches) { | ||
| matches = isMatched(desired, d.supported, data.matchVariables) && isMatched(supported, d.desired, data.matchVariables); | ||
| } | ||
| if (matches) { | ||
| const distance = d.distance * 10; | ||
| if (data.paradigmLocales.indexOf(serializeLSR(desired)) > -1 != data.paradigmLocales.indexOf(serializeLSR(supported)) > -1) { | ||
| return distance - 1; | ||
| } | ||
| return distance; | ||
| } | ||
| } | ||
| throw new Error("No matching distance found"); | ||
| } | ||
| function findMatchingDistanceImpl(desired, supported) { | ||
| var desiredLocale = new Intl.Locale(desired).maximize(); | ||
| var supportedLocale = new Intl.Locale(supported).maximize(); | ||
| var desiredLSR = { | ||
| language: desiredLocale.language, | ||
| script: desiredLocale.script || '', | ||
| region: desiredLocale.region || '', | ||
| }; | ||
| var supportedLSR = { | ||
| language: supportedLocale.language, | ||
| script: supportedLocale.script || '', | ||
| region: supportedLocale.region || '', | ||
| }; | ||
| var matchingDistance = 0; | ||
| var data = processData(); | ||
| if (desiredLSR.language !== supportedLSR.language) { | ||
| matchingDistance += findMatchingDistanceForLSR({ | ||
| language: desiredLocale.language, | ||
| script: '', | ||
| region: '', | ||
| }, { | ||
| language: supportedLocale.language, | ||
| script: '', | ||
| region: '', | ||
| }, data); | ||
| } | ||
| if (desiredLSR.script !== supportedLSR.script) { | ||
| matchingDistance += findMatchingDistanceForLSR({ | ||
| language: desiredLocale.language, | ||
| script: desiredLSR.script, | ||
| region: '', | ||
| }, { | ||
| language: supportedLocale.language, | ||
| script: supportedLSR.script, | ||
| region: '', | ||
| }, data); | ||
| } | ||
| if (desiredLSR.region !== supportedLSR.region) { | ||
| matchingDistance += findMatchingDistanceForLSR(desiredLSR, supportedLSR, data); | ||
| } | ||
| return matchingDistance; | ||
| const desiredLocale = new Intl.Locale(desired).maximize(); | ||
| const supportedLocale = new Intl.Locale(supported).maximize(); | ||
| const desiredLSR = { | ||
| language: desiredLocale.language, | ||
| script: desiredLocale.script || "", | ||
| region: desiredLocale.region || "" | ||
| }; | ||
| const supportedLSR = { | ||
| language: supportedLocale.language, | ||
| script: supportedLocale.script || "", | ||
| region: supportedLocale.region || "" | ||
| }; | ||
| let matchingDistance = 0; | ||
| const data = processData(); | ||
| if (desiredLSR.language !== supportedLSR.language) { | ||
| matchingDistance += findMatchingDistanceForLSR({ | ||
| language: desiredLocale.language, | ||
| script: "", | ||
| region: "" | ||
| }, { | ||
| language: supportedLocale.language, | ||
| script: "", | ||
| region: "" | ||
| }, data); | ||
| } | ||
| if (desiredLSR.script !== supportedLSR.script) { | ||
| matchingDistance += findMatchingDistanceForLSR({ | ||
| language: desiredLocale.language, | ||
| script: desiredLSR.script, | ||
| region: "" | ||
| }, { | ||
| language: supportedLocale.language, | ||
| script: supportedLSR.script, | ||
| region: "" | ||
| }, data); | ||
| } | ||
| if (desiredLSR.region !== supportedLSR.region) { | ||
| matchingDistance += findMatchingDistanceForLSR(desiredLSR, supportedLSR, data); | ||
| } | ||
| return matchingDistance; | ||
| } | ||
| /** | ||
| * Calculates the matching distance between two locales using the CLDR Enhanced Language Matching algorithm. | ||
| * This function is memoized for performance, as distance calculations are expensive. | ||
| * | ||
| * The distance represents how "far apart" two locales are, with 0 being identical (after maximization). | ||
| * Distances are calculated based on Language-Script-Region (LSR) differences using CLDR data. | ||
| * | ||
| * @param desired - The desired locale (e.g., "en-US") | ||
| * @param supported - The supported locale to compare against (e.g., "en-GB") | ||
| * @returns The calculated distance between the locales | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * findMatchingDistance('en-US', 'en-US') // 0 - identical | ||
| * findMatchingDistance('en-US', 'en-GB') // 40 - same language/script, different region | ||
| * findMatchingDistance('es-CO', 'es-419') // 39 - regional variant | ||
| * findMatchingDistance('en', 'fr') // 840 - completely different languages | ||
| * ``` | ||
| * | ||
| * @see https://unicode.org/reports/tr35/#EnhancedLanguageMatching | ||
| */ | ||
| export var findMatchingDistance = memoize(findMatchingDistanceImpl, { | ||
| serializer: function (args) { return "".concat(args[0], "|").concat(args[1]); }, | ||
| }); | ||
| * Calculates the matching distance between two locales using the CLDR Enhanced Language Matching algorithm. | ||
| * This function is memoized for performance, as distance calculations are expensive. | ||
| * | ||
| * The distance represents how "far apart" two locales are, with 0 being identical (after maximization). | ||
| * Distances are calculated based on Language-Script-Region (LSR) differences using CLDR data. | ||
| * | ||
| * @param desired - The desired locale (e.g., "en-US") | ||
| * @param supported - The supported locale to compare against (e.g., "en-GB") | ||
| * @returns The calculated distance between the locales | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * findMatchingDistance('en-US', 'en-US') // 0 - identical | ||
| * findMatchingDistance('en-US', 'en-GB') // 40 - same language/script, different region | ||
| * findMatchingDistance('es-CO', 'es-419') // 39 - regional variant | ||
| * findMatchingDistance('en', 'fr') // 840 - completely different languages | ||
| * ``` | ||
| * | ||
| * @see https://unicode.org/reports/tr35/#EnhancedLanguageMatching | ||
| */ | ||
| export const findMatchingDistance = memoize(findMatchingDistanceImpl, { serializer: (args) => `${args[0]}|${args[1]}` }); | ||
| /** | ||
| * Generates fallback candidates by progressively removing subtags | ||
| * e.g., "en-US" -> ["en-US", "en"] | ||
| * "zh-Hans-CN" -> ["zh-Hans-CN", "zh-Hans", "zh"] | ||
| */ | ||
| * Generates fallback candidates by progressively removing subtags | ||
| * e.g., "en-US" -> ["en-US", "en"] | ||
| * "zh-Hans-CN" -> ["zh-Hans-CN", "zh-Hans", "zh"] | ||
| */ | ||
| function getFallbackCandidates(locale) { | ||
| var candidates = []; | ||
| var current = locale; | ||
| while (current) { | ||
| candidates.push(current); | ||
| var lastDash = current.lastIndexOf('-'); | ||
| if (lastDash === -1) | ||
| break; | ||
| current = current.substring(0, lastDash); | ||
| } | ||
| return candidates; | ||
| const candidates = []; | ||
| let current = locale; | ||
| while (current) { | ||
| candidates.push(current); | ||
| const lastDash = current.lastIndexOf("-"); | ||
| if (lastDash === -1) break; | ||
| current = current.substring(0, lastDash); | ||
| } | ||
| return candidates; | ||
| } | ||
| /** | ||
| * Finds the best locale match using a three-tier optimization hierarchy. | ||
| * | ||
| * ## Three-Tier Matching Algorithm: | ||
| * | ||
| * **Tier 1 - Fast Path** (O(n)): Exact string matching via Set lookup | ||
| * - Example: 'en' matches 'en' exactly → distance 0 | ||
| * - Solves #4936: 48x faster than baseline (12ms vs 610ms with 700+ locales) | ||
| * | ||
| * **Tier 2 - Fallback Path** (O(k×n)): Maximization + progressive subtag removal | ||
| * - Maximizes requested locale, then removes subtags right-to-left | ||
| * - Example: "zh-TW" → "zh-Hant-TW" → ["zh-Hant-TW", "zh-Hant", "zh"] | ||
| * - Distance: 0 for maximized match, 10 per removed subtag + position penalty | ||
| * - 40-50x faster than full UTS #35, handles 99% of real-world cases correctly | ||
| * | ||
| * **Tier 3 - Slow Path** (O(n×m), memoized): Full UTS #35 CLDR matching | ||
| * - Calculates Language-Script-Region distances using CLDR data | ||
| * - Handles complex cases like cross-script matching (sr-Cyrl ↔ sr-Latn) | ||
| * - Only used when Tiers 1 & 2 find no match | ||
| * - Still 6x faster than baseline due to memoization | ||
| * | ||
| * ## Performance Impact of Maximization: | ||
| * | ||
| * While Tier 2 now calls `Intl.Locale().maximize()` once per requested locale, | ||
| * this is still much faster than Tier 3's full distance calculation: | ||
| * - Tier 1: ~12ms (exact match, no maximization) | ||
| * - Tier 2: ~13-15ms (maximization + fallback) | ||
| * - Tier 3: ~100ms+ (full UTS #35 with all supported locales) | ||
| * | ||
| * @param requestedLocales - Locale identifiers in preference order | ||
| * @param supportedLocales - Available locale identifiers | ||
| * @param threshold - Maximum distance (default: 838, from CLDR) | ||
| * @returns Matching result with distances | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * // Tier 1: Exact match | ||
| * findBestMatch(['en'], ['en', 'fr']) | ||
| * // → { matchedSupportedLocale: 'en', distances: { en: { en: 0 } } } | ||
| * | ||
| * // Tier 2: Fallback with maximization | ||
| * findBestMatch(['zh-TW'], ['zh-Hant']) | ||
| * // → zh-TW maximizes to zh-Hant-TW, falls back to zh-Hant (distance 0) | ||
| * | ||
| * findBestMatch(['en-US'], ['en']) | ||
| * // → en-US maximizes to en-Latn-US, falls back to en (distance 10) | ||
| * | ||
| * // Tier 3: Full calculation | ||
| * findBestMatch(['en-XZ'], ['ja', 'ko']) | ||
| * // → No fallback match, uses UTS #35 to find closest match | ||
| * ``` | ||
| * | ||
| * @see https://unicode.org/reports/tr35/#EnhancedLanguageMatching | ||
| * @see https://github.com/formatjs/formatjs/issues/4936 | ||
| */ | ||
| * Finds the best locale match using a three-tier optimization hierarchy. | ||
| * | ||
| * ## Three-Tier Matching Algorithm: | ||
| * | ||
| * **Tier 1 - Fast Path** (O(n)): Exact string matching via Set lookup | ||
| * - Example: 'en' matches 'en' exactly → distance 0 | ||
| * - Solves #4936: 48x faster than baseline (12ms vs 610ms with 700+ locales) | ||
| * | ||
| * **Tier 2 - Fallback Path** (O(k×n)): Maximization + progressive subtag removal | ||
| * - Maximizes requested locale, then removes subtags right-to-left | ||
| * - Example: "zh-TW" → "zh-Hant-TW" → ["zh-Hant-TW", "zh-Hant", "zh"] | ||
| * - Distance: 0 for maximized match, 10 per removed subtag + position penalty | ||
| * - 40-50x faster than full UTS #35, handles 99% of real-world cases correctly | ||
| * | ||
| * **Tier 3 - Slow Path** (O(n×m), memoized): Full UTS #35 CLDR matching | ||
| * - Calculates Language-Script-Region distances using CLDR data | ||
| * - Handles complex cases like cross-script matching (sr-Cyrl ↔ sr-Latn) | ||
| * - Only used when Tiers 1 & 2 find no match | ||
| * - Still 6x faster than baseline due to memoization | ||
| * | ||
| * ## Performance Impact of Maximization: | ||
| * | ||
| * While Tier 2 now calls `Intl.Locale().maximize()` once per requested locale, | ||
| * this is still much faster than Tier 3's full distance calculation: | ||
| * - Tier 1: ~12ms (exact match, no maximization) | ||
| * - Tier 2: ~13-15ms (maximization + fallback) | ||
| * - Tier 3: ~100ms+ (full UTS #35 with all supported locales) | ||
| * | ||
| * @param requestedLocales - Locale identifiers in preference order | ||
| * @param supportedLocales - Available locale identifiers | ||
| * @param threshold - Maximum distance (default: 838, from CLDR) | ||
| * @returns Matching result with distances | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * // Tier 1: Exact match | ||
| * findBestMatch(['en'], ['en', 'fr']) | ||
| * // → { matchedSupportedLocale: 'en', distances: { en: { en: 0 } } } | ||
| * | ||
| * // Tier 2: Fallback with maximization | ||
| * findBestMatch(['zh-TW'], ['zh-Hant']) | ||
| * // → zh-TW maximizes to zh-Hant-TW, falls back to zh-Hant (distance 0) | ||
| * | ||
| * findBestMatch(['en-US'], ['en']) | ||
| * // → en-US maximizes to en-Latn-US, falls back to en (distance 10) | ||
| * | ||
| * // Tier 3: Full calculation | ||
| * findBestMatch(['en-XZ'], ['ja', 'ko']) | ||
| * // → No fallback match, uses UTS #35 to find closest match | ||
| * ``` | ||
| * | ||
| * @see https://unicode.org/reports/tr35/#EnhancedLanguageMatching | ||
| * @see https://github.com/formatjs/formatjs/issues/4936 | ||
| */ | ||
| // WeakMap to cache canonicalized supported locales arrays | ||
| var canonicalizedSupportedCache = new WeakMap(); | ||
| export function findBestMatch(requestedLocales, supportedLocales, threshold) { | ||
| var _a; | ||
| if (threshold === void 0) { threshold = DEFAULT_MATCHING_THRESHOLD; } | ||
| var lowestDistance = Infinity; | ||
| var result = { | ||
| matchedDesiredLocale: '', | ||
| distances: {}, | ||
| }; | ||
| // Get or compute canonicalized supported locales (one by one to preserve indices) | ||
| var canonicalizedSupportedLocales = canonicalizedSupportedCache.get(supportedLocales); | ||
| if (!canonicalizedSupportedLocales) { | ||
| canonicalizedSupportedLocales = supportedLocales.map(function (locale) { | ||
| try { | ||
| var canonical = Intl.getCanonicalLocales([locale]); | ||
| return canonical[0] || locale; | ||
| } | ||
| catch (_a) { | ||
| return locale; | ||
| } | ||
| }); | ||
| canonicalizedSupportedCache.set(supportedLocales, canonicalizedSupportedLocales); | ||
| } | ||
| var supportedSet = new Set(canonicalizedSupportedLocales); | ||
| // === TIER 1: FAST PATH - Exact Match === | ||
| // Check for exact matches in ALL requested locales | ||
| // This is the fastest path and handles the majority of real-world cases | ||
| for (var i = 0; i < requestedLocales.length; i++) { | ||
| var desired = requestedLocales[i]; | ||
| if (supportedSet.has(desired)) { | ||
| var distance = 0 + i * 40; | ||
| result.distances[desired] = (_a = {}, _a[desired] = distance, _a); | ||
| if (distance < lowestDistance) { | ||
| lowestDistance = distance; | ||
| result.matchedDesiredLocale = desired; | ||
| result.matchedSupportedLocale = desired; | ||
| } | ||
| // Only return immediately if this is the first requested locale (distance=0) | ||
| // Otherwise, continue checking for potentially better matches | ||
| if (i === 0) { | ||
| return result; | ||
| } | ||
| } | ||
| } | ||
| // If we found an exact match in Tier 1 (but not for first locale), check Tier 2 | ||
| // to see if there's a better fallback match with lower distance | ||
| // If no exact match found, Tier 2 will find fallback matches | ||
| // === TIER 2: FALLBACK PATH - Maximization + Progressive Subtag Removal === | ||
| // Try maximization-based matching before resorting to expensive Tier 3 | ||
| // This handles cases like zh-TW → zh-Hant efficiently | ||
| for (var i = 0; i < requestedLocales.length; i++) { | ||
| var desired = requestedLocales[i]; | ||
| // Maximize then fallback (for linguistic accuracy like zh-TW → zh-Hant) | ||
| try { | ||
| var maximized = new Intl.Locale(desired).maximize().toString(); | ||
| if (maximized !== desired) { | ||
| var maximizedCandidates = getFallbackCandidates(maximized); | ||
| for (var j = 0; j < maximizedCandidates.length; j++) { | ||
| var candidate = maximizedCandidates[j]; | ||
| if (candidate === desired) | ||
| continue; // Already checked in Tier 1 | ||
| if (supportedSet.has(candidate)) { | ||
| // Check if candidate also maximizes to the same form | ||
| // e.g., zh-TW → zh-Hant-TW and zh-Hant → zh-Hant-TW (distance 0) | ||
| // but es-co → es-Latn-CO and es → es-Latn-ES (distance 10) | ||
| var distance = void 0; | ||
| try { | ||
| var candidateMaximized = new Intl.Locale(candidate) | ||
| .maximize() | ||
| .toString(); | ||
| distance = | ||
| candidateMaximized === maximized ? 0 + i * 40 : j * 10 + i * 40; | ||
| } | ||
| catch (_b) { | ||
| distance = j * 10 + i * 40; | ||
| } | ||
| if (!result.distances[desired]) { | ||
| result.distances[desired] = {}; | ||
| } | ||
| result.distances[desired][candidate] = distance; | ||
| if (distance < lowestDistance) { | ||
| lowestDistance = distance; | ||
| result.matchedDesiredLocale = desired; | ||
| result.matchedSupportedLocale = candidate; | ||
| } | ||
| break; // Stop after finding first maximized match | ||
| } | ||
| } | ||
| } | ||
| } | ||
| catch (_c) { | ||
| // Locale maximization failed, continue to Tier 3 | ||
| } | ||
| } | ||
| // If Tier 2 found a perfect maximized match (distance 0), return immediately (fast path) | ||
| if (result.matchedSupportedLocale && lowestDistance === 0) { | ||
| return result; | ||
| } | ||
| // === TIER 3: SLOW PATH - Full UTS #35 Distance Calculation === | ||
| // Always run Tier 3 for full CLDR accuracy | ||
| // Tier 3 may find better matches than Tier 2's fallback approach | ||
| // findMatchingDistance is memoized, so repeated calculations are cached | ||
| requestedLocales.forEach(function (desired, i) { | ||
| if (!result.distances[desired]) { | ||
| result.distances[desired] = {}; | ||
| } | ||
| canonicalizedSupportedLocales.forEach(function (canonicalLocale, supportedIndex) { | ||
| var originalSupported = supportedLocales[supportedIndex]; | ||
| // findMatchingDistance is memoized via fast-memoize | ||
| // Use the canonical locale for distance calculation | ||
| var distance = findMatchingDistance(desired, canonicalLocale); | ||
| // Add some weight to the distance based on the order of the supported locales | ||
| // Add penalty for the order of the requested locales, which currently is 0 since ECMA-402 | ||
| // doesn't really have room for weighted locales like `en; q=0.1` | ||
| var finalDistance = distance + 0 + i * 40; | ||
| // Store and return the original locale, not the canonical one | ||
| // Tier 3 overwrites Tier 2 distances (Tier 3 is more accurate) | ||
| result.distances[desired][originalSupported] = finalDistance; | ||
| if (finalDistance < lowestDistance) { | ||
| lowestDistance = finalDistance; | ||
| result.matchedDesiredLocale = desired; | ||
| result.matchedSupportedLocale = originalSupported; | ||
| } | ||
| }); | ||
| }); | ||
| if (lowestDistance >= threshold) { | ||
| result.matchedDesiredLocale = undefined; | ||
| result.matchedSupportedLocale = undefined; | ||
| } | ||
| return result; | ||
| const canonicalizedSupportedCache = new WeakMap(); | ||
| export function findBestMatch(requestedLocales, supportedLocales, threshold = DEFAULT_MATCHING_THRESHOLD) { | ||
| let lowestDistance = Infinity; | ||
| let result = { | ||
| matchedDesiredLocale: "", | ||
| distances: {} | ||
| }; | ||
| // Get or compute canonicalized supported locales (one by one to preserve indices) | ||
| let canonicalizedSupportedLocales = canonicalizedSupportedCache.get(supportedLocales); | ||
| if (!canonicalizedSupportedLocales) { | ||
| canonicalizedSupportedLocales = supportedLocales.map((locale) => { | ||
| try { | ||
| const canonical = Intl.getCanonicalLocales([locale]); | ||
| return canonical[0] || locale; | ||
| } catch { | ||
| return locale; | ||
| } | ||
| }); | ||
| canonicalizedSupportedCache.set(supportedLocales, canonicalizedSupportedLocales); | ||
| } | ||
| const supportedSet = new Set(canonicalizedSupportedLocales); | ||
| // === TIER 1: FAST PATH - Exact Match === | ||
| // Check for exact matches in ALL requested locales | ||
| // This is the fastest path and handles the majority of real-world cases | ||
| for (let i = 0; i < requestedLocales.length; i++) { | ||
| const desired = requestedLocales[i]; | ||
| if (supportedSet.has(desired)) { | ||
| const distance = 0 + i * 40; | ||
| result.distances[desired] = { [desired]: distance }; | ||
| if (distance < lowestDistance) { | ||
| lowestDistance = distance; | ||
| result.matchedDesiredLocale = desired; | ||
| result.matchedSupportedLocale = desired; | ||
| } | ||
| // Only return immediately if this is the first requested locale (distance=0) | ||
| // Otherwise, continue checking for potentially better matches | ||
| if (i === 0) { | ||
| return result; | ||
| } | ||
| } | ||
| } | ||
| // If we found an exact match in Tier 1 (but not for first locale), check Tier 2 | ||
| // to see if there's a better fallback match with lower distance | ||
| // If no exact match found, Tier 2 will find fallback matches | ||
| // === TIER 2: FALLBACK PATH - Maximization + Progressive Subtag Removal === | ||
| // Try maximization-based matching before resorting to expensive Tier 3 | ||
| // This handles cases like zh-TW → zh-Hant efficiently | ||
| for (let i = 0; i < requestedLocales.length; i++) { | ||
| const desired = requestedLocales[i]; | ||
| // Maximize then fallback (for linguistic accuracy like zh-TW → zh-Hant) | ||
| try { | ||
| const maximized = new Intl.Locale(desired).maximize().toString(); | ||
| if (maximized !== desired) { | ||
| const maximizedCandidates = getFallbackCandidates(maximized); | ||
| for (let j = 0; j < maximizedCandidates.length; j++) { | ||
| const candidate = maximizedCandidates[j]; | ||
| if (candidate === desired) continue; | ||
| if (supportedSet.has(candidate)) { | ||
| // Check if candidate also maximizes to the same form | ||
| // e.g., zh-TW → zh-Hant-TW and zh-Hant → zh-Hant-TW (distance 0) | ||
| // but es-co → es-Latn-CO and es → es-Latn-ES (distance 10) | ||
| let distance; | ||
| try { | ||
| const candidateMaximized = new Intl.Locale(candidate).maximize().toString(); | ||
| distance = candidateMaximized === maximized ? 0 + i * 40 : j * 10 + i * 40; | ||
| } catch { | ||
| distance = j * 10 + i * 40; | ||
| } | ||
| if (!result.distances[desired]) { | ||
| result.distances[desired] = {}; | ||
| } | ||
| result.distances[desired][candidate] = distance; | ||
| if (distance < lowestDistance) { | ||
| lowestDistance = distance; | ||
| result.matchedDesiredLocale = desired; | ||
| result.matchedSupportedLocale = candidate; | ||
| } | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| } catch {} | ||
| } | ||
| // If Tier 2 found a perfect maximized match (distance 0), return immediately (fast path) | ||
| if (result.matchedSupportedLocale && lowestDistance === 0) { | ||
| return result; | ||
| } | ||
| // === TIER 3: SLOW PATH - Full UTS #35 Distance Calculation === | ||
| // Always run Tier 3 for full CLDR accuracy | ||
| // Tier 3 may find better matches than Tier 2's fallback approach | ||
| // findMatchingDistance is memoized, so repeated calculations are cached | ||
| requestedLocales.forEach((desired, i) => { | ||
| if (!result.distances[desired]) { | ||
| result.distances[desired] = {}; | ||
| } | ||
| canonicalizedSupportedLocales.forEach((canonicalLocale, supportedIndex) => { | ||
| const originalSupported = supportedLocales[supportedIndex]; | ||
| // findMatchingDistance is memoized via fast-memoize | ||
| // Use the canonical locale for distance calculation | ||
| const distance = findMatchingDistance(desired, canonicalLocale); | ||
| // Add some weight to the distance based on the order of the supported locales | ||
| // Add penalty for the order of the requested locales, which currently is 0 since ECMA-402 | ||
| // doesn't really have room for weighted locales like `en; q=0.1` | ||
| const finalDistance = distance + 0 + i * 40; | ||
| // Store and return the original locale, not the canonical one | ||
| // Tier 3 overwrites Tier 2 distances (Tier 3 is more accurate) | ||
| result.distances[desired][originalSupported] = finalDistance; | ||
| if (finalDistance < lowestDistance) { | ||
| lowestDistance = finalDistance; | ||
| result.matchedDesiredLocale = desired; | ||
| result.matchedSupportedLocale = originalSupported; | ||
| } | ||
| }); | ||
| }); | ||
| if (lowestDistance >= threshold) { | ||
| result.matchedDesiredLocale = undefined; | ||
| result.matchedSupportedLocale = undefined; | ||
| } | ||
| return result; | ||
| } |
+3
-3
| export interface Opts { | ||
| algorithm: 'lookup' | 'best fit'; | ||
| algorithm: "lookup" | "best fit"; | ||
| } | ||
| export declare function match(requestedLocales: readonly string[], availableLocales: readonly string[], defaultLocale: string, opts?: Opts): string; | ||
| export { LookupSupportedLocales } from './abstract/LookupSupportedLocales.js'; | ||
| export { ResolveLocale } from './abstract/ResolveLocale.js'; | ||
| export { LookupSupportedLocales } from "./abstract/LookupSupportedLocales.js"; | ||
| export { ResolveLocale } from "./abstract/ResolveLocale.js"; |
+5
-7
@@ -1,9 +0,7 @@ | ||
| import { CanonicalizeLocaleList } from './abstract/CanonicalizeLocaleList.js'; | ||
| import { ResolveLocale } from './abstract/ResolveLocale.js'; | ||
| import { CanonicalizeLocaleList } from "./abstract/CanonicalizeLocaleList.js"; | ||
| import { ResolveLocale } from "./abstract/ResolveLocale.js"; | ||
| export function match(requestedLocales, availableLocales, defaultLocale, opts) { | ||
| return ResolveLocale(availableLocales, CanonicalizeLocaleList(requestedLocales), { | ||
| localeMatcher: (opts === null || opts === void 0 ? void 0 : opts.algorithm) || 'best fit', | ||
| }, [], {}, function () { return defaultLocale; }).locale; | ||
| return ResolveLocale(availableLocales, CanonicalizeLocaleList(requestedLocales), { localeMatcher: opts?.algorithm || "best fit" }, [], {}, () => defaultLocale).locale; | ||
| } | ||
| export { LookupSupportedLocales } from './abstract/LookupSupportedLocales.js'; | ||
| export { ResolveLocale } from './abstract/ResolveLocale.js'; | ||
| export { LookupSupportedLocales } from "./abstract/LookupSupportedLocales.js"; | ||
| export { ResolveLocale } from "./abstract/ResolveLocale.js"; |
+2
-2
| { | ||
| "name": "@formatjs/intl-localematcher", | ||
| "description": "Intl.LocaleMatcher ponyfill", | ||
| "version": "0.7.4", | ||
| "version": "0.7.5", | ||
| "license": "MIT", | ||
@@ -15,3 +15,3 @@ "author": "Long Ho <holevietlong@gmail.com>", | ||
| "tslib": "^2.8.0", | ||
| "@formatjs/fast-memoize": "3.0.2" | ||
| "@formatjs/fast-memoize": "3.0.3" | ||
| }, | ||
@@ -18,0 +18,0 @@ "bugs": "https://github.com/formatjs/formatjs/issues", |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
119046
-43.75%6233
-9.77%+ Added
- Removed
Updated