summaryrefslogtreecommitdiffstats
path: root/js/src/tests/non262/Intl
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/non262/Intl')
-rw-r--r--js/src/tests/non262/Intl/Array/shell.js0
-rw-r--r--js/src/tests/non262/Intl/Array/toLocaleString-date.js53
-rw-r--r--js/src/tests/non262/Intl/Array/toLocaleString-number.js34
-rw-r--r--js/src/tests/non262/Intl/Array/toLocaleString.js35
-rw-r--r--js/src/tests/non262/Intl/Collator/big5han-gb2312han.js22
-rw-r--r--js/src/tests/non262/Intl/Collator/browser.js0
-rw-r--r--js/src/tests/non262/Intl/Collator/call.js74
-rw-r--r--js/src/tests/non262/Intl/Collator/caseFirst.js197
-rw-r--r--js/src/tests/non262/Intl/Collator/collation.js90
-rw-r--r--js/src/tests/non262/Intl/Collator/compare.js137
-rw-r--r--js/src/tests/non262/Intl/Collator/construct-newtarget.js81
-rw-r--r--js/src/tests/non262/Intl/Collator/cross-compartment.js22
-rw-r--r--js/src/tests/non262/Intl/Collator/implicithan.js17
-rw-r--r--js/src/tests/non262/Intl/Collator/shell.js0
-rw-r--r--js/src/tests/non262/Intl/Collator/supportedLocalesOf.js355
-rw-r--r--js/src/tests/non262/Intl/Collator/toStringTag.js29
-rw-r--r--js/src/tests/non262/Intl/Date/browser.js0
-rw-r--r--js/src/tests/non262/Intl/Date/shell.js0
-rw-r--r--js/src/tests/non262/Intl/Date/toLocaleDateString_timeZone.js77
-rw-r--r--js/src/tests/non262/Intl/Date/toLocaleString_timeZone.js77
-rw-r--r--js/src/tests/non262/Intl/Date/toLocaleTimeString_timeZone.js77
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/browser.js3
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/calendar-aliases.js35
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/calendar-option.js67
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/call.js184
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/construct-newtarget.js81
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/cross-compartment.js70
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/dateTimeStyle.js57
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/day-period-hour-cycle.js102
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/day-period-standalone.js160
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/day-period.js40
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/era.js245
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/extended-time-zone-names.js124
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/field-widths.js225
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/format.js47
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/formatRange-gregorian-proleptic.js28
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/formatRange-hour-cycle.js450
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/formatRange-matches-format-output.js58
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/formatRange-original-skeleton.js18
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/formatToParts.js96
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/format_timeZone-non-meta.js62
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/format_timeZone.js104
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/fractional-second-digits-append-item.js58
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/fractional-second-digits.js43
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/hourCycle.js142
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/implied-script-has-consistent-output.js59
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/islamic.js89
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/japanese-gannen-year.js54
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/mozExtensions.js18
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/numberingSystem-option.js60
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/options-property-accesses.js77
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/related-year.js185
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/shell.js34
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/standalone-month.js11
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/supportedLocalesOf.js371
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/timeZone.js139
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/timeZone_backward_links.js156
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone.js153
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone_links.js48
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/timeZone_notbackward_links.js31
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/timeZone_version.js17
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/toStringTag.js29
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/tz-environment-variable.js67
-rw-r--r--js/src/tests/non262/Intl/DateTimeFormat/unwrapping.js248
-rw-r--r--js/src/tests/non262/Intl/DisplayNames/abbreviated.js28
-rw-r--r--js/src/tests/non262/Intl/DisplayNames/alias-and-parent-locales.js33
-rw-r--r--js/src/tests/non262/Intl/DisplayNames/browser.js0
-rw-r--r--js/src/tests/non262/Intl/DisplayNames/calendar.js123
-rw-r--r--js/src/tests/non262/Intl/DisplayNames/currency.js150
-rw-r--r--js/src/tests/non262/Intl/DisplayNames/dateTimeField.js176
-rw-r--r--js/src/tests/non262/Intl/DisplayNames/dayPeriod.js80
-rw-r--r--js/src/tests/non262/Intl/DisplayNames/language-dialect.js104
-rw-r--r--js/src/tests/non262/Intl/DisplayNames/language.js205
-rw-r--r--js/src/tests/non262/Intl/DisplayNames/month-calendar.js18
-rw-r--r--js/src/tests/non262/Intl/DisplayNames/month.js104
-rw-r--r--js/src/tests/non262/Intl/DisplayNames/quarter.js74
-rw-r--r--js/src/tests/non262/Intl/DisplayNames/region.js157
-rw-r--r--js/src/tests/non262/Intl/DisplayNames/script.js134
-rw-r--r--js/src/tests/non262/Intl/DisplayNames/shell.js6
-rw-r--r--js/src/tests/non262/Intl/DisplayNames/weekday.js77
-rw-r--r--js/src/tests/non262/Intl/ListFormat/browser.js0
-rw-r--r--js/src/tests/non262/Intl/ListFormat/conjunction-type.js116
-rw-r--r--js/src/tests/non262/Intl/ListFormat/cross-compartment.js42
-rw-r--r--js/src/tests/non262/Intl/ListFormat/disjunction-type.js108
-rw-r--r--js/src/tests/non262/Intl/ListFormat/same-compartment.js40
-rw-r--r--js/src/tests/non262/Intl/ListFormat/shell.js21
-rw-r--r--js/src/tests/non262/Intl/ListFormat/supported-locales.js18
-rw-r--r--js/src/tests/non262/Intl/ListFormat/unit-type.js149
-rw-r--r--js/src/tests/non262/Intl/Locale/apply-options-to-tag-canonicalize-twice.js11
-rw-r--r--js/src/tests/non262/Intl/Locale/browser.js0
-rw-r--r--js/src/tests/non262/Intl/Locale/coerce-options-before-validating-tag.js10
-rw-r--r--js/src/tests/non262/Intl/Locale/cross-compartment.js28
-rw-r--r--js/src/tests/non262/Intl/Locale/legacy.js75
-rw-r--r--js/src/tests/non262/Intl/Locale/likely-subtags-generated.js15797
-rw-r--r--js/src/tests/non262/Intl/Locale/likely-subtags.js61
-rw-r--r--js/src/tests/non262/Intl/Locale/same-compartment.js26
-rw-r--r--js/src/tests/non262/Intl/Locale/shell.js0
-rw-r--r--js/src/tests/non262/Intl/Locale/surface.js98
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/StringBuffer.js37
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/bigint-int64.js40
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/browser.js0
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/call.js184
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/construct-newtarget.js81
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/cross-compartment.js70
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/currency-narrow-symbol.js40
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/currency-sign-accounting.js192
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/duplicate-singleton-variant.js49
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/format-as-code-or-name.js75
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/format-string.js150
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/format.js55
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/formatRange-BigInt.js150
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/formatRange.js296
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-compact.js34
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-currency.js34
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-percent.js34
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-signDisplay.js34
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-unit.js41
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign.js34
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/formatRangeToParts.js174
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/formatToParts.js357
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/formatting-NaN.js35
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/negativeZeroFractionDigits.js21
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/notation-compact-long.js139
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/notation-compact-short.js136
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/notation-compact-with-fraction-digits.js17
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/notation-engineering.js136
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/notation-scientific.js136
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/numberingSystem-format.js18
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/numberingSystem-option.js60
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/options-emulate-undefined.js13
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/remove-unicode-extensions.js25
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/rounding-increment.js102
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/rounding-mode.js287
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/rounding-priority.js132
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/shell.js77
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/sign-display.js187
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/significantDigitsOfZero.js38
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/supportedLocalesOf.js371
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/toStringTag.js29
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/trailing-zero-display.js98
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/unit-compound-combinations.js65
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/unit-formatToParts-has-unit-field.js90
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/unit-well-formed.js267
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/unit.js104
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/unwrapping.js248
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/use-grouping-bool-string.js10
-rw-r--r--js/src/tests/non262/Intl/NumberFormat/use-grouping.js97
-rw-r--r--js/src/tests/non262/Intl/PluralRules/browser.js0
-rw-r--r--js/src/tests/non262/Intl/PluralRules/call.js53
-rw-r--r--js/src/tests/non262/Intl/PluralRules/construct-newtarget.js76
-rw-r--r--js/src/tests/non262/Intl/PluralRules/cross-compartment.js22
-rw-r--r--js/src/tests/non262/Intl/PluralRules/negativeZeroFractionDigits.js21
-rw-r--r--js/src/tests/non262/Intl/PluralRules/pluralrules.js18
-rw-r--r--js/src/tests/non262/Intl/PluralRules/resolvedOptions-overridden-species.js25
-rw-r--r--js/src/tests/non262/Intl/PluralRules/rounding.js17
-rw-r--r--js/src/tests/non262/Intl/PluralRules/select.js63
-rw-r--r--js/src/tests/non262/Intl/PluralRules/selectRange.js84
-rw-r--r--js/src/tests/non262/Intl/PluralRules/shell.js0
-rw-r--r--js/src/tests/non262/Intl/PluralRules/supportedLocalesOf.js369
-rw-r--r--js/src/tests/non262/Intl/README.txt27
-rw-r--r--js/src/tests/non262/Intl/RelativeTimeFormat/browser.js0
-rw-r--r--js/src/tests/non262/Intl/RelativeTimeFormat/construct-newtarget.js21
-rw-r--r--js/src/tests/non262/Intl/RelativeTimeFormat/cross-compartment.js22
-rw-r--r--js/src/tests/non262/Intl/RelativeTimeFormat/format.js145
-rw-r--r--js/src/tests/non262/Intl/RelativeTimeFormat/locale-fallback-handling.js15
-rw-r--r--js/src/tests/non262/Intl/RelativeTimeFormat/numbering-system.js22
-rw-r--r--js/src/tests/non262/Intl/RelativeTimeFormat/numberingSystem-option.js60
-rw-r--r--js/src/tests/non262/Intl/RelativeTimeFormat/relativetimeformat.js15
-rw-r--r--js/src/tests/non262/Intl/RelativeTimeFormat/shell.js0
-rw-r--r--js/src/tests/non262/Intl/RelativeTimeFormat/supportedLocalesOf.js373
-rw-r--r--js/src/tests/non262/Intl/String/shell.js0
-rw-r--r--js/src/tests/non262/Intl/String/toLocaleLowerCase.js64
-rw-r--r--js/src/tests/non262/Intl/String/toLocaleUpperCase.js64
-rw-r--r--js/src/tests/non262/Intl/TypedArray/shell.js0
-rw-r--r--js/src/tests/non262/Intl/TypedArray/toLocaleString.js103
-rw-r--r--js/src/tests/non262/Intl/available-locales-implied-script.js35
-rw-r--r--js/src/tests/non262/Intl/available-locales-resolved.js41
-rw-r--r--js/src/tests/non262/Intl/available-locales-supported.js26
-rw-r--r--js/src/tests/non262/Intl/best-available-locale-from-default-locale.js107
-rw-r--r--js/src/tests/non262/Intl/browser.js0
-rw-r--r--js/src/tests/non262/Intl/default-locale-shell.js16
-rw-r--r--js/src/tests/non262/Intl/duplicate-variants.js46
-rw-r--r--js/src/tests/non262/Intl/extensions/browser.js0
-rw-r--r--js/src/tests/non262/Intl/extensions/options-value-emulates-undefined.js29
-rw-r--r--js/src/tests/non262/Intl/extensions/shell.js0
-rw-r--r--js/src/tests/non262/Intl/extensions/unicode-extension-sequences.js74
-rw-r--r--js/src/tests/non262/Intl/fallback-symbol.js22
-rw-r--r--js/src/tests/non262/Intl/four-letter-language-codes.js22
-rw-r--r--js/src/tests/non262/Intl/getCalendarInfo.js76
-rw-r--r--js/src/tests/non262/Intl/getCanonicalLocales-overridden-arg-length.js20
-rw-r--r--js/src/tests/non262/Intl/getCanonicalLocales-overridden-push.js16
-rw-r--r--js/src/tests/non262/Intl/getCanonicalLocales-overridden-set.js16
-rw-r--r--js/src/tests/non262/Intl/getCanonicalLocales-overridden-species.js23
-rw-r--r--js/src/tests/non262/Intl/getCanonicalLocales-weird-cases.js25
-rw-r--r--js/src/tests/non262/Intl/getCanonicalLocales-with-duplicates.js15
-rw-r--r--js/src/tests/non262/Intl/getCanonicalLocales.js37
-rw-r--r--js/src/tests/non262/Intl/legacy-and-sign-locales-with-unicode-extensions.js79
-rw-r--r--js/src/tests/non262/Intl/resolved-locale-sorted-unicode-extension-keys.js109
-rw-r--r--js/src/tests/non262/Intl/shell.js340
-rw-r--r--js/src/tests/non262/Intl/supportedValuesOf-calendar.js25
-rw-r--r--js/src/tests/non262/Intl/supportedValuesOf-collation.js44
-rw-r--r--js/src/tests/non262/Intl/supportedValuesOf-currency.js24
-rw-r--r--js/src/tests/non262/Intl/supportedValuesOf-numberingSystem.js37
-rw-r--r--js/src/tests/non262/Intl/supportedValuesOf-timeZones-canonical.js487
-rw-r--r--js/src/tests/non262/Intl/supportedValuesOf-timeZones.js20
-rw-r--r--js/src/tests/non262/Intl/supportedValuesOf-unit.js20
-rw-r--r--js/src/tests/non262/Intl/tolower-ascii-equivalent.js47
-rw-r--r--js/src/tests/non262/Intl/unicode-bcp47-locale-ids-extlangs.js21
-rw-r--r--js/src/tests/non262/Intl/unicode-bcp47-locale-ids-language-mappings.js39
-rw-r--r--js/src/tests/non262/Intl/unicode-bcp47-locale-ids-languages-mappings-complex.js21
-rw-r--r--js/src/tests/non262/Intl/unicode-bcp47-locale-ids-legacy.js52
-rw-r--r--js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-and-subdivision.js12
-rw-r--r--js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-mappings-complex.js57
-rw-r--r--js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-mappings.js22
-rw-r--r--js/src/tests/non262/Intl/unicode-bcp47-locale-ids-sign-languages.js23
-rw-r--r--js/src/tests/non262/Intl/unicode-bcp47-locale-ids-transformed-ext.js71
-rw-r--r--js/src/tests/non262/Intl/unicode-bcp47-locale-ids-unicode-ext.js12
-rw-r--r--js/src/tests/non262/Intl/unicode-bcp47-locale-ids-variants-legacy-mappings.js47
-rw-r--r--js/src/tests/non262/Intl/unicode-bcp47-locale-ids-variants-sorted.js31
-rw-r--r--js/src/tests/non262/Intl/variant-with-preferred-value.js58
220 files changed, 32913 insertions, 0 deletions
diff --git a/js/src/tests/non262/Intl/Array/shell.js b/js/src/tests/non262/Intl/Array/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Intl/Array/shell.js
diff --git a/js/src/tests/non262/Intl/Array/toLocaleString-date.js b/js/src/tests/non262/Intl/Array/toLocaleString-date.js
new file mode 100644
index 0000000000..7711c60643
--- /dev/null
+++ b/js/src/tests/non262/Intl/Array/toLocaleString-date.js
@@ -0,0 +1,53 @@
+if (typeof Intl === "object") {
+ const localeSep = [,,].toLocaleString();
+
+ const date = new Date(Date.UTC(2012, 11, 12, 3, 0, 0));
+
+ assertEq([date].toLocaleString("en-us", {timeZone: "UTC"}), "12/12/2012, 3:00:00 AM");
+ assertEq([date].toLocaleString(["de", "en"], {timeZone: "UTC"}), "12.12.2012, 03:00:00");
+ assertEq([date].toLocaleString("th-th", {timeZone: "UTC"}), "12/12/2555 03:00:00");
+ assertEq([date].toLocaleString("th-th-u-nu-thai", {timeZone: "UTC"}), "๑๒/๑๒/๒๕๕๕ ๐๓:๐๐:๐๐");
+
+ const sampleValues = [
+ date, new Date(0),
+ ];
+ const sampleLocales = [
+ void 0,
+ "en",
+ "th-th-u-nu-thai",
+ "ja-jp",
+ "ar-ma-u-ca-islamicc",
+ ["tlh", "de"],
+ ];
+ const numericFormatOptions = {
+ timeZone: "UTC",
+ year: "numeric", month: "numeric", day: "numeric",
+ hour: "numeric", minute: "numeric", second: "numeric",
+ };
+ const longFormatOptions = {
+ timeZone: "UTC",
+ year: "numeric", month: "long", day: "numeric",
+ hour: "numeric", minute: "numeric", second: "numeric"
+ };
+ const sampleOptions = [
+ {timeZone: "UTC"},
+ longFormatOptions,
+ ];
+
+ for (let locale of sampleLocales) {
+ for (let options of sampleOptions) {
+ let dtfOptions;
+ if (options === longFormatOptions) {
+ dtfOptions = longFormatOptions;
+ } else {
+ dtfOptions = numericFormatOptions;
+ }
+ let dtf = new Intl.DateTimeFormat(locale, dtfOptions);
+ let expected = sampleValues.map(dtf.format).join(localeSep);
+ assertEq(sampleValues.toLocaleString(locale, options), expected);
+ }
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/Array/toLocaleString-number.js b/js/src/tests/non262/Intl/Array/toLocaleString-number.js
new file mode 100644
index 0000000000..6ca8a17837
--- /dev/null
+++ b/js/src/tests/non262/Intl/Array/toLocaleString-number.js
@@ -0,0 +1,34 @@
+if (typeof Intl === "object") {
+ const localeSep = [,,].toLocaleString();
+
+ assertEq([NaN].toLocaleString("ar"), "ليس رقم");
+ assertEq([NaN].toLocaleString(["zh-hant", "ar"]), "非數值");
+ assertEq([Infinity].toLocaleString("dz"), "གྲངས་མེད");
+ assertEq([-Infinity].toLocaleString(["fr", "en"]), "-∞");
+
+ const sampleValues = [
+ -0, +0, -1, +1, -2, +2, -0.5, +0.5,
+ ];
+ const sampleLocales = [
+ void 0,
+ "en",
+ "th-th-u-nu-thai",
+ ["tlh", "de"],
+ ];
+ const sampleOptions = [
+ void 0,
+ {},
+ {style: "percent"},
+ {style: "currency", currency: "USD", minimumIntegerDigits: 4},
+ ];
+ for (let locale of sampleLocales) {
+ for (let options of sampleOptions) {
+ let nf = new Intl.NumberFormat(locale, options);
+ let expected = sampleValues.map(nf.format).join(localeSep);
+ assertEq(sampleValues.toLocaleString(locale, options), expected);
+ }
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/Array/toLocaleString.js b/js/src/tests/non262/Intl/Array/toLocaleString.js
new file mode 100644
index 0000000000..f94e531f89
--- /dev/null
+++ b/js/src/tests/non262/Intl/Array/toLocaleString.js
@@ -0,0 +1,35 @@
+if (typeof Intl === "object") {
+ const localeSep = [,,].toLocaleString();
+
+ // Missing arguments are passed as |undefined|.
+ const objNoArgs = {
+ toLocaleString() {
+ assertEq(arguments.length, 2);
+ assertEq(arguments[0], undefined);
+ assertEq(arguments[1], undefined);
+ return "pass";
+ }
+ };
+ // - Single element case.
+ assertEq([objNoArgs].toLocaleString(), "pass");
+ // - More than one element.
+ assertEq([objNoArgs, objNoArgs].toLocaleString(), "pass" + localeSep + "pass");
+
+ // Ensure "locales" and "options" arguments are passed to the array elements.
+ const locales = {}, options = {};
+ const objWithArgs = {
+ toLocaleString() {
+ assertEq(arguments.length, 2);
+ assertEq(arguments[0], locales);
+ assertEq(arguments[1], options);
+ return "pass";
+ }
+ };
+ // - Single element case.
+ assertEq([objWithArgs].toLocaleString(locales, options), "pass");
+ // - More than one element.
+ assertEq([objWithArgs, objWithArgs].toLocaleString(locales, options), "pass" + localeSep + "pass");
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/Collator/big5han-gb2312han.js b/js/src/tests/non262/Intl/Collator/big5han-gb2312han.js
new file mode 100644
index 0000000000..cf6870ff7d
--- /dev/null
+++ b/js/src/tests/non262/Intl/Collator/big5han-gb2312han.js
@@ -0,0 +1,22 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let scrambled = ['𠙶', '𠇲', '㓙', '㑧', '假', '凷'];
+
+// Root or pinyin
+const fallback = ["假", "凷", "㑧", "㓙", "𠇲", "𠙶"];
+
+scrambled.sort(new Intl.Collator("zh-u-co-big5han").compare);
+assertEqArray(scrambled, fallback);
+
+scrambled.sort(new Intl.Collator("zh-u-co-gb2312").compare);
+assertEqArray(scrambled, fallback);
+
+assertEq(new Intl.Collator("zh-u-co-big5han").resolvedOptions().collation, "default");
+assertEq(new Intl.Collator("zh-u-co-gb2312").resolvedOptions().collation, "default");
+
+assertEq(Intl.supportedValuesOf("collation").includes("big5han"), false);
+assertEq(Intl.supportedValuesOf("collation").includes("gb2312"), false);
+
+reportCompare(0, 0, 'ok');
diff --git a/js/src/tests/non262/Intl/Collator/browser.js b/js/src/tests/non262/Intl/Collator/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Intl/Collator/browser.js
diff --git a/js/src/tests/non262/Intl/Collator/call.js b/js/src/tests/non262/Intl/Collator/call.js
new file mode 100644
index 0000000000..089764a2cb
--- /dev/null
+++ b/js/src/tests/non262/Intl/Collator/call.js
@@ -0,0 +1,74 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+function IsIntlService(c) {
+ return typeof c === "function" &&
+ c.hasOwnProperty("prototype") &&
+ c.prototype.hasOwnProperty("resolvedOptions");
+}
+
+function IsObject(o) {
+ return Object(o) === o;
+}
+
+function thisValues() {
+ const intlConstructors = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService);
+
+ return [
+ // Primitive values.
+ ...[undefined, null, true, "abc", Symbol(), 123],
+
+ // Object values.
+ ...[{}, [], /(?:)/, function(){}, new Proxy({}, {})],
+
+ // Intl objects.
+ ...[].concat(...intlConstructors.map(ctor => {
+ let args = [];
+ if (ctor === Intl.DisplayNames) {
+ // Intl.DisplayNames can't be constructed without any arguments.
+ args = [undefined, {type: "language"}];
+ }
+
+ return [
+ // Instance of an Intl constructor.
+ new ctor(...args),
+
+ // Instance of a subclassed Intl constructor.
+ new class extends ctor {}(...args),
+
+ // Object inheriting from an Intl constructor prototype.
+ Object.create(ctor.prototype),
+
+ // Intl object not inheriting from its default prototype.
+ Object.setPrototypeOf(new ctor(...args), Object.prototype),
+ ];
+ })),
+ ];
+}
+
+// Invoking [[Call]] for Intl.Collator always returns a new Collator instance.
+for (let thisValue of thisValues()) {
+ let obj = Intl.Collator.call(thisValue);
+ assertEq(Object.is(obj, thisValue), false);
+ assertEq(obj instanceof Intl.Collator, true);
+
+ // Ensure Intl.[[FallbackSymbol]] wasn't installed on |thisValue|.
+ if (IsObject(thisValue))
+ assertEqArray(Object.getOwnPropertySymbols(thisValue), []);
+}
+
+// Intl.Collator doesn't use the legacy Intl constructor compromise semantics.
+for (let thisValue of thisValues()) {
+ // Ensure instanceof operator isn't invoked for Intl.Collator.
+ Object.defineProperty(Intl.Collator, Symbol.hasInstance, {
+ get() {
+ assertEq(false, true, "@@hasInstance operator called");
+ }, configurable: true
+ });
+ let obj = Intl.Collator.call(thisValue);
+ delete Intl.Collator[Symbol.hasInstance];
+ assertEq(Object.is(obj, thisValue), false);
+ assertEq(obj instanceof Intl.Collator, true);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/Collator/caseFirst.js b/js/src/tests/non262/Intl/Collator/caseFirst.js
new file mode 100644
index 0000000000..d183c8fdd5
--- /dev/null
+++ b/js/src/tests/non262/Intl/Collator/caseFirst.js
@@ -0,0 +1,197 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Locales which use caseFirst=off for the standard (sort) collation type.
+const defaultLocales = Intl.Collator.supportedLocalesOf(["en", "de", "es", "sv", "ar", "zh", "ja"]);
+
+// Locales which use caseFirst=upper for the standard (sort) collation type.
+const upperFirstLocales = Intl.Collator.supportedLocalesOf(["cu", "da", "mt"]);
+
+// Default collation for zh (pinyin) reorders "á" before "a" at secondary strength level.
+const accentReordered = ["zh"];
+
+const allLocales = [...defaultLocales, ...upperFirstLocales];
+
+
+// Check default "caseFirst" option is resolved correctly.
+for (let locale of defaultLocales) {
+ let col = new Intl.Collator(locale, {usage: "sort"});
+ assertEq(col.resolvedOptions().caseFirst, "false");
+}
+for (let locale of upperFirstLocales) {
+ let col = new Intl.Collator(locale, {usage: "sort"});
+ assertEq(col.resolvedOptions().caseFirst, "upper");
+}
+for (let locale of allLocales) {
+ let col = new Intl.Collator(locale, {usage: "search"});
+ assertEq(col.resolvedOptions().caseFirst, "false");
+}
+
+
+const collOptions = {usage: "sort"};
+const primary = {sensitivity: "base"};
+const secondary = {sensitivity: "accent"};
+const tertiary = {sensitivity: "variant"};
+const caseLevel = {sensitivity: "case"};
+const strengths = [primary, secondary, tertiary, caseLevel];
+
+// "A" is sorted after "a" when caseFirst=off is the default and strength is tertiary.
+for (let locale of defaultLocales) {
+ let col = new Intl.Collator(locale, Object.assign({}, collOptions, tertiary));
+
+ assertEq(col.compare("A", "a"), 1);
+ assertEq(col.compare("a", "A"), -1);
+}
+for (let locale of defaultLocales.filter(loc => !accentReordered.includes(loc))) {
+ let col = new Intl.Collator(locale, Object.assign({}, collOptions, tertiary));
+
+ assertEq(col.compare("A", "á"), -1);
+ assertEq(col.compare("á", "A"), 1);
+}
+
+// Also sorted after "a" with the sensitivity=case collator.
+for (let locale of defaultLocales) {
+ let col = new Intl.Collator(locale, Object.assign({}, collOptions, caseLevel));
+
+ assertEq(col.compare("A", "a"), 1);
+ assertEq(col.compare("a", "A"), -1);
+
+ assertEq(col.compare("A", "á"), 1);
+ assertEq(col.compare("á", "A"), -1);
+}
+
+
+// "A" is sorted before "a" when caseFirst=upper is the default and strength is tertiary.
+for (let locale of upperFirstLocales) {
+ let col = new Intl.Collator(locale, Object.assign({}, collOptions, tertiary));
+
+ assertEq(col.compare("A", "a"), -1);
+ assertEq(col.compare("a", "A"), 1);
+
+ assertEq(col.compare("A", "á"), -1);
+ assertEq(col.compare("á", "A"), 1);
+}
+
+// Also sorted before "a" with the sensitivity=case collator.
+for (let locale of upperFirstLocales) {
+ let col = new Intl.Collator(locale, Object.assign({}, collOptions, caseLevel));
+
+ assertEq(col.compare("A", "a"), -1);
+ assertEq(col.compare("a", "A"), 1);
+
+ assertEq(col.compare("A", "á"), -1);
+ assertEq(col.compare("á", "A"), 1);
+}
+
+
+// caseFirst=upper doesn't change the sort order when strength is below tertiary.
+for (let locale of allLocales) {
+ let col = new Intl.Collator(locale, Object.assign({}, collOptions, secondary));
+
+ assertEq(col.compare("A", "a"), 0);
+ assertEq(col.compare("a", "A"), 0);
+}
+for (let locale of allLocales.filter(loc => !accentReordered.includes(loc))) {
+ let col = new Intl.Collator(locale, Object.assign({}, collOptions, secondary));
+
+ assertEq(col.compare("A", "á"), -1);
+ assertEq(col.compare("á", "A"), 1);
+}
+
+for (let locale of allLocales) {
+ let col = new Intl.Collator(locale, Object.assign({}, collOptions, primary));
+
+ assertEq(col.compare("A", "a"), 0);
+ assertEq(col.compare("a", "A"), 0);
+
+ assertEq(col.compare("A", "á"), 0);
+ assertEq(col.compare("á", "A"), 0);
+}
+
+
+// caseFirst=upper doesn't change the sort order when there's a primary difference.
+for (let locale of allLocales) {
+ for (let strength of strengths) {
+ let col = new Intl.Collator(locale, Object.assign({}, collOptions, strength));
+
+ assertEq(col.compare("A", "b"), -1);
+ assertEq(col.compare("a", "B"), -1);
+ }
+}
+
+
+// caseFirst set through Unicode extension tag.
+for (let locale of allLocales) {
+ let colKfFalse = new Intl.Collator(locale + "-u-kf-false", {});
+ let colKfLower = new Intl.Collator(locale + "-u-kf-lower", {});
+ let colKfUpper = new Intl.Collator(locale + "-u-kf-upper", {});
+
+ assertEq(colKfFalse.resolvedOptions().caseFirst, "false");
+ assertEq(colKfFalse.compare("A", "a"), 1);
+ assertEq(colKfFalse.compare("a", "A"), -1);
+
+ assertEq(colKfLower.resolvedOptions().caseFirst, "lower");
+ assertEq(colKfLower.compare("A", "a"), 1);
+ assertEq(colKfLower.compare("a", "A"), -1);
+
+ assertEq(colKfUpper.resolvedOptions().caseFirst, "upper");
+ assertEq(colKfUpper.compare("A", "a"), -1);
+ assertEq(colKfUpper.compare("a", "A"), 1);
+}
+
+
+// caseFirst set through options value.
+for (let locale of allLocales) {
+ let colKfFalse = new Intl.Collator(locale, {caseFirst: "false"});
+ let colKfLower = new Intl.Collator(locale, {caseFirst: "lower"});
+ let colKfUpper = new Intl.Collator(locale, {caseFirst: "upper"});
+
+ assertEq(colKfFalse.resolvedOptions().caseFirst, "false");
+ assertEq(colKfFalse.compare("A", "a"), 1);
+ assertEq(colKfFalse.compare("a", "A"), -1);
+
+ assertEq(colKfLower.resolvedOptions().caseFirst, "lower");
+ assertEq(colKfLower.compare("A", "a"), 1);
+ assertEq(colKfLower.compare("a", "A"), -1);
+
+ assertEq(colKfUpper.resolvedOptions().caseFirst, "upper");
+ assertEq(colKfUpper.compare("A", "a"), -1);
+ assertEq(colKfUpper.compare("a", "A"), 1);
+}
+
+
+// Test Unicode extension tag and options value, the latter should win.
+for (let locale of allLocales) {
+ let colKfFalse = new Intl.Collator(locale + "-u-kf-upper", {caseFirst: "false"});
+ let colKfLower = new Intl.Collator(locale + "-u-kf-upper", {caseFirst: "lower"});
+ let colKfUpper = new Intl.Collator(locale + "-u-kf-lower", {caseFirst: "upper"});
+
+ assertEq(colKfFalse.resolvedOptions().caseFirst, "false");
+ assertEq(colKfFalse.compare("A", "a"), 1);
+ assertEq(colKfFalse.compare("a", "A"), -1);
+
+ assertEq(colKfLower.resolvedOptions().caseFirst, "lower");
+ assertEq(colKfLower.compare("A", "a"), 1);
+ assertEq(colKfLower.compare("a", "A"), -1);
+
+ assertEq(colKfUpper.resolvedOptions().caseFirst, "upper");
+ assertEq(colKfUpper.compare("A", "a"), -1);
+ assertEq(colKfUpper.compare("a", "A"), 1);
+}
+
+// Ensure languages are properly detected when additional subtags are present.
+if (Intl.Collator.supportedLocalesOf("da").length !== 0) {
+ assertEq(new Intl.Collator("da-DK", {usage: "sort"}).resolvedOptions().caseFirst, "upper");
+ assertEq(new Intl.Collator("da-Latn-DK", {usage: "sort"}).resolvedOptions().caseFirst, "upper");
+}
+if (Intl.Collator.supportedLocalesOf("mt").length !== 0) {
+ assertEq(new Intl.Collator("mt-MT", {usage: "sort"}).resolvedOptions().caseFirst, "upper");
+ assertEq(new Intl.Collator("mt-Latn-MT", {usage: "sort"}).resolvedOptions().caseFirst, "upper");
+}
+
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/Collator/collation.js b/js/src/tests/non262/Intl/Collator/collation.js
new file mode 100644
index 0000000000..f73728b876
--- /dev/null
+++ b/js/src/tests/non262/Intl/Collator/collation.js
@@ -0,0 +1,90 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Collation can be set as Unicode locale extension or as a property.
+{
+ let c1 = new Intl.Collator("de", {usage: "sort"});
+ let c2 = new Intl.Collator("de", {usage: "sort", collation: "phonebk"});
+ let c3 = new Intl.Collator("de-u-co-phonebk", {usage: "sort"});
+
+ assertEq(c1.resolvedOptions().locale, "de");
+ assertEq(c2.resolvedOptions().locale, "de");
+ assertEq(c3.resolvedOptions().locale, "de-u-co-phonebk");
+
+ assertEq(c1.resolvedOptions().collation, "default");
+ assertEq(c2.resolvedOptions().collation, "phonebk");
+ assertEq(c3.resolvedOptions().collation, "phonebk");
+
+ assertEq(c1.compare("ä", "ae"), -1);
+ assertEq(c2.compare("ä", "ae"), 1);
+ assertEq(c3.compare("ä", "ae"), 1);
+}
+
+// Collation property overrides any Unicode locale extension.
+{
+ let c1 = new Intl.Collator("de-u-co-eor", {usage: "sort"});
+ let c2 = new Intl.Collator("de-u-co-eor", {usage: "sort", collation: "phonebk"});
+
+ // Ensure "eor" collation is supported.
+ assertEq(c1.resolvedOptions().locale, "de-u-co-eor");
+ assertEq(c1.resolvedOptions().collation, "eor");
+
+ // "phonebk" property overrides the Unicode locale extension.
+ assertEq(c2.resolvedOptions().locale, "de");
+ assertEq(c2.resolvedOptions().collation, "phonebk");
+
+ assertEq(c1.compare("ä", "ae"), -1);
+ assertEq(c2.compare("ä", "ae"), 1);
+}
+
+// The default sort collation can't be requested.
+{
+ // The default sort collation for Swedish (sv) was "reformed" before CLDR 42.
+ // It wasn't possible to override this and select the default root sort
+ // collation. Use English (en) as a locale which uses the root sort collation
+ // for comparison.
+ let c1 = new Intl.Collator("sv", {usage: "sort"});
+ let c2 = new Intl.Collator("sv-u-co-reformed", {usage: "sort"});
+ let c3 = new Intl.Collator("sv-u-co-standard", {usage: "sort"});
+ let c4 = new Intl.Collator("sv-u-co-default", {usage: "sort"});
+ let c5 = new Intl.Collator("en", {usage: "sort"});
+
+ assertEq(c1.resolvedOptions().locale, "sv");
+ assertEq(c2.resolvedOptions().locale, "sv");
+ assertEq(c3.resolvedOptions().locale, "sv");
+ assertEq(c4.resolvedOptions().locale, "sv");
+ assertEq(c5.resolvedOptions().locale, "en");
+
+ assertEq(c1.resolvedOptions().collation, "default");
+ assertEq(c2.resolvedOptions().collation, "default");
+ assertEq(c3.resolvedOptions().collation, "default");
+ assertEq(c4.resolvedOptions().collation, "default");
+ assertEq(c5.resolvedOptions().collation, "default");
+
+ assertEq(c1.compare("y", "ü"), -1);
+ assertEq(c2.compare("y", "ü"), -1);
+ assertEq(c3.compare("y", "ü"), -1);
+ assertEq(c4.compare("y", "ü"), -1);
+ assertEq(c5.compare("y", "ü"), 1);
+}
+
+// Search collations ignore any collation overrides.
+{
+ let c1 = new Intl.Collator("de", {usage: "search"});
+ let c2 = new Intl.Collator("de", {usage: "search", collation: "phonebk"});
+ let c3 = new Intl.Collator("de-u-co-phonebk", {usage: "search"});
+
+ assertEq(c1.resolvedOptions().locale, "de");
+ assertEq(c2.resolvedOptions().locale, "de");
+ assertEq(c3.resolvedOptions().locale, "de");
+
+ assertEq(c1.resolvedOptions().collation, "default");
+ assertEq(c2.resolvedOptions().collation, "default");
+ assertEq(c3.resolvedOptions().collation, "default");
+
+ assertEq(c1.compare("ä", "ae"), 1);
+ assertEq(c2.compare("ä", "ae"), 1);
+ assertEq(c3.compare("ä", "ae"), 1);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/Collator/compare.js b/js/src/tests/non262/Intl/Collator/compare.js
new file mode 100644
index 0000000000..6f57c722dd
--- /dev/null
+++ b/js/src/tests/non262/Intl/Collator/compare.js
@@ -0,0 +1,137 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests the compare function with a diverse set of locales and options.
+
+var input = [
+ "Argentina",
+ "Oerlikon",
+ "Offenbach",
+ "Sverige",
+ "Vaticano",
+ "Zimbabwe",
+ "la France",
+ "¡viva España!",
+ "Österreich",
+ "中国",
+ "日本",
+ "한국",
+];
+
+var collator, expected;
+
+function assertEqualArray(actual, expected, collator) {
+ var description = JSON.stringify(collator.resolvedOptions());
+ assertEq(actual.length, expected.length, "array length, " + description);
+ for (var i = 0; i < actual.length; i++) {
+ assertEq(actual[i], expected[i], "element " + i + ", " + description);
+ }
+}
+
+
+// Locale en-US; default options.
+collator = new Intl.Collator("en-US");
+expected = [
+ "¡viva España!",
+ "Argentina",
+ "la France",
+ "Oerlikon",
+ "Offenbach",
+ "Österreich",
+ "Sverige",
+ "Vaticano",
+ "Zimbabwe",
+ "한국",
+ "中国",
+ "日本",
+];
+assertEqualArray(input.sort(collator.compare), expected, collator);
+
+// Locale sv-SE; default options.
+// Swedish treats "Ö" as a separate character, which sorts after "Z".
+collator = new Intl.Collator("sv-SE");
+expected = [
+ "¡viva España!",
+ "Argentina",
+ "la France",
+ "Oerlikon",
+ "Offenbach",
+ "Sverige",
+ "Vaticano",
+ "Zimbabwe",
+ "Österreich",
+ "한국",
+ "中国",
+ "日本",
+];
+assertEqualArray(input.sort(collator.compare), expected, collator);
+
+// Locale sv-SE; ignore punctuation.
+collator = new Intl.Collator("sv-SE", {ignorePunctuation: true});
+expected = [
+ "Argentina",
+ "la France",
+ "Oerlikon",
+ "Offenbach",
+ "Sverige",
+ "Vaticano",
+ "¡viva España!",
+ "Zimbabwe",
+ "Österreich",
+ "한국",
+ "中国",
+ "日本",
+];
+assertEqualArray(input.sort(collator.compare), expected, collator);
+
+// Locale de-DE; default options.
+// In German standard sorting, umlauted characters are treated as variants
+// of their base characters: ä ≅ a, ö ≅ o, ü ≅ u.
+collator = new Intl.Collator("de-DE");
+expected = [
+ "¡viva España!",
+ "Argentina",
+ "la France",
+ "Oerlikon",
+ "Offenbach",
+ "Österreich",
+ "Sverige",
+ "Vaticano",
+ "Zimbabwe",
+ "한국",
+ "中国",
+ "日本",
+];
+assertEqualArray(input.sort(collator.compare), expected, collator);
+
+// Locale de-DE; phonebook sort order.
+// In German phonebook sorting, umlauted characters are expanded to two-vowel
+// sequences: ä → ae, ö → oe, ü → ue.
+collator = new Intl.Collator("de-DE-u-co-phonebk");
+expected = [
+ "¡viva España!",
+ "Argentina",
+ "la France",
+ "Oerlikon",
+ "Österreich",
+ "Offenbach",
+ "Sverige",
+ "Vaticano",
+ "Zimbabwe",
+ "한국",
+ "中国",
+ "日本",
+];
+assertEqualArray(input.sort(collator.compare), expected, collator);
+
+
+// Test the .name property of the "compare" getter.
+var desc = Object.getOwnPropertyDescriptor(Intl.Collator.prototype, "compare");
+assertEq(desc !== undefined, true);
+assertEq(typeof desc.get, "function");
+assertEq(desc.get.name, "get compare");
+
+
+reportCompare(0, 0, 'ok');
diff --git a/js/src/tests/non262/Intl/Collator/construct-newtarget.js b/js/src/tests/non262/Intl/Collator/construct-newtarget.js
new file mode 100644
index 0000000000..5db1abf373
--- /dev/null
+++ b/js/src/tests/non262/Intl/Collator/construct-newtarget.js
@@ -0,0 +1,81 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+
+// Test subclassing %Intl.Collator% works correctly.
+class MyCollator extends Intl.Collator {}
+
+var obj = new MyCollator();
+assertEq(obj instanceof MyCollator, true);
+assertEq(obj instanceof Intl.Collator, true);
+assertEq(Object.getPrototypeOf(obj), MyCollator.prototype);
+
+obj = Reflect.construct(MyCollator, []);
+assertEq(obj instanceof MyCollator, true);
+assertEq(obj instanceof Intl.Collator, true);
+assertEq(Object.getPrototypeOf(obj), MyCollator.prototype);
+
+obj = Reflect.construct(MyCollator, [], MyCollator);
+assertEq(obj instanceof MyCollator, true);
+assertEq(obj instanceof Intl.Collator, true);
+assertEq(Object.getPrototypeOf(obj), MyCollator.prototype);
+
+obj = Reflect.construct(MyCollator, [], Intl.Collator);
+assertEq(obj instanceof MyCollator, false);
+assertEq(obj instanceof Intl.Collator, true);
+assertEq(Object.getPrototypeOf(obj), Intl.Collator.prototype);
+
+
+// Set a different constructor as NewTarget.
+obj = Reflect.construct(MyCollator, [], Array);
+assertEq(obj instanceof MyCollator, false);
+assertEq(obj instanceof Intl.Collator, false);
+assertEq(obj instanceof Array, true);
+assertEq(Object.getPrototypeOf(obj), Array.prototype);
+
+obj = Reflect.construct(Intl.Collator, [], Array);
+assertEq(obj instanceof Intl.Collator, false);
+assertEq(obj instanceof Array, true);
+assertEq(Object.getPrototypeOf(obj), Array.prototype);
+
+
+// The prototype defaults to %CollatorPrototype% if null.
+function NewTargetNullPrototype() {}
+NewTargetNullPrototype.prototype = null;
+
+obj = Reflect.construct(Intl.Collator, [], NewTargetNullPrototype);
+assertEq(obj instanceof Intl.Collator, true);
+assertEq(Object.getPrototypeOf(obj), Intl.Collator.prototype);
+
+obj = Reflect.construct(MyCollator, [], NewTargetNullPrototype);
+assertEq(obj instanceof MyCollator, false);
+assertEq(obj instanceof Intl.Collator, true);
+assertEq(Object.getPrototypeOf(obj), Intl.Collator.prototype);
+
+
+// "prototype" property is retrieved exactly once.
+var trapLog = [], getLog = [];
+var ProxiedConstructor = new Proxy(Intl.Collator, new Proxy({
+ get(target, propertyKey, receiver) {
+ getLog.push(propertyKey);
+ return Reflect.get(target, propertyKey, receiver);
+ }
+}, {
+ get(target, propertyKey, receiver) {
+ trapLog.push(propertyKey);
+ return Reflect.get(target, propertyKey, receiver);
+ }
+}));
+
+obj = Reflect.construct(Intl.Collator, [], ProxiedConstructor);
+assertEqArray(trapLog, ["get"]);
+assertEqArray(getLog, ["prototype"]);
+assertEq(obj instanceof Intl.Collator, true);
+assertEq(Object.getPrototypeOf(obj), Intl.Collator.prototype);
+
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/Collator/cross-compartment.js b/js/src/tests/non262/Intl/Collator/cross-compartment.js
new file mode 100644
index 0000000000..a8cf3134ca
--- /dev/null
+++ b/js/src/tests/non262/Intl/Collator/cross-compartment.js
@@ -0,0 +1,22 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+var otherGlobal = newGlobal();
+
+var collator = new Intl.Collator();
+var ccwCollator = new otherGlobal.Intl.Collator();
+
+// Test Intl.Collator.prototype.compare with a CCW object.
+var Intl_Collator_compare_get = Object.getOwnPropertyDescriptor(Intl.Collator.prototype, "compare").get;
+
+assertEq(Intl_Collator_compare_get.call(ccwCollator)("a", "A"),
+ Intl_Collator_compare_get.call(collator)("a", "A"));
+
+// Test Intl.Collator.prototype.resolvedOptions with a CCW object.
+var Intl_Collator_resolvedOptions = Intl.Collator.prototype.resolvedOptions;
+
+assertEq(deepEqual(Intl_Collator_resolvedOptions.call(ccwCollator),
+ Intl_Collator_resolvedOptions.call(collator)),
+ true);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/Collator/implicithan.js b/js/src/tests/non262/Intl/Collator/implicithan.js
new file mode 100644
index 0000000000..518ecdb43e
--- /dev/null
+++ b/js/src/tests/non262/Intl/Collator/implicithan.js
@@ -0,0 +1,17 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let scrambled = ['𠙶', '𠇲', '㓙', '㑧', '假', '凷'];
+
+// Sort first by block and then by radical-stroke inside each block.
+// This matches the ICU/ICU4X implicithan root order, which is used
+// by Chrome as of October 2022. (As of October 2022, Safari uses
+// the unihan root order, which uses more data but uses radical-stroke
+// across blocks.)
+const byBlock = ['假', '凷', '㑧', '㓙', '𠇲', '𠙶'];
+
+scrambled.sort(new Intl.Collator().compare);
+assertEqArray(scrambled, byBlock);
+
+reportCompare(0, 0, 'ok');
diff --git a/js/src/tests/non262/Intl/Collator/shell.js b/js/src/tests/non262/Intl/Collator/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Intl/Collator/shell.js
diff --git a/js/src/tests/non262/Intl/Collator/supportedLocalesOf.js b/js/src/tests/non262/Intl/Collator/supportedLocalesOf.js
new file mode 100644
index 0000000000..7fbebca094
--- /dev/null
+++ b/js/src/tests/non262/Intl/Collator/supportedLocalesOf.js
@@ -0,0 +1,355 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||xulRuntime.shell)
+// -- test in browser only that ICU has locale data for all Mozilla languages
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This array contains the locales that ICU supports in
+// collation whose languages Mozilla localizes Firefox into.
+// Current as of ICU 50.1.2 and Firefox March 2013.
+var locales = [
+ "af",
+ "af-NA",
+ "af-ZA",
+ "ar",
+ "ar-001",
+ "ar-AE",
+ "ar-BH",
+ "ar-DJ",
+ "ar-DZ",
+ "ar-EG",
+ "ar-EH",
+ "ar-ER",
+ "ar-IL",
+ "ar-IQ",
+ "ar-JO",
+ "ar-KM",
+ "ar-KW",
+ "ar-LB",
+ "ar-LY",
+ "ar-MA",
+ "ar-MR",
+ "ar-OM",
+ "ar-PS",
+ "ar-QA",
+ "ar-SA",
+ "ar-SD",
+ "ar-SO",
+ "ar-SY",
+ "ar-TD",
+ "ar-TN",
+ "ar-YE",
+ "as",
+ "as-IN",
+ "be",
+ "be-BY",
+ "bg",
+ "bg-BG",
+ "bn",
+ "bn-BD",
+ "bn-IN",
+ "bs",
+ "bs-Cyrl",
+ "bs-Cyrl-BA",
+ "bs-Latn",
+ "bs-Latn-BA",
+ "ca",
+ "ca-AD",
+ "ca-ES",
+ "cs",
+ "cs-CZ",
+ "cy",
+ "cy-GB",
+ "da",
+ "da-DK",
+ "de",
+ "de-AT",
+ "de-BE",
+ "de-CH",
+ "de-DE",
+ "de-LI",
+ "de-LU",
+ "el",
+ "el-CY",
+ "el-GR",
+ "en",
+ "en-150",
+ "en-AG",
+ "en-AS",
+ "en-AU",
+ "en-BB",
+ "en-BE",
+ "en-BM",
+ "en-BS",
+ "en-BW",
+ "en-BZ",
+ "en-CA",
+ "en-CM",
+ "en-DM",
+ "en-FJ",
+ "en-FM",
+ "en-GB",
+ "en-GD",
+ "en-GG",
+ "en-GH",
+ "en-GI",
+ "en-GM",
+ "en-GU",
+ "en-HK",
+ "en-IE",
+ "en-IM",
+ "en-IN",
+ "en-JE",
+ "en-JM",
+ "en-KE",
+ "en-KI",
+ "en-KN",
+ "en-KY",
+ "en-LC",
+ "en-LR",
+ "en-LS",
+ "en-MG",
+ "en-MH",
+ "en-MP",
+ "en-MT",
+ "en-MU",
+ "en-MW",
+ "en-NA",
+ "en-NG",
+ "en-NZ",
+ "en-PG",
+ "en-PH",
+ "en-PK",
+ "en-PR",
+ "en-PW",
+ "en-SB",
+ "en-SC",
+ "en-SG",
+ "en-SL",
+ "en-SS",
+ "en-TC",
+ "en-TO",
+ "en-TT",
+ "en-TZ",
+ "en-UG",
+ "en-UM",
+ "en-US",
+ "en-US-POSIX",
+ "en-VC",
+ "en-VG",
+ "en-VI",
+ "en-VU",
+ "en-WS",
+ "en-ZA",
+ "en-ZM",
+ "en-ZW",
+ "eo",
+ "es",
+ "es-419",
+ "es-AR",
+ "es-BO",
+ "es-CL",
+ "es-CO",
+ "es-CR",
+ "es-CU",
+ "es-DO",
+ "es-EA",
+ "es-EC",
+ "es-ES",
+ "es-GQ",
+ "es-GT",
+ "es-HN",
+ "es-IC",
+ "es-MX",
+ "es-NI",
+ "es-PA",
+ "es-PE",
+ "es-PH",
+ "es-PR",
+ "es-PY",
+ "es-SV",
+ "es-US",
+ "es-UY",
+ "es-VE",
+ "et",
+ "et-EE",
+ "fa",
+ "fa-AF",
+ "fa-IR",
+ "fi",
+ "fi-FI",
+ "fr",
+ "fr-BE",
+ "fr-BF",
+ "fr-BI",
+ "fr-BJ",
+ "fr-BL",
+ "fr-CA",
+ "fr-CD",
+ "fr-CF",
+ "fr-CG",
+ "fr-CH",
+ "fr-CI",
+ "fr-CM",
+ "fr-DJ",
+ "fr-DZ",
+ "fr-FR",
+ "fr-GA",
+ "fr-GN",
+ "fr-GP",
+ "fr-GQ",
+ "fr-HT",
+ "fr-KM",
+ "fr-LU",
+ "fr-MA",
+ "fr-MC",
+ "fr-MF",
+ "fr-MG",
+ "fr-ML",
+ "fr-MQ",
+ "fr-MR",
+ "fr-MU",
+ "fr-NC",
+ "fr-NE",
+ "fr-PF",
+ "fr-RE",
+ "fr-RW",
+ "fr-SC",
+ "fr-SN",
+ "fr-SY",
+ "fr-TD",
+ "fr-TG",
+ "fr-TN",
+ "fr-VU",
+ "ga",
+ "ga-IE",
+ "gu",
+ "gu-IN",
+ "he",
+ "he-IL",
+ "hi",
+ "hi-IN",
+ "hr",
+ "hr-BA",
+ "hr-HR",
+ "hu",
+ "hu-HU",
+ "hy",
+ "hy-AM",
+ "id",
+ "id-ID",
+ "is",
+ "is-IS",
+ "it",
+ "it-CH",
+ "it-IT",
+ "it-SM",
+ "ja",
+ "ja-JP",
+ "kk",
+ "kk-KZ",
+ "km",
+ "km-KH",
+ "kn",
+ "kn-IN",
+ "ko",
+ "ko-KP",
+ "ko-KR",
+ "lt",
+ "lt-LT",
+ "lv",
+ "lv-LV",
+ "mk",
+ "mk-MK",
+ "ml",
+ "ml-IN",
+ "mr",
+ "mr-IN",
+ "nb",
+ "nb-NO",
+ "nl",
+ "nl-AW",
+ "nl-BE",
+ "nl-CW",
+ "nl-NL",
+ "nl-SR",
+ "nl-SX",
+ "nn",
+ "nn-NO",
+ "or",
+ "or-IN",
+ "pa",
+ "pa-Arab",
+ "pa-Arab-PK",
+ "pa-Guru",
+ "pa-Guru-IN",
+ "pl",
+ "pl-PL",
+ "pt",
+ "pt-AO",
+ "pt-BR",
+ "pt-CV",
+ "pt-GW",
+ "pt-MO",
+ "pt-MZ",
+ "pt-PT",
+ "pt-ST",
+ "pt-TL",
+ "ro",
+ "ro-MD",
+ "ro-RO",
+ "ru",
+ "ru-BY",
+ "ru-KG",
+ "ru-KZ",
+ "ru-MD",
+ "ru-RU",
+ "ru-UA",
+ "si",
+ "si-LK",
+ "sk",
+ "sk-SK",
+ "sl",
+ "sl-SI",
+ "sq",
+ "sq-AL",
+ "sq-MK",
+ "sr",
+ "sr-Cyrl",
+ "sr-Cyrl-BA",
+ "sr-Cyrl-ME",
+ "sr-Cyrl-RS",
+ "sr-Latn",
+ "sr-Latn-BA",
+ "sr-Latn-ME",
+ "sr-Latn-RS",
+ "sv",
+ "sv-AX",
+ "sv-FI",
+ "sv-SE",
+ "te",
+ "te-IN",
+ "th",
+ "th-TH",
+ "tr",
+ "tr-CY",
+ "tr-TR",
+ "uk",
+ "uk-UA",
+ "vi",
+ "vi-VN",
+ "zh",
+ "zh-Hans",
+ "zh-Hans-CN",
+ "zh-Hans-SG",
+ "zh-Hant",
+ "zh-Hant-HK",
+ "zh-Hant-MO",
+ "zh-Hant-TW",
+];
+
+
+var count = Intl.Collator.supportedLocalesOf(locales).length;
+
+reportCompare(locales.length, count, "Number of supported locales in Intl.Collator");
diff --git a/js/src/tests/non262/Intl/Collator/toStringTag.js b/js/src/tests/non262/Intl/Collator/toStringTag.js
new file mode 100644
index 0000000000..e092418df9
--- /dev/null
+++ b/js/src/tests/non262/Intl/Collator/toStringTag.js
@@ -0,0 +1,29 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+var desc = Object.getOwnPropertyDescriptor(Intl.Collator.prototype, Symbol.toStringTag);
+
+assertEq(desc !== undefined, true);
+assertEq(desc.value, "Intl.Collator");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+assertEq(Object.prototype.toString.call(Intl.Collator.prototype), "[object Intl.Collator]");
+assertEq(Object.prototype.toString.call(new Intl.Collator), "[object Intl.Collator]");
+
+Object.defineProperty(Intl.Collator.prototype, Symbol.toStringTag, {value: "Collator"});
+
+assertEq(Object.prototype.toString.call(Intl.Collator.prototype), "[object Collator]");
+assertEq(Object.prototype.toString.call(new Intl.Collator), "[object Collator]");
+
+delete Intl.Collator.prototype[Symbol.toStringTag];
+
+assertEq(Object.prototype.toString.call(Intl.Collator.prototype), "[object Object]");
+assertEq(Object.prototype.toString.call(new Intl.Collator), "[object Object]");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/Date/browser.js b/js/src/tests/non262/Intl/Date/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Intl/Date/browser.js
diff --git a/js/src/tests/non262/Intl/Date/shell.js b/js/src/tests/non262/Intl/Date/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Intl/Date/shell.js
diff --git a/js/src/tests/non262/Intl/Date/toLocaleDateString_timeZone.js b/js/src/tests/non262/Intl/Date/toLocaleDateString_timeZone.js
new file mode 100644
index 0000000000..e3c3013d30
--- /dev/null
+++ b/js/src/tests/non262/Intl/Date/toLocaleDateString_timeZone.js
@@ -0,0 +1,77 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const defaultLocale = "en-US";
+const defaultDate = Date.UTC(2012, 12-1, 6, 12, 0, 0);
+const defaultOptions = { timeZoneName: "short" };
+
+const tests = [
+ {
+ timeZone: "UTC",
+ result: "12/6/2012, UTC",
+ },
+ {
+ timeZone: "America/Los_Angeles",
+ result: "12/6/2012, PST",
+ },
+ {
+ timeZone: "Europe/Berlin", locale: "de",
+ options: { timeZoneName: "short" },
+ result: "6.12.2012, MEZ",
+ },
+ {
+ timeZone: "Europe/Paris", locale: "fr",
+ options: { timeZoneName: "long" },
+ result: "06/12/2012 heure normale d’Europe centrale",
+ },
+ {
+ timeZone: "Asia/Shanghai", locale: "zh-Hans-CN",
+ options: { timeZoneName: "long" },
+ result: "2012/12/6 中国标准时间",
+ },
+ {
+ timeZone: { toString: () => "Australia/Melbourne" }, locale: "en-AU",
+ result: "06/12/2012, AEDT",
+ },
+];
+
+for (let {timeZone, result, locale = defaultLocale, date = defaultDate, options = defaultOptions} of tests) {
+ let s = new Date(date).toLocaleDateString(locale, Object.assign({timeZone}, options));
+ assertEq(s, result);
+}
+
+
+// |undefined| or absent "timeZone" option selects the default time zone.
+{
+ let locale = defaultLocale;
+ let date = defaultDate;
+ let options = defaultOptions;
+
+ let absentTz = new Date(date).toLocaleDateString(locale, Object.assign({}, options));
+ let undefinedTz = new Date(date).toLocaleDateString(locale, Object.assign({timeZone: undefined}, options));
+ assertEq(undefinedTz, absentTz);
+}
+
+
+// RangeError is thrown for invalid time zone names.
+for (let timeZone of ["", "undefined", "UTC\0", "Vienna", "Africa", "America/NewYork"]) {
+ assertThrowsInstanceOf(() => {
+ new Date(defaultDate).toLocaleDateString(undefined, {timeZone});
+ }, RangeError);
+}
+
+// RangeError is thrown for these values, because ToString(<value>)
+// isn't a valid time zone name.
+for (let timeZone of [null, 0, 0.5, true, false, [], {}, function() {}]) {
+ assertThrowsInstanceOf(() => {
+ new Date(defaultDate).toLocaleDateString(undefined, {timeZone});
+ }, RangeError);
+}
+
+// ToString(<symbol>) throws TypeError.
+assertThrowsInstanceOf(() => {
+ new Date(defaultDate).toLocaleDateString(undefined, {timeZone: Symbol()});
+}, TypeError);
+
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/Date/toLocaleString_timeZone.js b/js/src/tests/non262/Intl/Date/toLocaleString_timeZone.js
new file mode 100644
index 0000000000..592e55070c
--- /dev/null
+++ b/js/src/tests/non262/Intl/Date/toLocaleString_timeZone.js
@@ -0,0 +1,77 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const defaultLocale = "en-US";
+const defaultDate = Date.UTC(2012, 12-1, 6, 12, 0, 0);
+const defaultOptions = {};
+
+const tests = [
+ {
+ timeZone: "UTC",
+ result: "12/6/2012, 12:00:00 PM",
+ },
+ {
+ timeZone: "America/Los_Angeles",
+ result: "12/6/2012, 4:00:00 AM",
+ },
+ {
+ timeZone: "Europe/Berlin", locale: "de",
+ options: { timeZoneName: "short" },
+ result: "6.12.2012, 13:00:00 MEZ",
+ },
+ {
+ timeZone: "Europe/Paris", locale: "fr",
+ options: { timeZoneName: "long" },
+ result: "06/12/2012 13:00:00 heure normale d’Europe centrale",
+ },
+ {
+ timeZone: "Asia/Shanghai", locale: "zh-Hans-CN",
+ options: { timeZoneName: "long" },
+ result: "2012/12/6 中国标准时间 20:00:00",
+ },
+ {
+ timeZone: { toString: () => "Australia/Melbourne" }, locale: "en-AU",
+ result: "06/12/2012, 11:00:00 pm",
+ },
+];
+
+for (let {timeZone, result, locale = defaultLocale, date = defaultDate, options = defaultOptions} of tests) {
+ let s = new Date(date).toLocaleString(locale, Object.assign({timeZone}, options));
+ assertEq(s, result);
+}
+
+
+// |undefined| or absent "timeZone" option selects the default time zone.
+{
+ let locale = defaultLocale;
+ let date = defaultDate;
+ let options = defaultOptions;
+
+ let absentTz = new Date(date).toLocaleString(locale, Object.assign({}, options));
+ let undefinedTz = new Date(date).toLocaleString(locale, Object.assign({timeZone: undefined}, options));
+ assertEq(undefinedTz, absentTz);
+}
+
+
+// RangeError is thrown for invalid time zone names.
+for (let timeZone of ["", "undefined", "UTC\0", "Vienna", "Africa", "America/NewYork"]) {
+ assertThrowsInstanceOf(() => {
+ new Date(defaultDate).toLocaleString(undefined, {timeZone});
+ }, RangeError);
+}
+
+// RangeError is thrown for these values, because ToString(<value>)
+// isn't a valid time zone name.
+for (let timeZone of [null, 0, 0.5, true, false, [], {}, function() {}]) {
+ assertThrowsInstanceOf(() => {
+ new Date(defaultDate).toLocaleString(undefined, {timeZone});
+ }, RangeError);
+}
+
+// ToString(<symbol>) throws TypeError.
+assertThrowsInstanceOf(() => {
+ new Date(defaultDate).toLocaleString(undefined, {timeZone: Symbol()});
+}, TypeError);
+
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/Date/toLocaleTimeString_timeZone.js b/js/src/tests/non262/Intl/Date/toLocaleTimeString_timeZone.js
new file mode 100644
index 0000000000..a9b8b5f980
--- /dev/null
+++ b/js/src/tests/non262/Intl/Date/toLocaleTimeString_timeZone.js
@@ -0,0 +1,77 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const defaultLocale = "en-US";
+const defaultDate = Date.UTC(2012, 12-1, 6, 12, 0, 0);
+const defaultOptions = {};
+
+const tests = [
+ {
+ timeZone: "UTC",
+ result: "12:00:00 PM",
+ },
+ {
+ timeZone: "America/Los_Angeles",
+ result: "4:00:00 AM",
+ },
+ {
+ timeZone: "Europe/Berlin", locale: "de",
+ options: { timeZoneName: "short" },
+ result: "13:00:00 MEZ",
+ },
+ {
+ timeZone: "Europe/Paris", locale: "fr",
+ options: { timeZoneName: "long" },
+ result: "13:00:00 heure normale d’Europe centrale",
+ },
+ {
+ timeZone: "Asia/Shanghai", locale: "zh-Hans-CN",
+ options: { timeZoneName: "long" },
+ result: "中国标准时间 20:00:00",
+ },
+ {
+ timeZone: { toString: () => "Australia/Melbourne" }, locale: "en-AU",
+ result: "11:00:00 pm",
+ },
+];
+
+for (let {timeZone, result, locale = defaultLocale, date = defaultDate, options = defaultOptions} of tests) {
+ let s = new Date(date).toLocaleTimeString(locale, Object.assign({timeZone}, options));
+ assertEq(s, result);
+}
+
+
+// |undefined| or absent "timeZone" option selects the default time zone.
+{
+ let locale = defaultLocale;
+ let date = defaultDate;
+ let options = defaultOptions;
+
+ let absentTz = new Date(date).toLocaleTimeString(locale, Object.assign({}, options));
+ let undefinedTz = new Date(date).toLocaleTimeString(locale, Object.assign({timeZone: undefined}, options));
+ assertEq(undefinedTz, absentTz);
+}
+
+
+// RangeError is thrown for invalid time zone names.
+for (let timeZone of ["", "undefined", "UTC\0", "Vienna", "Africa", "America/NewYork"]) {
+ assertThrowsInstanceOf(() => {
+ new Date(defaultDate).toLocaleTimeString(undefined, {timeZone});
+ }, RangeError);
+}
+
+// RangeError is thrown for these values, because ToString(<value>)
+// isn't a valid time zone name.
+for (let timeZone of [null, 0, 0.5, true, false, [], {}, function() {}]) {
+ assertThrowsInstanceOf(() => {
+ new Date(defaultDate).toLocaleTimeString(undefined, {timeZone});
+ }, RangeError);
+}
+
+// ToString(<symbol>) throws TypeError.
+assertThrowsInstanceOf(() => {
+ new Date(defaultDate).toLocaleTimeString(undefined, {timeZone: Symbol()});
+}, TypeError);
+
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/browser.js b/js/src/tests/non262/Intl/DateTimeFormat/browser.js
new file mode 100644
index 0000000000..5665e7ed44
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/browser.js
@@ -0,0 +1,3 @@
+if (typeof setTimeZone === "undefined") {
+ var setTimeZone = SpecialPowers.Cu.getJSTestingFunctions().setTimeZone;
+}
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/calendar-aliases.js b/js/src/tests/non262/Intl/DateTimeFormat/calendar-aliases.js
new file mode 100644
index 0000000000..901adcb45f
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/calendar-aliases.js
@@ -0,0 +1,35 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Ensure ethiopic-amete-alem is resolved to ethioaa instead of ethiopic.
+function testEthiopicAmeteAlem() {
+ var locale = "am-ET-u-nu-latn";
+ var opts = {timeZone: "Africa/Addis_Ababa"};
+ var dtfEthiopicAmeteAlem = new Intl.DateTimeFormat(`${locale}-ca-ethiopic-amete-alem`, opts);
+ var dtfEthioaa = new Intl.DateTimeFormat(`${locale}-ca-ethioaa`, opts);
+ var dtfEthiopic = new Intl.DateTimeFormat(`${locale}-ca-ethiopic`, opts);
+
+ var date = new Date(2016, 1 - 1, 1);
+
+ assertEq(dtfEthiopicAmeteAlem.format(date), dtfEthioaa.format(date));
+ assertEq(dtfEthiopicAmeteAlem.format(date) === dtfEthiopic.format(date), false);
+}
+
+// Ensure islamicc is resolved to islamic-civil.
+function testIslamicCivil() {
+ var locale = "ar-SA-u-nu-latn";
+ var opts = {timeZone: "Asia/Riyadh"};
+ var dtfIslamicCivil = new Intl.DateTimeFormat(`${locale}-ca-islamic-civil`, opts);
+ var dtfIslamicc = new Intl.DateTimeFormat(`${locale}-ca-islamicc`, opts);
+ var dtfIslamic = new Intl.DateTimeFormat(`${locale}-ca-islamic`, opts);
+
+ var date = new Date(2016, 1 - 1, 1);
+
+ assertEq(dtfIslamicCivil.format(date), dtfIslamicc.format(date));
+ assertEq(dtfIslamicCivil.format(date) === dtfIslamic.format(date), false);
+}
+
+testEthiopicAmeteAlem();
+testIslamicCivil();
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/calendar-option.js b/js/src/tests/non262/Intl/DateTimeFormat/calendar-option.js
new file mode 100644
index 0000000000..cbf73df5c9
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/calendar-option.js
@@ -0,0 +1,67 @@
+const defaultLocale = "en";
+const defaultCalendar = new Intl.DateTimeFormat(defaultLocale).resolvedOptions().calendar;
+
+function createWithLocale(locale, calendar) {
+ return new Intl.DateTimeFormat(locale, {calendar});
+}
+
+function create(calendar) {
+ return createWithLocale(defaultLocale, calendar);
+}
+
+// Empty string should throw.
+assertThrowsInstanceOf(() => create(""), RangeError);
+
+// Trailing \0 should throw.
+assertThrowsInstanceOf(() => create("gregory\0"), RangeError);
+
+// Too short or too long strings should throw.
+assertThrowsInstanceOf(() => create("a"), RangeError);
+assertThrowsInstanceOf(() => create("toolongstring"), RangeError);
+
+// Throw even when prefix is valid.
+assertThrowsInstanceOf(() => create("gregory-toolongstring"), RangeError);
+
+// |calendar| can be set to |undefined|.
+let dtf = create(undefined);
+assertEq(dtf.resolvedOptions().calendar, defaultCalendar);
+
+// Unsupported calendars are ignored.
+dtf = create("xxxxxxxx");
+assertEq(dtf.resolvedOptions().calendar, defaultCalendar);
+
+// Calendars in options overwrite Unicode extension keyword.
+dtf = createWithLocale(`${defaultLocale}-u-ca-iso8601`, "japanese");
+assertEq(dtf.resolvedOptions().locale, defaultLocale);
+assertEq(dtf.resolvedOptions().calendar, "japanese");
+
+// |calendar| option ignores case.
+dtf = create("CHINESE");
+assertEq(dtf.resolvedOptions().locale, defaultLocale);
+assertEq(dtf.resolvedOptions().calendar, "chinese");
+
+const calendars = [
+ "buddhist", "chinese", "coptic", "dangi", "ethioaa", "ethiopic-amete-alem",
+ "ethiopic", "gregory", "hebrew", "indian", "islamic", "islamic-umalqura",
+ "islamic-tbla", "islamic-civil", "islamic-rgsa", "iso8601", "japanese",
+ "persian", "roc", "islamicc",
+];
+
+// https://github.com/tc39/proposal-intl-locale/issues/96
+const canonical = {
+ "islamicc": "islamic-civil",
+ "ethiopic-amete-alem": "ethioaa",
+};
+
+for (let calendar of calendars) {
+ let dtf1 = new Intl.DateTimeFormat(`${defaultLocale}-u-ca-${calendar}`);
+ let dtf2 = new Intl.DateTimeFormat(defaultLocale, {calendar});
+
+ assertEq(dtf1.resolvedOptions().calendar, canonical[calendar] ?? calendar);
+ assertEq(dtf2.resolvedOptions().calendar, canonical[calendar] ?? calendar);
+
+ assertEq(dtf2.format(0), dtf1.format(0));
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/call.js b/js/src/tests/non262/Intl/DateTimeFormat/call.js
new file mode 100644
index 0000000000..752bda9c02
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/call.js
@@ -0,0 +1,184 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+function IsIntlService(c) {
+ return typeof c === "function" &&
+ c.hasOwnProperty("prototype") &&
+ c.prototype.hasOwnProperty("resolvedOptions");
+}
+
+function IsObject(o) {
+ return Object(o) === o;
+}
+
+function IsPrimitive(o) {
+ return Object(o) !== o;
+}
+
+function thisValues() {
+ const intlConstructors = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService);
+
+ return [
+ // Primitive values.
+ ...[undefined, null, true, "abc", Symbol(), 123],
+
+ // Object values.
+ ...[{}, [], /(?:)/, function(){}, new Proxy({}, {})],
+
+ // Intl objects.
+ ...[].concat(...intlConstructors.map(ctor => {
+ let args = [];
+ if (ctor === Intl.DisplayNames) {
+ // Intl.DisplayNames can't be constructed without any arguments.
+ args = [undefined, {type: "language"}];
+ }
+
+ return [
+ // Instance of an Intl constructor.
+ new ctor(...args),
+
+ // Instance of a subclassed Intl constructor.
+ new class extends ctor {}(...args),
+
+ // Object inheriting from an Intl constructor prototype.
+ Object.create(ctor.prototype),
+
+ // Intl object not inheriting from its default prototype.
+ Object.setPrototypeOf(new ctor(...args), Object.prototype),
+ ];
+ })),
+ ];
+}
+
+const intlFallbackSymbol = Object.getOwnPropertySymbols(Intl.DateTimeFormat.call(Object.create(Intl.DateTimeFormat.prototype)))[0];
+
+// Invoking [[Call]] for Intl.DateTimeFormat returns a new instance unless called
+// with an instance inheriting from Intl.DateTimeFormat.prototype.
+for (let thisValue of thisValues()) {
+ let obj = Intl.DateTimeFormat.call(thisValue);
+
+ if (!Intl.DateTimeFormat.prototype.isPrototypeOf(thisValue)) {
+ assertEq(Object.is(obj, thisValue), false);
+ assertEq(obj instanceof Intl.DateTimeFormat, true);
+ if (IsObject(thisValue))
+ assertEqArray(Object.getOwnPropertySymbols(thisValue), []);
+ } else {
+ assertEq(Object.is(obj, thisValue), true);
+ assertEq(obj instanceof Intl.DateTimeFormat, true);
+ assertEqArray(Object.getOwnPropertySymbols(thisValue), [intlFallbackSymbol]);
+ }
+}
+
+// Intl.DateTimeFormat uses the legacy Intl constructor compromise semantics.
+// - Test when InstanceofOperator(thisValue, %DateTimeFormat%) returns true.
+for (let thisValue of thisValues().filter(IsObject)) {
+ let isPrototypeOf = Intl.DateTimeFormat.prototype.isPrototypeOf(thisValue);
+ let hasInstanceCalled = false;
+ Object.defineProperty(Intl.DateTimeFormat, Symbol.hasInstance, {
+ value() {
+ assertEq(hasInstanceCalled, false);
+ hasInstanceCalled = true;
+ return true;
+ }, configurable: true
+ });
+ let obj = Intl.DateTimeFormat.call(thisValue);
+ delete Intl.DateTimeFormat[Symbol.hasInstance];
+
+ assertEq(Object.is(obj, thisValue), isPrototypeOf);
+ assertEq(hasInstanceCalled, false);
+ assertEqArray(Object.getOwnPropertySymbols(thisValue), isPrototypeOf ? [intlFallbackSymbol] : []);
+}
+// - Test when InstanceofOperator(thisValue, %DateTimeFormat%) returns false.
+for (let thisValue of thisValues().filter(IsObject)) {
+ let isPrototypeOf = Intl.DateTimeFormat.prototype.isPrototypeOf(thisValue);
+ let hasInstanceCalled = false;
+ Object.defineProperty(Intl.DateTimeFormat, Symbol.hasInstance, {
+ value() {
+ assertEq(hasInstanceCalled, false);
+ hasInstanceCalled = true;
+ return false;
+ }, configurable: true
+ });
+ let obj = Intl.DateTimeFormat.call(thisValue);
+ delete Intl.DateTimeFormat[Symbol.hasInstance];
+
+ assertEq(Object.is(obj, thisValue), isPrototypeOf);
+ assertEq(obj instanceof Intl.DateTimeFormat, true);
+ assertEq(hasInstanceCalled, false);
+ assertEqArray(Object.getOwnPropertySymbols(thisValue), isPrototypeOf ? [intlFallbackSymbol] : []);
+}
+// - Test with primitive values.
+for (let thisValue of thisValues().filter(IsPrimitive)) {
+ // Ensure @@hasInstance is not called.
+ Object.defineProperty(Intl.DateTimeFormat, Symbol.hasInstance, {
+ value() { assertEq(true, false); }, configurable: true
+ });
+ let obj = Intl.DateTimeFormat.call(thisValue);
+ delete Intl.DateTimeFormat[Symbol.hasInstance];
+
+ assertEq(Object.is(obj, thisValue), false);
+ assertEq(obj instanceof Intl.DateTimeFormat, true);
+}
+
+// Throws an error when attempting to install [[FallbackSymbol]] twice.
+{
+ let thisValue = Object.create(Intl.DateTimeFormat.prototype);
+ assertEqArray(Object.getOwnPropertySymbols(thisValue), []);
+
+ assertEq(Intl.DateTimeFormat.call(thisValue), thisValue);
+ assertEqArray(Object.getOwnPropertySymbols(thisValue), [intlFallbackSymbol]);
+
+ assertThrowsInstanceOf(() => Intl.DateTimeFormat.call(thisValue), TypeError);
+ assertEqArray(Object.getOwnPropertySymbols(thisValue), [intlFallbackSymbol]);
+}
+
+// Throws an error when the thisValue is non-extensible.
+{
+ let thisValue = Object.create(Intl.DateTimeFormat.prototype);
+ Object.preventExtensions(thisValue);
+
+ assertThrowsInstanceOf(() => Intl.DateTimeFormat.call(thisValue), TypeError);
+ assertEqArray(Object.getOwnPropertySymbols(thisValue), []);
+}
+
+// [[FallbackSymbol]] is installed as a frozen property holding an Intl.DateTimeFormat instance.
+{
+ let thisValue = Object.create(Intl.DateTimeFormat.prototype);
+ Intl.DateTimeFormat.call(thisValue);
+
+ let desc = Object.getOwnPropertyDescriptor(thisValue, intlFallbackSymbol);
+ assertEq(desc !== undefined, true);
+ assertEq(desc.writable, false);
+ assertEq(desc.enumerable, false);
+ assertEq(desc.configurable, false);
+ assertEq(desc.value instanceof Intl.DateTimeFormat, true);
+}
+
+// Ensure [[FallbackSymbol]] is installed last by changing the [[Prototype]]
+// during initialization.
+{
+ let thisValue = {};
+ let options = {
+ get hour12() {
+ Object.setPrototypeOf(thisValue, Intl.DateTimeFormat.prototype);
+ return false;
+ }
+ };
+ let obj = Intl.DateTimeFormat.call(thisValue, undefined, options);
+ assertEq(Object.is(obj, thisValue), true);
+ assertEqArray(Object.getOwnPropertySymbols(thisValue), [intlFallbackSymbol]);
+}
+{
+ let thisValue = Object.create(Intl.DateTimeFormat.prototype);
+ let options = {
+ get hour12() {
+ Object.setPrototypeOf(thisValue, Object.prototype);
+ return false;
+ }
+ };
+ let obj = Intl.DateTimeFormat.call(thisValue, undefined, options);
+ assertEq(Object.is(obj, thisValue), false);
+ assertEqArray(Object.getOwnPropertySymbols(thisValue), []);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/construct-newtarget.js b/js/src/tests/non262/Intl/DateTimeFormat/construct-newtarget.js
new file mode 100644
index 0000000000..bbc08c79a1
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/construct-newtarget.js
@@ -0,0 +1,81 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+
+// Test subclassing %Intl.DateTimeFormat% works correctly.
+class MyDateTimeFormat extends Intl.DateTimeFormat {}
+
+var obj = new MyDateTimeFormat();
+assertEq(obj instanceof MyDateTimeFormat, true);
+assertEq(obj instanceof Intl.DateTimeFormat, true);
+assertEq(Object.getPrototypeOf(obj), MyDateTimeFormat.prototype);
+
+obj = Reflect.construct(MyDateTimeFormat, []);
+assertEq(obj instanceof MyDateTimeFormat, true);
+assertEq(obj instanceof Intl.DateTimeFormat, true);
+assertEq(Object.getPrototypeOf(obj), MyDateTimeFormat.prototype);
+
+obj = Reflect.construct(MyDateTimeFormat, [], MyDateTimeFormat);
+assertEq(obj instanceof MyDateTimeFormat, true);
+assertEq(obj instanceof Intl.DateTimeFormat, true);
+assertEq(Object.getPrototypeOf(obj), MyDateTimeFormat.prototype);
+
+obj = Reflect.construct(MyDateTimeFormat, [], Intl.DateTimeFormat);
+assertEq(obj instanceof MyDateTimeFormat, false);
+assertEq(obj instanceof Intl.DateTimeFormat, true);
+assertEq(Object.getPrototypeOf(obj), Intl.DateTimeFormat.prototype);
+
+
+// Set a different constructor as NewTarget.
+obj = Reflect.construct(MyDateTimeFormat, [], Array);
+assertEq(obj instanceof MyDateTimeFormat, false);
+assertEq(obj instanceof Intl.DateTimeFormat, false);
+assertEq(obj instanceof Array, true);
+assertEq(Object.getPrototypeOf(obj), Array.prototype);
+
+obj = Reflect.construct(Intl.DateTimeFormat, [], Array);
+assertEq(obj instanceof Intl.DateTimeFormat, false);
+assertEq(obj instanceof Array, true);
+assertEq(Object.getPrototypeOf(obj), Array.prototype);
+
+
+// The prototype defaults to %DateTimeFormatPrototype% if null.
+function NewTargetNullPrototype() {}
+NewTargetNullPrototype.prototype = null;
+
+obj = Reflect.construct(Intl.DateTimeFormat, [], NewTargetNullPrototype);
+assertEq(obj instanceof Intl.DateTimeFormat, true);
+assertEq(Object.getPrototypeOf(obj), Intl.DateTimeFormat.prototype);
+
+obj = Reflect.construct(MyDateTimeFormat, [], NewTargetNullPrototype);
+assertEq(obj instanceof MyDateTimeFormat, false);
+assertEq(obj instanceof Intl.DateTimeFormat, true);
+assertEq(Object.getPrototypeOf(obj), Intl.DateTimeFormat.prototype);
+
+
+// "prototype" property is retrieved exactly once.
+var trapLog = [], getLog = [];
+var ProxiedConstructor = new Proxy(Intl.DateTimeFormat, new Proxy({
+ get(target, propertyKey, receiver) {
+ getLog.push(propertyKey);
+ return Reflect.get(target, propertyKey, receiver);
+ }
+}, {
+ get(target, propertyKey, receiver) {
+ trapLog.push(propertyKey);
+ return Reflect.get(target, propertyKey, receiver);
+ }
+}));
+
+obj = Reflect.construct(Intl.DateTimeFormat, [], ProxiedConstructor);
+assertEqArray(trapLog, ["get"]);
+assertEqArray(getLog, ["prototype"]);
+assertEq(obj instanceof Intl.DateTimeFormat, true);
+assertEq(Object.getPrototypeOf(obj), Intl.DateTimeFormat.prototype);
+
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/cross-compartment.js b/js/src/tests/non262/Intl/DateTimeFormat/cross-compartment.js
new file mode 100644
index 0000000000..dac99bdc19
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/cross-compartment.js
@@ -0,0 +1,70 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+var otherGlobal = newGlobal();
+
+var dateTimeFormat = new Intl.DateTimeFormat();
+var ccwDateTimeFormat = new otherGlobal.Intl.DateTimeFormat();
+
+// Test Intl.DateTimeFormat.prototype.format with a CCW object.
+var Intl_DateTimeFormat_format_get = Object.getOwnPropertyDescriptor(Intl.DateTimeFormat.prototype, "format").get;
+
+assertEq(Intl_DateTimeFormat_format_get.call(ccwDateTimeFormat)(0),
+ Intl_DateTimeFormat_format_get.call(dateTimeFormat)(0));
+
+// Test Intl.DateTimeFormat.prototype.formatToParts with a CCW object.
+var Intl_DateTimeFormat_formatToParts = Intl.DateTimeFormat.prototype.formatToParts;
+
+assertEq(deepEqual(Intl_DateTimeFormat_formatToParts.call(ccwDateTimeFormat, 0),
+ Intl_DateTimeFormat_formatToParts.call(dateTimeFormat, 0)),
+ true);
+
+// Test Intl.DateTimeFormat.prototype.resolvedOptions with a CCW object.
+var Intl_DateTimeFormat_resolvedOptions = Intl.DateTimeFormat.prototype.resolvedOptions;
+
+assertEq(deepEqual(Intl_DateTimeFormat_resolvedOptions.call(ccwDateTimeFormat),
+ Intl_DateTimeFormat_resolvedOptions.call(dateTimeFormat)),
+ true);
+
+// Special case for Intl.DateTimeFormat: The Intl fallback symbol.
+
+function fallbackSymbol(global) {
+ var DTF = global.Intl.DateTimeFormat;
+ return Object.getOwnPropertySymbols(DTF.call(Object.create(DTF.prototype)))[0];
+}
+
+const intlFallbackSymbol = fallbackSymbol(this);
+const otherIntlFallbackSymbol = fallbackSymbol(otherGlobal);
+assertEq(intlFallbackSymbol === otherIntlFallbackSymbol, false);
+
+// Test when the fallback symbol points to a CCW DateTimeFormat object.
+var objWithFallbackCCWDateTimeFormat = {
+ __proto__: Intl.DateTimeFormat.prototype,
+ [intlFallbackSymbol]: ccwDateTimeFormat,
+};
+
+assertEq(Intl_DateTimeFormat_format_get.call(objWithFallbackCCWDateTimeFormat)(0),
+ Intl_DateTimeFormat_format_get.call(dateTimeFormat)(0));
+
+assertEq(deepEqual(Intl_DateTimeFormat_resolvedOptions.call(objWithFallbackCCWDateTimeFormat),
+ Intl_DateTimeFormat_resolvedOptions.call(dateTimeFormat)),
+ true);
+
+// Ensure the fallback symbol(s) are not accessed for CCW DateTimeFormat objects.
+var ccwDateTimeFormatWithPoisonedFallback = new otherGlobal.Intl.DateTimeFormat();
+Object.setPrototypeOf(ccwDateTimeFormatWithPoisonedFallback, Intl.DateTimeFormat.prototype);
+Object.defineProperty(ccwDateTimeFormatWithPoisonedFallback, intlFallbackSymbol, {
+ get() { throw new Error(); }
+});
+Object.defineProperty(ccwDateTimeFormatWithPoisonedFallback, otherIntlFallbackSymbol, {
+ get() { throw new Error(); }
+});
+
+assertEq(Intl_DateTimeFormat_format_get.call(ccwDateTimeFormatWithPoisonedFallback)(0),
+ Intl_DateTimeFormat_format_get.call(dateTimeFormat)(0));
+
+assertEq(deepEqual(Intl_DateTimeFormat_resolvedOptions.call(ccwDateTimeFormatWithPoisonedFallback),
+ Intl_DateTimeFormat_resolvedOptions.call(dateTimeFormat)),
+ true);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/dateTimeStyle.js b/js/src/tests/non262/Intl/DateTimeFormat/dateTimeStyle.js
new file mode 100644
index 0000000000..1dd4c35316
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/dateTimeStyle.js
@@ -0,0 +1,57 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Date style
+
+var dtf = new Intl.DateTimeFormat("en-US", {dateStyle: 'long'});
+assertEq(dtf.resolvedOptions().dateStyle, 'long');
+assertEq(dtf.resolvedOptions().hasOwnProperty('year'), false);
+assertEq(dtf.resolvedOptions().hasOwnProperty('month'), false);
+assertEq(dtf.resolvedOptions().hasOwnProperty('day'), false);
+
+// Time style
+
+var dtf = new Intl.DateTimeFormat("en-US", {timeStyle: 'long'});
+assertEq(dtf.resolvedOptions().timeStyle, 'long');
+assertEq(dtf.resolvedOptions().hasOwnProperty('hour'), false);
+assertEq(dtf.resolvedOptions().hasOwnProperty('minute'), false);
+assertEq(dtf.resolvedOptions().hasOwnProperty('second'), false);
+
+// Date/Time style
+
+var dtf = new Intl.DateTimeFormat("en-US", {dateStyle: 'medium', timeStyle: 'medium'});
+assertEq(dtf.resolvedOptions().timeStyle, 'medium');
+assertEq(dtf.resolvedOptions().dateStyle, 'medium');
+assertEq(dtf.resolvedOptions().hasOwnProperty('hour'), false);
+assertEq(dtf.resolvedOptions().hasOwnProperty('minute'), false);
+assertEq(dtf.resolvedOptions().hasOwnProperty('second'), false);
+assertEq(dtf.resolvedOptions().hasOwnProperty('year'), false);
+assertEq(dtf.resolvedOptions().hasOwnProperty('month'), false);
+assertEq(dtf.resolvedOptions().hasOwnProperty('day'), false);
+
+// Error when mixing date/timeStyle with other date-time options.
+
+assertThrowsInstanceOf(() => {
+ new Intl.DateTimeFormat("en-US", {dateStyle: 'medium', year: 'numeric'});
+}, TypeError);
+
+assertThrowsInstanceOf(() => {
+ new Intl.DateTimeFormat("en-US", {timeStyle: 'medium', year: 'numeric'});
+}, TypeError);
+
+// Error when using dateStyle in toLocaleTimeString.
+
+assertThrowsInstanceOf(() => {
+ new Date().toLocaleTimeString("en-US", {dateStyle: 'long'});
+}, TypeError);
+
+// Error when using dateStyle in toLocaleDateString.
+
+assertThrowsInstanceOf(() => {
+ new Date().toLocaleDateString("en-US", {timeStyle: 'long'});
+}, TypeError);
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, 'ok');
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/day-period-hour-cycle.js b/js/src/tests/non262/Intl/DateTimeFormat/day-period-hour-cycle.js
new file mode 100644
index 0000000000..6bfbf94df3
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/day-period-hour-cycle.js
@@ -0,0 +1,102 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const {
+ Year, Month, Day, DayPeriod, Hour, Minute, Literal
+} = DateTimeFormatParts;
+
+// If the locale defaults to a 24-hour-cycle, the "dayPeriod" option is ignored if an "hour" option
+// is also present, unless the hour-cycle is manually set to a 12-hour-cycle.
+
+const tests = [
+ {
+ date: new Date("2019-01-01T12:00:00"),
+ options: { dayPeriod: "short", hour: "numeric", },
+ locales: {
+ en: [Hour("12"), Literal(" "), DayPeriod("noon")],
+ de: [Hour("12"), Literal(" Uhr")],
+ },
+ },
+ {
+ date: new Date("2019-01-01T12:00:00"),
+ options: { dayPeriod: "short", hour: "numeric", hour12: true },
+ locales: {
+ en: [Hour("12"), Literal(" "), DayPeriod("noon")],
+ de: [Hour("12"), Literal(" "), DayPeriod("mittags")],
+ },
+ },
+ {
+ date: new Date("2019-01-01T12:00:00"),
+ options: { dayPeriod: "short", hour: "numeric", hour12: false },
+ locales: {
+ en: [Hour("12")],
+ de: [Hour("12"), Literal(" Uhr")],
+ },
+ },
+ {
+ date: new Date("2019-01-01T12:00:00"),
+ options: { dayPeriod: "short", hour: "numeric", hourCycle: "h12" },
+ locales: {
+ en: [Hour("12"), Literal(" "), DayPeriod("noon")],
+ de: [Hour("12"), Literal(" "), DayPeriod("mittags")],
+ },
+ },
+ {
+ date: new Date("2019-01-01T12:00:00"),
+ options: { dayPeriod: "short", hour: "numeric", hourCycle: "h11" },
+ locales: {
+ en: [Hour("0"), Literal(" "), DayPeriod("noon")],
+ de: [Hour("0"), Literal(" "), DayPeriod("mittags")],
+ },
+ },
+ {
+ date: new Date("2019-01-01T12:00:00"),
+ options: { dayPeriod: "short", hour: "numeric", hourCycle: "h23" },
+ locales: {
+ en: [Hour("12")],
+ de: [Hour("12"), Literal(" Uhr")],
+ },
+ },
+ {
+ date: new Date("2019-01-01T12:00:00"),
+ options: { dayPeriod: "short", hour: "numeric", hourCycle: "h24" },
+ locales: {
+ en: [Hour("12")],
+ de: [Hour("12"), Literal(" Uhr")],
+ },
+ },
+
+ // The default hour-cycle is irrelevant when an "hour" option isn't present.
+ {
+ date: new Date("2019-01-01T12:00:00"),
+ options: { dayPeriod: "short", day: "numeric", month: "numeric", year: "numeric" },
+ locales: {
+ en: [Month("1"), Literal("/"), Day("1"), Literal("/"), Year("2019"), Literal(", "), DayPeriod("noon")],
+ de: [Day("1"), Literal("."), Month("1"), Literal("."), Year("2019"), Literal(", "), DayPeriod("mittags")],
+ },
+ },
+
+ // ICU replacement pattern for missing <appendItem> entries in CLDR.
+ {
+ date: new Date("2019-01-01T12:00:00"),
+ options: { dayPeriod: "short", minute: "numeric" },
+ locales: {
+ en: [Minute("0"), Literal(" (AM/PM: "), DayPeriod("noon"), Literal(")")],
+ de: [Minute("0"), Literal(" (Tageshälfte: "), DayPeriod("mittags"), Literal(")")],
+ },
+ },
+];
+
+for (let {date, options, locales} of tests) {
+ for (let [locale, parts] of Object.entries(locales)) {
+ let dtf = new Intl.DateTimeFormat(locale, options);
+
+ assertEq(dtf.format(date), parts.map(({value}) => value).join(""),
+ `locale=${locale}, date=${date}, options=${JSON.stringify(options)}`);
+
+ assertDeepEq(dtf.formatToParts(date), parts,
+ `locale=${locale}, date=${date}, options=${JSON.stringify(options)}`);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/day-period-standalone.js b/js/src/tests/non262/Intl/DateTimeFormat/day-period-standalone.js
new file mode 100644
index 0000000000..203ba03766
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/day-period-standalone.js
@@ -0,0 +1,160 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Tests using various locales to cover all day period types:
+// "midnight", "noon", "morning1", "morning2", "afternoon1", "afternoon2",
+// "evening1", "evening2", "night1", "night2".
+
+const tests = [
+ {
+ // ICU doesn't support "midnight" and instead uses "night1" resp. "night2".
+ // ICU bug: https://unicode-org.atlassian.net/projects/ICU/issues/ICU-12278
+ date: new Date("2019-01-01T00:00:00"),
+ locales: {
+ en: { narrow: "at night", short: "at night", long: "at night" },
+ de: { narrow: "nachts", short: "nachts", long: "nachts" },
+ th: { narrow: "กลางคืน", short: "กลางคืน", long: "กลางคืน" },
+ ja: { narrow: "夜中", short: "夜中", long: "夜中" },
+ }
+ },
+ {
+ date: new Date("2019-01-01T03:00:00"),
+ locales: {
+ en: { narrow: "at night", short: "at night", long: "at night" },
+ de: { narrow: "nachts", short: "nachts", long: "nachts" },
+ th: { narrow: "กลางคืน", short: "กลางคืน", long: "กลางคืน" },
+ ja: { narrow: "夜中", short: "夜中", long: "夜中" },
+ }
+ },
+ {
+ date: new Date("2019-01-01T04:00:00"),
+ locales: {
+ en: { narrow: "at night", short: "at night", long: "at night" },
+ de: { narrow: "nachts", short: "nachts", long: "nachts" },
+ th: { narrow: "กลางคืน", short: "กลางคืน", long: "กลางคืน" },
+ ja: { narrow: "朝", short: "朝", long: "朝" },
+ }
+ },
+ {
+ date: new Date("2019-01-01T05:00:00"),
+ locales: {
+ en: { narrow: "at night", short: "at night", long: "at night" },
+ de: { narrow: "morgens", short: "morgens", long: "morgens" },
+ th: { narrow: "กลางคืน", short: "กลางคืน", long: "กลางคืน" },
+ ja: { narrow: "朝", short: "朝", long: "朝" },
+ }
+ },
+ {
+ date: new Date("2019-01-01T06:00:00"),
+ locales: {
+ en: { narrow: "in the morning", short: "in the morning", long: "in the morning" },
+ de: { narrow: "morgens", short: "morgens", long: "morgens" },
+ th: { narrow: "เช้า", short: "ในตอนเช้า", long: "ในตอนเช้า" },
+ ja: { narrow: "朝", short: "朝", long: "朝" },
+ }
+ },
+ {
+ date: new Date("2019-01-01T10:00:00"),
+ locales: {
+ en: { narrow: "in the morning", short: "in the morning", long: "in the morning" },
+ de: { narrow: "vorm.", short: "vorm.", long: "vormittags" },
+ th: { narrow: "เช้า", short: "ในตอนเช้า", long: "ในตอนเช้า" },
+ ja: { narrow: "朝", short: "朝", long: "朝" },
+ }
+ },
+ {
+ date: new Date("2019-01-01T12:00:00"),
+ locales: {
+ en: { narrow: "n", short: "noon", long: "noon" },
+ de: { narrow: "mittags", short: "mittags", long: "mittags" },
+ th: { narrow: "เที่ยง", short: "เที่ยง", long: "เที่ยง" },
+ ja: { narrow: "正午", short: "正午", long: "正午" },
+ }
+ },
+ {
+ date: new Date("2019-01-01T13:00:00"),
+ locales: {
+ en: { narrow: "in the afternoon", short: "in the afternoon", long: "in the afternoon" },
+ de: { narrow: "nachm.", short: "nachm.", long: "nachmittags" },
+ th: { narrow: "บ่าย", short: "บ่าย", long: "บ่าย" },
+ ja: { narrow: "昼", short: "昼", long: "昼" },
+ }
+ },
+ {
+ date: new Date("2019-01-01T15:00:00"),
+ locales: {
+ en: { narrow: "in the afternoon", short: "in the afternoon", long: "in the afternoon" },
+ de: { narrow: "nachm.", short: "nachm.", long: "nachmittags" },
+ th: { narrow: "บ่าย", short: "บ่าย", long: "บ่าย" },
+ ja: { narrow: "昼", short: "昼", long: "昼" },
+ }
+ },
+ {
+ date: new Date("2019-01-01T16:00:00"),
+ locales: {
+ en: { narrow: "in the afternoon", short: "in the afternoon", long: "in the afternoon" },
+ de: { narrow: "nachm.", short: "nachm.", long: "nachmittags" },
+ th: { narrow: "เย็น", short: "ในตอนเย็น", long: "ในตอนเย็น" },
+ ja: { narrow: "夕方", short: "夕方", long: "夕方" },
+ }
+ },
+ {
+ date: new Date("2019-01-01T18:00:00"),
+ locales: {
+ en: { narrow: "in the evening", short: "in the evening", long: "in the evening" },
+ de: { narrow: "abends", short: "abends", long: "abends" },
+ th: { narrow: "ค่ำ", short: "ค่ำ", long: "ค่ำ" },
+ ja: { narrow: "夕方", short: "夕方", long: "夕方" },
+ }
+ },
+ {
+ date: new Date("2019-01-01T19:00:00"),
+ locales: {
+ en: { narrow: "in the evening", short: "in the evening", long: "in the evening" },
+ de: { narrow: "abends", short: "abends", long: "abends" },
+ th: { narrow: "ค่ำ", short: "ค่ำ", long: "ค่ำ" },
+ ja: { narrow: "夜", short: "夜", long: "夜" },
+ }
+ },
+ {
+ date: new Date("2019-01-01T21:00:00"),
+ locales: {
+ en: { narrow: "at night", short: "at night", long: "at night" },
+ de: { narrow: "abends", short: "abends", long: "abends" },
+ th: { narrow: "กลางคืน", short: "กลางคืน", long: "กลางคืน" },
+ ja: { narrow: "夜", short: "夜", long: "夜" },
+ }
+ },
+ {
+ date: new Date("2019-01-01T22:00:00"),
+ locales: {
+ en: { narrow: "at night", short: "at night", long: "at night" },
+ de: { narrow: "abends", short: "abends", long: "abends" },
+ th: { narrow: "กลางคืน", short: "กลางคืน", long: "กลางคืน" },
+ ja: { narrow: "夜", short: "夜", long: "夜" },
+ }
+ },
+ {
+ date: new Date("2019-01-01T23:00:00"),
+ locales: {
+ en: { narrow: "at night", short: "at night", long: "at night" },
+ de: { narrow: "abends", short: "abends", long: "abends" },
+ th: { narrow: "กลางคืน", short: "กลางคืน", long: "กลางคืน" },
+ ja: { narrow: "夜中", short: "夜中", long: "夜中" },
+ }
+ },
+];
+
+for (let {date, locales} of tests) {
+ for (let [locale, formats] of Object.entries(locales)) {
+ for (let [dayPeriod, expected] of Object.entries(formats)) {
+ let dtf = new Intl.DateTimeFormat(locale, {dayPeriod});
+
+ assertEq(dtf.format(date), expected,
+ `locale=${locale}, date=${date}, dayPeriod=${dayPeriod}`);
+ assertDeepEq(dtf.formatToParts(date), [{type: "dayPeriod", value: expected}]);
+ }
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/day-period.js b/js/src/tests/non262/Intl/DateTimeFormat/day-period.js
new file mode 100644
index 0000000000..486970e519
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/day-period.js
@@ -0,0 +1,40 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const {
+ Weekday, DayPeriod, Literal
+} = DateTimeFormatParts;
+
+const tests = [
+ // https://unicode-org.atlassian.net/browse/ICU-20741
+ {
+ date: new Date("2019-01-01T12:00:00"),
+ options: { dayPeriod: "long", weekday: "long", },
+ locales: {
+ "en-001": [Weekday("Tuesday"), Literal(", "), DayPeriod("noon")],
+ },
+ },
+
+ // https://unicode-org.atlassian.net/browse/ICU-20740
+ {
+ date: new Date("2019-01-01T12:00:00"),
+ options: { dayPeriod: "narrow", weekday: "long", },
+ locales: {
+ "bs-Cyrl": [Weekday("уторак"), Literal(" "), DayPeriod("подне")],
+ },
+ },
+];
+
+for (let {date, options, locales} of tests) {
+ for (let [locale, parts] of Object.entries(locales)) {
+ let dtf = new Intl.DateTimeFormat(locale, options);
+
+ assertEq(dtf.format(date), parts.map(({value}) => value).join(""),
+ `locale=${locale}, date=${date}, options=${JSON.stringify(options)}`);
+
+ assertDeepEq(dtf.formatToParts(date), parts,
+ `locale=${locale}, date=${date}, options=${JSON.stringify(options)}`);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/era.js b/js/src/tests/non262/Intl/DateTimeFormat/era.js
new file mode 100644
index 0000000000..716fa2cf0d
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/era.js
@@ -0,0 +1,245 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const {
+ Era, Year, Month, Day, Literal
+} = DateTimeFormatParts;
+
+const tests = {
+ "en": [
+ {
+ options: {
+ day: "numeric",
+ month: "numeric",
+ year: "numeric",
+ era: "short",
+ timeZone: "UTC",
+ },
+ dates: [
+ {
+ date: new Date("1970-01-01T00:00:00.000Z"),
+ parts: [
+ Month("1"), Literal("/"), Day("1"), Literal("/"), Year("1970"), Literal(" "), Era("AD")
+ ],
+ },
+ {
+ date: new Date("-001970-01-01T00:00:00.000Z"),
+ parts: [
+ Month("1"), Literal("/"), Day("1"), Literal("/"), Year("1971"), Literal(" "), Era("BC")
+ ],
+ },
+ ],
+ },
+ ],
+ "en-001": [
+ {
+ options: {
+ day: "numeric",
+ month: "numeric",
+ year: "numeric",
+ era: "short",
+ timeZone: "UTC",
+ },
+ dates: [
+ {
+ date: new Date("1970-01-01T00:00:00.000Z"),
+ parts: [
+ Day("1"), Literal("/"), Month("1"), Literal("/"), Year("1970"), Literal(" "), Era("AD")
+ ],
+ },
+ {
+ date: new Date("-001970-01-01T00:00:00.000Z"),
+ parts: [
+ Day("1"), Literal("/"), Month("1"), Literal("/"), Year("1971"), Literal(" "), Era("BC")
+ ],
+ },
+ ],
+ },
+ ],
+ "de": [
+ {
+ options: {
+ day: "numeric",
+ month: "numeric",
+ year: "numeric",
+ era: "short",
+ timeZone: "UTC",
+ },
+ dates: [
+ {
+ date: new Date("1970-01-01T00:00:00.000Z"),
+ parts: [
+ Day("01"), Literal("."), Month("01"), Literal("."), Year("1970"), Literal(" "), Era("n. Chr.")
+ ],
+ },
+ {
+ date: new Date("-001970-01-01T00:00:00.000Z"),
+ parts: [
+ Day("01"), Literal("."), Month("01"), Literal("."), Year("1971"), Literal(" "), Era("v. Chr.")
+ ],
+ },
+ ],
+ },
+ ],
+ "fr": [
+ {
+ options: {
+ day: "numeric",
+ month: "numeric",
+ year: "numeric",
+ era: "short",
+ timeZone: "UTC",
+ },
+ dates: [
+ {
+ date: new Date("1970-01-01T00:00:00.000Z"),
+ parts: [
+ Day("01"), Literal("/"), Month("01"), Literal("/"), Year("1970"), Literal(" "), Era("ap. J.-C.")
+ ],
+ },
+ {
+ date: new Date("-001970-01-01T00:00:00.000Z"),
+ parts: [
+ Day("01"), Literal("/"), Month("01"), Literal("/"), Year("1971"), Literal(" "), Era("av. J.-C.")
+ ],
+ },
+ ],
+ },
+ ],
+ "es": [
+ {
+ options: {
+ day: "numeric",
+ month: "numeric",
+ year: "numeric",
+ era: "short",
+ timeZone: "UTC",
+ },
+ dates: [
+ {
+ date: new Date("1970-01-01T00:00:00.000Z"),
+ parts: [
+ Day("1"), Literal("/"), Month("1"), Literal("/"), Year("1970"), Literal(" "), Era("d. C.")
+ ],
+ },
+ {
+ date: new Date("-001970-01-01T00:00:00.000Z"),
+ parts: [
+ Day("1"), Literal("/"), Month("1"), Literal("/"), Year("1971"), Literal(" "), Era("a. C.")
+ ],
+ },
+ ],
+ },
+ ],
+ "nl": [
+ {
+ options: {
+ day: "numeric",
+ month: "numeric",
+ year: "numeric",
+ era: "short",
+ timeZone: "UTC",
+ },
+ dates: [
+ {
+ date: new Date("1970-01-01T00:00:00.000Z"),
+ parts: [
+ Day("1"), Literal("/"), Month("1"), Literal("/"), Year("1970"), Literal(" "), Era("n.Chr.")
+ ],
+ },
+ {
+ date: new Date("-001970-01-01T00:00:00.000Z"),
+ parts: [
+ Day("1"), Literal("/"), Month("1"), Literal("/"), Year("1971"), Literal(" "), Era("v.Chr.")
+ ],
+ },
+ ],
+ },
+ ],
+ "ja": [
+ {
+ options: {
+ day: "numeric",
+ month: "numeric",
+ year: "numeric",
+ era: "short",
+ timeZone: "UTC",
+ },
+ dates: [
+ {
+ date: new Date("1970-01-01T00:00:00.000Z"),
+ parts: [
+ Era("西暦"), Year("1970"), Literal("/"), Month("1"), Literal("/"), Day("1")
+ ],
+ },
+ {
+ date: new Date("-001970-01-01T00:00:00.000Z"),
+ parts: [
+ Era("紀元前"), Year("1971"), Literal("/"), Month("1"), Literal("/"), Day("1")
+ ],
+ },
+ ],
+ },
+ ],
+ "zh": [
+ {
+ options: {
+ day: "numeric",
+ month: "numeric",
+ year: "numeric",
+ era: "short",
+ timeZone: "UTC",
+ },
+ dates: [
+ {
+ date: new Date("1970-01-01T00:00:00.000Z"),
+ parts: [
+ Era("公元"), Literal(" "), Year("1970"), Literal("-"), Month("01"), Literal("-"), Day("01")
+ ],
+ },
+ {
+ date: new Date("-001970-01-01T00:00:00.000Z"),
+ parts: [
+ Era("公元前"), Literal(" "), Year("1971"), Literal("-"), Month("01"), Literal("-"), Day("01")
+ ],
+ },
+ ],
+ },
+ ],
+ "ar": [
+ {
+ options: {
+ day: "numeric",
+ month: "numeric",
+ year: "numeric",
+ era: "short",
+ timeZone: "UTC",
+ },
+ dates: [
+ {
+ date: new Date("1970-01-01T00:00:00.000Z"),
+ parts: [
+ Day("٠١"), Literal("-"), Month("٠١"), Literal("-"), Year("١٩٧٠"), Literal(" "), Era("م")
+ ],
+ },
+ {
+ date: new Date("-001970-01-01T00:00:00.000Z"),
+ parts: [
+ Day("٠١"), Literal("-"), Month("٠١"), Literal("-"), Year("١٩٧١"), Literal(" "), Era("ق.م")
+ ],
+ },
+ ],
+ },
+ ],
+};
+
+for (let [locale, inputs] of Object.entries(tests)) {
+ for (let {options, dates} of inputs) {
+ let dtf = new Intl.DateTimeFormat(locale, options);
+ for (let {date, parts} of dates) {
+ assertParts(dtf, date, parts);
+ }
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/extended-time-zone-names.js b/js/src/tests/non262/Intl/DateTimeFormat/extended-time-zone-names.js
new file mode 100644
index 0000000000..12090c4119
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/extended-time-zone-names.js
@@ -0,0 +1,124 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const tests = {
+ "America/Los_Angeles": {
+ date: Date.UTC(2021, 5-1, 20, 12, 0, 0),
+ timeZoneName: "longGeneric",
+ locales: {
+ "en": "5/20/2021, Pacific Time",
+ "de": "20.5.2021, Nordamerikanische Westküstenzeit",
+ "fr": "20/05/2021 à heure du Pacifique nord-américain",
+ "ar": "٢٠‏/٥‏/٢٠٢١ توقيت المحيط الهادي",
+ "th": "20/5/2564 เวลาแปซิฟิกในอเมริกาเหนือ",
+ "zh": "2021/5/20 北美太平洋时间",
+ "ja": "2021/5/20 アメリカ太平洋時間",
+ }
+ },
+ "America/Los_Angeles": {
+ date: Date.UTC(2021, 5-1, 20, 12, 0, 0),
+ timeZoneName: "shortGeneric",
+ locales: {
+ "en": "5/20/2021, PT",
+ "de": "20.5.2021, Los Angeles Zeit",
+ "fr": "20/05/2021 à heure : Los Angeles",
+ "ar": "٢٠‏/٥‏/٢٠٢١ توقيت Los Angeles",
+ "th": "20/5/2564 เวลาLos Angeles",
+ "zh": "2021/5/20 Los Angeles时间",
+ "ja": "2021/5/20 Los Angeles時間",
+ }
+ },
+ "America/Los_Angeles": {
+ date: Date.UTC(2021, 5-1, 20, 12, 0, 0),
+ timeZoneName: "longOffset",
+ locales: {
+ "en": "5/20/2021, GMT-07:00",
+ "de": "20.5.2021, GMT-07:00",
+ "fr": "20/05/2021 à UTC−07:00",
+ "ar": "٢٠‏/٥‏/٢٠٢١ غرينتش-٠٧:٠٠",
+ "th": "20/5/2564 GMT-07:00",
+ "zh": "2021/5/20 GMT-07:00",
+ "ja": "2021/5/20 GMT-07:00",
+ }
+ },
+ "America/Los_Angeles": {
+ date: Date.UTC(2021, 5-1, 20, 12, 0, 0),
+ timeZoneName: "shortOffset",
+ locales: {
+ "en": "5/20/2021, GMT-7",
+ "de": "20.5.2021, GMT-7",
+ "fr": "20/05/2021 UTC−7",
+ "ar": "٢٠‏/٥‏/٢٠٢١، غرينتش-٧",
+ "th": "20/5/2564 GMT-7",
+ "zh": "2021/5/20 GMT-7",
+ "ja": "2021/5/20 GMT-7",
+ }
+ },
+ "Europe/Berlin": {
+ date: Date.UTC(2021, 5-1, 20, 12, 0, 0),
+ timeZoneName: "longGeneric",
+ locales: {
+ "en": "5/20/2021, Central European Time",
+ "de": "20.5.2021, Mitteleuropäische Zeit",
+ "fr": "20/05/2021 à heure d’Europe centrale",
+ "ar": "٢٠‏/٥‏/٢٠٢١ توقيت وسط أوروبا",
+ "th": "20/5/2564 เวลายุโรปกลาง",
+ "zh": "2021/5/20 中欧时间",
+ "ja": "2021/5/20 中央ヨーロッパ時間",
+ }
+ },
+ "Europe/Berlin": {
+ date: Date.UTC(2021, 5-1, 20, 12, 0, 0),
+ timeZoneName: "shortGeneric",
+ locales: {
+ "en": "5/20/2021, Germany Time",
+ "de": "20.5.2021, MEZ",
+ "fr": "20/05/2021 heure : Allemagne",
+ "ar": "٢٠‏/٥‏/٢٠٢١، توقيت ألمانيا",
+ "th": "20/5/2564 เวลาเยอรมนี",
+ "zh": "2021/5/20 德国时间",
+ "ja": "2021/5/20 ドイツ時間",
+ }
+ },
+ "Africa/Monrovia": {
+ date: Date.UTC(1971, 12-1, 6, 12, 0, 0),
+ timeZoneName: "longOffset",
+ locales: {
+ "en": "12/6/1971, GMT-00:44:30",
+ "de": "6.12.1971, GMT-00:44:30",
+ "fr": "06/12/1971 UTC−00:44:30",
+ "ar": "٦‏/١٢‏/١٩٧١ غرينتش-٠٠:٤٤:٣٠",
+ "th": "6/12/2514 GMT-00:44:30",
+ "zh": "1971/12/6 GMT-00:44:30",
+ "ja": "1971/12/6 GMT-00:44:30",
+ }
+ },
+ "Africa/Monrovia": {
+ date: Date.UTC(1971, 12-1, 6, 12, 0, 0),
+ timeZoneName: "shortOffset",
+ locales: {
+ "en": "12/6/1971, GMT-0:44:30",
+ "de": "6.12.1971, GMT-0:44:30",
+ "fr": "06/12/1971 UTC−0:44:30",
+ "ar": "٦‏/١٢‏/١٩٧١، غرينتش-٠:٤٤:٣٠",
+ "th": "6/12/2514 GMT-0:44:30",
+ "zh": "1971/12/6 GMT-0:44:30",
+ "ja": "1971/12/6 GMT-0:44:30",
+ }
+ },
+};
+
+for (let [timeZone, {timeZoneName, date, locales}] of Object.entries(tests)) {
+ for (let [locale, expected] of Object.entries(locales)) {
+ let dtf = new Intl.DateTimeFormat(locale, {timeZone, timeZoneName});
+ assertEq(dtf.format(date), expected);
+
+ let parts = dtf.formatToParts(date);
+ assertEq(parts.map(p => p.value).join(""), expected);
+ assertEq(parts.filter(p => p.type === "timeZoneName").length, 1);
+
+ assertEq(dtf.resolvedOptions().timeZoneName, timeZoneName);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/field-widths.js b/js/src/tests/non262/Intl/DateTimeFormat/field-widths.js
new file mode 100644
index 0000000000..789d0fdaa6
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/field-widths.js
@@ -0,0 +1,225 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const date = new Date(Date.UTC(2021, 1-1, 2, 3, 4, 5, 678));
+
+const tests = [
+ // Standalone 'hour' field.
+ {
+ options: {
+ hour: "numeric",
+ },
+ locales: {
+ "en": "3 AM",
+ "de": "03 Uhr",
+ },
+ },
+ {
+ options: {
+ hour: "2-digit",
+ },
+ locales: {
+ "en": "03 AM",
+ "de": "03 Uhr",
+ },
+ },
+
+ // Standalone 'minute' field.
+ {
+ options: {
+ minute: "numeric",
+ },
+ locales: {
+ "en": "4",
+ "de": "4",
+ },
+ },
+ {
+ options: {
+ minute: "2-digit",
+ },
+ locales: {
+ "en": "04",
+ "de": "04",
+ },
+ },
+
+ // Standalone 'second' field.
+ {
+ options: {
+ second: "numeric",
+ },
+ locales: {
+ "en": "5",
+ "de": "5",
+ },
+ },
+ {
+ options: {
+ second: "2-digit",
+ },
+ locales: {
+ "en": "05",
+ "de": "05",
+ },
+ },
+
+ // 'hour' and 'minute' fields with all possible field width combinations.
+ {
+ options: {
+ hour: "numeric",
+ minute: "numeric",
+ },
+ locales: {
+ "en": "3:04 AM",
+ "de": "03:04",
+ },
+ },
+ {
+ options: {
+ hour: "numeric",
+ minute: "2-digit",
+ },
+ locales: {
+ "en": "3:04 AM",
+ "de": "03:04",
+ },
+ },
+ {
+ options: {
+ hour: "2-digit",
+ minute: "numeric",
+ },
+ locales: {
+ "en": "03:04 AM",
+ "de": "03:04",
+ },
+ },
+ {
+ options: {
+ hour: "2-digit",
+ minute: "2-digit",
+ },
+ locales: {
+ "en": "03:04 AM",
+ "de": "03:04",
+ },
+ },
+
+ // 'minute' and 'second' fields with all possible field width combinations.
+ {
+ options: {
+ minute: "numeric",
+ second: "numeric",
+ },
+ locales: {
+ "en": "04:05",
+ "de": "04:05",
+ },
+ },
+ {
+ options: {
+ minute: "numeric",
+ second: "2-digit",
+ },
+ locales: {
+ "en": "04:05",
+ "de": "04:05",
+ },
+ },
+ {
+ options: {
+ minute: "2-digit",
+ second: "numeric",
+ },
+ locales: {
+ "en": "04:05",
+ "de": "04:05",
+ },
+ },
+ {
+ options: {
+ minute: "2-digit",
+ second: "2-digit",
+ },
+ locales: {
+ "en": "04:05",
+ "de": "04:05",
+ },
+ },
+
+ // Test 'hour' and 'minute' with 'hourCycle=h12'.
+ {
+ options: {
+ hour: "numeric",
+ minute: "numeric",
+ hourCycle: "h12",
+ },
+ locales: {
+ "en": "3:04 AM",
+ "de": "3:04 AM",
+ },
+ },
+ {
+ options: {
+ hour: "2-digit",
+ minute: "2-digit",
+ hourCycle: "h12",
+ },
+ locales: {
+ "en": "03:04 AM",
+ "de": "03:04 AM",
+ },
+ },
+
+ // Test 'hour' and 'minute' with 'hourCycle=h23'.
+ {
+ options: {
+ hour: "numeric",
+ minute: "numeric",
+ hourCycle: "h23",
+ },
+ locales: {
+ "en": "03:04",
+ "de": "03:04",
+ },
+ },
+ {
+ options: {
+ hour: "2-digit",
+ minute: "2-digit",
+ hourCycle: "h23",
+ },
+ locales: {
+ "en": "03:04",
+ "de": "03:04",
+ },
+ },
+];
+
+for (let {options, locales} of tests) {
+ for (let [locale, expected] of Object.entries(locales)) {
+ let dtf = new Intl.DateTimeFormat(locale, {timeZone: "UTC", ...options});
+ assertEq(dtf.format(date), expected);
+ }
+}
+
+const toLocaleTests = {
+ "en": "1/2/2021, 3:04:05 AM",
+ "de": "2.1.2021, 03:04:05",
+};
+
+for (let [locale, expected] of Object.entries(toLocaleTests)) {
+ assertEq(date.toLocaleString(locale, {timeZone: "UTC"}), expected);
+}
+
+const toLocaleTimeTests = {
+ "en": "3:04:05 AM",
+ "de": "03:04:05",
+};
+
+for (let [locale, expected] of Object.entries(toLocaleTimeTests)) {
+ assertEq(date.toLocaleTimeString(locale, {timeZone: "UTC"}), expected);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/format.js b/js/src/tests/non262/Intl/DateTimeFormat/format.js
new file mode 100644
index 0000000000..224d19cfa8
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/format.js
@@ -0,0 +1,47 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests the format function with a diverse set of locales and options.
+// Always use UTC to avoid dependencies on test environment.
+
+var format;
+var date = Date.UTC(2012, 11, 12, 3, 0, 0);
+var longFormatOptions = {timeZone: "UTC",
+ year: "numeric", month: "long", day: "numeric",
+ hour: "numeric", minute: "numeric", second: "numeric"};
+
+// Locale en-US; default options.
+format = new Intl.DateTimeFormat("en-us", {timeZone: "UTC"});
+assertEq(format.format(date), "12/12/2012");
+
+// Locale th-TH; default options.
+// Thailand uses the Buddhist calendar.
+format = new Intl.DateTimeFormat("th-th", {timeZone: "UTC"});
+assertEq(format.format(date), "12/12/2555");
+
+// Locale th-TH; long format, Thai digits.
+format = new Intl.DateTimeFormat("th-th-u-nu-thai", longFormatOptions);
+assertEq(format.format(date), "๑๒ ธันวาคม ๒๕๕๕ เวลา ๐๓:๐๐:๐๐");
+
+// Locale ja-JP; long format.
+format = new Intl.DateTimeFormat("ja-jp", longFormatOptions);
+assertEq(format.format(date), "2012年12月12日 3:00:00");
+
+// Locale ar-MA; long format, Islamic civilian calendar.
+format = new Intl.DateTimeFormat("ar-ma-u-ca-islamicc", longFormatOptions);
+assertEq(format.format(date), "28 محرم 1434 هـ في 03:00:00");
+
+// Locale en-IE: timeZoneName for crash test
+format = new Intl.DateTimeFormat("en-IE", {timeZone: "UTC", timeZoneName: "short"});
+assertEq(format.format(date), "12/12/2012, UTC");
+
+// Test the .name property of the "format" getter.
+var desc = Object.getOwnPropertyDescriptor(Intl.DateTimeFormat.prototype, "format");
+assertEq(desc !== undefined, true);
+assertEq(typeof desc.get, "function");
+assertEq(desc.get.name, "get format");
+
+
+reportCompare(0, 0, 'ok');
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/formatRange-gregorian-proleptic.js b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-gregorian-proleptic.js
new file mode 100644
index 0000000000..9356577b47
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-gregorian-proleptic.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Ensure formatRange() uses a proleptic Gregorian calendar.
+// ICU bug: https://unicode-org.atlassian.net/browse/ICU-20705
+
+let dtf = new Intl.DateTimeFormat("en", {timeZone: "UTC"});
+
+// The Gregorian calendar was first introduced in 15 October 1582.
+const firstGregorian = new Date("1582-10-15");
+assertEq(dtf.formatRange(firstGregorian, firstGregorian), dtf.format(firstGregorian));
+
+// To deal with the ten days' difference between the Julian and the Gregorian calendar, some days
+// were skipped, so that 4 October 1582 was followed by 15 October 1582.
+const lastJulian = new Date("1582-10-04");
+assertEq(dtf.formatRange(lastJulian, lastJulian), dtf.format(lastJulian));
+
+function rangePart(source, parts) {
+ return parts.filter(x => x.source === source).map(x => x.value).join("");
+}
+
+// Test with non-empty range.
+assertEq(rangePart("startRange", dtf.formatRangeToParts(lastJulian, firstGregorian)),
+ dtf.format(lastJulian));
+assertEq(rangePart("endRange", dtf.formatRangeToParts(lastJulian, firstGregorian)),
+ dtf.format(firstGregorian));
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/formatRange-hour-cycle.js b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-hour-cycle.js
new file mode 100644
index 0000000000..7921f502cc
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-hour-cycle.js
@@ -0,0 +1,450 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Test formatRange supports the different hour-cycle options.
+//
+// ICU bugs:
+// https://unicode-org.atlassian.net/browse/ICU-21154
+// https://unicode-org.atlassian.net/browse/ICU-21155
+// https://unicode-org.atlassian.net/browse/ICU-21156
+// https://unicode-org.atlassian.net/browse/ICU-21342
+// https://unicode-org.atlassian.net/browse/ICU-21343
+
+// Test locales which default to a 12-hour and a 24-hour clock.
+
+let tests = {
+ "en": [
+ // Midnight to morning.
+ {
+ start: 0,
+ end: 10,
+ data: [
+ "12 – 10 AM",
+ "0 – 10 AM",
+ "12 – 10 AM",
+ "00 – 10",
+ "24 – 10",
+ ],
+ },
+ // Midnight to noon.
+ {
+ start: 0,
+ end: 12,
+ data: [
+ "12 AM – 12 PM",
+ "0 AM – 0 PM",
+ "12 AM – 12 PM",
+ "00 – 12",
+ "24 – 12",
+ ],
+ },
+ // Midnight to evening.
+ {
+ start: 0,
+ end: 22,
+ data: [
+ "12 AM – 10 PM",
+ "0 AM – 10 PM",
+ "12 AM – 10 PM",
+ "00 – 22",
+ "24 – 22",
+ ],
+ },
+ // Midnight to midnight.
+ {
+ start: 0,
+ end: 24,
+ data: [
+ "1/1/1970, 12 AM – 1/2/1970, 12 AM",
+ "1/1/1970, 0 AM – 1/2/1970, 0 AM",
+ "1/1/1970, 12 AM – 1/2/1970, 12 AM",
+ "1/1/1970, 00 – 1/2/1970, 00",
+ "1/1/1970, 24 – 1/2/1970, 24",
+ ],
+ },
+
+ // Morning to morning.
+ {
+ start: 1,
+ end: 10,
+ data: [
+ "1 – 10 AM",
+ "1 – 10 AM",
+ "1 – 10 AM",
+ "01 – 10",
+ "01 – 10",
+ ],
+ },
+ // Morning to noon.
+ {
+ start: 1,
+ end: 12,
+ data: [
+ "1 AM – 12 PM",
+ "1 AM – 0 PM",
+ "1 AM – 12 PM",
+ "01 – 12",
+ "01 – 12",
+ ],
+ },
+ // Morning to evening.
+ {
+ start: 1,
+ end: 22,
+ data: [
+ "1 AM – 10 PM",
+ "1 AM – 10 PM",
+ "1 AM – 10 PM",
+ "01 – 22",
+ "01 – 22",
+ ],
+ },
+ // Morning to midnight.
+ {
+ start: 1,
+ end: 24,
+ data: [
+ "1/1/1970, 1 AM – 1/2/1970, 12 AM",
+ "1/1/1970, 1 AM – 1/2/1970, 0 AM",
+ "1/1/1970, 1 AM – 1/2/1970, 12 AM",
+ "1/1/1970, 01 – 1/2/1970, 00",
+ "1/1/1970, 01 – 1/2/1970, 24",
+ ],
+ },
+
+ // Noon to morning.
+ {
+ start: 12,
+ end: 24 + 1,
+ data: [
+ "1/1/1970, 12 PM – 1/2/1970, 1 AM",
+ "1/1/1970, 0 PM – 1/2/1970, 1 AM",
+ "1/1/1970, 12 PM – 1/2/1970, 1 AM",
+ "1/1/1970, 12 – 1/2/1970, 01",
+ "1/1/1970, 12 – 1/2/1970, 01",
+ ],
+ },
+ // Noon to noon.
+ {
+ start: 12,
+ end: 24 + 12,
+ data: [
+ "1/1/1970, 12 PM – 1/2/1970, 12 PM",
+ "1/1/1970, 0 PM – 1/2/1970, 0 PM",
+ "1/1/1970, 12 PM – 1/2/1970, 12 PM",
+ "1/1/1970, 12 – 1/2/1970, 12",
+ "1/1/1970, 12 – 1/2/1970, 12",
+ ],
+ },
+ // Noon to evening.
+ {
+ start: 12,
+ end: 22,
+ data: [
+ "12 – 10 PM",
+ "0 – 10 PM",
+ "12 – 10 PM",
+ "12 – 22",
+ "12 – 22",
+ ],
+ },
+ // Noon to midnight.
+ {
+ start: 12,
+ end: 24,
+ data: [
+ "1/1/1970, 12 PM – 1/2/1970, 12 AM",
+ "1/1/1970, 0 PM – 1/2/1970, 0 AM",
+ "1/1/1970, 12 PM – 1/2/1970, 12 AM",
+ "1/1/1970, 12 – 1/2/1970, 00",
+ "1/1/1970, 12 – 1/2/1970, 24",
+ ],
+ },
+
+ // Evening to morning.
+ {
+ start: 22,
+ end: 24 + 1,
+ data: [
+ "1/1/1970, 10 PM – 1/2/1970, 1 AM",
+ "1/1/1970, 10 PM – 1/2/1970, 1 AM",
+ "1/1/1970, 10 PM – 1/2/1970, 1 AM",
+ "1/1/1970, 22 – 1/2/1970, 01",
+ "1/1/1970, 22 – 1/2/1970, 01",
+ ],
+ },
+ // Evening to noon.
+ {
+ start: 22,
+ end: 24 + 12,
+ data: [
+ "1/1/1970, 10 PM – 1/2/1970, 12 PM",
+ "1/1/1970, 10 PM – 1/2/1970, 0 PM",
+ "1/1/1970, 10 PM – 1/2/1970, 12 PM",
+ "1/1/1970, 22 – 1/2/1970, 12",
+ "1/1/1970, 22 – 1/2/1970, 12",
+ ],
+ },
+ // Evening to evening.
+ {
+ start: 22,
+ end: 23,
+ data: [
+ "10 – 11 PM",
+ "10 – 11 PM",
+ "10 – 11 PM",
+ "22 – 23",
+ "22 – 23",
+ ],
+ },
+ // Evening to midnight.
+ {
+ start: 22,
+ end: 24,
+ data: [
+ "1/1/1970, 10 PM – 1/2/1970, 12 AM",
+ "1/1/1970, 10 PM – 1/2/1970, 0 AM",
+ "1/1/1970, 10 PM – 1/2/1970, 12 AM",
+ "1/1/1970, 22 – 1/2/1970, 00",
+ "1/1/1970, 22 – 1/2/1970, 24",
+ ],
+ },
+ ],
+
+ "de": [
+ // Midnight to morning.
+ {
+ start: 0,
+ end: 10,
+ data: [
+ "00–10 Uhr",
+ "0 – 10 Uhr AM",
+ "12 – 10 Uhr AM",
+ "00–10 Uhr",
+ "24–10 Uhr",
+ ],
+ },
+ // Midnight to noon.
+ {
+ start: 0,
+ end: 12,
+ data: [
+ "00–12 Uhr",
+ "0 Uhr AM – 0 Uhr PM",
+ "12 Uhr AM – 12 Uhr PM",
+ "00–12 Uhr",
+ "24–12 Uhr",
+ ],
+ },
+ // Midnight to evening.
+ {
+ start: 0,
+ end: 22,
+ data: [
+ "00–22 Uhr",
+ "0 Uhr AM – 10 Uhr PM",
+ "12 Uhr AM – 10 Uhr PM",
+ "00–22 Uhr",
+ "24–22 Uhr",
+ ],
+ },
+ // Midnight to midnight.
+ {
+ start: 0,
+ end: 24,
+ data: [
+ "1.1.1970, 00 Uhr – 2.1.1970, 00 Uhr",
+ "1.1.1970, 0 Uhr AM – 2.1.1970, 0 Uhr AM",
+ "1.1.1970, 12 Uhr AM – 2.1.1970, 12 Uhr AM",
+ "1.1.1970, 00 Uhr – 2.1.1970, 00 Uhr",
+ "1.1.1970, 24 Uhr – 2.1.1970, 24 Uhr",
+ ],
+ },
+
+ // Morning to morning.
+ {
+ start: 1,
+ end: 10,
+ data: [
+ "01–10 Uhr",
+ "1 – 10 Uhr AM",
+ "1 – 10 Uhr AM",
+ "01–10 Uhr",
+ "01–10 Uhr",
+ ],
+ },
+ // Morning to noon.
+ {
+ start: 1,
+ end: 12,
+ data: [
+ "01–12 Uhr",
+ "1 Uhr AM – 0 Uhr PM",
+ "1 Uhr AM – 12 Uhr PM",
+ "01–12 Uhr",
+ "01–12 Uhr",
+ ],
+ },
+ // Morning to evening.
+ {
+ start: 1,
+ end: 22,
+ data: [
+ "01–22 Uhr",
+ "1 Uhr AM – 10 Uhr PM",
+ "1 Uhr AM – 10 Uhr PM",
+ "01–22 Uhr",
+ "01–22 Uhr",
+ ],
+ },
+ // Morning to midnight.
+ {
+ start: 1,
+ end: 24,
+ data: [
+ "1.1.1970, 01 Uhr – 2.1.1970, 00 Uhr",
+ "1.1.1970, 1 Uhr AM – 2.1.1970, 0 Uhr AM",
+ "1.1.1970, 1 Uhr AM – 2.1.1970, 12 Uhr AM",
+ "1.1.1970, 01 Uhr – 2.1.1970, 00 Uhr",
+ "1.1.1970, 01 Uhr – 2.1.1970, 24 Uhr",
+ ],
+ },
+
+ // Noon to morning.
+ {
+ start: 12,
+ end: 24 + 1,
+ data: [
+ "1.1.1970, 12 Uhr – 2.1.1970, 01 Uhr",
+ "1.1.1970, 0 Uhr PM – 2.1.1970, 1 Uhr AM",
+ "1.1.1970, 12 Uhr PM – 2.1.1970, 1 Uhr AM",
+ "1.1.1970, 12 Uhr – 2.1.1970, 01 Uhr",
+ "1.1.1970, 12 Uhr – 2.1.1970, 01 Uhr",
+ ],
+ },
+ // Noon to noon.
+ {
+ start: 12,
+ end: 24 + 12,
+ data: [
+ "1.1.1970, 12 Uhr – 2.1.1970, 12 Uhr",
+ "1.1.1970, 0 Uhr PM – 2.1.1970, 0 Uhr PM",
+ "1.1.1970, 12 Uhr PM – 2.1.1970, 12 Uhr PM",
+ "1.1.1970, 12 Uhr – 2.1.1970, 12 Uhr",
+ "1.1.1970, 12 Uhr – 2.1.1970, 12 Uhr",
+ ],
+ },
+ // Noon to evening.
+ {
+ start: 12,
+ end: 22,
+ data: [
+ "12–22 Uhr",
+ "0 – 10 Uhr PM",
+ "12 – 10 Uhr PM",
+ "12–22 Uhr",
+ "12–22 Uhr",
+ ],
+ },
+ // Noon to midnight.
+ {
+ start: 12,
+ end: 24,
+ data: [
+ "1.1.1970, 12 Uhr – 2.1.1970, 00 Uhr",
+ "1.1.1970, 0 Uhr PM – 2.1.1970, 0 Uhr AM",
+ "1.1.1970, 12 Uhr PM – 2.1.1970, 12 Uhr AM",
+ "1.1.1970, 12 Uhr – 2.1.1970, 00 Uhr",
+ "1.1.1970, 12 Uhr – 2.1.1970, 24 Uhr",
+ ],
+ },
+
+ // Evening to morning.
+ {
+ start: 22,
+ end: 24 + 1,
+ data: [
+ "1.1.1970, 22 Uhr – 2.1.1970, 01 Uhr",
+ "1.1.1970, 10 Uhr PM – 2.1.1970, 1 Uhr AM",
+ "1.1.1970, 10 Uhr PM – 2.1.1970, 1 Uhr AM",
+ "1.1.1970, 22 Uhr – 2.1.1970, 01 Uhr",
+ "1.1.1970, 22 Uhr – 2.1.1970, 01 Uhr",
+ ],
+ },
+ // Evening to noon.
+ {
+ start: 22,
+ end: 24 + 12,
+ data: [
+ "1.1.1970, 22 Uhr – 2.1.1970, 12 Uhr",
+ "1.1.1970, 10 Uhr PM – 2.1.1970, 0 Uhr PM",
+ "1.1.1970, 10 Uhr PM – 2.1.1970, 12 Uhr PM",
+ "1.1.1970, 22 Uhr – 2.1.1970, 12 Uhr",
+ "1.1.1970, 22 Uhr – 2.1.1970, 12 Uhr",
+ ],
+ },
+ // Evening to evening.
+ {
+ start: 22,
+ end: 23,
+ data: [
+ "22–23 Uhr",
+ "10 – 11 Uhr PM",
+ "10 – 11 Uhr PM",
+ "22–23 Uhr",
+ "22–23 Uhr",
+ ],
+ },
+ // Evening to midnight.
+ {
+ start: 22,
+ end: 24,
+ data: [
+ "1.1.1970, 22 Uhr – 2.1.1970, 00 Uhr",
+ "1.1.1970, 10 Uhr PM – 2.1.1970, 0 Uhr AM",
+ "1.1.1970, 10 Uhr PM – 2.1.1970, 12 Uhr AM",
+ "1.1.1970, 22 Uhr – 2.1.1970, 00 Uhr",
+ "1.1.1970, 22 Uhr – 2.1.1970, 24 Uhr",
+ ],
+ },
+ ],
+};
+
+const hourCycles = [undefined, "h11", "h12", "h23", "h24"];
+const hour12Values = [true, false];
+const options = {hour: "2-digit", timeZone: "UTC"};
+const hourToMillis = 60 * 60 * 1000;
+
+for (let [locale, test] of Object.entries(tests)) {
+ // Find the matching hourCycle for each hour12 value.
+ let hour12Cycles = hour12Values.map(hour12 => {
+ let {hourCycle} = new Intl.DateTimeFormat(locale, {...options, hour12}).resolvedOptions();
+ return hourCycles.indexOf(hourCycle);
+ });
+
+ for (let {start, end, data} of Object.values(test)) {
+ assertEq(data.length, hourCycles.length);
+
+ // Test all possible "hourCycle" values, including |undefined|.
+ for (let i = 0; i < hourCycles.length; i++) {
+ let hourCycle = hourCycles[i];
+ let expected = data[i];
+ let dtf = new Intl.DateTimeFormat(locale, {...options, hourCycle});
+
+ assertEq(dtf.formatRange(start * hourToMillis, end * hourToMillis), expected,
+ `hourCycle: ${hourCycle}`);
+ }
+
+ // Test all possible "hour12" values.
+ for (let i = 0; i < hour12Values.length; i++) {
+ let hour12 = hour12Values[i];
+ let dtf = new Intl.DateTimeFormat(locale, {...options, hour12});
+ let expected = data[hour12Cycles[i]];
+
+ assertEq(dtf.formatRange(start * hourToMillis, end * hourToMillis), expected,
+ `hour12: ${hour12}`);
+ }
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/formatRange-matches-format-output.js b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-matches-format-output.js
new file mode 100644
index 0000000000..67cebd1843
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-matches-format-output.js
@@ -0,0 +1,58 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// formatRange() returns the same output as format() when the date-time difference between
+// the start and end date is too small.
+
+// Test case when skeleton can't be retrieved from resolved pattern (bug 1298794).
+// - Best-fit pattern for the skeleton "MMMMMdd" is "M月dd日".
+// - Best-fit pattern for the skeleton "Mdd" is "M/dd".
+//
+// So in both cases the skeleton characters in the pattern are "Mdd", which means we can't
+// retrieve the original input skeleton by simply inspecting the resolved pattern.
+//
+// Also see: https://unicode-org.atlassian.net/browse/ICU-13518
+{
+ let dtf = new Intl.DateTimeFormat("zh", {month: "narrow", day: "2-digit", timeZone: "UTC"});
+ assertEq(dtf.formatRange(0, 0), dtf.format(0));
+}
+
+// Test that date-/time-style leads to the same output.
+// ICU bug: https://unicode-org.atlassian.net/browse/ICU-20710
+{
+ let dtf = new Intl.DateTimeFormat("en", {dateStyle: "full", timeStyle: "full"});
+ assertEq(dtf.formatRange(0, 0), dtf.format(0));
+}
+
+// Test that the hourCycle option is correctly processed (test with h24).
+// ICU bug: https://unicode-org.atlassian.net/browse/ICU-20707
+{
+ let dtf = new Intl.DateTimeFormat("en-u-hc-h24", {hour: "2-digit", timeZone:"UTC"});
+ assertEq(dtf.formatRange(0, 0), dtf.format(0));
+}
+{
+ let dtf = new Intl.DateTimeFormat("en", {hourCycle: "h24", hour: "2-digit", timeZone:"UTC"});
+ assertEq(dtf.formatRange(0, 0), dtf.format(0));
+}
+
+// Test that the hourCycle option is correctly processed (test with h11).
+// ICU bug: https://unicode-org.atlassian.net/browse/ICU-20707
+{
+ let dt = 60 * 60 * 1000; // one hour
+ let dtf = new Intl.DateTimeFormat("en-u-hc-h11", {hour: "2-digit", timeZone:"UTC"});
+ assertEq(dtf.formatRange(dt, dt), dtf.format(dt));
+}
+{
+ let dt = 60 * 60 * 1000; // one hour
+ let dtf = new Intl.DateTimeFormat("en", {hourCycle: "h11", hour: "2-digit", timeZone:"UTC"});
+ assertEq(dtf.formatRange(dt, dt), dtf.format(dt));
+}
+
+// Test that non-default calendars work correctly.
+// ICU bug: https://unicode-org.atlassian.net/browse/ICU-20706
+{
+ let dtf = new Intl.DateTimeFormat("en-001-u-ca-hebrew");
+ assertEq(dtf.formatRange(0, 0), dtf.format(0));
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/formatRange-original-skeleton.js b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-original-skeleton.js
new file mode 100644
index 0000000000..c24598794e
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-original-skeleton.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Test that the interval formatting uses the original skeleton, not the skeleton
+// derived from the resolved pattern.
+{
+ let dtf = new Intl.DateTimeFormat("zh-Hans-CN", {
+ formatMatcher: "best fit",
+ month: "narrow",
+ day: "2-digit",
+ timeZone: "UTC"
+ });
+
+ assertEq(dtf.format(Date.UTC(2016, 7, 1)), "8月01日");
+ assertEq(dtf.formatRange(Date.UTC(2016, 7, 1), Date.UTC(2016, 7, 2)), "8月1日至2日");
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/formatToParts.js b/js/src/tests/non262/Intl/DateTimeFormat/formatToParts.js
new file mode 100644
index 0000000000..62f0d69406
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/formatToParts.js
@@ -0,0 +1,96 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+// Tests the format function with a diverse set of locales and options.
+// Always use UTC to avoid dependencies on test environment.
+
+const {
+ Era, Year, Month, Weekday, Day, DayPeriod, Hour, Minute, Second, Literal
+} = DateTimeFormatParts
+
+var format;
+var date = Date.UTC(2012, 11, 17, 3, 0, 42);
+
+// Locale en-US; default options.
+format = new Intl.DateTimeFormat("en-us", {timeZone: "UTC"});
+assertParts(format, date, [
+ Month("12"), Literal("/"), Day("17"), Literal("/"), Year("2012"),
+]);
+
+// Just date
+format = new Intl.DateTimeFormat("en-us", {
+ year: 'numeric',
+ month: 'numeric',
+ day: 'numeric',
+ timeZone: "UTC"});
+assertParts(format, date, [
+ Month("12"), Literal("/"), Day("17"), Literal("/"), Year("2012"),
+]);
+
+// Just time in hour24
+format = new Intl.DateTimeFormat("en-us", {
+ hour: 'numeric',
+ minute: 'numeric',
+ second: 'numeric',
+ hour12: false,
+ timeZone: "UTC"});
+assertParts(format, date, [
+ Hour("03"), Literal(":"), Minute("00"), Literal(":"), Second("42"),
+]);
+
+// Just time in hour12
+format = new Intl.DateTimeFormat("en-us", {
+ hour: 'numeric',
+ minute: 'numeric',
+ second: 'numeric',
+ hour12: true,
+ timeZone: "UTC"});
+assertParts(format, date, [
+ Hour("3"), Literal(":"), Minute("00"), Literal(":"), Second("42"), Literal(" "), DayPeriod("AM"),
+]);
+
+// Just month.
+format = new Intl.DateTimeFormat("en-us", {
+ month: "narrow",
+ timeZone: "UTC"});
+assertParts(format, date, [
+ Month("D"),
+]);
+
+// Just weekday.
+format = new Intl.DateTimeFormat("en-us", {
+ weekday: "narrow",
+ timeZone: "UTC"});
+assertParts(format, date, [
+ Weekday("M"),
+]);
+
+// Year and era.
+format = new Intl.DateTimeFormat("en-us", {
+ year: "numeric",
+ era: "short",
+ timeZone: "UTC"});
+assertParts(format, date, [
+ Year("2012"), Literal(" "), Era("AD"),
+]);
+
+// Time and date
+format = new Intl.DateTimeFormat("en-us", {
+ weekday: 'long',
+ year: 'numeric',
+ month: 'numeric',
+ day: 'numeric',
+ hour: 'numeric',
+ minute: 'numeric',
+ second: 'numeric',
+ hour12: true,
+ timeZone: "UTC"});
+assertParts(format, date, [
+ Weekday("Monday"), Literal(", "), Month("12"), Literal("/"), Day("17"), Literal("/"), Year("2012"),
+ Literal(", "),
+ Hour("3"), Literal(":"), Minute("00"), Literal(":"), Second("42"), Literal(" "), DayPeriod("AM"),
+]);
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, 'ok');
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/format_timeZone-non-meta.js b/js/src/tests/non262/Intl/DateTimeFormat/format_timeZone-non-meta.js
new file mode 100644
index 0000000000..f3de06bb97
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/format_timeZone-non-meta.js
@@ -0,0 +1,62 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Ensure we provide 'long' and 'short' descriptive names for non-meta time
+// zones. (CLDR stores names for Etc/UTC, Europe/Dublin, and Europe/London as
+// non-meta zones.)
+
+const date = new Date(Date.UTC(2018, 7-1, 24));
+const tests = [
+ {
+ locale: "en-US",
+ timeZoneName: "long",
+ zones: {
+ "Etc/UTC": "7/24/2018, Coordinated Universal Time",
+ "Europe/Dublin": "7/24/2018, Irish Standard Time",
+ "Europe/London": "7/24/2018, British Summer Time",
+ }
+ },
+ {
+ locale: "de",
+ timeZoneName: "long",
+ zones: {
+ "Etc/UTC": "24.7.2018, Koordinierte Weltzeit",
+ "Europe/Dublin": "24.7.2018, Irische Sommerzeit",
+ "Europe/London": "24.7.2018, Britische Sommerzeit",
+ }
+ },
+
+ {
+ locale: "en-US",
+ timeZoneName: "short",
+ zones: {
+ "Europe/Dublin": "7/24/2018, GMT+1",
+ "Europe/London": "7/24/2018, GMT+1",
+ }
+ },
+ {
+ locale: "en-GB",
+ timeZoneName: "short",
+ zones: {
+ "Europe/Dublin": "24/07/2018, GMT+1",
+ "Europe/London": "24/07/2018, BST",
+ }
+ },
+ {
+ locale: "en-IE",
+ timeZoneName: "short",
+ zones: {
+ "Europe/Dublin": "24/7/2018, IST",
+ "Europe/London": "24/7/2018, GMT+1",
+ }
+ },
+];
+
+for (let {locale, timeZoneName, zones} of tests) {
+ for (let [timeZone, expected] of Object.entries(zones)) {
+ assertEq(new Intl.DateTimeFormat(locale, {timeZone, timeZoneName}).format(date),
+ expected);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/format_timeZone.js b/js/src/tests/non262/Intl/DateTimeFormat/format_timeZone.js
new file mode 100644
index 0000000000..5cc3bf10cf
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/format_timeZone.js
@@ -0,0 +1,104 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const defaultLocale = "en-US";
+const defaultDate = Date.UTC(2012, 12-1, 6, 12, 0, 0);
+const defaultOptions = {
+ year: "numeric", month: "numeric", day: "numeric",
+ hour: "numeric", minute: "numeric", second: "numeric",
+};
+const longFormatOptions = Object.assign({}, defaultOptions, {
+ month: "long"
+});
+const tzNameFormatOptions = Object.assign({}, defaultOptions, {
+ timeZoneName: "short"
+});
+
+const tzMapper = [
+ x => x,
+ x => x.toUpperCase(),
+ x => x.toLowerCase(),
+];
+
+const tests = [
+ {
+ timeZone: "UTC",
+ result: "12/6/2012, 12:00:00 PM",
+ },
+ {
+ timeZone: "America/Los_Angeles",
+ result: "12/6/2012, 4:00:00 AM",
+ },
+ {
+ timeZone: "America/New_York",
+ options: tzNameFormatOptions,
+ result: "12/6/2012, 7:00:00 AM EST",
+ },
+ {
+ timeZone: "America/Caracas",
+ result: "12/6/2012, 7:30:00 AM",
+ },
+ {
+ timeZone: "Europe/London",
+ result: "12/6/2012, 12:00:00 PM",
+ },
+ {
+ timeZone: "Africa/Casablanca",
+ locale: "ar-MA-u-ca-islamicc", options: longFormatOptions,
+ result: "22 محرم 1434 هـ في 12:00:00",
+ },
+ {
+ timeZone: "Europe/Berlin",
+ locale: "de-DE", options: tzNameFormatOptions,
+ result: "6.12.2012, 13:00:00 MEZ",
+ },
+ {
+ timeZone: "Asia/Kathmandu",
+ result: "12/6/2012, 5:45:00 PM",
+ },
+ {
+ timeZone: "Asia/Bangkok",
+ locale: "th-th-u-nu-thai", options: longFormatOptions,
+ result: "๖ ธันวาคม ๒๕๕๕ เวลา ๑๙:๐๐:๐๐",
+ },
+ {
+ timeZone: "Asia/Tokyo",
+ locale: "ja-JP", options: longFormatOptions,
+ result: "2012年12月6日 21:00:00",
+ },
+ {
+ timeZone: "Australia/Lord_Howe",
+ result: "12/6/2012, 11:00:00 PM",
+ },
+ {
+ timeZone: "Australia/Lord_Howe",
+ date: Date.UTC(2012, 7-1, 6, 12, 0, 0),
+ result: "7/6/2012, 10:30:00 PM",
+ },
+ {
+ timeZone: "Pacific/Kiritimati",
+ date: Date.UTC(1978, 12-1, 6, 12, 0, 0),
+ result: "12/6/1978, 1:20:00 AM",
+ },
+ {
+ timeZone: "Africa/Monrovia",
+ date: Date.UTC(1971, 12-1, 6, 12, 0, 0),
+ result: "12/6/1971, 11:15:30 AM",
+ },
+ {
+ timeZone: "Asia/Riyadh",
+ date: Date.UTC(1946, 12-1, 6, 12, 0, 0),
+ result: "12/6/1946, 3:06:52 PM",
+ },
+];
+
+for (let {timeZone, result, locale = defaultLocale, date = defaultDate, options = defaultOptions} of tests) {
+ for (let map of tzMapper) {
+ let dtf = new Intl.DateTimeFormat(locale, Object.assign({timeZone: map(timeZone)}, options));
+ assertEq(dtf.format(date), result);
+ assertEq(dtf.resolvedOptions().timeZone, timeZone);
+ }
+}
+
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/fractional-second-digits-append-item.js b/js/src/tests/non262/Intl/DateTimeFormat/fractional-second-digits-append-item.js
new file mode 100644
index 0000000000..0ef5540179
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/fractional-second-digits-append-item.js
@@ -0,0 +1,58 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const {
+ DayPeriod, Hour, Minute, Second, FractionalSecond, Literal
+} = DateTimeFormatParts
+
+const tests = [
+ // https://unicode-org.atlassian.net/browse/CLDR-13184
+ // https://unicode-org.atlassian.net/browse/CLDR-13623
+ {
+ locale: "en",
+ date: new Date("2020-01-01T00:00:00.123"),
+ options: {hour: "numeric", fractionalSecondDigits: 3},
+ parts: [
+ Hour("12"),
+ Literal(" "),
+ DayPeriod("AM"),
+ Literal(" (Fractional Second: "),
+ FractionalSecond("123"),
+ Literal(")")
+ ]
+ },
+
+ // https://unicode-org.atlassian.net/browse/ICU-20992
+ {
+ locale: "ckb-IR",
+ date: new Date("2020-01-01T00:00:00.123"),
+ options: {minute: "2-digit", fractionalSecondDigits: 3},
+ parts: [
+ Minute("٠٠"),
+ Literal(":"),
+ Second("٠٠"),
+ Literal("٫"),
+ FractionalSecond("١٢٣"),
+ ]
+ },
+
+ // https://unicode-org.atlassian.net/browse/ICU-20992
+ {
+ locale: "ckb-IR",
+ date: new Date("2020-01-01T00:00:00.123"),
+ options: {dayPeriod: "short", fractionalSecondDigits: 3},
+ parts: [
+ FractionalSecond("١٢٣"),
+ Literal(" (Dayperiod: "),
+ DayPeriod("ب.ن"),
+ Literal(")")
+ ]
+ },
+];
+
+for (let {locale, date, options, parts} of tests) {
+ let dtf = new Intl.DateTimeFormat(locale, options);
+ assertParts(dtf, date, parts);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/fractional-second-digits.js b/js/src/tests/non262/Intl/DateTimeFormat/fractional-second-digits.js
new file mode 100644
index 0000000000..c6c29be604
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/fractional-second-digits.js
@@ -0,0 +1,43 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const {
+ Second, FractionalSecond, Literal
+} = DateTimeFormatParts
+
+const tests = [
+ {
+ date: new Date("2019-01-01T00:00:00.123"),
+ digits: {
+ 1: [Second("0"), Literal("."), FractionalSecond("1")],
+ 2: [Second("0"), Literal("."), FractionalSecond("12")],
+ 3: [Second("0"), Literal("."), FractionalSecond("123")],
+ }
+ },
+ {
+ date: new Date("2019-01-01T00:00:00.023"),
+ digits: {
+ 1: [Second("0"), Literal("."), FractionalSecond("0")],
+ 2: [Second("0"), Literal("."), FractionalSecond("02")],
+ 3: [Second("0"), Literal("."), FractionalSecond("023")],
+ }
+ },
+ {
+ date: new Date("2019-01-01T00:00:00.003"),
+ digits: {
+ 1: [Second("0"), Literal("."), FractionalSecond("0")],
+ 2: [Second("0"), Literal("."), FractionalSecond("00")],
+ 3: [Second("0"), Literal("."), FractionalSecond("003")],
+ }
+ },
+];
+
+for (let {date, digits} of tests) {
+ for (let [fractionalSecondDigits, parts] of Object.entries(digits)) {
+ let dtf = new Intl.DateTimeFormat("en", {second: "numeric", fractionalSecondDigits});
+
+ assertParts(dtf, date, parts);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/hourCycle.js b/js/src/tests/non262/Intl/DateTimeFormat/hourCycle.js
new file mode 100644
index 0000000000..21414c72cf
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/hourCycle.js
@@ -0,0 +1,142 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const hourCycleToH12Map = {
+ "h11": true,
+ "h12": true,
+ "h23": false,
+ "h24": false,
+};
+
+for (const key of Object.keys(hourCycleToH12Map)) {
+ const langTag = "en-US";
+ const loc = `${langTag}-u-hc-${key}`;
+
+ const dtf = new Intl.DateTimeFormat(loc, {hour: "numeric"});
+ const dtf2 = new Intl.DateTimeFormat(langTag, {hour: "numeric", hourCycle: key});
+ assertEq(dtf.resolvedOptions().hourCycle, dtf2.resolvedOptions().hourCycle);
+}
+
+
+/* Legacy hour12 compatibility */
+
+// When constructed with hourCycle option, resolvedOptions' hour12 is correct.
+for (const key of Object.keys(hourCycleToH12Map)) {
+ const dtf = new Intl.DateTimeFormat("en-US", {hour: "numeric", hourCycle: key});
+ assertEq(dtf.resolvedOptions().hour12, hourCycleToH12Map[key]);
+}
+
+// When constructed with hour12 option, resolvedOptions' hourCycle is correct
+for (const [key, value] of Object.entries(hourCycleToH12Map)) {
+ const dtf = new Intl.DateTimeFormat("en-US", {hour: "numeric", hour12: value});
+ assertEq(hourCycleToH12Map[dtf.resolvedOptions().hourCycle], value);
+}
+
+// When constructed with both hour12 and hourCycle options that don't match
+// hour12 takes a precedence.
+for (const [key, value] of Object.entries(hourCycleToH12Map)) {
+ const dtf = new Intl.DateTimeFormat("en-US", {
+ hour: "numeric",
+ hourCycle: key,
+ hour12: !value
+ });
+ assertEq(hourCycleToH12Map[dtf.resolvedOptions().hourCycle], !value);
+ assertEq(dtf.resolvedOptions().hour12, !value);
+}
+
+// When constructed with hourCycle as extkey, resolvedOptions' hour12 is correct.
+for (const [key, value] of Object.entries(hourCycleToH12Map)) {
+ const langTag = "en-US";
+ const loc = `${langTag}-u-hc-${key}`;
+
+ const dtf = new Intl.DateTimeFormat(loc, {hour: "numeric"});
+ assertEq(dtf.resolvedOptions().hour12, value);
+}
+
+const expectedValuesENUS = {
+ h11: "0 AM",
+ h12: "12 AM",
+ h23: "00",
+ h24: "24"
+};
+
+const exampleDate = new Date(2017, 10-1, 10, 0);
+for (const [key, val] of Object.entries(expectedValuesENUS)) {
+ assertEq(
+ Intl.DateTimeFormat("en-US", {hour: "numeric", hourCycle: key}).format(exampleDate),
+ val
+ );
+}
+
+const invalidHourCycleValues = [
+ "h28",
+ "f28",
+];
+
+for (const key of invalidHourCycleValues) {
+ const langTag = "en-US";
+ const loc = `${langTag}-u-hc-${key}`;
+
+ const dtf = new Intl.DateTimeFormat(loc, {hour: "numeric"});
+ assertEq(dtf.resolvedOptions().hour12, true); // default value for en-US
+ assertEq(dtf.resolvedOptions().hourCycle, "h12"); //default value for en-US
+}
+
+{
+ // hourCycle is not present in resolvedOptions when the formatter has no hour field
+ const options = Intl.DateTimeFormat("en-US", {hourCycle:"h11"}).resolvedOptions();
+ assertEq("hourCycle" in options, false);
+ assertEq("hour12" in options, false);
+}
+
+{
+ // Make sure that hourCycle option overrides the unicode extension
+ let dtf = Intl.DateTimeFormat("en-US-u-hc-h23", {hourCycle: "h24", hour: "numeric"});
+ assertEq(
+ dtf.resolvedOptions().hourCycle,
+ "h24"
+ );
+}
+
+{
+ // Make sure that hour12 option overrides the unicode extension
+ let dtf = Intl.DateTimeFormat("en-US-u-hc-h23", {hour12: true, hour: "numeric"});
+ assertEq(
+ dtf.resolvedOptions().hourCycle,
+ "h12"
+ );
+}
+
+{
+ // Make sure that hour12 option overrides hourCycle options
+ let dtf = Intl.DateTimeFormat("en-US",
+ {hourCycle: "h12", hour12: false, hour: "numeric"});
+ assertEq(
+ dtf.resolvedOptions().hourCycle,
+ "h23"
+ );
+}
+
+{
+ // Make sure that hour12 option overrides hourCycle options
+ let dtf = Intl.DateTimeFormat("en-u-hc-h11", {hour: "numeric"});
+ assertEq(
+ dtf.resolvedOptions().locale,
+ "en-u-hc-h11"
+ );
+}
+
+{
+ // Make sure that hour12 option overrides unicode extension
+ let dtf = Intl.DateTimeFormat("en-u-hc-h11", {hour: "numeric", hourCycle: "h24"});
+ assertEq(
+ dtf.resolvedOptions().locale,
+ "en"
+ );
+ assertEq(
+ dtf.resolvedOptions().hourCycle,
+ "h24"
+ );
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/implied-script-has-consistent-output.js b/js/src/tests/non262/Intl/DateTimeFormat/implied-script-has-consistent-output.js
new file mode 100644
index 0000000000..6c0b4d2f59
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/implied-script-has-consistent-output.js
@@ -0,0 +1,59 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+if (typeof getAvailableLocalesOf === "undefined") {
+ var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf;
+}
+
+// Retrieve all available locales of Intl.DateTimeFormat.
+const available = getAvailableLocalesOf("DateTimeFormat");
+
+const options = [
+ // Include "hour" to catch hour cycle differences.
+ //
+ // For example "ff-Latn-GH" (Fulah as spoken in Ghana) uses a 12-hour clock,
+ // whereas "ff" (Fulah) uses a 24-hour clock. When the user creates the
+ // formatter for "ff-GH", it should use the same formatter data as "ff-Latn-GH"
+ // and it shouldn't fallback to "ff".
+ {hour: "2-digit", minute: "2-digit", timeZone: "UTC"},
+
+ // Include "timeZoneName" to catch script differences, e.g traditional or
+ // simplified Chinese characters.
+ {timeZoneName: "long", timeZone: "America/Los_Angeles"},
+];
+
+// Pick a date after 12 pm to catch any hour cycle differences.
+const date = Date.UTC(2021, 6-1, 7, 15, 0);
+
+available.map(x => {
+ return new Intl.Locale(x);
+}).filter(loc => {
+ // Find all locales which have both a script and a region subtag.
+ return loc.script && loc.region;
+}).filter(loc => {
+ // Skip "sd-Deva-IN" and Fulah because of <https://unicode-org.atlassian.net/browse/ICU-21974>.
+ return !((loc.language === "sd" && loc.script === "Deva" && loc.region === "IN") ||
+ (loc.language === "ff" && (loc.script === "Adlm" || loc.script === "Latn") &&
+ (loc.region === "GH" || loc.region === "GM" || loc.region === "LR" || loc.region === "SL"))
+ );
+}).forEach(loc => {
+ // Remove the script subtag from the locale.
+ let noScript = new Intl.Locale(`${loc.language}-${loc.region}`);
+
+ // Add the likely script subtag.
+ let maximized = noScript.maximize();
+
+ for (let opt of options) {
+ // Formatter for the locale without a script subtag.
+ let df1 = new Intl.DateTimeFormat(noScript, opt);
+
+ // Formatter for the locale with the likely script subtag added.
+ let df2 = new Intl.DateTimeFormat(maximized, opt);
+
+ // The output for the locale without a script subtag should match the output
+ // with the likely script subtag added.
+ assertEq(df1.format(date), df2.format(date), `Mismatch for locale "${noScript}" (${maximized})`);
+ }
+});
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/islamic.js b/js/src/tests/non262/Intl/DateTimeFormat/islamic.js
new file mode 100644
index 0000000000..3a88590ea5
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/islamic.js
@@ -0,0 +1,89 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+function civilDate(options, date) {
+ var opts = Object.assign({timeZone: "Asia/Riyadh"}, options);
+ return new Intl.DateTimeFormat("ar-SA-u-ca-islamic-civil-nu-latn", opts).format(date);
+}
+
+function tabularDate(options, date) {
+ var opts = Object.assign({timeZone: "Asia/Riyadh"}, options);
+ return new Intl.DateTimeFormat("ar-SA-u-ca-islamic-tbla-nu-latn", opts).format(date);
+}
+
+function sightingDate(options, date) {
+ var opts = Object.assign({timeZone: "Asia/Riyadh"}, options);
+ return new Intl.DateTimeFormat("ar-SA-u-ca-islamic-rgsa-nu-latn", opts).format(date);
+}
+
+function ummAlQuraDate(options, date) {
+ var opts = Object.assign({timeZone: "Asia/Riyadh"}, options);
+ return new Intl.DateTimeFormat("ar-SA-u-ca-umalqura-nu-latn", opts).format(date);
+}
+
+// Test islamic-tbla (Tabular / Thursday epoch).
+// Compare with islamic-civil (Tabular / Friday epoch).
+function testIslamicTbla() {
+ var date = new Date(Date.UTC(2015, 1 - 1, 1));
+
+ // Month and year are the same.
+ var monthYear = {year: "numeric", month: "numeric"};
+ assertEq(civilDate(monthYear, date), tabularDate(monthYear, date));
+
+ // Day is different by one.
+ var day = {day: "numeric"};
+ assertEq(Number(civilDate(day, date)) - Number(tabularDate(day, date)), -1);
+}
+
+// Test islamic-rgsa (Saudi Arabia sighting).
+// Sighting of the hilal (crescent moon) in Saudi Arabia.
+function testIslamicRgsa() {
+ var date1 = new Date(Date.UTC(1975, 5 - 1, 6));
+ var date2 = new Date(Date.UTC(2015, 1 - 1, 1));
+ var dayMonthYear = {year: "numeric", month: "numeric", day: "numeric"};
+
+ assertEq(sightingDate(dayMonthYear, date1), tabularDate(dayMonthYear, date1));
+ assertEq(sightingDate(dayMonthYear, date2), civilDate(dayMonthYear, date2));
+}
+
+// Test islamic-umalqura (Umm al-Qura).
+function testIslamicUmalqura() {
+ var year = {year: "numeric"};
+ var month = {month: "numeric"};
+ var day = {day: "numeric"};
+
+ // From ICU test files, which in turn was generated from:
+ // Official Umm-al-Qura calendar of SA:
+ // home, http://www.ummulqura.org.sa/default.aspx
+ // converter, http://www.ummulqura.org.sa/Index.aspx
+ var dates = [
+ [ {year: 2016, month: 1, day: 11}, {year: 1437, month: 4, day: 1} ],
+ [ {year: 2016, month: 2, day: 10}, {year: 1437, month: 5, day: 1} ],
+ [ {year: 2016, month: 3, day: 10}, {year: 1437, month: 6, day: 1} ],
+ [ {year: 2016, month: 4, day: 8}, {year: 1437, month: 7, day: 1} ],
+ [ {year: 2016, month: 5, day: 8}, {year: 1437, month: 8, day: 1} ],
+ [ {year: 2016, month: 6, day: 6}, {year: 1437, month: 9, day: 1} ],
+ [ {year: 2016, month: 7, day: 6}, {year: 1437, month: 10, day: 1} ],
+ [ {year: 2016, month: 8, day: 4}, {year: 1437, month: 11, day: 1} ],
+ [ {year: 2016, month: 9, day: 2}, {year: 1437, month: 12, day: 1} ],
+ [ {year: 2016, month: 10, day: 2}, {year: 1438, month: 1, day: 1} ],
+ [ {year: 2016, month: 11, day: 1}, {year: 1438, month: 2, day: 1} ],
+ [ {year: 2016, month: 11, day: 30}, {year: 1438, month: 3, day: 1} ],
+ [ {year: 2016, month: 12, day: 30}, {year: 1438, month: 4, day: 1} ],
+ ];
+
+ for (var [gregorian, ummAlQura] of dates) {
+ var date = new Date(Date.UTC(gregorian.year, gregorian.month - 1, gregorian.day));
+
+ // Use parseInt() to remove the trailing era indicator.
+ assertEq(parseInt(ummAlQuraDate(year, date), 10), ummAlQura.year);
+ assertEq(Number(ummAlQuraDate(month, date)), ummAlQura.month);
+ assertEq(Number(ummAlQuraDate(day, date)), ummAlQura.day);
+ }
+}
+
+testIslamicTbla();
+testIslamicRgsa();
+testIslamicUmalqura();
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/japanese-gannen-year.js b/js/src/tests/non262/Intl/DateTimeFormat/japanese-gannen-year.js
new file mode 100644
index 0000000000..e972d2e55a
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/japanese-gannen-year.js
@@ -0,0 +1,54 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+var dtf = new Intl.DateTimeFormat("ja-u-ca-japanese", {
+ era: "short",
+ timeZone: "Asia/Tokyo",
+});
+
+var endShowa = new Date("1989-01-07T00:00:00.000Z");
+var startHeisei = new Date("1989-01-08T00:00:00.000Z");
+
+assertEq(dtf.format(endShowa), "昭和64/1/7");
+assertEq(dtf.format(startHeisei), "平成1/1/8");
+
+var parts = dtf.formatToParts(startHeisei);
+assertEq(parts.filter(p => p.type === "era")[0].value, "平成");
+assertEq(parts.filter(p => p.type === "year")[0].value, "1");
+
+var dtf = new Intl.DateTimeFormat("ja-u-ca-japanese", {
+ era: "short",
+ year: "numeric",
+ month: "long",
+ day: "numeric",
+ timeZone: "Asia/Tokyo",
+});
+
+assertEq(dtf.format(endShowa), "昭和64年1月7日");
+assertEq(dtf.format(startHeisei), "平成元年1月8日");
+
+var parts = dtf.formatToParts(startHeisei);
+assertEq(parts.filter(p => p.type === "era")[0].value, "平成");
+assertEq(parts.filter(p => p.type === "year")[0].value, "元");
+
+// ICU returns mixed numbers when an explicit numbering system is present.
+
+var dtf = new Intl.DateTimeFormat("ja-u-ca-japanese-nu-arab", {
+ era: "short",
+ timeZone: "Asia/Tokyo",
+});
+
+assertEq(dtf.format(endShowa), "昭和٦٤/١/٧");
+assertEq(dtf.format(startHeisei), "平成١/١/٨");
+
+var dtf = new Intl.DateTimeFormat("ja-u-ca-japanese-nu-arab", {
+ era: "short",
+ year: "numeric",
+ month: "numeric",
+ timeZone: "Asia/Tokyo",
+});
+
+assertEq(dtf.format(endShowa), "昭和64年١月");
+assertEq(dtf.format(startHeisei), "平成元年١月");
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/mozExtensions.js b/js/src/tests/non262/Intl/DateTimeFormat/mozExtensions.js
new file mode 100644
index 0000000000..7db314d413
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/mozExtensions.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||!this.hasOwnProperty("addIntlExtras"))
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+let mozIntl = {};
+addIntlExtras(mozIntl);
+
+// Pattern
+
+var dtf = new Intl.DateTimeFormat("en-US", {pattern: "HH:mm MM/dd/YYYY"});
+var mozDtf = new mozIntl.DateTimeFormat("en-US", {pattern: "HH:mm MM/dd/YYYY"});
+
+assertEq(dtf.resolvedOptions().hasOwnProperty('pattern'), false);
+assertEq(mozDtf.resolvedOptions().pattern, "HH:mm MM/dd/YYYY");
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, 'ok');
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/numberingSystem-option.js b/js/src/tests/non262/Intl/DateTimeFormat/numberingSystem-option.js
new file mode 100644
index 0000000000..474910da47
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/numberingSystem-option.js
@@ -0,0 +1,60 @@
+const defaultLocale = "en";
+const defaultNumberingSystem = new Intl.DateTimeFormat(defaultLocale).resolvedOptions().numberingSystem;
+
+function createWithLocale(locale, numberingSystem) {
+ return new Intl.DateTimeFormat(locale, {numberingSystem});
+}
+
+function create(numberingSystem) {
+ return createWithLocale(defaultLocale, numberingSystem);
+}
+
+// Empty string should throw.
+assertThrowsInstanceOf(() => create(""), RangeError);
+
+// Trailing \0 should throw.
+assertThrowsInstanceOf(() => create("latn\0"), RangeError);
+
+// Too short or too long strings should throw.
+assertThrowsInstanceOf(() => create("a"), RangeError);
+assertThrowsInstanceOf(() => create("toolongstring"), RangeError);
+
+// Throw even when prefix is valid.
+assertThrowsInstanceOf(() => create("latn-toolongstring"), RangeError);
+
+// |numberingSystem| can be set to |undefined|.
+let dtf = create(undefined);
+assertEq(dtf.resolvedOptions().numberingSystem, defaultNumberingSystem);
+
+// Unsupported numbering systems are ignored.
+dtf = create("xxxxxxxx");
+assertEq(dtf.resolvedOptions().numberingSystem, defaultNumberingSystem);
+
+// Numbering system in options overwrite Unicode extension keyword.
+dtf = createWithLocale(`${defaultLocale}-u-nu-thai`, "arab");
+assertEq(dtf.resolvedOptions().locale, defaultLocale);
+assertEq(dtf.resolvedOptions().numberingSystem, "arab");
+
+// |numberingSystem| option ignores case.
+dtf = create("ARAB");
+assertEq(dtf.resolvedOptions().locale, defaultLocale);
+assertEq(dtf.resolvedOptions().numberingSystem, "arab");
+
+for (let [numberingSystem, {algorithmic}] of Object.entries(numberingSystems)) {
+ let dtf1 = new Intl.DateTimeFormat(`${defaultLocale}-u-nu-${numberingSystem}`);
+ let dtf2 = new Intl.DateTimeFormat(defaultLocale, {numberingSystem});
+
+ if (!algorithmic) {
+ assertEq(dtf1.resolvedOptions().numberingSystem, numberingSystem);
+ assertEq(dtf2.resolvedOptions().numberingSystem, numberingSystem);
+ } else {
+ // We don't yet support algorithmic numbering systems.
+ assertEq(dtf1.resolvedOptions().numberingSystem, defaultNumberingSystem);
+ assertEq(dtf2.resolvedOptions().numberingSystem, defaultNumberingSystem);
+ }
+
+ assertEq(dtf2.format(0), dtf1.format(0));
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/options-property-accesses.js b/js/src/tests/non262/Intl/DateTimeFormat/options-property-accesses.js
new file mode 100644
index 0000000000..e9a13c1534
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/options-property-accesses.js
@@ -0,0 +1,77 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+var log;
+var proxy = new Proxy({
+ year: "numeric",
+ hour: "numeric",
+}, new Proxy({
+ get(t, pk, r) {
+ log.push(pk);
+ return Reflect.get(t, pk, r);
+ }
+}, {
+ get(t, pk, r) {
+ assertEq(pk, "get");
+ return Reflect.get(t, pk, r);
+ }
+}));
+
+var constructorAccesses = [
+ // ToDateTimeOptions(options, "any", "date").
+ "weekday", "year", "month", "day",
+ "dayPeriod", "hour", "minute", "second", "fractionalSecondDigits",
+ "dateStyle", "timeStyle",
+
+ // InitializeDateTimeFormat
+ "localeMatcher", "calendar", "numberingSystem", "hour12", "hourCycle", "timeZone",
+
+ // Table 5: Components of date and time formats
+ "weekday", "era", "year", "month", "day", "dayPeriod", "hour", "minute", "second",
+ "fractionalSecondDigits", "timeZoneName",
+
+ // InitializeDateTimeFormat
+ "formatMatcher",
+ "dateStyle", "timeStyle",
+];
+
+log = [];
+new Intl.DateTimeFormat(undefined, proxy);
+
+assertEqArray(log, constructorAccesses);
+
+log = [];
+new Date().toLocaleString(undefined, proxy);
+
+assertEqArray(log, [
+ // ToDateTimeOptions(options, "any", "all").
+ "weekday", "year", "month", "day",
+ "dayPeriod", "hour", "minute", "second", "fractionalSecondDigits",
+ "dateStyle", "timeStyle",
+
+ ...constructorAccesses
+]);
+
+log = [];
+new Date().toLocaleDateString(undefined, proxy);
+
+assertEqArray(log, [
+ // ToDateTimeOptions(options, "date", "date").
+ "weekday", "year", "month", "day",
+ "dateStyle", "timeStyle",
+
+ ...constructorAccesses
+]);
+
+log = [];
+new Date().toLocaleTimeString(undefined, proxy);
+
+assertEqArray(log, [
+ // ToDateTimeOptions(options, "time", "time").
+ "dayPeriod", "hour", "minute", "second", "fractionalSecondDigits",
+ "dateStyle", "timeStyle",
+
+ ...constructorAccesses
+]);
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/related-year.js b/js/src/tests/non262/Intl/DateTimeFormat/related-year.js
new file mode 100644
index 0000000000..296de04883
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/related-year.js
@@ -0,0 +1,185 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const {
+ Era, Year, YearName, RelatedYear, Month, Day, Literal
+} = DateTimeFormatParts
+
+const tests = [
+ // Test with non-leap month.
+ {
+ date: new Date("2020-04-23T00:00:00Z"),
+ options: {},
+ calendar: "chinese",
+ locales: {
+ "en": [Month("4"), Literal("/"), Day("1"), Literal("/"), RelatedYear("2020")],
+ "de": [Day("1"), Literal("."), Month("4"), Literal("."), Year("37")],
+ "ja": [YearName("庚子"), Literal("-"), Month("4"), Literal("-"), Day("1")],
+ "zh": [RelatedYear("2020"), Literal("年"), Month("四月"), Day("1")],
+ "ar": [RelatedYear("٢٠٢٠"), Literal("-"), Month("٠٤"), Literal("-"), Day("٠١")],
+ }
+ },
+
+ // Test with leap month.
+ {
+ date: new Date("2020-05-23T00:00:00Z"),
+ options: {},
+ calendar: "chinese",
+ locales: {
+ "en": [Month("4bis"), Literal("/"), Day("1"), Literal("/"), RelatedYear("2020")],
+ "de": [Day("1"), Literal("."), Month("4bis"), Literal("."), Year("37")],
+ "ja": [YearName("庚子"), Literal("-"), Month("閏4"), Literal("-"), Day("1")],
+ "zh": [RelatedYear("2020"), Literal("年"), Month("闰四月"), Day("1")],
+ "ar": [RelatedYear("٢٠٢٠"), Literal("-"), Month("٠٤bis"), Literal("-"), Day("٠١")],
+ }
+ },
+
+ // Display only "year" field.
+ {
+ date: new Date("2020-04-23T00:00:00Z"),
+ options: {year: "numeric"},
+ calendar: "chinese",
+ locales: {
+ "en": [RelatedYear("2020"), Literal("("), YearName("geng-zi"), Literal(")")],
+ "de": [YearName("geng-zi")],
+ "ja": [YearName("庚子"), Literal("年")],
+ "zh": [RelatedYear("2020"), YearName("庚子"), Literal("年")],
+ "ar": [Year("٣٧")],
+ }
+ },
+
+ // Display only "month" field.
+ {
+ date: new Date("2020-04-23T00:00:00Z"),
+ options: {month: "long"},
+ calendar: "chinese",
+ locales: {
+ "en": [Month("Fourth Month")],
+ "de": [Month("M04")],
+ "ja": [Month("四月")],
+ "zh": [Month("四月")],
+ "ar": [Month("M04")],
+ }
+ },
+
+ // Display only "month" field. (Leap month)
+ {
+ date: new Date("2020-05-23T00:00:00Z"),
+ options: {month: "long"},
+ calendar: "chinese",
+ locales: {
+ "en": [Month("Fourth Monthbis")],
+ "de": [Month("M04bis")],
+ "ja": [Month("閏四月")],
+ "zh": [Month("闰四月")],
+ "ar": [Month("M04bis")],
+ }
+ },
+
+ // Display "year" and "month" fields.
+ {
+ date: new Date("2020-04-23T00:00:00Z"),
+ options: {year: "numeric", month: "long"},
+ calendar: "chinese",
+ locales: {
+ "en": [Month("Fourth Month"), Literal(" "), RelatedYear("2020"), Literal("("), YearName("geng-zi"), Literal(")")],
+ "de": [Month("M04"), Literal(" "), YearName("geng-zi")],
+ "ja": [YearName("庚子"), Literal("年"), Month("四月")],
+ "zh": [RelatedYear("2020"), YearName("庚子"), Literal("年"), Month("四月")],
+ "ar": [RelatedYear("٢٠٢٠"), Literal("("), YearName("geng-zi"), Literal(") "), Month("M04")],
+ }
+ },
+
+ // Display "year" and "month" fields. (Leap month)
+ {
+ date: new Date("2020-05-23T00:00:00Z"),
+ options: {year: "numeric", month: "long"},
+ calendar: "chinese",
+ locales: {
+ "en": [Month("Fourth Monthbis"), Literal(" "), RelatedYear("2020"), Literal("("), YearName("geng-zi"), Literal(")")],
+ "de": [Month("M04bis"), Literal(" "), YearName("geng-zi")],
+ "ja": [YearName("庚子"), Literal("年"), Month("閏四月")],
+ "zh": [RelatedYear("2020"), YearName("庚子"), Literal("年"), Month("闰四月")],
+ "ar": [RelatedYear("٢٠٢٠"), Literal("("), YearName("geng-zi"), Literal(") "), Month("M04bis")],
+ }
+ },
+
+ // Related year in traditional Korean calendar.
+ {
+ date: new Date("2019-01-01T00:00:00Z"),
+ options: {},
+ calendar: "dangi",
+ locales: {
+ "en": [Month("11"), Literal("/"), Day("26"), Literal("/"), RelatedYear("2018")],
+ "ko": [RelatedYear("2018"), Literal(". "), Month("11"), Literal(". "), Day("26"), Literal(".")],
+ }
+ },
+
+ // Allowing the calendar to modify the pattern selection choice can result in falling back to
+ // the root locale patterns in more cases. That can result in displaying the era field by
+ // default, among other things.
+ {
+ date: new Date("2019-01-01T00:00:00Z"),
+ options: {},
+ calendar: "buddhist",
+ locales: {
+ "en": [Month("1"), Literal("/"), Day("1"), Literal("/"), Year("2562"), Literal(" "), Era("BE")],
+ "th": [Day("1"), Literal("/"), Month("1"), Literal("/"), Year("2562")],
+ }
+ },
+ {
+ date: new Date("2019-01-01T00:00:00Z"),
+ options: {},
+ calendar: "hebrew",
+ locales: {
+ "en": [Day("24"), Literal(" "), Month("Tevet"), Literal(" "), Year("5779")],
+ "he": [Day("24"), Literal(" ב"), Month("טבת"), Literal(" "), Year("5779")],
+ "fr": [Day("24"), Literal("/"), Month("04"), Literal("/"), Year("5779"), Literal(" "), Era("A. M.")],
+ }
+ },
+ {
+ date: new Date("2019-01-01T00:00:00Z"),
+ options: {},
+ calendar: "islamic",
+ locales: {
+ "en": [Month("4"), Literal("/"), Day("25"), Literal("/"), Year("1440"), Literal(" "), Era("AH")],
+ "ar": [Day("٢٥"), Literal("\u200F/"), Month("٤"), Literal("\u200F/"), Year("١٤٤٠"), Literal(" "), Era("هـ")],
+ }
+ },
+ {
+ date: new Date("2019-01-01T00:00:00Z"),
+ options: {},
+ calendar: "japanese",
+ locales: {
+ "en": [Month("1"), Literal("/"), Day("1"), Literal("/"), Year("31"), Literal(" "), Era("H")],
+ "ja": [Era("H"), Year("31"), Literal("/"), Month("1"), Literal("/"), Day("1")],
+ }
+ },
+ {
+ date: new Date("2019-01-01T00:00:00Z"),
+ options: {},
+ calendar: "persian",
+ locales: {
+ "en": [Month("10"), Literal("/"), Day("11"), Literal("/"), Year("1397"), Literal(" "), Era("AP")],
+ "fa": [Year("۱۳۹۷"), Literal("/"), Month("۱۰"), Literal("/"), Day("۱۱")],
+ }
+ },
+ {
+ date: new Date("2019-01-01T00:00:00Z"),
+ options: {},
+ calendar: "roc",
+ locales: {
+ "en": [Month("1"), Literal("/"), Day("1"), Literal("/"), Year("108"), Literal(" "), Era("Minguo")],
+ "zh-Hant-TW": [Era("民國"), Year("108"), Literal("/"), Month("1"), Literal("/"), Day("1")],
+ }
+ },
+];
+
+for (let {date, options, calendar, locales} of tests) {
+ for (let [locale, result] of Object.entries(locales)) {
+ let df = new Intl.DateTimeFormat(`${locale}-u-ca-${calendar}`, {timeZone: "UTC", ...options});
+ assertParts(df, date, result);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/shell.js b/js/src/tests/non262/Intl/DateTimeFormat/shell.js
new file mode 100644
index 0000000000..c2f9e7138b
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/shell.js
@@ -0,0 +1,34 @@
+function GenericPartCreator(type) {
+ return str => ({ type, value: str });
+}
+
+const DateTimeFormatParts = {
+ Weekday: GenericPartCreator("weekday"),
+ Era: GenericPartCreator("era"),
+ Year: GenericPartCreator("year"),
+ YearName: GenericPartCreator("yearName"),
+ RelatedYear: GenericPartCreator("relatedYear"),
+ Month: GenericPartCreator("month"),
+ Day: GenericPartCreator("day"),
+ DayPeriod: GenericPartCreator("dayPeriod"),
+ Hour: GenericPartCreator("hour"),
+ Minute: GenericPartCreator("minute"),
+ Second: GenericPartCreator("second"),
+ FractionalSecond: GenericPartCreator("fractionalSecond"),
+ TimeZoneName: GenericPartCreator("timeZoneName"),
+ Unknown: GenericPartCreator("unknown"),
+ Literal: GenericPartCreator("literal"),
+};
+
+function assertParts(df, x, expected) {
+ var parts = df.formatToParts(x);
+ assertEq(parts.map(part => part.value).join(""), df.format(x),
+ "formatToParts and format must agree");
+
+ var len = parts.length;
+ assertEq(len, expected.length, "parts count mismatch");
+ for (var i = 0; i < len; i++) {
+ assertEq(parts[i].type, expected[i].type, "type mismatch at " + i);
+ assertEq(parts[i].value, expected[i].value, "value mismatch at " + i);
+ }
+}
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/standalone-month.js b/js/src/tests/non262/Intl/DateTimeFormat/standalone-month.js
new file mode 100644
index 0000000000..c8aab5888e
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/standalone-month.js
@@ -0,0 +1,11 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+for (let weekday of ["long", "short", "narrow"]) {
+ let dtf = new Intl.DateTimeFormat("en", {weekday});
+ let options = dtf.resolvedOptions();
+
+ assertEq(options.weekday, weekday);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/supportedLocalesOf.js b/js/src/tests/non262/Intl/DateTimeFormat/supportedLocalesOf.js
new file mode 100644
index 0000000000..b957f9cd60
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/supportedLocalesOf.js
@@ -0,0 +1,371 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||xulRuntime.shell)
+// -- test in browser only that ICU has locale data for all Mozilla languages
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This array contains the locales that ICU supports in
+// date and time formatting whose languages Mozilla localizes Firefox into.
+// Current as of ICU 50.1.2 and Firefox March 2013.
+var locales = [
+ "af",
+ "af-NA",
+ "af-ZA",
+ "ar",
+ "ar-001",
+ "ar-AE",
+ "ar-BH",
+ "ar-DJ",
+ "ar-DZ",
+ "ar-EG",
+ "ar-EH",
+ "ar-ER",
+ "ar-IL",
+ "ar-IQ",
+ "ar-JO",
+ "ar-KM",
+ "ar-KW",
+ "ar-LB",
+ "ar-LY",
+ "ar-MA",
+ "ar-MR",
+ "ar-OM",
+ "ar-PS",
+ "ar-QA",
+ "ar-SA",
+ "ar-SD",
+ "ar-SO",
+ "ar-SY",
+ "ar-TD",
+ "ar-TN",
+ "ar-YE",
+ "as",
+ "as-IN",
+ "be",
+ "be-BY",
+ "bg",
+ "bg-BG",
+ "bn",
+ "bn-BD",
+ "bn-IN",
+ "br",
+ "br-FR",
+ "bs",
+ "bs-Cyrl",
+ "bs-Cyrl-BA",
+ "bs-Latn",
+ "bs-Latn-BA",
+ "ca",
+ "ca-AD",
+ "ca-ES",
+ "cs",
+ "cs-CZ",
+ "cy",
+ "cy-GB",
+ "da",
+ "da-DK",
+ "de",
+ "de-AT",
+ "de-BE",
+ "de-CH",
+ "de-DE",
+ "de-LI",
+ "de-LU",
+ "el",
+ "el-CY",
+ "el-GR",
+ "en",
+ "en-150",
+ "en-AG",
+ "en-AS",
+ "en-AU",
+ "en-BB",
+ "en-BE",
+ "en-BM",
+ "en-BS",
+ "en-BW",
+ "en-BZ",
+ "en-CA",
+ "en-CM",
+ "en-DM",
+ "en-FJ",
+ "en-FM",
+ "en-GB",
+ "en-GD",
+ "en-GG",
+ "en-GH",
+ "en-GI",
+ "en-GM",
+ "en-GU",
+ "en-GY",
+ "en-HK",
+ "en-IE",
+ "en-IM",
+ "en-IN",
+ "en-JE",
+ "en-JM",
+ "en-KE",
+ "en-KI",
+ "en-KN",
+ "en-KY",
+ "en-LC",
+ "en-LR",
+ "en-LS",
+ "en-MG",
+ "en-MH",
+ "en-MP",
+ "en-MT",
+ "en-MU",
+ "en-MW",
+ "en-NA",
+ "en-NG",
+ "en-NZ",
+ "en-PG",
+ "en-PH",
+ "en-PK",
+ "en-PR",
+ "en-PW",
+ "en-SB",
+ "en-SC",
+ "en-SG",
+ "en-SL",
+ "en-SS",
+ "en-SZ",
+ "en-TC",
+ "en-TO",
+ "en-TT",
+ "en-TZ",
+ "en-UG",
+ "en-UM",
+ "en-US",
+ "en-US-POSIX",
+ "en-VC",
+ "en-VG",
+ "en-VI",
+ "en-VU",
+ "en-WS",
+ "en-ZA",
+ "en-ZM",
+ "en-ZW",
+ "eo",
+ "es",
+ "es-419",
+ "es-AR",
+ "es-BO",
+ "es-CL",
+ "es-CO",
+ "es-CR",
+ "es-CU",
+ "es-DO",
+ "es-EA",
+ "es-EC",
+ "es-ES",
+ "es-GQ",
+ "es-GT",
+ "es-HN",
+ "es-IC",
+ "es-MX",
+ "es-NI",
+ "es-PA",
+ "es-PE",
+ "es-PH",
+ "es-PR",
+ "es-PY",
+ "es-SV",
+ "es-US",
+ "es-UY",
+ "es-VE",
+ "et",
+ "et-EE",
+ "eu",
+ "eu-ES",
+ "fa",
+ "fa-AF",
+ "fa-IR",
+ "ff",
+ "ff-SN",
+ "fi",
+ "fi-FI",
+ "fr",
+ "fr-BE",
+ "fr-BF",
+ "fr-BI",
+ "fr-BJ",
+ "fr-BL",
+ "fr-CA",
+ "fr-CD",
+ "fr-CF",
+ "fr-CG",
+ "fr-CH",
+ "fr-CI",
+ "fr-CM",
+ "fr-DJ",
+ "fr-DZ",
+ "fr-FR",
+ "fr-GA",
+ "fr-GF",
+ "fr-GN",
+ "fr-GP",
+ "fr-GQ",
+ "fr-HT",
+ "fr-KM",
+ "fr-LU",
+ "fr-MA",
+ "fr-MC",
+ "fr-MF",
+ "fr-MG",
+ "fr-ML",
+ "fr-MQ",
+ "fr-MR",
+ "fr-MU",
+ "fr-NC",
+ "fr-NE",
+ "fr-PF",
+ "fr-RE",
+ "fr-RW",
+ "fr-SC",
+ "fr-SN",
+ "fr-SY",
+ "fr-TD",
+ "fr-TG",
+ "fr-TN",
+ "fr-VU",
+ "fr-YT",
+ "ga",
+ "ga-IE",
+ "gl",
+ "gl-ES",
+ "gu",
+ "gu-IN",
+ "he",
+ "he-IL",
+ "hi",
+ "hi-IN",
+ "hr",
+ "hr-BA",
+ "hr-HR",
+ "hu",
+ "hu-HU",
+ "hy",
+ "hy-AM",
+ "id",
+ "id-ID",
+ "is",
+ "is-IS",
+ "it",
+ "it-CH",
+ "it-IT",
+ "it-SM",
+ "ja",
+ "ja-JP",
+ "kk",
+ "kk-Cyrl",
+ "kk-Cyrl-KZ",
+ "km",
+ "km-KH",
+ "kn",
+ "kn-IN",
+ "ko",
+ "ko-KP",
+ "ko-KR",
+ "lt",
+ "lt-LT",
+ "lv",
+ "lv-LV",
+ "mk",
+ "mk-MK",
+ "ml",
+ "ml-IN",
+ "mr",
+ "mr-IN",
+ "nb",
+ "nb-NO",
+ "nl",
+ "nl-AW",
+ "nl-BE",
+ "nl-CW",
+ "nl-NL",
+ "nl-SR",
+ "nl-SX",
+ "nn",
+ "nn-NO",
+ "or",
+ "or-IN",
+ "pa",
+ "pa-Arab",
+ "pa-Arab-PK",
+ "pa-Guru",
+ "pa-Guru-IN",
+ "pl",
+ "pl-PL",
+ "pt",
+ "pt-AO",
+ "pt-BR",
+ "pt-CV",
+ "pt-GW",
+ "pt-MO",
+ "pt-MZ",
+ "pt-PT",
+ "pt-ST",
+ "pt-TL",
+ "rm",
+ "rm-CH",
+ "ro",
+ "ro-MD",
+ "ro-RO",
+ "ru",
+ "ru-BY",
+ "ru-KG",
+ "ru-KZ",
+ "ru-MD",
+ "ru-RU",
+ "ru-UA",
+ "si",
+ "si-LK",
+ "sk",
+ "sk-SK",
+ "sl",
+ "sl-SI",
+ "sq",
+ "sq-AL",
+ "sq-MK",
+ "sr",
+ "sr-Cyrl",
+ "sr-Cyrl-BA",
+ "sr-Cyrl-ME",
+ "sr-Cyrl-RS",
+ "sr-Latn",
+ "sr-Latn-BA",
+ "sr-Latn-ME",
+ "sr-Latn-RS",
+ "sv",
+ "sv-AX",
+ "sv-FI",
+ "sv-SE",
+ "te",
+ "te-IN",
+ "th",
+ "th-TH",
+ "tr",
+ "tr-CY",
+ "tr-TR",
+ "uk",
+ "uk-UA",
+ "vi",
+ "vi-VN",
+ "zh",
+ "zh-Hans",
+ "zh-Hans-CN",
+ "zh-Hans-HK",
+ "zh-Hans-MO",
+ "zh-Hans-SG",
+ "zh-Hant",
+ "zh-Hant-HK",
+ "zh-Hant-MO",
+ "zh-Hant-TW",
+];
+
+var count = Intl.DateTimeFormat.supportedLocalesOf(locales).length;
+
+reportCompare(locales.length, count, "Number of supported locales in Intl.DateTimeFormat");
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/timeZone.js b/js/src/tests/non262/Intl/DateTimeFormat/timeZone.js
new file mode 100644
index 0000000000..eca6ed27ee
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/timeZone.js
@@ -0,0 +1,139 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const tzMapper = [
+ x => x,
+ x => x.toUpperCase(),
+ x => x.toLowerCase(),
+];
+
+
+const utcTimeZones = [
+ // Etc/UTC and Etc/GMT are normalized to UTC.
+ "Etc/UTC", "Etc/GMT",
+
+ // Links to Etc/GMT. (tzdata/etcetera)
+ "GMT", "Etc/Greenwich", "Etc/GMT-0", "Etc/GMT+0", "Etc/GMT0",
+
+ // Links to Etc/UTC. (tzdata/etcetera)
+ "Etc/Universal", "Etc/Zulu",
+
+ // Links to Etc/GMT. (tzdata/backward)
+ "GMT+0", "GMT-0", "GMT0", "Greenwich",
+
+ // Links to Etc/UTC. (tzdata/backward)
+ "UTC", "Universal", "Zulu", "Etc/UCT", "UCT",
+];
+
+for (let timeZone of utcTimeZones) {
+ for (let map of tzMapper) {
+ let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)});
+ assertEq(dtf.resolvedOptions().timeZone, "UTC");
+ }
+}
+
+
+const invalidTimeZones = [
+ "", "null", "undefined", "UTC\0",
+
+ // ICU time zone name for invalid time zones.
+ "Etc/Unknown",
+
+ // ICU custom time zones.
+ "GMT-1", "GMT+1", "GMT-10", "GMT+10",
+ "GMT-10:00", "GMT+10:00",
+ "GMT-1000", "GMT+1000",
+
+ // Legacy ICU time zones.
+ "ACT", "AET", "AGT", "ART", "AST", "BET", "BST", "CAT", "CNT", "CST",
+ "CTT", "EAT", "ECT", "IET", "IST", "JST", "MIT", "NET", "NST", "PLT",
+ "PNT", "PRT", "PST", "SST", "VST",
+
+ // Deprecated IANA time zones.
+ "SystemV/AST4ADT", "SystemV/EST5EDT", "SystemV/CST6CDT", "SystemV/MST7MDT",
+ "SystemV/PST8PDT", "SystemV/YST9YDT", "SystemV/AST4", "SystemV/EST5",
+ "SystemV/CST6", "SystemV/MST7", "SystemV/PST8", "SystemV/YST9", "SystemV/HST10",
+];
+
+for (let timeZone of invalidTimeZones) {
+ for (let map of tzMapper) {
+ assertThrowsInstanceOf(() => {
+ new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)});
+ }, RangeError);
+ }
+}
+
+
+// GMT[+-]hh is invalid, but Etc/GMT[+-]hh is a valid IANA time zone.
+for (let gmtOffset = -14; gmtOffset <= 12; ++gmtOffset) {
+ // Skip Etc/GMT0.
+ if (gmtOffset === 0)
+ continue;
+
+ let timeZone = `Etc/GMT${gmtOffset > 0 ? "+" : ""}${gmtOffset}`;
+ for (let map of tzMapper) {
+ let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)});
+ assertEq(dtf.resolvedOptions().timeZone, timeZone);
+ }
+}
+
+
+const invalidEtcGMTNames = [
+ // Out of bounds GMT offset.
+ "Etc/GMT-15", "Etc/GMT+13",
+
+ // Etc/GMT[+-]hh:mm isn't a IANA time zone name.
+ "Etc/GMT-10:00", "Etc/GMT+10:00",
+ "Etc/GMT-1000", "Etc/GMT+1000",
+];
+
+for (let timeZone of invalidEtcGMTNames) {
+ for (let map of tzMapper) {
+ assertThrowsInstanceOf(() => {
+ new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)});
+ }, RangeError);
+ }
+}
+
+
+// RangeError is thrown for primitive values, because ToString(<primitive>)
+// isn't a valid time zone name.
+for (let nonStrings of [null, 0, 0.5, true, false]) {
+ assertThrowsInstanceOf(() => {
+ new Intl.DateTimeFormat(undefined, {timeZone: nonStrings});
+ }, RangeError);
+}
+
+// ToString(<symbol>) throws TypeError.
+assertThrowsInstanceOf(() => {
+ new Intl.DateTimeFormat(undefined, {timeZone: Symbol()});
+}, TypeError);
+
+// |undefined| or absent "timeZone" option selects the default time zone.
+{
+ let {timeZone: tzAbsent} = new Intl.DateTimeFormat(undefined, {}).resolvedOptions();
+ let {timeZone: tzUndefined} = new Intl.DateTimeFormat(undefined, {timeZone: undefined}).resolvedOptions();
+
+ assertEq(typeof tzAbsent, "string");
+ assertEq(typeof tzUndefined, "string");
+ assertEq(tzUndefined, tzAbsent);
+
+ // The default time zone isn't a link name.
+ let {timeZone: tzDefault} = new Intl.DateTimeFormat(undefined, {timeZone: tzAbsent}).resolvedOptions();
+ assertEq(tzDefault, tzAbsent);
+}
+
+// Objects are converted through ToString().
+{
+ let timeZone = "Europe/Warsaw";
+ let obj = {
+ toString() {
+ return timeZone;
+ }
+ };
+ let dtf = new Intl.DateTimeFormat(undefined, {timeZone: obj});
+ assertEq(dtf.resolvedOptions().timeZone, timeZone);
+}
+
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backward_links.js b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backward_links.js
new file mode 100644
index 0000000000..234616bfd9
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backward_links.js
@@ -0,0 +1,156 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Generated by make_intl_data.py. DO NOT EDIT.
+// tzdata version = 2023c
+
+const tzMapper = [
+ x => x,
+ x => x.toUpperCase(),
+ x => x.toLowerCase(),
+];
+
+// Link names derived from IANA Time Zone Database, backward file.
+const links = {
+ "Africa/Asmera": "Africa/Asmara",
+ "America/Atka": "America/Adak",
+ "America/Buenos_Aires": "America/Argentina/Buenos_Aires",
+ "America/Catamarca": "America/Argentina/Catamarca",
+ "America/Cordoba": "America/Argentina/Cordoba",
+ "America/Fort_Wayne": "America/Indiana/Indianapolis",
+ "America/Godthab": "America/Nuuk",
+ "America/Indianapolis": "America/Indiana/Indianapolis",
+ "America/Jujuy": "America/Argentina/Jujuy",
+ "America/Knox_IN": "America/Indiana/Knox",
+ "America/Kralendijk": "America/Curacao",
+ "America/Louisville": "America/Kentucky/Louisville",
+ "America/Lower_Princes": "America/Curacao",
+ "America/Marigot": "America/Port_of_Spain",
+ "America/Mendoza": "America/Argentina/Mendoza",
+ "America/Porto_Acre": "America/Rio_Branco",
+ "America/Santa_Isabel": "America/Tijuana",
+ "America/Shiprock": "America/Denver",
+ "America/St_Barthelemy": "America/Port_of_Spain",
+ "America/Virgin": "America/St_Thomas",
+ "Antarctica/South_Pole": "Antarctica/McMurdo",
+ "Arctic/Longyearbyen": "Europe/Oslo",
+ "Asia/Ashkhabad": "Asia/Ashgabat",
+ "Asia/Calcutta": "Asia/Kolkata",
+ "Asia/Chungking": "Asia/Chongqing",
+ "Asia/Dacca": "Asia/Dhaka",
+ "Asia/Istanbul": "Europe/Istanbul",
+ "Asia/Katmandu": "Asia/Kathmandu",
+ "Asia/Macao": "Asia/Macau",
+ "Asia/Rangoon": "Asia/Yangon",
+ "Asia/Saigon": "Asia/Ho_Chi_Minh",
+ "Asia/Thimbu": "Asia/Thimphu",
+ "Asia/Ujung_Pandang": "Asia/Makassar",
+ "Asia/Ulan_Bator": "Asia/Ulaanbaatar",
+ "Atlantic/Faeroe": "Atlantic/Faroe",
+ "Australia/ACT": "Australia/Sydney",
+ "Australia/Canberra": "Australia/Sydney",
+ "Australia/LHI": "Australia/Lord_Howe",
+ "Australia/NSW": "Australia/Sydney",
+ "Australia/North": "Australia/Darwin",
+ "Australia/Queensland": "Australia/Brisbane",
+ "Australia/South": "Australia/Adelaide",
+ "Australia/Tasmania": "Australia/Hobart",
+ "Australia/Victoria": "Australia/Melbourne",
+ "Australia/West": "Australia/Perth",
+ "Australia/Yancowinna": "Australia/Broken_Hill",
+ "Brazil/Acre": "America/Rio_Branco",
+ "Brazil/DeNoronha": "America/Noronha",
+ "Brazil/East": "America/Sao_Paulo",
+ "Brazil/West": "America/Manaus",
+ "Canada/Atlantic": "America/Halifax",
+ "Canada/Central": "America/Winnipeg",
+ "Canada/Eastern": "America/Toronto",
+ "Canada/Mountain": "America/Edmonton",
+ "Canada/Newfoundland": "America/St_Johns",
+ "Canada/Pacific": "America/Vancouver",
+ "Canada/Saskatchewan": "America/Regina",
+ "Canada/Yukon": "America/Whitehorse",
+ "Chile/Continental": "America/Santiago",
+ "Chile/EasterIsland": "Pacific/Easter",
+ "Cuba": "America/Havana",
+ "Egypt": "Africa/Cairo",
+ "Eire": "Europe/Dublin",
+ "Etc/GMT+0": "Etc/GMT",
+ "Etc/GMT-0": "Etc/GMT",
+ "Etc/GMT0": "Etc/GMT",
+ "Etc/Greenwich": "Etc/GMT",
+ "Etc/UCT": "Etc/UTC",
+ "Etc/Universal": "Etc/UTC",
+ "Etc/Zulu": "Etc/UTC",
+ "Europe/Bratislava": "Europe/Prague",
+ "Europe/Busingen": "Europe/Zurich",
+ "Europe/Kiev": "Europe/Kyiv",
+ "Europe/Mariehamn": "Europe/Helsinki",
+ "Europe/Nicosia": "Asia/Nicosia",
+ "Europe/Podgorica": "Europe/Belgrade",
+ "Europe/San_Marino": "Europe/Rome",
+ "Europe/Vatican": "Europe/Rome",
+ "GB": "Europe/London",
+ "GB-Eire": "Europe/London",
+ "GMT+0": "Etc/GMT",
+ "GMT-0": "Etc/GMT",
+ "GMT0": "Etc/GMT",
+ "Greenwich": "Etc/GMT",
+ "Hongkong": "Asia/Hong_Kong",
+ "Iceland": "Atlantic/Reykjavik",
+ "Iran": "Asia/Tehran",
+ "Israel": "Asia/Jerusalem",
+ "Jamaica": "America/Jamaica",
+ "Japan": "Asia/Tokyo",
+ "Kwajalein": "Pacific/Kwajalein",
+ "Libya": "Africa/Tripoli",
+ "Mexico/BajaNorte": "America/Tijuana",
+ "Mexico/BajaSur": "America/Mazatlan",
+ "Mexico/General": "America/Mexico_City",
+ "NZ": "Pacific/Auckland",
+ "NZ-CHAT": "Pacific/Chatham",
+ "Navajo": "America/Denver",
+ "PRC": "Asia/Shanghai",
+ "Pacific/Ponape": "Pacific/Pohnpei",
+ "Pacific/Samoa": "Pacific/Pago_Pago",
+ "Pacific/Truk": "Pacific/Chuuk",
+ "Pacific/Yap": "Pacific/Chuuk",
+ "Poland": "Europe/Warsaw",
+ "Portugal": "Europe/Lisbon",
+ "ROC": "Asia/Taipei",
+ "ROK": "Asia/Seoul",
+ "Singapore": "Asia/Singapore",
+ "Turkey": "Europe/Istanbul",
+ "UCT": "Etc/UTC",
+ "US/Alaska": "America/Anchorage",
+ "US/Aleutian": "America/Adak",
+ "US/Arizona": "America/Phoenix",
+ "US/Central": "America/Chicago",
+ "US/East-Indiana": "America/Indiana/Indianapolis",
+ "US/Eastern": "America/New_York",
+ "US/Hawaii": "Pacific/Honolulu",
+ "US/Indiana-Starke": "America/Indiana/Knox",
+ "US/Michigan": "America/Detroit",
+ "US/Mountain": "America/Denver",
+ "US/Pacific": "America/Los_Angeles",
+ "US/Samoa": "Pacific/Pago_Pago",
+ "UTC": "Etc/UTC",
+ "Universal": "Etc/UTC",
+ "W-SU": "Europe/Moscow",
+ "Zulu": "Etc/UTC",
+};
+
+for (let [linkName, target] of Object.entries(links)) {
+ if (target === "Etc/UTC" || target === "Etc/GMT")
+ target = "UTC";
+
+ for (let map of tzMapper) {
+ let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(linkName)});
+ let resolvedTimeZone = dtf.resolvedOptions().timeZone;
+ assertEq(resolvedTimeZone, target, `${linkName} -> ${target}`);
+ }
+}
+
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
+
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone.js b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone.js
new file mode 100644
index 0000000000..0c5882deca
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone.js
@@ -0,0 +1,153 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Generated by make_intl_data.py. DO NOT EDIT.
+// tzdata version = 2023c
+
+const tzMapper = [
+ x => x,
+ x => x.toUpperCase(),
+ x => x.toLowerCase(),
+];
+
+// This file was generated with historical, pre-1970 backzone information
+// respected. Therefore, every zone key listed below is its own Zone, not
+// a Link to a modern-day target as IANA ignoring backzones would say.
+
+// Backzone zones derived from IANA Time Zone Database.
+const links = {
+ "Africa/Accra": "Africa/Accra",
+ "Africa/Addis_Ababa": "Africa/Addis_Ababa",
+ "Africa/Asmara": "Africa/Asmara",
+ "Africa/Bamako": "Africa/Bamako",
+ "Africa/Bangui": "Africa/Bangui",
+ "Africa/Banjul": "Africa/Banjul",
+ "Africa/Blantyre": "Africa/Blantyre",
+ "Africa/Brazzaville": "Africa/Brazzaville",
+ "Africa/Bujumbura": "Africa/Bujumbura",
+ "Africa/Conakry": "Africa/Conakry",
+ "Africa/Dakar": "Africa/Dakar",
+ "Africa/Dar_es_Salaam": "Africa/Dar_es_Salaam",
+ "Africa/Djibouti": "Africa/Djibouti",
+ "Africa/Douala": "Africa/Douala",
+ "Africa/Freetown": "Africa/Freetown",
+ "Africa/Gaborone": "Africa/Gaborone",
+ "Africa/Harare": "Africa/Harare",
+ "Africa/Kampala": "Africa/Kampala",
+ "Africa/Kigali": "Africa/Kigali",
+ "Africa/Kinshasa": "Africa/Kinshasa",
+ "Africa/Libreville": "Africa/Libreville",
+ "Africa/Lome": "Africa/Lome",
+ "Africa/Luanda": "Africa/Luanda",
+ "Africa/Lubumbashi": "Africa/Lubumbashi",
+ "Africa/Lusaka": "Africa/Lusaka",
+ "Africa/Malabo": "Africa/Malabo",
+ "Africa/Maseru": "Africa/Maseru",
+ "Africa/Mbabane": "Africa/Mbabane",
+ "Africa/Mogadishu": "Africa/Mogadishu",
+ "Africa/Niamey": "Africa/Niamey",
+ "Africa/Nouakchott": "Africa/Nouakchott",
+ "Africa/Ouagadougou": "Africa/Ouagadougou",
+ "Africa/Porto-Novo": "Africa/Porto-Novo",
+ "Africa/Timbuktu": "Africa/Timbuktu",
+ "America/Anguilla": "America/Anguilla",
+ "America/Antigua": "America/Antigua",
+ "America/Argentina/ComodRivadavia": "America/Argentina/ComodRivadavia",
+ "America/Aruba": "America/Aruba",
+ "America/Atikokan": "America/Atikokan",
+ "America/Blanc-Sablon": "America/Blanc-Sablon",
+ "America/Cayman": "America/Cayman",
+ "America/Coral_Harbour": "America/Coral_Harbour",
+ "America/Creston": "America/Creston",
+ "America/Curacao": "America/Curacao",
+ "America/Dominica": "America/Dominica",
+ "America/Ensenada": "America/Ensenada",
+ "America/Grenada": "America/Grenada",
+ "America/Guadeloupe": "America/Guadeloupe",
+ "America/Montreal": "America/Montreal",
+ "America/Montserrat": "America/Montserrat",
+ "America/Nassau": "America/Nassau",
+ "America/Nipigon": "America/Nipigon",
+ "America/Pangnirtung": "America/Pangnirtung",
+ "America/Port_of_Spain": "America/Port_of_Spain",
+ "America/Rainy_River": "America/Rainy_River",
+ "America/Rosario": "America/Rosario",
+ "America/St_Kitts": "America/St_Kitts",
+ "America/St_Lucia": "America/St_Lucia",
+ "America/St_Thomas": "America/St_Thomas",
+ "America/St_Vincent": "America/St_Vincent",
+ "America/Thunder_Bay": "America/Thunder_Bay",
+ "America/Tortola": "America/Tortola",
+ "America/Yellowknife": "America/Yellowknife",
+ "Antarctica/DumontDUrville": "Antarctica/DumontDUrville",
+ "Antarctica/McMurdo": "Antarctica/McMurdo",
+ "Antarctica/Syowa": "Antarctica/Syowa",
+ "Antarctica/Vostok": "Antarctica/Vostok",
+ "Asia/Aden": "Asia/Aden",
+ "Asia/Bahrain": "Asia/Bahrain",
+ "Asia/Brunei": "Asia/Brunei",
+ "Asia/Chongqing": "Asia/Chongqing",
+ "Asia/Harbin": "Asia/Harbin",
+ "Asia/Kashgar": "Asia/Kashgar",
+ "Asia/Kuala_Lumpur": "Asia/Kuala_Lumpur",
+ "Asia/Kuwait": "Asia/Kuwait",
+ "Asia/Muscat": "Asia/Muscat",
+ "Asia/Phnom_Penh": "Asia/Phnom_Penh",
+ "Asia/Tel_Aviv": "Asia/Tel_Aviv",
+ "Asia/Vientiane": "Asia/Vientiane",
+ "Atlantic/Jan_Mayen": "Atlantic/Jan_Mayen",
+ "Atlantic/Reykjavik": "Atlantic/Reykjavik",
+ "Atlantic/St_Helena": "Atlantic/St_Helena",
+ "Australia/Currie": "Australia/Currie",
+ "Europe/Amsterdam": "Europe/Amsterdam",
+ "Europe/Belfast": "Europe/Belfast",
+ "Europe/Copenhagen": "Europe/Copenhagen",
+ "Europe/Guernsey": "Europe/Guernsey",
+ "Europe/Isle_of_Man": "Europe/Isle_of_Man",
+ "Europe/Jersey": "Europe/Jersey",
+ "Europe/Ljubljana": "Europe/Ljubljana",
+ "Europe/Luxembourg": "Europe/Luxembourg",
+ "Europe/Monaco": "Europe/Monaco",
+ "Europe/Oslo": "Europe/Oslo",
+ "Europe/Sarajevo": "Europe/Sarajevo",
+ "Europe/Skopje": "Europe/Skopje",
+ "Europe/Stockholm": "Europe/Stockholm",
+ "Europe/Tiraspol": "Europe/Tiraspol",
+ "Europe/Uzhgorod": "Europe/Uzhgorod",
+ "Europe/Vaduz": "Europe/Vaduz",
+ "Europe/Zagreb": "Europe/Zagreb",
+ "Europe/Zaporozhye": "Europe/Zaporozhye",
+ "Indian/Antananarivo": "Indian/Antananarivo",
+ "Indian/Christmas": "Indian/Christmas",
+ "Indian/Cocos": "Indian/Cocos",
+ "Indian/Comoro": "Indian/Comoro",
+ "Indian/Kerguelen": "Indian/Kerguelen",
+ "Indian/Mahe": "Indian/Mahe",
+ "Indian/Mayotte": "Indian/Mayotte",
+ "Indian/Reunion": "Indian/Reunion",
+ "Pacific/Chuuk": "Pacific/Chuuk",
+ "Pacific/Enderbury": "Pacific/Enderbury",
+ "Pacific/Funafuti": "Pacific/Funafuti",
+ "Pacific/Johnston": "Pacific/Johnston",
+ "Pacific/Majuro": "Pacific/Majuro",
+ "Pacific/Midway": "Pacific/Midway",
+ "Pacific/Pohnpei": "Pacific/Pohnpei",
+ "Pacific/Saipan": "Pacific/Saipan",
+ "Pacific/Wake": "Pacific/Wake",
+ "Pacific/Wallis": "Pacific/Wallis",
+};
+
+for (let [linkName, target] of Object.entries(links)) {
+ if (target === "Etc/UTC" || target === "Etc/GMT")
+ target = "UTC";
+
+ for (let map of tzMapper) {
+ let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(linkName)});
+ let resolvedTimeZone = dtf.resolvedOptions().timeZone;
+ assertEq(resolvedTimeZone, target, `${linkName} -> ${target}`);
+ }
+}
+
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
+
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone_links.js b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone_links.js
new file mode 100644
index 0000000000..15806dd42c
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone_links.js
@@ -0,0 +1,48 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Generated by make_intl_data.py. DO NOT EDIT.
+// tzdata version = 2023c
+
+const tzMapper = [
+ x => x,
+ x => x.toUpperCase(),
+ x => x.toLowerCase(),
+];
+
+// This file was generated with historical, pre-1970 backzone information
+// respected. Therefore, every zone key listed below points to a target
+// in the backzone file and not to its modern-day target as IANA ignoring
+// backzones would say.
+
+// Backzone links derived from IANA Time Zone Database.
+const links = {
+ "Africa/Asmera": "Africa/Asmara",
+ "America/Kralendijk": "America/Curacao",
+ "America/Lower_Princes": "America/Curacao",
+ "America/Marigot": "America/Port_of_Spain",
+ "America/St_Barthelemy": "America/Port_of_Spain",
+ "America/Virgin": "America/St_Thomas",
+ "Antarctica/South_Pole": "Antarctica/McMurdo",
+ "Arctic/Longyearbyen": "Europe/Oslo",
+ "Asia/Chungking": "Asia/Chongqing",
+ "Iceland": "Atlantic/Reykjavik",
+ "Pacific/Ponape": "Pacific/Pohnpei",
+ "Pacific/Truk": "Pacific/Chuuk",
+ "Pacific/Yap": "Pacific/Chuuk",
+};
+
+for (let [linkName, target] of Object.entries(links)) {
+ if (target === "Etc/UTC" || target === "Etc/GMT")
+ target = "UTC";
+
+ for (let map of tzMapper) {
+ let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(linkName)});
+ let resolvedTimeZone = dtf.resolvedOptions().timeZone;
+ assertEq(resolvedTimeZone, target, `${linkName} -> ${target}`);
+ }
+}
+
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
+
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/timeZone_notbackward_links.js b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_notbackward_links.js
new file mode 100644
index 0000000000..7dbd456c2e
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_notbackward_links.js
@@ -0,0 +1,31 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Generated by make_intl_data.py. DO NOT EDIT.
+// tzdata version = 2023c
+
+const tzMapper = [
+ x => x,
+ x => x.toUpperCase(),
+ x => x.toLowerCase(),
+];
+
+// Link names derived from IANA Time Zone Database, excluding backward file.
+const links = {
+ "GMT": "Etc/GMT",
+};
+
+for (let [linkName, target] of Object.entries(links)) {
+ if (target === "Etc/UTC" || target === "Etc/GMT")
+ target = "UTC";
+
+ for (let map of tzMapper) {
+ let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(linkName)});
+ let resolvedTimeZone = dtf.resolvedOptions().timeZone;
+ assertEq(resolvedTimeZone, target, `${linkName} -> ${target}`);
+ }
+}
+
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
+
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/timeZone_version.js b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_version.js
new file mode 100644
index 0000000000..15c7553dd8
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_version.js
@@ -0,0 +1,17 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Generated by make_intl_data.py. DO NOT EDIT.
+// tzdata version = 2023c
+const tzdata = "2023c";
+
+if (typeof getICUOptions === "undefined") {
+ var getICUOptions = SpecialPowers.Cu.getJSTestingFunctions().getICUOptions;
+}
+
+var options = getICUOptions();
+
+assertEq(options.tzdata, tzdata);
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
+
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/toStringTag.js b/js/src/tests/non262/Intl/DateTimeFormat/toStringTag.js
new file mode 100644
index 0000000000..136632f71f
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/toStringTag.js
@@ -0,0 +1,29 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+var desc = Object.getOwnPropertyDescriptor(Intl.DateTimeFormat.prototype, Symbol.toStringTag);
+
+assertEq(desc !== undefined, true);
+assertEq(desc.value, "Intl.DateTimeFormat");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+assertEq(Object.prototype.toString.call(Intl.DateTimeFormat.prototype), "[object Intl.DateTimeFormat]");
+assertEq(Object.prototype.toString.call(new Intl.DateTimeFormat), "[object Intl.DateTimeFormat]");
+
+Object.defineProperty(Intl.DateTimeFormat.prototype, Symbol.toStringTag, {value: "DateTimeFormat"});
+
+assertEq(Object.prototype.toString.call(Intl.DateTimeFormat.prototype), "[object DateTimeFormat]");
+assertEq(Object.prototype.toString.call(new Intl.DateTimeFormat), "[object DateTimeFormat]");
+
+delete Intl.DateTimeFormat.prototype[Symbol.toStringTag];
+
+assertEq(Object.prototype.toString.call(Intl.DateTimeFormat.prototype), "[object Object]");
+assertEq(Object.prototype.toString.call(new Intl.DateTimeFormat), "[object Object]");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/tz-environment-variable.js b/js/src/tests/non262/Intl/DateTimeFormat/tz-environment-variable.js
new file mode 100644
index 0000000000..6128abb9d1
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/tz-environment-variable.js
@@ -0,0 +1,67 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||(xulRuntime.OS=="WINNT"&&!xulRuntime.shell)) -- Windows browser in automation doesn't pick up new time zones correctly
+
+// From bug 1330149:
+//
+// Windows only supports a very limited set of IANA time zone names for the TZ
+// environment variable.
+//
+// TZ format supported by Windows: "TZ=tzn[+|-]hh[:mm[:ss]][dzn]".
+//
+// Complete list of all IANA time zone ids matching that format.
+//
+// From tzdata's "northamerica" file:
+// EST5EDT
+// CST6CDT
+// MST7MDT
+// PST8PDT
+//
+// From tzdata's "backward" file:
+// GMT+0
+// GMT-0
+// GMT0
+//
+// Also supported on Windows even though they don't match the format listed
+// above.
+//
+// From tzdata's "backward" file:
+// UCT
+// UTC
+//
+// From tzdata's "etcetera" file:
+// GMT
+
+function inTimeZone(tzname, fn) {
+ setTimeZone(tzname);
+ try {
+ fn();
+ } finally {
+ setTimeZone("PST8PDT");
+ }
+}
+
+const timeZones = [
+ { id: "EST5EDT" },
+ { id: "CST6CDT" },
+ { id: "MST7MDT" },
+ { id: "PST8PDT" },
+ // ICU on non-Windows platforms doesn't accept these three time zone
+ // identifiers, cf. isValidOlsonID in $ICU/source/common/putil.cpp. We
+ // could add support for them, but it seems unlikely they're used in
+ // practice, so we just skip over them.
+ // { id: "GMT+0", normalized: "UTC" },
+ // { id: "GMT-0", normalized: "UTC" },
+ // { id: "GMT0", normalized: "UTC" },
+ { id: "UCT", normalized: "UTC" },
+ { id: "UTC", normalized: "UTC" },
+ { id: "GMT", normalized: "UTC" },
+];
+
+for (let {id, normalized = id} of timeZones) {
+ inTimeZone(id, () => {
+ let opts = new Intl.DateTimeFormat().resolvedOptions();
+ assertEq(opts.timeZone, normalized);
+ });
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/DateTimeFormat/unwrapping.js b/js/src/tests/non262/Intl/DateTimeFormat/unwrapping.js
new file mode 100644
index 0000000000..d2fc991cb4
--- /dev/null
+++ b/js/src/tests/non262/Intl/DateTimeFormat/unwrapping.js
@@ -0,0 +1,248 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Test UnwrapDateTimeFormat operation.
+
+const dateTimeFormatFunctions = [];
+dateTimeFormatFunctions.push({
+ function: Intl.DateTimeFormat.prototype.resolvedOptions,
+ unwrap: true,
+});
+dateTimeFormatFunctions.push({
+ function: Object.getOwnPropertyDescriptor(Intl.DateTimeFormat.prototype, "format").get,
+ unwrap: true,
+});
+dateTimeFormatFunctions.push({
+ function: Intl.DateTimeFormat.prototype.formatToParts,
+ unwrap: false,
+});
+
+function IsIntlService(c) {
+ return typeof c === "function" &&
+ c.hasOwnProperty("prototype") &&
+ c.prototype.hasOwnProperty("resolvedOptions");
+}
+
+function IsObject(o) {
+ return Object(o) === o;
+}
+
+function IsPrimitive(o) {
+ return Object(o) !== o;
+}
+
+function intlObjects(ctor) {
+ let args = [];
+ if (ctor === Intl.DisplayNames) {
+ // Intl.DisplayNames can't be constructed without any arguments.
+ args = [undefined, {type: "language"}];
+ }
+
+ return [
+ // Instance of an Intl constructor.
+ new ctor(...args),
+
+ // Instance of a subclassed Intl constructor.
+ new class extends ctor {}(...args),
+
+ // Intl object not inheriting from its default prototype.
+ Object.setPrototypeOf(new ctor(...args), Object.prototype),
+ ];
+}
+
+function thisValues(C) {
+ const intlConstructors = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService);
+
+ return [
+ // Primitive values.
+ ...[undefined, null, true, "abc", Symbol(), 123],
+
+ // Object values.
+ ...[{}, [], /(?:)/, function(){}, new Proxy({}, {})],
+
+ // Intl objects.
+ ...[].concat(...intlConstructors.filter(ctor => ctor !== C).map(intlObjects)),
+
+ // Object inheriting from an Intl constructor prototype.
+ ...intlConstructors.map(ctor => Object.create(ctor.prototype)),
+ ];
+}
+
+const intlFallbackSymbol = Object.getOwnPropertySymbols(Intl.DateTimeFormat.call(Object.create(Intl.DateTimeFormat.prototype)))[0];
+
+// Test Intl.DateTimeFormat.prototype methods.
+for (let {function: dateTimeFormatFunction, unwrap} of dateTimeFormatFunctions) {
+ // Test a TypeError is thrown when the this-value isn't an initialized
+ // Intl.DateTimeFormat instance.
+ for (let thisValue of thisValues(Intl.DateTimeFormat)) {
+ assertThrowsInstanceOf(() => dateTimeFormatFunction.call(thisValue), TypeError);
+ }
+
+ // And test no error is thrown for initialized Intl.DateTimeFormat instances.
+ for (let thisValue of intlObjects(Intl.DateTimeFormat)) {
+ dateTimeFormatFunction.call(thisValue);
+ }
+
+ // Manually add [[FallbackSymbol]] to objects and then repeat the tests from above.
+ for (let thisValue of thisValues(Intl.DateTimeFormat)) {
+ assertThrowsInstanceOf(() => dateTimeFormatFunction.call({
+ __proto__: Intl.DateTimeFormat.prototype,
+ [intlFallbackSymbol]: thisValue,
+ }), TypeError);
+ }
+
+ for (let thisValue of intlObjects(Intl.DateTimeFormat)) {
+ let obj = {
+ __proto__: Intl.DateTimeFormat.prototype,
+ [intlFallbackSymbol]: thisValue,
+ };
+ if (unwrap) {
+ dateTimeFormatFunction.call(obj);
+ } else {
+ assertThrowsInstanceOf(() => dateTimeFormatFunction.call(obj), TypeError);
+ }
+ }
+
+ // Ensure [[FallbackSymbol]] isn't retrieved for Intl.DateTimeFormat instances.
+ for (let thisValue of intlObjects(Intl.DateTimeFormat)) {
+ Object.defineProperty(thisValue, intlFallbackSymbol, {
+ get() { assertEq(false, true); }
+ });
+ dateTimeFormatFunction.call(thisValue);
+ }
+
+ // Ensure [[FallbackSymbol]] is only retrieved for objects inheriting from Intl.DateTimeFormat.prototype.
+ for (let thisValue of thisValues(Intl.DateTimeFormat).filter(IsObject)) {
+ if (Intl.DateTimeFormat.prototype.isPrototypeOf(thisValue))
+ continue;
+ Object.defineProperty(thisValue, intlFallbackSymbol, {
+ get() { assertEq(false, true); }
+ });
+ assertThrowsInstanceOf(() => dateTimeFormatFunction.call(thisValue), TypeError);
+ }
+
+ // Repeat the test from above, but also change Intl.DateTimeFormat[@@hasInstance]
+ // so it always returns |true|.
+ for (let thisValue of thisValues(Intl.DateTimeFormat).filter(IsObject)) {
+ let isPrototypeOf = Intl.DateTimeFormat.prototype.isPrototypeOf(thisValue);
+ let hasInstanceCalled = false, symbolGetterCalled = false;
+ Object.defineProperty(Intl.DateTimeFormat, Symbol.hasInstance, {
+ value() {
+ assertEq(hasInstanceCalled, false);
+ hasInstanceCalled = true;
+ return true;
+ }, configurable: true
+ });
+ Object.defineProperty(thisValue, intlFallbackSymbol, {
+ get() {
+ assertEq(symbolGetterCalled, false);
+ symbolGetterCalled = true;
+ return null;
+ }, configurable: true
+ });
+
+ assertThrowsInstanceOf(() => dateTimeFormatFunction.call(thisValue), TypeError);
+
+ delete Intl.DateTimeFormat[Symbol.hasInstance];
+
+ assertEq(hasInstanceCalled, false);
+ assertEq(symbolGetterCalled, unwrap && isPrototypeOf);
+ }
+
+ // Test with primitive values.
+ for (let thisValue of thisValues(Intl.DateTimeFormat).filter(IsPrimitive)) {
+ // Ensure @@hasInstance is not called.
+ Object.defineProperty(Intl.DateTimeFormat, Symbol.hasInstance, {
+ value() { assertEq(true, false); }, configurable: true
+ });
+ let isUndefinedOrNull = thisValue === undefined || thisValue === null;
+ let symbolHolder;
+ if (!isUndefinedOrNull) {
+ // Ensure the fallback symbol isn't retrieved from the primitive wrapper prototype.
+ symbolHolder = Object.getPrototypeOf(thisValue);
+ Object.defineProperty(symbolHolder, intlFallbackSymbol, {
+ get() { assertEq(true, false); }, configurable: true
+ });
+ }
+
+ assertThrowsInstanceOf(() => dateTimeFormatFunction.call(thisValue), TypeError);
+
+ delete Intl.DateTimeFormat[Symbol.hasInstance];
+ if (!isUndefinedOrNull)
+ delete symbolHolder[intlFallbackSymbol];
+ }
+}
+
+// Test format() returns the correct result for objects initialized as Intl.DateTimeFormat instances.
+{
+ // An actual Intl.DateTimeFormat instance.
+ let dateTimeFormat = new Intl.DateTimeFormat();
+
+ // An object initialized as a DateTimeFormat instance.
+ let thisValue = Object.create(Intl.DateTimeFormat.prototype);
+ Intl.DateTimeFormat.call(thisValue);
+
+ // Object with [[FallbackSymbol]] set to DateTimeFormat instance.
+ let fakeObj = {
+ __proto__: Intl.DateTimeFormat.prototype,
+ [intlFallbackSymbol]: dateTimeFormat,
+ };
+
+ for (let number of [0, Date.now(), -Date.now()]) {
+ let expected = dateTimeFormat.format(number);
+ assertEq(thisValue.format(number), expected);
+ assertEq(thisValue[intlFallbackSymbol].format(number), expected);
+ assertEq(fakeObj.format(number), expected);
+ }
+}
+
+// Ensure formatToParts() doesn't use the fallback semantics.
+{
+ let formatToParts = Intl.DateTimeFormat.prototype.formatToParts;
+
+ // An object initialized as a DateTimeFormat instance.
+ let thisValue = Object.create(Intl.DateTimeFormat.prototype);
+ Intl.DateTimeFormat.call(thisValue);
+ assertThrowsInstanceOf(() => formatToParts.call(thisValue), TypeError);
+
+ // Object with [[FallbackSymbol]] set to DateTimeFormat instance.
+ let fakeObj = {
+ __proto__: Intl.DateTimeFormat.prototype,
+ [intlFallbackSymbol]: new Intl.DateTimeFormat(),
+ };
+ assertThrowsInstanceOf(() => formatToParts.call(fakeObj), TypeError);
+}
+
+// Test resolvedOptions() returns the same results.
+{
+ // An actual Intl.DateTimeFormat instance.
+ let dateTimeFormat = new Intl.DateTimeFormat();
+
+ // An object initialized as a DateTimeFormat instance.
+ let thisValue = Object.create(Intl.DateTimeFormat.prototype);
+ Intl.DateTimeFormat.call(thisValue);
+
+ // Object with [[FallbackSymbol]] set to DateTimeFormat instance.
+ let fakeObj = {
+ __proto__: Intl.DateTimeFormat.prototype,
+ [intlFallbackSymbol]: dateTimeFormat,
+ };
+
+ function assertEqOptions(actual, expected) {
+ actual = Object.entries(actual);
+ expected = Object.entries(expected);
+
+ assertEq(actual.length, expected.length, "options count mismatch");
+ for (var i = 0; i < expected.length; i++) {
+ assertEq(actual[i][0], expected[i][0], "key mismatch at " + i);
+ assertEq(actual[i][1], expected[i][1], "value mismatch at " + i);
+ }
+ }
+
+ let expected = dateTimeFormat.resolvedOptions();
+ assertEqOptions(thisValue.resolvedOptions(), expected);
+ assertEqOptions(thisValue[intlFallbackSymbol].resolvedOptions(), expected);
+ assertEqOptions(fakeObj.resolvedOptions(), expected);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/DisplayNames/abbreviated.js b/js/src/tests/non262/Intl/DisplayNames/abbreviated.js
new file mode 100644
index 0000000000..4203ffcbac
--- /dev/null
+++ b/js/src/tests/non262/Intl/DisplayNames/abbreviated.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.hasOwnProperty('addIntlExtras'))
+
+addMozIntlDisplayNames(this);
+
+const tests = {
+ "en": {
+ long: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
+ abbreviated: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
+ short: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
+ narrow: ["M", "T", "W", "T", "F", "S", "S"],
+ },
+};
+
+for (let [locale, localeTests] of Object.entries(tests)) {
+ for (let [style, weekdays] of Object.entries(localeTests)) {
+ let dn = new Intl.DisplayNames(locale, {type: "weekday", style});
+
+ let resolved = dn.resolvedOptions();
+ assertEq(resolved.style, style);
+
+ for (let [day, expected] of weekdays.entries()) {
+ assertEq(dn.of(day + 1), expected);
+ }
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/DisplayNames/alias-and-parent-locales.js b/js/src/tests/non262/Intl/DisplayNames/alias-and-parent-locales.js
new file mode 100644
index 0000000000..d60a1593d4
--- /dev/null
+++ b/js/src/tests/non262/Intl/DisplayNames/alias-and-parent-locales.js
@@ -0,0 +1,33 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+// Ensure alias and parent locales are correctly picked up when calling into ICU.
+
+// "zh-HK" is an alias to "zh-Hant-HK", so display names should default to
+// traditional instead of simplified characters.
+{
+ const zh_Hant = new Intl.DisplayNames("zh-Hant", {type: "region"});
+ const zh_Hans = new Intl.DisplayNames("zh-Hans", {type: "region"});
+ const zh_HK = new Intl.DisplayNames("zh-HK", {type: "region"});
+
+ // We assume traditional and simplified have different outputs.
+ assertEq(zh_Hant.of("US") === zh_Hans.of("US"), false);
+
+ // "zh-HK" should use traditional characters.
+ assertEq(zh_HK.of("US"), zh_Hant.of("US"));
+}
+
+// The parent locale of "en-AU" is "en-001" and not "en" (because "en" actually means "en-US").
+{
+ const en = new Intl.DisplayNames("en", {type: "language"});
+ const en_001 = new Intl.DisplayNames("en-001", {type: "language"});
+ const en_AU = new Intl.DisplayNames("en-AU", {type: "language"});
+
+ // We assume "en" and "en-001" have different outputs.
+ assertEq(en.of("nds-NL") === en_001.of("nds-NL"), false);
+
+ // "en-AU" should have the same output as "en-001".
+ assertEq(en_AU.of("nds-NL"), en_001.of("nds-NL"));
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/DisplayNames/browser.js b/js/src/tests/non262/Intl/DisplayNames/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Intl/DisplayNames/browser.js
diff --git a/js/src/tests/non262/Intl/DisplayNames/calendar.js b/js/src/tests/non262/Intl/DisplayNames/calendar.js
new file mode 100644
index 0000000000..0700ee2888
--- /dev/null
+++ b/js/src/tests/non262/Intl/DisplayNames/calendar.js
@@ -0,0 +1,123 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+const tests = {
+ "en": {
+ long: {
+ "gregory": "Gregorian Calendar",
+ "iso8601": "ISO-8601 Calendar",
+ "japanese": "Japanese Calendar",
+ "islamic-civil": "Islamic Calendar (tabular, civil epoch)",
+ "islamicc": "Islamic Calendar (tabular, civil epoch)",
+ "ethioaa": "Ethiopic Amete Alem Calendar",
+ "ethiopic-amete-alem": "Ethiopic Amete Alem Calendar",
+ },
+ short: {},
+ narrow: {},
+ },
+ "de": {
+ long: {
+ "gregory": "Gregorianischer Kalender",
+ "iso8601": "ISO-8601-Kalender",
+ "japanese": "Japanischer Kalender",
+ "islamic-civil": "Bürgerlicher islamischer Kalender (tabellarisch)",
+ "islamicc": "Bürgerlicher islamischer Kalender (tabellarisch)",
+ "ethioaa": "Äthiopischer Amätä-Aläm-Kalender",
+ "ethiopic-amete-alem": "Äthiopischer Amätä-Aläm-Kalender",
+ },
+ short: {},
+ narrow: {},
+ },
+ "fr": {
+ long: {
+ "gregory": "calendrier grégorien",
+ "iso8601": "calendrier ISO 8601",
+ "japanese": "calendrier japonais",
+ "islamic-civil": "calendrier musulman (tabulaire, époque civile)",
+ "islamicc": "calendrier musulman (tabulaire, époque civile)",
+ "ethioaa": "calendrier éthiopien Amete Alem",
+ "ethiopic-amete-alem": "calendrier éthiopien Amete Alem",
+ },
+ short: {},
+ narrow: {},
+ },
+ "zh": {
+ long: {
+ "gregory": "公历",
+ "iso8601": "国际标准历法",
+ "japanese": "和历",
+ "islamic-civil": "伊斯兰希吉来日历",
+ "islamicc": "伊斯兰希吉来日历",
+ "ethioaa": "埃塞俄比亚阿米特阿莱姆日历",
+ "ethiopic-amete-alem": "埃塞俄比亚阿米特阿莱姆日历",
+ },
+ short: {},
+ narrow: {},
+ },
+};
+
+for (let [locale, localeTests] of Object.entries(tests)) {
+ for (let [style, styleTests] of Object.entries(localeTests)) {
+ let dn = new Intl.DisplayNames(locale, {type: "calendar", style});
+
+ let resolved = dn.resolvedOptions();
+ assertEq(resolved.locale, locale);
+ assertEq(resolved.style, style);
+ assertEq(resolved.type, "calendar");
+ assertEq(resolved.fallback, "code");
+
+ let inheritedTests = {...localeTests.long, ...localeTests.short, ...localeTests.narrow};
+ for (let [calendar, expected] of Object.entries({...inheritedTests, ...styleTests})) {
+ assertEq(dn.of(calendar), expected);
+
+ // Also works with objects.
+ assertEq(dn.of(Object(calendar)), expected);
+ }
+ }
+}
+
+{
+ let dn = new Intl.DisplayNames("en", {type: "calendar"});
+
+ // Performs ToString on the input and then validates the stringified result.
+ assertThrowsInstanceOf(() => dn.of(), RangeError);
+ assertThrowsInstanceOf(() => dn.of(undefined), RangeError);
+ assertThrowsInstanceOf(() => dn.of(Symbol()), TypeError);
+ assertThrowsInstanceOf(() => dn.of(0), RangeError);
+
+ // Throws an error if |code| isn't a well-formed calendar type.
+ assertThrowsInstanceOf(() => dn.of("gregorian"), RangeError);
+ assertThrowsInstanceOf(() => dn.of("grëgory"), RangeError);
+ assertThrowsInstanceOf(() => dn.of("grēgory"), RangeError);
+}
+
+// Test fallback behaviour.
+{
+ let dn1 = new Intl.DisplayNames("en", {type: "calendar"});
+ let dn2 = new Intl.DisplayNames("en", {type: "calendar", fallback: "code"});
+ let dn3 = new Intl.DisplayNames("en", {type: "calendar", fallback: "none"});
+
+ assertEq(dn1.resolvedOptions().fallback, "code");
+ assertEq(dn2.resolvedOptions().fallback, "code");
+ assertEq(dn3.resolvedOptions().fallback, "none");
+
+ // "invalid" isn't a known calendar type.
+ assertEq(dn1.of("invalid"), "invalid");
+ assertEq(dn2.of("invalid"), "invalid");
+ assertEq(dn3.of("invalid"), undefined);
+
+ // The returned fallback is in canonical case.
+ assertEq(dn1.of("INVALID"), "invalid");
+ assertEq(dn2.of("INVALID"), "invalid");
+ assertEq(dn3.of("INVALID"), undefined);
+}
+
+// Test when case isn't canonical.
+{
+ let dn = new Intl.DisplayNames("en", {type: "calendar", fallback: "none"});
+
+ assertEq(dn.of("gregory"), "Gregorian Calendar");
+ assertEq(dn.of("GREGORY"), "Gregorian Calendar");
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/DisplayNames/currency.js b/js/src/tests/non262/Intl/DisplayNames/currency.js
new file mode 100644
index 0000000000..1571249106
--- /dev/null
+++ b/js/src/tests/non262/Intl/DisplayNames/currency.js
@@ -0,0 +1,150 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+const tests = {
+ "en": {
+ long: {
+ "USD": "US Dollar",
+ "EUR": "Euro",
+ "FRF": "French Franc",
+ "CNY": "Chinese Yuan",
+ "XAU": "Gold",
+ },
+ short: {
+ "USD": "$",
+ "EUR": "€",
+ "FRF": "FRF",
+ "CNY": "CN¥",
+ "XAU": "XAU",
+ },
+ narrow: {
+ "USD": "USD",
+ "EUR": "EUR",
+ "CNY": "CNY",
+ },
+ },
+ "de": {
+ long: {
+ "USD": "US-Dollar",
+ "EUR": "Euro",
+ "FRF": "Französischer Franc",
+ "CNY": "Renminbi Yuan",
+ "XAU": "Unze Gold",
+ },
+ short: {
+ "USD": "$",
+ "EUR": "€",
+ "FRF": "FRF",
+ "CNY": "CN¥",
+ "XAU": "XAU",
+ },
+ narrow: {
+ "CNY": "¥",
+ },
+ },
+ "fr": {
+ long: {
+ "USD": "dollar des États-Unis",
+ "EUR": "euro",
+ "FRF": "franc français",
+ "CNY": "yuan renminbi chinois",
+ "XAU": "or",
+ },
+ short: {
+ "USD": "$US",
+ "EUR": "€",
+ "FRF": "F",
+ "CNY": "CNY",
+ "XAU": "XAU",
+ },
+ narrow: {
+ "USD": "$",
+ "CNY": "¥",
+ },
+ },
+ "zh": {
+ long: {
+ "USD": "美元",
+ "EUR": "欧元",
+ "FRF": "法国法郎",
+ "CNY": "人民币",
+ "XAU": "黄金",
+ },
+ short: {
+ "USD": "US$",
+ "EUR": "€",
+ "FRF": "FRF",
+ "CNY": "¥",
+ "XAU": "XAU",
+ },
+ narrow: {
+ "USD": "$",
+ },
+ },
+};
+
+for (let [locale, localeTests] of Object.entries(tests)) {
+ for (let [style, styleTests] of Object.entries(localeTests)) {
+ let dn = new Intl.DisplayNames(locale, {type: "currency", style});
+
+ let resolved = dn.resolvedOptions();
+ assertEq(resolved.locale, locale);
+ assertEq(resolved.style, style);
+ assertEq(resolved.type, "currency");
+ assertEq(resolved.fallback, "code");
+
+ let inheritedTests = {...localeTests.long, ...localeTests.short, ...localeTests.narrow};
+ for (let [currency, expected] of Object.entries({...inheritedTests, ...styleTests})) {
+ assertEq(dn.of(currency), expected);
+
+ // Also works with objects.
+ assertEq(dn.of(Object(currency)), expected);
+ }
+ }
+}
+
+{
+ let dn = new Intl.DisplayNames("en", {type: "currency"});
+
+ // Performs ToString on the input and then validates the stringified result.
+ assertThrowsInstanceOf(() => dn.of(), RangeError);
+ assertThrowsInstanceOf(() => dn.of(null), RangeError);
+ assertThrowsInstanceOf(() => dn.of(Symbol()), TypeError);
+ assertThrowsInstanceOf(() => dn.of(0), RangeError);
+
+ // Throws an error if |code| isn't a well-formed currency code.
+ assertThrowsInstanceOf(() => dn.of("us"), RangeError);
+ assertThrowsInstanceOf(() => dn.of("euro"), RangeError);
+ assertThrowsInstanceOf(() => dn.of("€uro"), RangeError);
+}
+
+// Test fallback behaviour.
+{
+ let dn1 = new Intl.DisplayNames("en", {type: "currency"});
+ let dn2 = new Intl.DisplayNames("en", {type: "currency", fallback: "code"});
+ let dn3 = new Intl.DisplayNames("en", {type: "currency", fallback: "none"});
+
+ assertEq(dn1.resolvedOptions().fallback, "code");
+ assertEq(dn2.resolvedOptions().fallback, "code");
+ assertEq(dn3.resolvedOptions().fallback, "none");
+
+ // "AAA" is not a registered currency code.
+ assertEq(dn1.of("AAA"), "AAA");
+ assertEq(dn2.of("AAA"), "AAA");
+ assertEq(dn3.of("AAA"), undefined);
+
+ // The returned fallback is in canonical case.
+ assertEq(dn1.of("aaa"), "AAA");
+ assertEq(dn2.of("aaa"), "AAA");
+ assertEq(dn3.of("aaa"), undefined);
+}
+
+// Test when case isn't canonical.
+{
+ let dn = new Intl.DisplayNames("en", {type: "currency", fallback: "none"});
+
+ assertEq(dn.of("USD"), "US Dollar");
+ assertEq(dn.of("usd"), "US Dollar");
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/DisplayNames/dateTimeField.js b/js/src/tests/non262/Intl/DisplayNames/dateTimeField.js
new file mode 100644
index 0000000000..94bdf53899
--- /dev/null
+++ b/js/src/tests/non262/Intl/DisplayNames/dateTimeField.js
@@ -0,0 +1,176 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+const tests = {
+ "en": {
+ long: {
+ "era": "era",
+ "year": "year",
+ "quarter": "quarter",
+ "month": "month",
+ "weekOfYear": "week",
+ "weekday": "day of the week",
+ "day": "day",
+ "dayPeriod": "AM/PM",
+ "hour": "hour",
+ "minute": "minute",
+ "second": "second",
+ "timeZoneName": "time zone",
+ },
+ short: {
+ "year": "yr.",
+ "quarter": "qtr.",
+ "month": "mo.",
+ "weekOfYear": "wk.",
+ "weekday": "day of wk.",
+ "dayPeriod": "AM/PM",
+ "hour": "hr.",
+ "minute": "min.",
+ "second": "sec.",
+ "timeZoneName": "zone",
+ },
+ narrow: {
+ "year": "yr",
+ "quarter": "qtr",
+ "month": "mo",
+ "weekOfYear": "wk",
+ "hour": "hr",
+ "minute": "min",
+ "second": "sec",
+ },
+ },
+ "de": {
+ long: {
+ "era": "Epoche",
+ "year": "Jahr",
+ "quarter": "Quartal",
+ "month": "Monat",
+ "weekOfYear": "Woche",
+ "weekday": "Wochentag",
+ "day": "Tag",
+ "dayPeriod": "Tageshälfte",
+ "hour": "Stunde",
+ "minute": "Minute",
+ "second": "Sekunde",
+ "timeZoneName": "Zeitzone",
+ },
+ short: {
+ "era": "Epoche",
+ "year": "Jahr",
+ "quarter": "Quart.",
+ "month": "Monat",
+ "weekOfYear": "Woche",
+ "weekday": "Wochentag",
+ "day": "Tag",
+ "dayPeriod": "Tageshälfte",
+ "hour": "Std.",
+ "minute": "Min.",
+ "second": "Sek.",
+ "timeZoneName": "Zeitzone",
+ },
+ narrow: {
+ "era": "E",
+ "year": "J",
+ "quarter": "Q",
+ "month": "M",
+ "weekOfYear": "W",
+ "weekday": "Wochent.",
+ "dayPeriod": "Tagesh.",
+ "timeZoneName": "Zeitz.",
+ },
+ },
+ "fr": {
+ long: {
+ "era": "ère",
+ "year": "année",
+ "quarter": "trimestre",
+ "month": "mois",
+ "weekOfYear": "semaine",
+ "weekday": "jour de la semaine",
+ "day": "jour",
+ "dayPeriod": "cadran",
+ "hour": "heure",
+ "minute": "minute",
+ "second": "seconde",
+ "timeZoneName": "fuseau horaire",
+ },
+ short: {
+ "year": "an",
+ "quarter": "trim.",
+ "month": "m.",
+ "weekOfYear": "sem.",
+ "weekday": "j (sem.)",
+ "day": "j",
+ "hour": "h",
+ "minute": "min",
+ "second": "s",
+ },
+ narrow: {
+ "year": "a",
+ },
+ },
+ "zh": {
+ long: {
+ "era": "纪元",
+ "year": "年",
+ "quarter": "季度",
+ "month": "月",
+ "weekOfYear": "周",
+ "weekday": "工作日",
+ "day": "日",
+ "dayPeriod": "上午/下午",
+ "hour": "小时",
+ "minute": "分钟",
+ "second": "秒",
+ "timeZoneName": "时区",
+ },
+ short: {
+ "quarter": "季",
+ "minute": "分",
+ },
+ narrow: {},
+ },
+};
+
+for (let [locale, localeTests] of Object.entries(tests)) {
+ for (let [style, styleTests] of Object.entries(localeTests)) {
+ let dn = new Intl.DisplayNames(locale, {type: "dateTimeField", style});
+
+ let resolved = dn.resolvedOptions();
+ assertEq(resolved.locale, locale);
+ assertEq(resolved.style, style);
+ assertEq(resolved.type, "dateTimeField");
+ assertEq(resolved.fallback, "code");
+
+ let inheritedTests = {...localeTests.long, ...localeTests.short, ...localeTests.narrow};
+ for (let [field, expected] of Object.entries({...inheritedTests, ...styleTests})) {
+ assertEq(dn.of(field), expected);
+
+ // Also works with objects.
+ assertEq(dn.of(Object(field)), expected);
+ }
+ }
+}
+
+{
+ let dn = new Intl.DisplayNames("en", {type: "dateTimeField"});
+
+ // Performs ToString on the input and then validates the stringified result.
+ assertThrowsInstanceOf(() => dn.of(), RangeError);
+ assertThrowsInstanceOf(() => dn.of(null), RangeError);
+ assertThrowsInstanceOf(() => dn.of(Symbol()), TypeError);
+ assertThrowsInstanceOf(() => dn.of(0), RangeError);
+ assertThrowsInstanceOf(() => dn.of(1), RangeError);
+
+ // Throws an error if not one of ["era", "year", "quarter", "month", "weekOfYear", "weekday",
+ // "day", "dayPeriod", "hour", "minute", "second", "timeZoneName"].
+ assertThrowsInstanceOf(() => dn.of(""), RangeError);
+ assertThrowsInstanceOf(() => dn.of("ERA"), RangeError);
+ assertThrowsInstanceOf(() => dn.of("Era"), RangeError);
+ assertThrowsInstanceOf(() => dn.of("era\0"), RangeError);
+ assertThrowsInstanceOf(() => dn.of("dayperiod"), RangeError);
+ assertThrowsInstanceOf(() => dn.of("day-period"), RangeError);
+ assertThrowsInstanceOf(() => dn.of("timezoneName"), RangeError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/DisplayNames/dayPeriod.js b/js/src/tests/non262/Intl/DisplayNames/dayPeriod.js
new file mode 100644
index 0000000000..cfeafdf5ee
--- /dev/null
+++ b/js/src/tests/non262/Intl/DisplayNames/dayPeriod.js
@@ -0,0 +1,80 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.hasOwnProperty('addIntlExtras'))
+
+addMozIntlDisplayNames(this);
+
+const tests = {
+ "en": {
+ long: {
+ "am": "AM",
+ "pm": "PM",
+ },
+ short: {},
+ narrow: {},
+ },
+ "de": {
+ long: {
+ "am": "AM",
+ "pm": "PM",
+ },
+ short: {},
+ narrow: {},
+ },
+ "fr": {
+ long: {
+ "am": "AM",
+ "pm": "PM",
+ },
+ short: {},
+ narrow: {},
+ },
+ "zh": {
+ long: {
+ "am": "上午",
+ "pm": "下午",
+ },
+ short: {},
+ narrow: {},
+ },
+};
+
+for (let [locale, localeTests] of Object.entries(tests)) {
+ let defaultCalendar = new Intl.DateTimeFormat(locale).resolvedOptions().calendar;
+
+ for (let [style, styleTests] of Object.entries(localeTests)) {
+ let dn = new Intl.DisplayNames(locale, {type: "dayPeriod", style});
+
+ let resolved = dn.resolvedOptions();
+ assertEq(resolved.locale, locale);
+ assertEq(resolved.calendar, defaultCalendar);
+ assertEq(resolved.style, style);
+ assertEq(resolved.type, "dayPeriod");
+ assertEq(resolved.fallback, "code");
+
+ let inheritedTests = {...localeTests.long, ...localeTests.short, ...localeTests.narrow};
+ for (let [dayPeriod, expected] of Object.entries({...inheritedTests, ...styleTests})) {
+ assertEq(dn.of(dayPeriod), expected);
+
+ // Also works with objects.
+ assertEq(dn.of(Object(dayPeriod)), expected);
+ }
+ }
+}
+
+{
+ let dn = new Intl.DisplayNames("en", {type: "dayPeriod"});
+
+ // Performs ToString on the input and then validates the stringified result.
+ assertThrowsInstanceOf(() => dn.of(), RangeError);
+ assertThrowsInstanceOf(() => dn.of(null), RangeError);
+ assertThrowsInstanceOf(() => dn.of(Symbol()), TypeError);
+ assertThrowsInstanceOf(() => dn.of(0), RangeError);
+ assertThrowsInstanceOf(() => dn.of(1), RangeError);
+
+ // Throws an error if not one of ["am", "pm"].
+ assertThrowsInstanceOf(() => dn.of(""), RangeError);
+ assertThrowsInstanceOf(() => dn.of("AM"), RangeError);
+ assertThrowsInstanceOf(() => dn.of("PM"), RangeError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/DisplayNames/language-dialect.js b/js/src/tests/non262/Intl/DisplayNames/language-dialect.js
new file mode 100644
index 0000000000..c2999bd673
--- /dev/null
+++ b/js/src/tests/non262/Intl/DisplayNames/language-dialect.js
@@ -0,0 +1,104 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+const tests = {
+ "en": {
+ long: {
+ "de": "German",
+ "de-AT": "Austrian German",
+ "de-1996": "German (German orthography of 1996)",
+ "en": "English",
+ "en-Hant-GB": "British English (Traditional)",
+ "en-Hans-US": "American English (Simplified)",
+ "fr": "French",
+ "nl-BE": "Flemish",
+ "cr-Cans": "Cree (Unified Canadian Aboriginal Syllabics)",
+ },
+ short: {
+ "en-Hant-GB": "UK English (Traditional)",
+ "en-Hans-US": "US English (Simplified)",
+ "cr-Cans": "Cree (UCAS)",
+ },
+ narrow: {},
+ },
+ "de": {
+ long: {
+ "de": "Deutsch",
+ "de-AT": "Österreichisches Deutsch",
+ "de-1996": "Deutsch (Neue deutsche Rechtschreibung)",
+ "en": "Englisch",
+ "en-Hant-GB": "Englisch (Traditionell, Vereinigtes Königreich)",
+ "en-Hans-US": "Englisch (Vereinfacht, Vereinigte Staaten)",
+ "fr": "Französisch",
+ "nl-BE": "Flämisch",
+ },
+ short: {
+ "en-Hant-GB": "Englisch (GB) (Traditionell)",
+ "en-Hans-US": "Englisch (USA) (Vereinfacht)",
+ },
+ narrow: {},
+ },
+ "fr": {
+ long: {
+ "de": "allemand",
+ "de-AT": "allemand autrichien",
+ "de-1996": "allemand (orthographe allemande de 1996)",
+ "en": "anglais",
+ "en-Hant-GB": "anglais britannique (traditionnel)",
+ "en-Hans-US": "anglais américain (simplifié)",
+ "fr": "français",
+ "nl-BE": "flamand",
+ },
+ short: {
+ "en-Hant-GB": "anglais britannique (traditionnel)",
+ "en-Hans-US": "anglais américain (simplifié)",
+ },
+ narrow: {},
+ },
+ "zh": {
+ long: {
+ "zh": "中文",
+ "zh-Hant": "繁体中文",
+ "zh-Hant-CN": "繁体中文(中国)",
+ "zh-Hans-HK": "简体中文(中国香港特别行政区)",
+ },
+ short: {
+ "zh-Hans-HK": "简体中文(香港)"
+ },
+ narrow: {},
+ },
+ "ar": {
+ long: {
+ "ar": "العربية",
+ "ar-SA": "العربية (المملكة العربية السعودية)",
+ "zh-MO": "الصينية (منطقة ماكاو الإدارية الخاصة)",
+ },
+ short: {
+ "zh-MO": "الصينية (مكاو)",
+ },
+ narrow: {},
+ },
+};
+
+for (let [locale, localeTests] of Object.entries(tests)) {
+ for (let [style, styleTests] of Object.entries(localeTests)) {
+ let dn = new Intl.DisplayNames(locale, {type: "language", languageDisplay: "dialect", style});
+
+ let resolved = dn.resolvedOptions();
+ assertEq(resolved.locale, locale);
+ assertEq(resolved.style, style);
+ assertEq(resolved.type, "language");
+ assertEq(resolved.languageDisplay, "dialect");
+ assertEq(resolved.fallback, "code");
+
+ let inheritedTests = {...localeTests.long, ...localeTests.short, ...localeTests.narrow};
+ for (let [language, expected] of Object.entries({...inheritedTests, ...styleTests})) {
+ assertEq(dn.of(language), expected);
+
+ // Also works with objects.
+ assertEq(dn.of(Object(language)), expected);
+ }
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/DisplayNames/language.js b/js/src/tests/non262/Intl/DisplayNames/language.js
new file mode 100644
index 0000000000..48fb72056e
--- /dev/null
+++ b/js/src/tests/non262/Intl/DisplayNames/language.js
@@ -0,0 +1,205 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+const tests = {
+ "en": {
+ long: {
+ "de": "German",
+ "de-AT": "German (Austria)",
+ "de-1996": "German (German orthography of 1996)",
+ "en": "English",
+ "en-Hant-GB": "English (Traditional, United Kingdom)",
+ "en-Hans-US": "English (Simplified, United States)",
+ "fr": "French",
+ "nl-BE": "Dutch (Belgium)",
+ "cr-Cans": "Cree (Unified Canadian Aboriginal Syllabics)",
+ },
+ short: {
+ "en-Hant-GB": "English (Traditional, UK)",
+ "en-Hans-US": "English (Simplified, US)",
+ "cr-Cans": "Cree (UCAS)",
+ },
+ narrow: {},
+ },
+ "de": {
+ long: {
+ "de": "Deutsch",
+ "de-AT": "Deutsch (Österreich)",
+ "de-1996": "Deutsch (Neue deutsche Rechtschreibung)",
+ "en": "Englisch",
+ "en-Hant-GB": "Englisch (Traditionell, Vereinigtes Königreich)",
+ "en-Hans-US": "Englisch (Vereinfacht, Vereinigte Staaten)",
+ "fr": "Französisch",
+ "nl-BE": "Niederländisch (Belgien)",
+ },
+ short: {
+ "en-Hant-GB": "Englisch (Traditionell, UK)",
+ "en-Hans-US": "Englisch (Vereinfacht, USA)",
+ },
+ narrow: {},
+ },
+ "fr": {
+ long: {
+ "de": "allemand",
+ "de-AT": "allemand (Autriche)",
+ "de-1996": "allemand (orthographe allemande de 1996)",
+ "en": "anglais",
+ "en-Hant-GB": "anglais (traditionnel, Royaume-Uni)",
+ "en-Hans-US": "anglais (simplifié, États-Unis)",
+ "fr": "français",
+ "nl-BE": "néerlandais (Belgique)",
+ },
+ short: {
+ "en-Hant-GB": "anglais (traditionnel, R.-U.)",
+ "en-Hans-US": "anglais (simplifié, É.-U.)",
+ },
+ narrow: {},
+ },
+ "zh": {
+ long: {
+ "zh": "中文",
+ "zh-Hant": "中文(繁体)",
+ "zh-Hant-CN": "中文(繁体,中国)",
+ "zh-Hans-HK": "中文(简体,中国香港特别行政区)",
+ },
+ short: {
+ "zh-Hans-HK": "中文(简体,香港)"
+ },
+ narrow: {},
+ },
+ "ar": {
+ long: {
+ "ar": "العربية",
+ "ar-SA": "العربية (المملكة العربية السعودية)",
+ "zh-MO": "الصينية (منطقة ماكاو الإدارية الخاصة)",
+ },
+ short: {
+ "zh-MO": "الصينية (مكاو)",
+ },
+ narrow: {},
+ },
+};
+
+for (let [locale, localeTests] of Object.entries(tests)) {
+ for (let [style, styleTests] of Object.entries(localeTests)) {
+ let dn = new Intl.DisplayNames(locale, {type: "language", languageDisplay: "standard", style});
+
+ let resolved = dn.resolvedOptions();
+ assertEq(resolved.locale, locale);
+ assertEq(resolved.style, style);
+ assertEq(resolved.type, "language");
+ assertEq(resolved.languageDisplay, "standard");
+ assertEq(resolved.fallback, "code");
+
+ let inheritedTests = {...localeTests.long, ...localeTests.short, ...localeTests.narrow};
+ for (let [language, expected] of Object.entries({...inheritedTests, ...styleTests})) {
+ assertEq(dn.of(language), expected);
+
+ // Also works with objects.
+ assertEq(dn.of(Object(language)), expected);
+ }
+ }
+}
+
+{
+ let dn = new Intl.DisplayNames("en", {type: "language"});
+
+ // Performs ToString on the input and then validates the stringified result.
+ assertThrowsInstanceOf(() => dn.of(), RangeError);
+ assertThrowsInstanceOf(() => dn.of(null), RangeError);
+ assertThrowsInstanceOf(() => dn.of(Symbol()), TypeError);
+ assertThrowsInstanceOf(() => dn.of(0), RangeError);
+
+ // Throws an error if |code| can't be parsed as a `unicode_language_id` production.
+ assertThrowsInstanceOf(() => dn.of("en-"), RangeError);
+ assertThrowsInstanceOf(() => dn.of("en-u-ca-gregory"), RangeError);
+ assertThrowsInstanceOf(() => dn.of("en-x-private"), RangeError);
+}
+
+// Test fallback behaviour.
+{
+ let dn1 = new Intl.DisplayNames("en", {type: "language"});
+ let dn2 = new Intl.DisplayNames("en", {type: "language", fallback: "code"});
+ let dn3 = new Intl.DisplayNames("en", {type: "language", fallback: "none"});
+
+ assertEq(dn1.resolvedOptions().fallback, "code");
+ assertEq(dn2.resolvedOptions().fallback, "code");
+ assertEq(dn3.resolvedOptions().fallback, "none");
+
+ // "aaa" is not a registered language code.
+ assertEq(dn1.of("aaa"), "aaa");
+ assertEq(dn2.of("aaa"), "aaa");
+ assertEq(dn3.of("aaa"), undefined);
+
+ // "aaa" is not a registered language code.
+ assertEq(dn1.of("aaa-Latn"), "aaa-Latn");
+ assertEq(dn2.of("aaa-Latn"), "aaa-Latn");
+ assertEq(dn3.of("aaa-Latn"), undefined);
+
+ // "Aaaa" is not a registered script code.
+ assertEq(dn1.of("en-Aaaa"), "en-Aaaa");
+ assertEq(dn2.of("en-Aaaa"), "en-Aaaa");
+ assertEq(dn3.of("en-Aaaa"), undefined);
+
+ // "AA" is not a registered region code.
+ assertEq(dn1.of("en-AA"), "en-AA");
+ assertEq(dn2.of("en-AA"), "en-AA");
+ assertEq(dn3.of("en-AA"), undefined);
+
+ // "XZ" doesn't have any localised names.
+ assertEq(dn1.of("en-XZ"), "en-XZ");
+ assertEq(dn2.of("en-XZ"), "en-XZ");
+ assertEq(dn3.of("en-XZ"), undefined);
+
+ // "998" is canonicalised to "XZ".
+ assertEq(dn1.of("en-998"), "en-XZ");
+ assertEq(dn2.of("en-998"), "en-XZ");
+ assertEq(dn3.of("en-998"), undefined);
+
+ // The returned fallback is in canonical case.
+ assertEq(dn1.of("AAA"), "aaa");
+ assertEq(dn2.of("AAA"), "aaa");
+ assertEq(dn3.of("AAA"), undefined);
+
+ assertEq(dn1.of("En-aaaa"), "en-Aaaa");
+ assertEq(dn2.of("En-aaaa"), "en-Aaaa");
+ assertEq(dn3.of("En-aaaa"), undefined);
+
+ assertEq(dn1.of("EN-aa"), "en-AA");
+ assertEq(dn2.of("EN-aa"), "en-AA");
+ assertEq(dn3.of("EN-aa"), undefined);
+}
+
+// Ensure language tag canonicalisation is performed.
+{
+ let dn = new Intl.DisplayNames("en", {type: "language", fallback: "none"});
+
+ assertEq(dn.of("ru-RU"), "Russian (Russia)");
+
+ // ICU's canonicalisation supports "SU" -> "RU".
+ assertEq(Intl.getCanonicalLocales("ru-SU")[0], "ru-RU");
+ assertEq(dn.of("ru-SU"), "Russian (Russia)");
+
+ // ICU's canonicalisation doesn't support "172" -> "RU".
+ assertEq(Intl.getCanonicalLocales("ru-172")[0], "ru-RU");
+ assertEq(dn.of("ru-172"), "Russian (Russia)");
+}
+
+// Test when case isn't canonical.
+{
+ let dn = new Intl.DisplayNames("en", {type: "language", fallback: "none"});
+
+ assertEq(dn.of("IT-LATN-IT"), "Italian (Latin, Italy)");
+ assertEq(dn.of("it-latn-it"), "Italian (Latin, Italy)");
+}
+
+// resolvedOptions() only outputs "languageDisplay" when the type is "language".
+{
+ let dn1 = new Intl.DisplayNames("en", {type: "language"});
+ let dn2 = new Intl.DisplayNames("en", {type: "script"});
+
+ assertEq(dn1.resolvedOptions().languageDisplay, "dialect");
+ assertEq(dn2.resolvedOptions().hasOwnProperty("languageDisplay"), false);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/DisplayNames/month-calendar.js b/js/src/tests/non262/Intl/DisplayNames/month-calendar.js
new file mode 100644
index 0000000000..9a7d9abdaa
--- /dev/null
+++ b/js/src/tests/non262/Intl/DisplayNames/month-calendar.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.hasOwnProperty('addIntlExtras'))
+
+addMozIntlDisplayNames(this);
+
+let dn1 = new Intl.DisplayNames("en", {type: "month", calendar: "gregory"});
+assertEq(dn1.of(1), "January");
+assertEq(dn1.resolvedOptions().calendar, "gregory");
+
+let dn2 = new Intl.DisplayNames("en", {type: "month", calendar: "hebrew"});
+assertEq(dn2.of(1), "Tishri");
+assertEq(dn2.resolvedOptions().calendar, "hebrew");
+
+let dn3 = new Intl.DisplayNames("en", {type: "month", calendar: "islamicc"});
+assertEq(dn3.of(1), "Muharram");
+assertEq(dn3.resolvedOptions().calendar, "islamic-civil");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/DisplayNames/month.js b/js/src/tests/non262/Intl/DisplayNames/month.js
new file mode 100644
index 0000000000..0bd7a02a80
--- /dev/null
+++ b/js/src/tests/non262/Intl/DisplayNames/month.js
@@ -0,0 +1,104 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.hasOwnProperty('addIntlExtras'))
+
+addMozIntlDisplayNames(this);
+
+const tests = {
+ "en": {
+ long: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", 13],
+ short: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 13],
+ narrow: ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D", 13],
+ },
+ "de": {
+ long: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember", 13],
+ short: ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez", 13],
+ narrow: ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D", 13],
+ },
+ "fr": {
+ long: ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre", 13],
+ short: ["janv.", "févr.", "mars", "avr.", "mai", "juin", "juil.", "août", "sept.", "oct.", "nov.", "déc.", 13],
+ narrow: ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D", 13],
+ },
+ "zh": {
+ long: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月", 13],
+ short: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月", 13],
+ narrow: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", 13],
+ },
+ "zh-u-ca-chinese": {
+ long: ["正月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "腊月", 13],
+ short: ["正月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "腊月", 13],
+ narrow: ["正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "冬", "腊", 13],
+ },
+ "en-u-ca-hebrew": {
+ long: ["Tishri", "Heshvan", "Kislev", "Tevet", "Shevat", "Adar I", "Adar", "Nisan", "Iyar", "Sivan", "Tamuz", "Av", "Elul"],
+ short: ["Tishri", "Heshvan", "Kislev", "Tevet", "Shevat", "Adar I", "Adar", "Nisan", "Iyar", "Sivan", "Tamuz", "Av", "Elul"],
+ narrow: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13"],
+ },
+};
+
+for (let [locale, localeTests] of Object.entries(tests)) {
+ let defaultCalendar = new Intl.DateTimeFormat(locale).resolvedOptions().calendar;
+
+ for (let [style, styleTests] of Object.entries(localeTests)) {
+ let dn = new Intl.DisplayNames(locale, {type: "month", style});
+
+ let resolved = dn.resolvedOptions();
+ assertEq(resolved.locale, locale);
+ assertEq(resolved.calendar, defaultCalendar);
+ assertEq(resolved.style, style);
+ assertEq(resolved.type, "month");
+ assertEq(resolved.fallback, "code");
+
+ for (let i = 0; i < 13; i++) {
+ assertEq(dn.of(i + 1), String(styleTests[i]));
+
+ // Also works with strings.
+ assertEq(dn.of(String(i + 1)), String(styleTests[i]));
+
+ // Also works with objects.
+ assertEq(dn.of(Object(i + 1)), String(styleTests[i]));
+ }
+ }
+}
+
+{
+ let dn = new Intl.DisplayNames("en", {type: "month"});
+
+ // Performs ToString on the input and then validates the stringified result.
+ assertThrowsInstanceOf(() => dn.of(), RangeError);
+ assertThrowsInstanceOf(() => dn.of(null), RangeError);
+ assertThrowsInstanceOf(() => dn.of(Symbol()), TypeError);
+
+ // Throws an error if |code| isn't an integer.
+ assertThrowsInstanceOf(() => dn.of(1.5), RangeError);
+ assertThrowsInstanceOf(() => dn.of(-Infinity), RangeError);
+ assertThrowsInstanceOf(() => dn.of(Infinity), RangeError);
+ assertThrowsInstanceOf(() => dn.of(NaN), RangeError);
+
+ // Throws an error if outside of [1, 13].
+ assertThrowsInstanceOf(() => dn.of(-1), RangeError);
+ assertThrowsInstanceOf(() => dn.of(0), RangeError);
+ assertThrowsInstanceOf(() => dn.of(14), RangeError);
+}
+
+// Test fallback behaviour.
+{
+ let dn1 = new Intl.DisplayNames("en", {type: "month"});
+ let dn2 = new Intl.DisplayNames("en", {type: "month", fallback: "code"});
+ let dn3 = new Intl.DisplayNames("en", {type: "month", fallback: "none"});
+
+ assertEq(dn1.resolvedOptions().fallback, "code");
+ assertEq(dn2.resolvedOptions().fallback, "code");
+ assertEq(dn3.resolvedOptions().fallback, "none");
+
+ assertEq(dn1.resolvedOptions().calendar, "gregory");
+ assertEq(dn2.resolvedOptions().calendar, "gregory");
+ assertEq(dn3.resolvedOptions().calendar, "gregory");
+
+ // The Gregorian calendar doesn't have a thirteenth month.
+ assertEq(dn1.of("13"), "13");
+ assertEq(dn2.of("13"), "13");
+ assertEq(dn3.of("13"), undefined);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/DisplayNames/quarter.js b/js/src/tests/non262/Intl/DisplayNames/quarter.js
new file mode 100644
index 0000000000..f74b3b439a
--- /dev/null
+++ b/js/src/tests/non262/Intl/DisplayNames/quarter.js
@@ -0,0 +1,74 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.hasOwnProperty('addIntlExtras'))
+
+addMozIntlDisplayNames(this);
+
+const tests = {
+ "en": {
+ long: ["1st quarter", "2nd quarter", "3rd quarter", "4th quarter"],
+ short: ["Q1", "Q2", "Q3", "Q4"],
+ narrow: ["1", "2", "3", "4"],
+ },
+ "de": {
+ long: ["1. Quartal", "2. Quartal", "3. Quartal", "4. Quartal"],
+ short: ["Q1", "Q2", "Q3", "Q4"],
+ narrow: ["1", "2", "3", "4"],
+ },
+ "fr": {
+ long: ["1er trimestre", "2e trimestre", "3e trimestre", "4e trimestre"],
+ short: ["T1", "T2", "T3", "T4"],
+ narrow: ["1", "2", "3", "4"],
+ },
+ "zh": {
+ long: ["第一季度", "第二季度", "第三季度", "第四季度"],
+ short: ["1季度", "2季度", "3季度", "4季度"],
+ narrow: ["1", "2", "3", "4"],
+ },
+};
+
+for (let [locale, localeTests] of Object.entries(tests)) {
+ let defaultCalendar = new Intl.DateTimeFormat(locale).resolvedOptions().calendar;
+
+ for (let [style, styleTests] of Object.entries(localeTests)) {
+ let dn = new Intl.DisplayNames(locale, {type: "quarter", style});
+
+ let resolved = dn.resolvedOptions();
+ assertEq(resolved.locale, locale);
+ assertEq(resolved.calendar, defaultCalendar);
+ assertEq(resolved.style, style);
+ assertEq(resolved.type, "quarter");
+ assertEq(resolved.fallback, "code");
+
+ for (let i = 0; i < 4; i++) {
+ assertEq(dn.of(i + 1), styleTests[i]);
+
+ // Also works with strings.
+ assertEq(dn.of(String(i + 1)), styleTests[i]);
+
+ // Also works with objects.
+ assertEq(dn.of(Object(i + 1)), styleTests[i]);
+ }
+ }
+}
+
+{
+ let dn = new Intl.DisplayNames("en", {type: "quarter"});
+
+ // Performs ToString on the input and then validates the stringified result.
+ assertThrowsInstanceOf(() => dn.of(), RangeError);
+ assertThrowsInstanceOf(() => dn.of(null), RangeError);
+ assertThrowsInstanceOf(() => dn.of(Symbol()), TypeError);
+
+ // Throws an error if |code| isn't an integer.
+ assertThrowsInstanceOf(() => dn.of(1.5), RangeError);
+ assertThrowsInstanceOf(() => dn.of(-Infinity), RangeError);
+ assertThrowsInstanceOf(() => dn.of(Infinity), RangeError);
+ assertThrowsInstanceOf(() => dn.of(NaN), RangeError);
+
+ // Throws an error if outside of [1, 4].
+ assertThrowsInstanceOf(() => dn.of(-1), RangeError);
+ assertThrowsInstanceOf(() => dn.of(0), RangeError);
+ assertThrowsInstanceOf(() => dn.of(5), RangeError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/DisplayNames/region.js b/js/src/tests/non262/Intl/DisplayNames/region.js
new file mode 100644
index 0000000000..2d1bfe58d8
--- /dev/null
+++ b/js/src/tests/non262/Intl/DisplayNames/region.js
@@ -0,0 +1,157 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+const tests = {
+ "en": {
+ long: {
+ "DE": "Germany",
+ "GB": "United Kingdom",
+ "US": "United States",
+ "FR": "France",
+ },
+ short: {
+ "GB": "UK",
+ "US": "US",
+ },
+ narrow: {},
+ },
+ "de": {
+ long: {
+ "DE": "Deutschland",
+ "GB": "Vereinigtes Königreich",
+ "US": "Vereinigte Staaten",
+ "FR": "Frankreich",
+ },
+ short: {
+ "GB": "UK",
+ "US": "USA",
+ },
+ narrow: {},
+ },
+ "fr": {
+ long: {
+ "DE": "Allemagne",
+ "GB": "Royaume-Uni",
+ "US": "États-Unis",
+ "FR": "France",
+ },
+ short: {
+ "GB": "R.-U.",
+ "US": "É.-U.",
+ },
+ narrow: {},
+ },
+ "zh": {
+ long: {
+ "CN": "中国",
+ "HK": "中国香港特别行政区",
+ },
+ short: {
+ "HK": "香港"
+ },
+ narrow: {},
+ },
+ "ar": {
+ long: {
+ "SA": "المملكة العربية السعودية",
+ "MO": "منطقة ماكاو الإدارية الخاصة",
+ },
+ short: {
+ "MO": "مكاو",
+ },
+ narrow: {},
+ },
+};
+
+for (let [locale, localeTests] of Object.entries(tests)) {
+ for (let [style, styleTests] of Object.entries(localeTests)) {
+ let dn = new Intl.DisplayNames(locale, {type: "region", style});
+
+ let resolved = dn.resolvedOptions();
+ assertEq(resolved.locale, locale);
+ assertEq(resolved.style, style);
+ assertEq(resolved.type, "region");
+ assertEq(resolved.fallback, "code");
+
+ let inheritedTests = {...localeTests.long, ...localeTests.short, ...localeTests.narrow};
+ for (let [region, expected] of Object.entries({...inheritedTests, ...styleTests})) {
+ assertEq(dn.of(region), expected);
+
+ // Also works with objects.
+ assertEq(dn.of(Object(region)), expected);
+ }
+ }
+}
+
+{
+ let dn = new Intl.DisplayNames("en", {type: "region"});
+
+ // Performs ToString on the input and then validates the stringified result.
+ assertThrowsInstanceOf(() => dn.of(), RangeError);
+ assertThrowsInstanceOf(() => dn.of(null), RangeError);
+ assertThrowsInstanceOf(() => dn.of(Symbol()), TypeError);
+ assertThrowsInstanceOf(() => dn.of(0), RangeError);
+
+ // Throws an error if |code| can't be parsed as a `unicode_region_subtag` production.
+ assertThrowsInstanceOf(() => dn.of("CA-"), RangeError);
+ assertThrowsInstanceOf(() => dn.of("en-CA"), RangeError);
+}
+
+// Test fallback behaviour.
+{
+ let dn1 = new Intl.DisplayNames("en", {type: "region"});
+ let dn2 = new Intl.DisplayNames("en", {type: "region", fallback: "code"});
+ let dn3 = new Intl.DisplayNames("en", {type: "region", fallback: "none"});
+
+ assertEq(dn1.resolvedOptions().fallback, "code");
+ assertEq(dn2.resolvedOptions().fallback, "code");
+ assertEq(dn3.resolvedOptions().fallback, "none");
+
+ // "AA" is not a registered region code.
+ assertEq(dn1.of("AA"), "AA");
+ assertEq(dn2.of("AA"), "AA");
+ assertEq(dn3.of("AA"), undefined);
+
+ // The returned fallback is in canonical case.
+ assertEq(dn1.of("aa"), "AA");
+ assertEq(dn2.of("aa"), "AA");
+ assertEq(dn3.of("aa"), undefined);
+
+ // "998" is canonicalised to "XZ", but "XZ" has no localised names.
+ assertEq(new Intl.Locale("und-998").region, "XZ");
+
+ // Ensure we return the input and not the canonicalised input.
+ assertEq(dn1.of("998"), "998");
+ assertEq(dn2.of("998"), "998");
+ assertEq(dn3.of("998"), undefined);
+
+ // "XZ" should be consistent with "998".
+ assertEq(dn1.of("XZ"), "XZ");
+ assertEq(dn2.of("XZ"), "XZ");
+ assertEq(dn3.of("XZ"), undefined);
+}
+
+// Ensure language tag canonicalisation is performed.
+{
+ let dn = new Intl.DisplayNames("en", {type: "region", fallback: "none"});
+
+ assertEq(dn.of("RU"), "Russia");
+
+ // ICU's canonicalisation supports "SU" -> "RU".
+ assertEq(Intl.getCanonicalLocales("ru-SU")[0], "ru-RU");
+ assertEq(dn.of("SU"), "Russia");
+
+ // ICU's canonicalisation doesn't support "172" -> "RU".
+ assertEq(Intl.getCanonicalLocales("ru-172")[0], "ru-RU");
+ assertEq(dn.of("172"), "Russia");
+}
+
+// Test when case isn't canonical.
+{
+ let dn = new Intl.DisplayNames("en", {type: "region", fallback: "none"});
+
+ assertEq(dn.of("IT"), "Italy");
+ assertEq(dn.of("it"), "Italy");
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/DisplayNames/script.js b/js/src/tests/non262/Intl/DisplayNames/script.js
new file mode 100644
index 0000000000..43b3ad5308
--- /dev/null
+++ b/js/src/tests/non262/Intl/DisplayNames/script.js
@@ -0,0 +1,134 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+const tests = {
+ "en": {
+ long: {
+ "Latn": "Latin",
+ "Hant": "Traditional Han",
+ "Hans": "Simplified Han",
+ "Cans": "Unified Canadian Aboriginal Syllabics",
+ },
+ short: {
+ "Hant": "Traditional",
+ "Hans": "Simplified",
+ "Cans": "UCAS",
+ },
+ narrow: {},
+ },
+ "de": {
+ long: {
+ "Latn": "Lateinisch",
+ "Hant": "Traditionelles Chinesisch",
+ "Hans": "Vereinfachtes Chinesisch",
+ },
+ short: {
+ "Hant": "Traditionell",
+ "Hans": "Vereinfacht",
+ },
+ narrow: {},
+ },
+ "fr": {
+ long: {
+ "Latn": "latin",
+ "Hant": "sinogrammes traditionnels",
+ "Hans": "sinogrammes simplifiés",
+ },
+ short: {
+ "Hant": "traditionnel",
+ "Hans": "simplifié",
+ },
+ narrow: {},
+ },
+ "zh": {
+ long: {
+ "Latn": "拉丁文",
+ "Hant": "繁体中文",
+ "Hans": "简体中文",
+ },
+ short: {
+ "Hant": "繁体",
+ "Hans": "简体",
+ },
+ narrow: {},
+ },
+ "ar": {
+ long: {
+ "Latn": "اللاتينية",
+ "Arab": "العربية",
+ "Hant": "الهان التقليدية",
+ "Hans": "الهان المبسطة",
+ },
+ short: {
+ "Hant": "التقليدية",
+ "Hans": "المبسطة",
+ },
+ narrow: {},
+ },
+};
+
+for (let [locale, localeTests] of Object.entries(tests)) {
+ for (let [style, styleTests] of Object.entries(localeTests)) {
+ let dn = new Intl.DisplayNames(locale, {type: "script", style});
+
+ let resolved = dn.resolvedOptions();
+ assertEq(resolved.locale, locale);
+ assertEq(resolved.style, style);
+ assertEq(resolved.type, "script");
+ assertEq(resolved.fallback, "code");
+
+ let inheritedTests = {...localeTests.long, ...localeTests.short, ...localeTests.narrow};
+ for (let [script, expected] of Object.entries({...inheritedTests, ...styleTests})) {
+ assertEq(dn.of(script), expected);
+
+ // Also works with objects.
+ assertEq(dn.of(Object(script)), expected);
+ }
+ }
+}
+
+{
+ let dn = new Intl.DisplayNames("en", {type: "script"});
+
+ // Performs ToString on the input and then validates the stringified result.
+ assertThrowsInstanceOf(() => dn.of(), RangeError);
+ assertThrowsInstanceOf(() => dn.of(Symbol()), TypeError);
+ assertThrowsInstanceOf(() => dn.of(0), RangeError);
+
+ // ToString(null) = "null", which passes `unicode_script_subtag`.
+ dn.of(null); // no error
+
+ // Throws an error if |code| can't be parsed as a `unicode_script_subtag` production.
+ assertThrowsInstanceOf(() => dn.of("latn-"), RangeError);
+ assertThrowsInstanceOf(() => dn.of("en-latn"), RangeError);
+}
+
+// Test fallback behaviour.
+{
+ let dn1 = new Intl.DisplayNames("en", {type: "script"});
+ let dn2 = new Intl.DisplayNames("en", {type: "script", fallback: "code"});
+ let dn3 = new Intl.DisplayNames("en", {type: "script", fallback: "none"});
+
+ assertEq(dn1.resolvedOptions().fallback, "code");
+ assertEq(dn2.resolvedOptions().fallback, "code");
+ assertEq(dn3.resolvedOptions().fallback, "none");
+
+ // "Aaaa" is not a registered script code.
+ assertEq(dn1.of("Aaaa"), "Aaaa");
+ assertEq(dn2.of("Aaaa"), "Aaaa");
+ assertEq(dn3.of("Aaaa"), undefined);
+
+ // The returned fallback is in canonical case.
+ assertEq(dn1.of("aaaa"), "Aaaa");
+ assertEq(dn2.of("aaaa"), "Aaaa");
+ assertEq(dn3.of("aaaa"), undefined);
+}
+
+// Test when case isn't canonical.
+{
+ let dn = new Intl.DisplayNames("en", {type: "script", fallback: "none"});
+
+ assertEq(dn.of("LATN"), "Latin");
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/DisplayNames/shell.js b/js/src/tests/non262/Intl/DisplayNames/shell.js
new file mode 100644
index 0000000000..20326b0254
--- /dev/null
+++ b/js/src/tests/non262/Intl/DisplayNames/shell.js
@@ -0,0 +1,6 @@
+// Add |Intl.MozDisplayNames| to the Intl object.
+function addMozIntlDisplayNames(global) {
+ let obj = {};
+ global.addIntlExtras(obj);
+ global.Intl.DisplayNames = obj.DisplayNames;
+}
diff --git a/js/src/tests/non262/Intl/DisplayNames/weekday.js b/js/src/tests/non262/Intl/DisplayNames/weekday.js
new file mode 100644
index 0000000000..fd19f24bb1
--- /dev/null
+++ b/js/src/tests/non262/Intl/DisplayNames/weekday.js
@@ -0,0 +1,77 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.hasOwnProperty('addIntlExtras'))
+
+addMozIntlDisplayNames(this);
+
+const tests = {
+ "en": {
+ long: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
+ // short: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
+ short: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
+ narrow: ["M", "T", "W", "T", "F", "S", "S"],
+ },
+ "de": {
+ long: ["Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"],
+ // short: ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"],
+ short: ["Mo.", "Di.", "Mi.", "Do.", "Fr.", "Sa.", "So."],
+ narrow: ["M", "D", "M", "D", "F", "S", "S"],
+ },
+ "fr": {
+ long: ["lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche"],
+ // short: ["lun.", "mar.", "mer.", "jeu.", "ven.", "sam.", "dim."],
+ short: ["lu", "ma", "me", "je", "ve", "sa", "di"],
+ narrow: ["L", "M", "M", "J", "V", "S", "D"],
+ },
+ "zh": {
+ long: ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"],
+ short: ["周一", "周二", "周三", "周四", "周五", "周六", "周日"],
+ narrow: ["一", "二", "三", "四", "五", "六", "日"],
+ },
+};
+
+for (let [locale, localeTests] of Object.entries(tests)) {
+ let defaultCalendar = new Intl.DateTimeFormat(locale).resolvedOptions().calendar;
+
+ for (let [style, styleTests] of Object.entries(localeTests)) {
+ let dn = new Intl.DisplayNames(locale, {type: "weekday", style});
+
+ let resolved = dn.resolvedOptions();
+ assertEq(resolved.locale, locale);
+ assertEq(resolved.calendar, defaultCalendar);
+ assertEq(resolved.style, style);
+ assertEq(resolved.type, "weekday");
+ assertEq(resolved.fallback, "code");
+
+ for (let i = 0; i < 7; i++) {
+ assertEq(dn.of(i + 1), styleTests[i]);
+
+ // Also works with strings.
+ assertEq(dn.of(String(i + 1)), styleTests[i]);
+
+ // Also works with objects.
+ assertEq(dn.of(Object(i + 1)), styleTests[i]);
+ }
+ }
+}
+
+{
+ let dn = new Intl.DisplayNames("en", {type: "weekday"});
+
+ // Performs ToString on the input and then validates the stringified result.
+ assertThrowsInstanceOf(() => dn.of(), RangeError);
+ assertThrowsInstanceOf(() => dn.of(null), RangeError);
+ assertThrowsInstanceOf(() => dn.of(Symbol()), TypeError);
+
+ // Throws an error if |code| isn't an integer.
+ assertThrowsInstanceOf(() => dn.of(1.5), RangeError);
+ assertThrowsInstanceOf(() => dn.of(-Infinity), RangeError);
+ assertThrowsInstanceOf(() => dn.of(Infinity), RangeError);
+ assertThrowsInstanceOf(() => dn.of(NaN), RangeError);
+
+ // Throws an error if outside of [1, 7].
+ assertThrowsInstanceOf(() => dn.of(-1), RangeError);
+ assertThrowsInstanceOf(() => dn.of(0), RangeError);
+ assertThrowsInstanceOf(() => dn.of(8), RangeError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/ListFormat/browser.js b/js/src/tests/non262/Intl/ListFormat/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Intl/ListFormat/browser.js
diff --git a/js/src/tests/non262/Intl/ListFormat/conjunction-type.js b/js/src/tests/non262/Intl/ListFormat/conjunction-type.js
new file mode 100644
index 0000000000..320a235271
--- /dev/null
+++ b/js/src/tests/non262/Intl/ListFormat/conjunction-type.js
@@ -0,0 +1,116 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+// Note: Use the same test locales as used in unit-type.js
+
+const {Element, Literal} = ListFormatParts;
+const styles = ["long", "short", "narrow"];
+
+// Test with zero elements.
+{
+ const list = [];
+ const expected = [];
+ const locales = ["ar", "de", "en", "es", "ja", "nl", "th", "zh"];
+
+ for (let locale of locales) {
+ for (let style of styles) {
+ let lf = new Intl.ListFormat(locale, {type: "conjunction", style});
+ assertParts(lf, list, expected);
+ }
+ }
+}
+
+// Test with one element.
+{
+ const list = ["A"];
+ const expected = [Element(list[0])];
+ const locales = ["ar", "de", "en", "es", "ja", "nl", "th", "zh"];
+
+ for (let locale of locales) {
+ for (let style of styles) {
+ let lf = new Intl.ListFormat(locale, {type: "conjunction", style});
+ assertParts(lf, list, expected);
+ }
+ }
+}
+
+// Test with two elements to cover the [[Template2]] case.
+{
+ const list = ["A", "B"];
+
+ const testData = {
+ "ar": { long: [Element("A"), Literal(" و"), Element("B")] },
+ "de": { long: [Element("A"), Literal(" und "), Element("B")] },
+ "en": {
+ long: [Element("A"), Literal(" and "), Element("B")],
+ short: [Element("A"), Literal(" & "), Element("B")],
+ narrow: [Element("A"), Literal(", "), Element("B")],
+ },
+ "es": { long: [Element("A"), Literal(" y "), Element("B")] },
+ "ja": { long: [Element("A"), Literal("、"), Element("B")] },
+ "nl": { long: [Element("A"), Literal(" en "), Element("B")] },
+ "th": { long: [Element("A"), Literal("และ"), Element("B")] },
+ "zh": {
+ long: [Element("A"), Literal("和"), Element("B")],
+ narrow: [Element("A"), Literal("、"), Element("B")],
+ },
+ };
+
+ for (let [locale, localeData] of Object.entries(testData)) {
+ for (let style of styles) {
+ let lf = new Intl.ListFormat(locale, {type: "conjunction", style});
+ let {[style]: expected = localeData.long} = localeData;
+ assertParts(lf, list, expected);
+ }
+ }
+}
+
+// Test with more than two elements.
+//
+// Use four elements to cover all template parts ([[TemplateStart]], [[TemplateMiddle]], and
+// [[TemplateEnd]]).
+{
+ const list = ["A", "B", "C", "D"];
+
+ const testData = {
+ "ar": {
+ long: [Element("A"), Literal(" و"), Element("B"), Literal(" و"), Element("C"), Literal(" و"), Element("D")],
+ short: [Element("A"), Literal(" و"), Element("B"), Literal(" و"), Element("C"), Literal(" و"), Element("D")],
+ narrow: [Element("A"), Literal(" و"), Element("B"), Literal(" و"), Element("C"), Literal(" و"), Element("D")],
+ },
+ "de": {
+ long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(" und "), Element("D")],
+ },
+ "en": {
+ long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(", and "), Element("D")],
+ short: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(", & "), Element("D")],
+ narrow: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(", "), Element("D")],
+ },
+ "es": {
+ long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(" y "), Element("D")],
+ },
+ "ja": {
+ long: [Element("A"), Literal("、"), Element("B"), Literal("、"), Element("C"), Literal("、"), Element("D")],
+ },
+ "nl": {
+ long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(" en "), Element("D")],
+ },
+ "th": {
+ long: [Element("A"), Literal(" "), Element("B"), Literal(" "), Element("C"), Literal(" และ"), Element("D")],
+ },
+ "zh": {
+ long: [Element("A"), Literal("、"), Element("B"), Literal("、"), Element("C"), Literal("和"), Element("D")],
+ narrow: [Element("A"), Literal("、"), Element("B"), Literal("、"), Element("C"), Literal("、"), Element("D")],
+ },
+ };
+
+ for (let [locale, localeData] of Object.entries(testData)) {
+ for (let style of styles) {
+ let lf = new Intl.ListFormat(locale, {type: "conjunction", style});
+ let {[style]: expected = localeData.long} = localeData;
+ assertParts(lf, list, expected);
+ }
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/ListFormat/cross-compartment.js b/js/src/tests/non262/Intl/ListFormat/cross-compartment.js
new file mode 100644
index 0000000000..37c45ef75c
--- /dev/null
+++ b/js/src/tests/non262/Intl/ListFormat/cross-compartment.js
@@ -0,0 +1,42 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+var g = newGlobal();
+
+var locale = "en";
+var list = ["a", "b", "c"];
+
+var listFormat = new Intl.ListFormat(locale);
+var ccwListFormat = new g.Intl.ListFormat(locale);
+
+// Intl.ListFormat.prototype.format
+{
+ var fn = Intl.ListFormat.prototype.format;
+
+ var expectedValue = fn.call(listFormat, list);
+ var actualValue = fn.call(ccwListFormat, list);
+
+ assertEq(actualValue, expectedValue);
+}
+
+// Intl.ListFormat.prototype.formatToParts
+{
+ var fn = Intl.ListFormat.prototype.formatToParts;
+
+ var expectedValue = fn.call(listFormat, list);
+ var actualValue = fn.call(ccwListFormat, list);
+
+ assertDeepEq(actualValue, expectedValue);
+}
+
+// Intl.ListFormat.prototype.resolvedOptions
+{
+ var fn = Intl.ListFormat.prototype.resolvedOptions;
+
+ var expectedValue = fn.call(listFormat);
+ var actualValue = fn.call(ccwListFormat);
+
+ assertDeepEq(actualValue, expectedValue);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/ListFormat/disjunction-type.js b/js/src/tests/non262/Intl/ListFormat/disjunction-type.js
new file mode 100644
index 0000000000..2713a8ae07
--- /dev/null
+++ b/js/src/tests/non262/Intl/ListFormat/disjunction-type.js
@@ -0,0 +1,108 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+// Note: Use the same test locales as used in unit-type.js
+
+const {Element, Literal} = ListFormatParts;
+const styles = ["long", "short", "narrow"];
+
+// Test with zero elements.
+{
+ const list = [];
+ const expected = [];
+ const locales = ["ar", "de", "en", "es", "ja", "nl", "th", "zh"];
+
+ for (let locale of locales) {
+ for (let style of styles) {
+ let lf = new Intl.ListFormat(locale, {type: "disjunction", style});
+ assertParts(lf, list, expected);
+ }
+ }
+}
+
+// Test with one element.
+{
+ const list = ["A"];
+ const expected = [Element(list[0])];
+ const locales = ["ar", "de", "en", "es", "ja", "nl", "th", "zh"];
+
+ for (let locale of locales) {
+ for (let style of styles) {
+ let lf = new Intl.ListFormat(locale, {type: "disjunction", style});
+ assertParts(lf, list, expected);
+ }
+ }
+}
+
+// Test with two elements to cover the [[Template2]] case.
+{
+ const list = ["A", "B"];
+
+ const testData = {
+ "ar": { long: [Element("A"), Literal(" أو "), Element("B")] },
+ "de": { long: [Element("A"), Literal(" oder "), Element("B")] },
+ "en": { long: [Element("A"), Literal(" or "), Element("B")] },
+ "es": { long: [Element("A"), Literal(" o "), Element("B")] },
+ "ja": { long: [Element("A"), Literal("または"), Element("B")] },
+ "nl": { long: [Element("A"), Literal(" of "), Element("B")] },
+ "th": {
+ long: [Element("A"), Literal(" หรือ "), Element("B")],
+ short: [Element("A"), Literal("หรือ"), Element("B")],
+ narrow: [Element("A"), Literal("หรือ"), Element("B")],
+ },
+ "zh": { long: [Element("A"), Literal("或"), Element("B")] },
+ };
+
+ for (let [locale, localeData] of Object.entries(testData)) {
+ for (let style of styles) {
+ let lf = new Intl.ListFormat(locale, {type: "disjunction", style});
+ let {[style]: expected = localeData.long} = localeData;
+ assertParts(lf, list, expected);
+ }
+ }
+}
+
+// Test with more than two elements.
+//
+// Use four elements to cover all template parts ([[TemplateStart]], [[TemplateMiddle]], and
+// [[TemplateEnd]]).
+{
+ const list = ["A", "B", "C", "D"];
+
+ const testData = {
+ "ar": {
+ long: [Element("A"), Literal(" أو "), Element("B"), Literal(" أو "), Element("C"), Literal(" أو "), Element("D")],
+ },
+ "de": {
+ long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(" oder "), Element("D")],
+ },
+ "en": {
+ long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(", or "), Element("D")],
+ },
+ "es": {
+ long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(" o "), Element("D")],
+ },
+ "ja": {
+ long: [Element("A"), Literal("、"), Element("B"), Literal("、"), Element("C"), Literal("、または"), Element("D")],
+ },
+ "nl": {
+ long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(" of "), Element("D")],
+ },
+ "th": {
+ long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(" หรือ "), Element("D")],
+ },
+ "zh": {
+ long: [Element("A"), Literal("、"), Element("B"), Literal("、"), Element("C"), Literal("或"), Element("D")],
+ },
+ };
+
+ for (let [locale, localeData] of Object.entries(testData)) {
+ for (let style of styles) {
+ let lf = new Intl.ListFormat(locale, {type: "disjunction", style});
+ let {[style]: expected = localeData.long} = localeData;
+ assertParts(lf, list, expected);
+ }
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/ListFormat/same-compartment.js b/js/src/tests/non262/Intl/ListFormat/same-compartment.js
new file mode 100644
index 0000000000..a51a041a08
--- /dev/null
+++ b/js/src/tests/non262/Intl/ListFormat/same-compartment.js
@@ -0,0 +1,40 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.wrapWithProto)
+
+var locale = "en";
+var list = ["a", "b", "c"];
+
+var listFormat = new Intl.ListFormat(locale);
+var scwListFormat = wrapWithProto(listFormat, Intl.ListFormat.prototype);
+
+// Intl.ListFormat.prototype.format
+{
+ var fn = Intl.ListFormat.prototype.format;
+
+ var expectedValue = fn.call(listFormat, list);
+ var actualValue = fn.call(scwListFormat, list);
+
+ assertEq(actualValue, expectedValue);
+}
+
+// Intl.ListFormat.prototype.formatToParts
+{
+ var fn = Intl.ListFormat.prototype.formatToParts;
+
+ var expectedValue = fn.call(listFormat, list);
+ var actualValue = fn.call(scwListFormat, list);
+
+ assertDeepEq(actualValue, expectedValue);
+}
+
+// Intl.ListFormat.prototype.resolvedOptions
+{
+ var fn = Intl.ListFormat.prototype.resolvedOptions;
+
+ var expectedValue = fn.call(listFormat);
+ var actualValue = fn.call(scwListFormat);
+
+ assertDeepEq(actualValue, expectedValue);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/ListFormat/shell.js b/js/src/tests/non262/Intl/ListFormat/shell.js
new file mode 100644
index 0000000000..70056a579e
--- /dev/null
+++ b/js/src/tests/non262/Intl/ListFormat/shell.js
@@ -0,0 +1,21 @@
+function GenericPartCreator(type) {
+ return str => ({ type, value: str });
+}
+
+const ListFormatParts = {
+ Element: GenericPartCreator("element"),
+ Literal: GenericPartCreator("literal"),
+};
+
+function assertParts(lf, x, expected) {
+ var parts = lf.formatToParts(x);
+ assertEq(parts.map(part => part.value).join(""), lf.format(x),
+ "formatToParts and format must agree");
+
+ var len = parts.length;
+ assertEq(len, expected.length, "parts count mismatch");
+ for (var i = 0; i < len; i++) {
+ assertEq(parts[i].type, expected[i].type, "type mismatch at " + i);
+ assertEq(parts[i].value, expected[i].value, "value mismatch at " + i);
+ }
+}
diff --git a/js/src/tests/non262/Intl/ListFormat/supported-locales.js b/js/src/tests/non262/Intl/ListFormat/supported-locales.js
new file mode 100644
index 0000000000..f5d05e2da5
--- /dev/null
+++ b/js/src/tests/non262/Intl/ListFormat/supported-locales.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+// Intl.ListFormat.supportedLocalesOf returns an empty array for unsupported locales.
+assertEq(Intl.ListFormat.supportedLocalesOf("art-lobjan").length, 0);
+
+// And a non-empty array for supported locales.
+assertEq(Intl.ListFormat.supportedLocalesOf("en").length, 1);
+assertEq(Intl.ListFormat.supportedLocalesOf("en")[0], "en");
+
+// If the locale is supported per |Intl.ListFormat.supportedLocalesOf|, the resolved locale
+// should reflect this.
+for (let locale of Intl.ListFormat.supportedLocalesOf(["en", "de", "th", "ar"])) {
+ let lf = new Intl.ListFormat(locale);
+ assertEq(lf.resolvedOptions().locale, locale);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/ListFormat/unit-type.js b/js/src/tests/non262/Intl/ListFormat/unit-type.js
new file mode 100644
index 0000000000..8c76677865
--- /dev/null
+++ b/js/src/tests/non262/Intl/ListFormat/unit-type.js
@@ -0,0 +1,149 @@
+// |reftest| skip -- "unit" type currently not supported
+
+const {Element, Literal} = ListFormatParts;
+const styles = ["long", "short", "narrow"];
+
+// Test with zero elements.
+{
+ const list = [];
+ const expected = [];
+ const locales = ["ar", "de", "en", "es", "ja", "nl", "th", "zh"];
+
+ for (let locale of locales) {
+ for (let style of styles) {
+ let lf = new Intl.ListFormat(locale, {type: "unit", style});
+ assertParts(lf, list, expected);
+ }
+ }
+}
+
+// Test with one element.
+{
+ const list = ["A"];
+ const expected = [Element(list[0])];
+ const locales = ["ar", "de", "en", "es", "ja", "nl", "th", "zh"];
+
+ for (let locale of locales) {
+ for (let style of styles) {
+ let lf = new Intl.ListFormat(locale, {type: "unit", style});
+ assertParts(lf, list, expected);
+ }
+ }
+}
+
+// Test with two elements to cover the [[Template2]] case.
+{
+ const list = ["A", "B"];
+
+ const testData = {
+ "ar": {
+ long: [Element("A"), Literal(" و"), Element("B")],
+ narrow: [Element("A"), Literal("، "), Element("B")],
+ },
+ "de": {
+ long: [Element("A"), Literal(", "), Element("B")],
+ },
+ "en": {
+ long: [Element("A"), Literal(", "), Element("B")],
+ narrow: [Element("A"), Literal(" "), Element("B")],
+ },
+ "es": {
+ long: [Element("A"), Literal(" y "), Element("B")],
+ narrow: [Element("A"), Literal(" "), Element("B")],
+ },
+ "ja": {
+ long: [Element("A"), Literal(" "), Element("B")],
+ narrow: [Element("A"), Element("B")],
+ },
+ "nl": {
+ long: [Element("A"), Literal(" en "), Element("B")],
+ short: [Element("A"), Literal(", "), Element("B")],
+ narrow: [Element("A"), Literal(", "), Element("B")],
+ },
+ "th": {
+ long: [Element("A"), Literal(" และ "), Element("B")],
+ short: [Element("A"), Literal(" "), Element("B")],
+ narrow: [Element("A"), Literal(" "), Element("B")],
+ },
+ "zh": {
+ long: [Element("A"), Element("B")],
+ },
+ };
+
+ for (let [locale, localeData] of Object.entries(testData)) {
+ for (let style of styles) {
+ let lf = new Intl.ListFormat(locale, {type: "unit", style});
+ let {[style]: expected = localeData.long} = localeData;
+ assertParts(lf, list, expected);
+ }
+ }
+}
+
+// Test with more than two elements.
+//
+// Use four elements to cover all template parts ([[TemplateStart]], [[TemplateMiddle]], and
+// [[TemplateEnd]]).
+{
+ const list = ["A", "B", "C", "D"];
+
+ const testData = {
+ // non-ASCII case
+ "ar": {
+ long: [Element("A"), Literal("، و"), Element("B"), Literal("، و"), Element("C"), Literal("، و"), Element("D")],
+ narrow: [Element("A"), Literal("، "), Element("B"), Literal("، "), Element("C"), Literal("، "), Element("D")],
+ },
+
+ // all values are equal
+ "de": {
+ long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(" und "), Element("D")],
+ },
+
+ // long and short values are equal
+ "en": {
+ long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(", "), Element("D")],
+ narrow: [Element("A"), Literal(" "), Element("B"), Literal(" "), Element("C"), Literal(" "), Element("D")],
+ },
+
+ // all values are different
+ "es": {
+ long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(" y "), Element("D")],
+ short: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(", "), Element("D")],
+ narrow: [Element("A"), Literal(" "), Element("B"), Literal(" "), Element("C"), Literal(" "), Element("D")],
+ },
+
+ // no spacing for narrow case
+ "ja": {
+ long: [Element("A"), Literal(" "), Element("B"), Literal(" "), Element("C"), Literal(" "), Element("D")],
+ narrow: [Element("A"), Element("B"), Element("C"), Element("D")],
+ },
+
+ // short and narrow values are equal
+ "nl": {
+ long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(" en "), Element("D")],
+ short: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(", "), Element("D")],
+ narrow: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(", "), Element("D")],
+ },
+
+ // another non-ASCII case
+ "th": {
+ long: [Element("A"), Literal(" "), Element("B"), Literal(" "), Element("C"), Literal(" และ "), Element("D")],
+ narrow: [Element("A"), Literal(" "), Element("B"), Literal(" "), Element("C"), Literal(" "), Element("D")],
+ },
+
+ // no whitespace at all
+ "zh": {
+ long: [Element("A"), Element("B"), Element("C"), Element("D")],
+ },
+ };
+
+ for (let [locale, localeData] of Object.entries(testData)) {
+ for (let style of styles) {
+ let lf = new Intl.ListFormat(locale, {type: "unit", style});
+ let {[style]: expected = localeData.long} = localeData;
+ assertParts(lf, list, expected);
+ }
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/Locale/apply-options-to-tag-canonicalize-twice.js b/js/src/tests/non262/Intl/Locale/apply-options-to-tag-canonicalize-twice.js
new file mode 100644
index 0000000000..2a96200757
--- /dev/null
+++ b/js/src/tests/non262/Intl/Locale/apply-options-to-tag-canonicalize-twice.js
@@ -0,0 +1,11 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+// ApplyOptionsToTag canonicalises the locale identifier before applying the
+// options. That means "und-Armn-SU" is first canonicalised to "und-Armn-AM",
+// then the language is changed to "ru". If "ru" were applied first, the result
+// would be "ru-Armn-RU" instead.
+assertEq(new Intl.Locale("und-Armn-SU", {language:"ru"}).toString(),
+ "ru-Armn-AM");
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/Locale/browser.js b/js/src/tests/non262/Intl/Locale/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Intl/Locale/browser.js
diff --git a/js/src/tests/non262/Intl/Locale/coerce-options-before-validating-tag.js b/js/src/tests/non262/Intl/Locale/coerce-options-before-validating-tag.js
new file mode 100644
index 0000000000..7f57a61132
--- /dev/null
+++ b/js/src/tests/non262/Intl/Locale/coerce-options-before-validating-tag.js
@@ -0,0 +1,10 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+// Throw a TypeError when the |options| argument is null before validating the
+// language tag argument.
+assertThrowsInstanceOf(() => {
+ new Intl.Locale("invalid_tag", null);
+}, TypeError);
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/Locale/cross-compartment.js b/js/src/tests/non262/Intl/Locale/cross-compartment.js
new file mode 100644
index 0000000000..d3788e3eb7
--- /dev/null
+++ b/js/src/tests/non262/Intl/Locale/cross-compartment.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+var g = newGlobal();
+
+var tag = "de-Latn-AT-u-ca-gregory-nu-latn-co-phonebk-kf-false-kn-hc-h23";
+var locale = new Intl.Locale(tag);
+var ccwLocale = new g.Intl.Locale(tag);
+
+for (var [key, {get, value = get}] of Object.entries(Object.getOwnPropertyDescriptors(Intl.Locale.prototype))) {
+ if (typeof value === "function") {
+ if (key !== "constructor") {
+ var expectedValue = value.call(locale);
+
+ if (typeof expectedValue === "string" || typeof expectedValue === "boolean") {
+ assertEq(value.call(ccwLocale), expectedValue, key);
+ } else if (expectedValue instanceof Intl.Locale) {
+ assertEq(value.call(ccwLocale).toString(), expectedValue.toString(), key);
+ } else {
+ throw new Error("unexpected result value");
+ }
+ } else {
+ assertEq(new value(ccwLocale).toString(), new value(locale).toString(), key);
+ }
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/Locale/legacy.js b/js/src/tests/non262/Intl/Locale/legacy.js
new file mode 100644
index 0000000000..835e886122
--- /dev/null
+++ b/js/src/tests/non262/Intl/Locale/legacy.js
@@ -0,0 +1,75 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+var testData = [
+ {
+ tag: "cel-gaulish",
+ options: {
+ numberingSystem: "latn",
+ },
+ canonical: "xtg-u-nu-latn",
+ extensions: {
+ numberingSystem: "latn",
+ },
+ },
+
+ {
+ tag: "cel-gaulish",
+ options: {
+ region: "FR",
+ numberingSystem: "latn",
+ },
+ canonical: "xtg-FR-u-nu-latn",
+ extensions: {
+ numberingSystem: "latn",
+ },
+ },
+
+ {
+ tag: "art-lojban",
+ options: {
+ numberingSystem: "latn",
+ },
+ canonical: "jbo-u-nu-latn",
+ extensions: {
+ numberingSystem: "latn",
+ },
+ },
+
+ {
+ tag: "art-lojban",
+ options: {
+ region: "ZZ",
+ numberingSystem: "latn",
+ },
+ canonical: "jbo-ZZ-u-nu-latn",
+ extensions: {
+ numberingSystem: "latn",
+ },
+ },
+];
+
+for (var {tag, options, canonical, extensions} of testData) {
+ var loc = new Intl.Locale(tag, options);
+ assertEq(loc.toString(), canonical);
+
+ for (var [name, value] of Object.entries(extensions)) {
+ assertEq(loc[name], value);
+ }
+}
+
+var errorTestData = [
+ "en-gb-oed",
+ "i-default",
+ "sgn-ch-de",
+ "zh-min",
+ "zh-min-nan",
+ "zh-hakka-hakka",
+];
+
+for (var tag of errorTestData) {
+ assertThrowsInstanceOf(() => new Intl.Locale(tag), RangeError);
+ assertThrowsInstanceOf(() => new Intl.Locale(tag, {}), RangeError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/Locale/likely-subtags-generated.js b/js/src/tests/non262/Intl/Locale/likely-subtags-generated.js
new file mode 100644
index 0000000000..91d23ae663
--- /dev/null
+++ b/js/src/tests/non262/Intl/Locale/likely-subtags-generated.js
@@ -0,0 +1,15797 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+// Generated by make_intl_data.py. DO NOT EDIT.
+
+// Extracted from likelySubtags.xml.
+// Derived from CLDR Supplemental Data, version 43.
+// https://unicode.org/Public/cldr/43/cldr-common-43.0.zip
+var maxLikelySubtags = {
+ "aa": "aa-Latn-ET",
+ "aaa": "aaa-Latn-NG",
+ "aab": "aab-Latn-NG",
+ "aac": "aac-Latn-PG",
+ "aad": "aad-Latn-PG",
+ "aae": "aae-Latn-IT",
+ "aae-Grek": "aae-Grek-IT",
+ "aaf": "aaf-Mlym-IN",
+ "aaf-Arab": "aaf-Arab-IN",
+ "aag": "aag-Latn-PG",
+ "aah": "aah-Latn-PG",
+ "aai": "aai-Latn-ZZ",
+ "aak": "aak-Latn-ZZ",
+ "aal": "aal-Latn-CM",
+ "aan": "aan-Latn-BR",
+ "aao": "aao-Arab-DZ",
+ "aap": "aap-Latn-BR",
+ "aaq": "aaq-Latn-US",
+ "aas": "aas-Latn-TZ",
+ "aat": "aat-Grek-GR",
+ "aau": "aau-Latn-ZZ",
+ "aaw": "aaw-Latn-PG",
+ "aax": "aax-Latn-ID",
+ "aaz": "aaz-Latn-ID",
+ "ab": "ab-Cyrl-GE",
+ "aba": "aba-Latn-CI",
+ "abb": "abb-Latn-CM",
+ "abc": "abc-Latn-PH",
+ "abd": "abd-Latn-PH",
+ "abe": "abe-Latn-CA",
+ "abf": "abf-Latn-MY",
+ "abg": "abg-Latn-PG",
+ "abh": "abh-Arab-TJ",
+ "abi": "abi-Latn-ZZ",
+ "abl": "abl-Rjng-ID",
+ "abl-Latn": "abl-Latn-ID",
+ "abm": "abm-Latn-NG",
+ "abn": "abn-Latn-NG",
+ "abo": "abo-Latn-NG",
+ "abp": "abp-Latn-PH",
+ "abq": "abq-Cyrl-ZZ",
+ "abr": "abr-Latn-GH",
+ "abs": "abs-Latn-ID",
+ "abt": "abt-Latn-ZZ",
+ "abu": "abu-Latn-CI",
+ "abv": "abv-Arab-BH",
+ "abw": "abw-Latn-PG",
+ "abx": "abx-Latn-PH",
+ "aby": "aby-Latn-ZZ",
+ "abz": "abz-Latn-ID",
+ "aca": "aca-Latn-CO",
+ "acb": "acb-Latn-NG",
+ "acd": "acd-Latn-ZZ",
+ "ace": "ace-Latn-ID",
+ "acf": "acf-Latn-LC",
+ "ach": "ach-Latn-UG",
+ "acm": "acm-Arab-IQ",
+ "acn": "acn-Latn-CN",
+ "acp": "acp-Latn-NG",
+ "acq": "acq-Arab-YE",
+ "acr": "acr-Latn-GT",
+ "acs": "acs-Latn-BR",
+ "act": "act-Latn-NL",
+ "acu": "acu-Latn-EC",
+ "acv": "acv-Latn-US",
+ "acw": "acw-Arab-SA",
+ "acx": "acx-Arab-OM",
+ "acy": "acy-Latn-CY",
+ "acy-Arab": "acy-Arab-CY",
+ "acy-Grek": "acy-Grek-CY",
+ "acz": "acz-Latn-SD",
+ "ada": "ada-Latn-GH",
+ "adb": "adb-Latn-TL",
+ "add": "add-Latn-CM",
+ "ade": "ade-Latn-ZZ",
+ "adf": "adf-Arab-OM",
+ "adg": "adg-Latn-AU",
+ "adh": "adh-Latn-UG",
+ "adi": "adi-Latn-IN",
+ "adi-Tibt": "adi-Tibt-CN",
+ "adj": "adj-Latn-ZZ",
+ "adl": "adl-Latn-IN",
+ "adn": "adn-Latn-ID",
+ "ado": "ado-Latn-PG",
+ "adp": "dz-Tibt-BT",
+ "adq": "adq-Latn-GH",
+ "adr": "adr-Latn-ID",
+ "adt": "adt-Latn-AU",
+ "adu": "adu-Latn-NG",
+ "adw": "adw-Latn-BR",
+ "adx": "adx-Tibt-CN",
+ "ady": "ady-Cyrl-RU",
+ "adz": "adz-Latn-ZZ",
+ "ae": "ae-Avst-IR",
+ "aea": "aea-Latn-AU",
+ "aeb": "aeb-Arab-TN",
+ "aec": "aec-Arab-EG",
+ "aee": "aee-Arab-AF",
+ "aek": "aek-Latn-NC",
+ "ael": "ael-Latn-CM",
+ "aem": "aem-Latn-VN",
+ "aeq": "aeq-Arab-PK",
+ "aer": "aer-Latn-AU",
+ "aeu": "aeu-Latn-CN",
+ "aew": "aew-Latn-PG",
+ "aey": "aey-Latn-ZZ",
+ "aez": "aez-Latn-PG",
+ "af": "af-Latn-ZA",
+ "afb": "afb-Arab-KW",
+ "afd": "afd-Latn-PG",
+ "afe": "afe-Latn-NG",
+ "afh": "afh-Latn-GH",
+ "afi": "afi-Latn-PG",
+ "afk": "afk-Latn-PG",
+ "afn": "afn-Latn-NG",
+ "afo": "afo-Latn-NG",
+ "afp": "afp-Latn-PG",
+ "afs": "afs-Latn-MX",
+ "afu": "afu-Latn-GH",
+ "afz": "afz-Latn-ID",
+ "aga": "aga-Latn-PE",
+ "agb": "agb-Latn-NG",
+ "agc": "agc-Latn-ZZ",
+ "agd": "agd-Latn-ZZ",
+ "age": "age-Latn-PG",
+ "agf": "agf-Latn-ID",
+ "agg": "agg-Latn-ZZ",
+ "agh": "agh-Latn-CD",
+ "agi": "agi-Deva-IN",
+ "agj": "agj-Ethi-ET",
+ "agj-Arab": "agj-Arab-ET",
+ "agk": "agk-Latn-PH",
+ "agl": "agl-Latn-PG",
+ "agm": "agm-Latn-ZZ",
+ "agn": "agn-Latn-PH",
+ "ago": "ago-Latn-ZZ",
+ "agq": "agq-Latn-CM",
+ "agr": "agr-Latn-PE",
+ "ags": "ags-Latn-CM",
+ "agt": "agt-Latn-PH",
+ "agu": "agu-Latn-GT",
+ "agv": "agv-Latn-PH",
+ "agw": "agw-Latn-SB",
+ "agx": "agx-Cyrl-RU",
+ "agy": "agy-Latn-PH",
+ "agz": "agz-Latn-PH",
+ "aha": "aha-Latn-ZZ",
+ "ahb": "ahb-Latn-VU",
+ "ahg": "ahg-Ethi-ET",
+ "ahh": "ahh-Latn-ID",
+ "ahi": "ahi-Latn-CI",
+ "ahk": "ahk-Latn-MM",
+ "ahk-Mymr": "ahk-Mymr-MM",
+ "ahk-TH": "ahk-Latn-TH",
+ "ahk-Thai": "ahk-Thai-TH",
+ "ahl": "ahl-Latn-ZZ",
+ "ahm": "ahm-Latn-CI",
+ "ahn": "ahn-Latn-NG",
+ "aho": "aho-Ahom-IN",
+ "ahp": "ahp-Latn-CI",
+ "ahr": "ahr-Deva-IN",
+ "ahs": "ahs-Latn-NG",
+ "aht": "aht-Latn-US",
+ "aia": "aia-Latn-SB",
+ "aib": "aib-Arab-CN",
+ "aic": "aic-Latn-PG",
+ "aid": "aid-Latn-AU",
+ "aie": "aie-Latn-PG",
+ "aif": "aif-Latn-PG",
+ "aig": "aig-Latn-AG",
+ "aij": "aij-Hebr-IL",
+ "aik": "aik-Latn-NG",
+ "ail": "ail-Latn-PG",
+ "aim": "aim-Latn-IN",
+ "ain": "ain-Kana-JP",
+ "ain-Latn": "ain-Latn-JP",
+ "aio": "aio-Mymr-IN",
+ "aip": "aip-Latn-ID",
+ "aiq": "aiq-Arab-AF",
+ "air": "air-Latn-ID",
+ "ait": "ait-Latn-BR",
+ "aiw": "aiw-Latn-ET",
+ "aiw-Arab": "aiw-Arab-ET",
+ "aiw-Ethi": "aiw-Ethi-ET",
+ "aix": "aix-Latn-PG",
+ "aiy": "aiy-Latn-CF",
+ "aja": "aja-Latn-SS",
+ "ajg": "ajg-Latn-ZZ",
+ "aji": "aji-Latn-NC",
+ "ajn": "ajn-Latn-AU",
+ "ajp": "ajp-Arab-JO",
+ "ajt": "aeb-Arab-TN",
+ "ajw": "ajw-Latn-NG",
+ "ajz": "ajz-Latn-IN",
+ "ak": "ak-Latn-GH",
+ "akb": "akb-Latn-ID",
+ "akb-Batk": "akb-Batk-ID",
+ "akc": "akc-Latn-ID",
+ "akd": "akd-Latn-NG",
+ "ake": "ake-Latn-GY",
+ "akf": "akf-Latn-NG",
+ "akg": "akg-Latn-ID",
+ "akh": "akh-Latn-PG",
+ "aki": "aki-Latn-PG",
+ "akk": "akk-Xsux-IQ",
+ "akl": "akl-Latn-PH",
+ "ako": "ako-Latn-SR",
+ "akp": "akp-Latn-GH",
+ "akq": "akq-Latn-PG",
+ "akr": "akr-Latn-VU",
+ "aks": "aks-Latn-TG",
+ "akt": "akt-Latn-PG",
+ "aku": "aku-Latn-CM",
+ "akv": "akv-Cyrl-RU",
+ "akw": "akw-Latn-CG",
+ "akz": "akz-Latn-US",
+ "ala": "ala-Latn-ZZ",
+ "alc": "alc-Latn-CL",
+ "ald": "ald-Latn-CI",
+ "ale": "ale-Latn-US",
+ "alf": "alf-Latn-NG",
+ "alh": "alh-Latn-AU",
+ "ali": "ali-Latn-ZZ",
+ "alj": "alj-Latn-PH",
+ "alk": "alk-Laoo-LA",
+ "all": "all-Mlym-IN",
+ "alm": "alm-Latn-VU",
+ "aln": "aln-Latn-XK",
+ "alo": "alo-Latn-ID",
+ "alp": "alp-Latn-ID",
+ "alq": "alq-Latn-CA",
+ "alr": "alr-Cyrl-RU",
+ "alt": "alt-Cyrl-RU",
+ "alu": "alu-Latn-SB",
+ "alw": "alw-Ethi-ET",
+ "alx": "alx-Latn-PG",
+ "aly": "aly-Latn-AU",
+ "alz": "alz-Latn-CD",
+ "am": "am-Ethi-ET",
+ "ama": "ama-Latn-BR",
+ "amb": "amb-Latn-NG",
+ "amc": "amc-Latn-PE",
+ "ame": "ame-Latn-PE",
+ "amf": "amf-Latn-ET",
+ "amf-Ethi": "amf-Ethi-ET",
+ "amg": "amg-Latn-AU",
+ "ami": "ami-Latn-TW",
+ "amj": "amj-Latn-TD",
+ "amk": "amk-Latn-ID",
+ "amm": "amm-Latn-ZZ",
+ "amn": "amn-Latn-ZZ",
+ "amo": "amo-Latn-NG",
+ "amp": "amp-Latn-ZZ",
+ "amq": "amq-Latn-ID",
+ "amr": "amr-Latn-PE",
+ "ams": "ams-Jpan-JP",
+ "amt": "amt-Latn-PG",
+ "amu": "amu-Latn-MX",
+ "amv": "amv-Latn-ID",
+ "amw": "amw-Syrc-SY",
+ "amw-Arab": "amw-Arab-SY",
+ "amw-Armi": "amw-Armi-SY",
+ "amw-Latn": "amw-Latn-SY",
+ "amx": "amx-Latn-AU",
+ "amy": "amy-Latn-AU",
+ "amz": "amz-Latn-AU",
+ "an": "an-Latn-ES",
+ "ana": "ana-Latn-CO",
+ "anb": "anb-Latn-PE",
+ "anc": "anc-Latn-ZZ",
+ "and": "and-Latn-ID",
+ "ane": "ane-Latn-NC",
+ "anf": "anf-Latn-GH",
+ "ang": "ang-Latn-GB",
+ "anh": "anh-Latn-PG",
+ "ani": "ani-Cyrl-RU",
+ "anj": "anj-Latn-PG",
+ "ank": "ank-Latn-ZZ",
+ "anl": "anl-Latn-MM",
+ "anm": "anm-Latn-IN",
+ "ann": "ann-Latn-NG",
+ "ano": "ano-Latn-CO",
+ "anp": "anp-Deva-IN",
+ "anr": "anr-Deva-IN",
+ "ans": "ans-Latn-CO",
+ "ant": "ant-Latn-AU",
+ "anu": "anu-Ethi-ET",
+ "anu-Arab": "anu-Arab-SS",
+ "anu-Latn": "anu-Latn-SS",
+ "anv": "anv-Latn-CM",
+ "anw": "anw-Latn-NG",
+ "anx": "anx-Latn-PG",
+ "any": "any-Latn-ZZ",
+ "anz": "anz-Latn-PG",
+ "aoa": "aoa-Latn-ST",
+ "aob": "aob-Latn-PG",
+ "aoc": "aoc-Latn-VE",
+ "aod": "aod-Latn-PG",
+ "aoe": "aoe-Latn-PG",
+ "aof": "aof-Latn-PG",
+ "aog": "aog-Latn-PG",
+ "aoi": "aoi-Latn-AU",
+ "aoj": "aoj-Latn-ZZ",
+ "aok": "aok-Latn-NC",
+ "aol": "aol-Latn-ID",
+ "aom": "aom-Latn-ZZ",
+ "aon": "aon-Latn-PG",
+ "aor": "aor-Latn-VU",
+ "aos": "aos-Latn-ID",
+ "aot": "aot-Beng-BD",
+ "aot-Latn": "aot-Latn-IN",
+ "aox": "aox-Latn-GY",
+ "aoz": "aoz-Latn-ID",
+ "apb": "apb-Latn-SB",
+ "apc": "apc-Arab-SY",
+ "apd": "apd-Arab-TG",
+ "ape": "ape-Latn-ZZ",
+ "apf": "apf-Latn-PH",
+ "apg": "apg-Latn-ID",
+ "aph": "aph-Deva-NP",
+ "api": "api-Latn-BR",
+ "apj": "apj-Latn-US",
+ "apk": "apk-Latn-US",
+ "apl": "apl-Latn-US",
+ "apm": "apm-Latn-US",
+ "apn": "apn-Latn-BR",
+ "apo": "apo-Latn-PG",
+ "app": "app-Latn-VU",
+ "apr": "apr-Latn-ZZ",
+ "aps": "aps-Latn-ZZ",
+ "apt": "apt-Latn-IN",
+ "apu": "apu-Latn-BR",
+ "apv": "apv-Latn-BR",
+ "apw": "apw-Latn-US",
+ "apx": "apx-Latn-ID",
+ "apy": "apy-Latn-BR",
+ "apz": "apz-Latn-ZZ",
+ "aqc": "aqc-Cyrl-RU",
+ "aqd": "aqd-Latn-ML",
+ "aqg": "aqg-Latn-NG",
+ "aqk": "aqk-Latn-NG",
+ "aqm": "aqm-Latn-ID",
+ "aqn": "aqn-Latn-PH",
+ "aqr": "aqr-Latn-NC",
+ "aqt": "aqt-Latn-PY",
+ "aqz": "aqz-Latn-BR",
+ "ar": "ar-Arab-EG",
+ "arc": "arc-Armi-IR",
+ "arc-Nbat": "arc-Nbat-JO",
+ "arc-Palm": "arc-Palm-SY",
+ "ard": "ard-Latn-AU",
+ "are": "are-Latn-AU",
+ "arh": "arh-Latn-ZZ",
+ "ari": "ari-Latn-US",
+ "arj": "arj-Latn-BR",
+ "ark": "ark-Latn-BR",
+ "arl": "arl-Latn-PE",
+ "arn": "arn-Latn-CL",
+ "aro": "aro-Latn-BO",
+ "arp": "arp-Latn-US",
+ "arq": "arq-Arab-DZ",
+ "arr": "arr-Latn-BR",
+ "ars": "ars-Arab-SA",
+ "aru": "aru-Latn-BR",
+ "arw": "arw-Latn-SR",
+ "arx": "arx-Latn-BR",
+ "ary": "ary-Arab-MA",
+ "arz": "arz-Arab-EG",
+ "as": "as-Beng-IN",
+ "asa": "asa-Latn-TZ",
+ "asb": "asb-Latn-CA",
+ "asc": "asc-Latn-ID",
+ "ase": "ase-Sgnw-US",
+ "asg": "asg-Latn-ZZ",
+ "ash": "ash-Latn-PE",
+ "asi": "asi-Latn-ID",
+ "asj": "asj-Latn-CM",
+ "ask": "ask-Arab-AF",
+ "asl": "asl-Latn-ID",
+ "asn": "asn-Latn-BR",
+ "aso": "aso-Latn-ZZ",
+ "ass": "ass-Latn-CM",
+ "ast": "ast-Latn-ES",
+ "asu": "asu-Latn-BR",
+ "asv": "asv-Latn-CD",
+ "asx": "asx-Latn-PG",
+ "asy": "asy-Latn-ID",
+ "asz": "asz-Latn-ID",
+ "ata": "ata-Latn-ZZ",
+ "atb": "atb-Latn-CN",
+ "atb-Lisu": "atb-Lisu-CN",
+ "atc": "atc-Latn-PE",
+ "atd": "atd-Latn-PH",
+ "ate": "ate-Latn-PG",
+ "atg": "atg-Latn-ZZ",
+ "ati": "ati-Latn-CI",
+ "atj": "atj-Latn-CA",
+ "atk": "atk-Latn-PH",
+ "atl": "atl-Latn-PH",
+ "atm": "atm-Latn-PH",
+ "atn": "atn-Arab-IR",
+ "ato": "ato-Latn-CM",
+ "atp": "atp-Latn-PH",
+ "atq": "atq-Latn-ID",
+ "atr": "atr-Latn-BR",
+ "ats": "ats-Latn-US",
+ "att": "att-Latn-PH",
+ "atu": "atu-Latn-SS",
+ "atv": "atv-Cyrl-RU",
+ "atw": "atw-Latn-US",
+ "atx": "atx-Latn-BR",
+ "aty": "aty-Latn-VU",
+ "atz": "atz-Latn-PH",
+ "aua": "aua-Latn-SB",
+ "auc": "auc-Latn-EC",
+ "aud": "aud-Latn-SB",
+ "aug": "aug-Latn-BJ",
+ "auh": "auh-Latn-ZM",
+ "aui": "aui-Latn-PG",
+ "auj": "auj-Arab-LY",
+ "auj-Latn": "auj-Latn-LY",
+ "auj-Tfng": "auj-Tfng-LY",
+ "auk": "auk-Latn-PG",
+ "aul": "aul-Latn-VU",
+ "aum": "aum-Latn-NG",
+ "aun": "aun-Latn-PG",
+ "auo": "auo-Latn-NG",
+ "aup": "aup-Latn-PG",
+ "auq": "auq-Latn-ID",
+ "aur": "aur-Latn-PG",
+ "aut": "aut-Latn-PF",
+ "auu": "auu-Latn-ID",
+ "auw": "auw-Latn-ID",
+ "auy": "auy-Latn-ZZ",
+ "auz": "auz-Arab-UZ",
+ "av": "av-Cyrl-RU",
+ "avb": "avb-Latn-PG",
+ "avd": "avd-Arab-IR",
+ "avi": "avi-Latn-CI",
+ "avk": "avk-Latn-001",
+ "avl": "avl-Arab-ZZ",
+ "avm": "avm-Latn-AU",
+ "avn": "avn-Latn-ZZ",
+ "avo": "avo-Latn-BR",
+ "avs": "avs-Latn-PE",
+ "avt": "avt-Latn-ZZ",
+ "avu": "avu-Latn-ZZ",
+ "avv": "avv-Latn-BR",
+ "awa": "awa-Deva-IN",
+ "awb": "awb-Latn-ZZ",
+ "awc": "awc-Latn-NG",
+ "awe": "awe-Latn-BR",
+ "awg": "awg-Latn-AU",
+ "awh": "awh-Latn-ID",
+ "awi": "awi-Latn-PG",
+ "awk": "awk-Latn-AU",
+ "awm": "awm-Latn-PG",
+ "awn": "awn-Ethi-ET",
+ "awo": "awo-Latn-ZZ",
+ "awr": "awr-Latn-ID",
+ "aws": "aws-Latn-ID",
+ "awt": "awt-Latn-BR",
+ "awu": "awu-Latn-ID",
+ "awv": "awv-Latn-ID",
+ "aww": "aww-Latn-PG",
+ "awx": "awx-Latn-ZZ",
+ "awy": "awy-Latn-ID",
+ "axb": "axb-Latn-AR",
+ "axe": "axe-Latn-AU",
+ "axg": "axg-Latn-BR",
+ "axk": "axk-Latn-CF",
+ "axl": "axl-Latn-AU",
+ "axm": "axm-Armn-AM",
+ "axx": "axx-Latn-NC",
+ "ay": "ay-Latn-BO",
+ "aya": "aya-Latn-PG",
+ "ayb": "ayb-Latn-ZZ",
+ "ayc": "ayc-Latn-PE",
+ "ayd": "ayd-Latn-AU",
+ "aye": "aye-Latn-NG",
+ "ayg": "ayg-Latn-TG",
+ "ayh": "ayh-Arab-YE",
+ "ayi": "ayi-Latn-NG",
+ "ayk": "ayk-Latn-NG",
+ "ayl": "ayl-Arab-LY",
+ "ayn": "ayn-Arab-YE",
+ "ayo": "ayo-Latn-PY",
+ "ayp": "ayp-Arab-IQ",
+ "ayq": "ayq-Latn-PG",
+ "ays": "ays-Latn-PH",
+ "ayt": "ayt-Latn-PH",
+ "ayu": "ayu-Latn-NG",
+ "ayz": "ayz-Latn-ID",
+ "az": "az-Latn-AZ",
+ "az-Arab": "az-Arab-IR",
+ "az-IQ": "az-Arab-IQ",
+ "az-IR": "az-Arab-IR",
+ "az-RU": "az-Cyrl-RU",
+ "azb": "azb-Arab-IR",
+ "azb-Cyrl": "azb-Cyrl-AZ",
+ "azb-Latn": "azb-Latn-AZ",
+ "azd": "azd-Latn-MX",
+ "azg": "azg-Latn-MX",
+ "azm": "azm-Latn-MX",
+ "azn": "azn-Latn-MX",
+ "azo": "azo-Latn-CM",
+ "azt": "azt-Latn-PH",
+ "azz": "azz-Latn-MX",
+ "ba": "ba-Cyrl-RU",
+ "baa": "baa-Latn-SB",
+ "bab": "bab-Latn-GW",
+ "bac": "bac-Latn-ID",
+ "bae": "bae-Latn-VE",
+ "baf": "baf-Latn-CM",
+ "bag": "bag-Latn-CM",
+ "bah": "bah-Latn-BS",
+ "baj": "baj-Latn-ID",
+ "bal": "bal-Arab-PK",
+ "ban": "ban-Latn-ID",
+ "bao": "bao-Latn-CO",
+ "bap": "bap-Deva-NP",
+ "bar": "bar-Latn-AT",
+ "bas": "bas-Latn-CM",
+ "bau": "bau-Latn-NG",
+ "bav": "bav-Latn-ZZ",
+ "baw": "baw-Latn-CM",
+ "bax": "bax-Bamu-CM",
+ "bay": "bay-Latn-ID",
+ "bba": "bba-Latn-ZZ",
+ "bbb": "bbb-Latn-ZZ",
+ "bbc": "bbc-Latn-ID",
+ "bbd": "bbd-Latn-ZZ",
+ "bbe": "bbe-Latn-CD",
+ "bbf": "bbf-Latn-PG",
+ "bbg": "bbg-Latn-GA",
+ "bbi": "bbi-Latn-CM",
+ "bbj": "bbj-Latn-CM",
+ "bbk": "bbk-Latn-CM",
+ "bbl": "bbl-Geor-GE",
+ "bbm": "bbm-Latn-CD",
+ "bbn": "bbn-Latn-PG",
+ "bbo": "bbo-Latn-BF",
+ "bbp": "bbp-Latn-ZZ",
+ "bbq": "bbq-Latn-CM",
+ "bbr": "bbr-Latn-ZZ",
+ "bbs": "bbs-Latn-NG",
+ "bbt": "bbt-Latn-NG",
+ "bbu": "bbu-Latn-NG",
+ "bbv": "bbv-Latn-PG",
+ "bbw": "bbw-Latn-CM",
+ "bbx": "bbx-Latn-CM",
+ "bby": "bby-Latn-CM",
+ "bca": "bca-Latn-CN",
+ "bca-Hani": "bca-Hani-CN",
+ "bcb": "bcb-Latn-SN",
+ "bcd": "bcd-Latn-ID",
+ "bce": "bce-Latn-CM",
+ "bcf": "bcf-Latn-ZZ",
+ "bcg": "bcg-Latn-GN",
+ "bch": "bch-Latn-ZZ",
+ "bci": "bci-Latn-CI",
+ "bcj": "bcj-Latn-AU",
+ "bck": "bck-Latn-AU",
+ "bcm": "bcm-Latn-ZZ",
+ "bcn": "bcn-Latn-ZZ",
+ "bco": "bco-Latn-ZZ",
+ "bcp": "bcp-Latn-CD",
+ "bcq": "bcq-Ethi-ZZ",
+ "bcr": "bcr-Latn-CA",
+ "bcs": "bcs-Latn-NG",
+ "bct": "bct-Latn-CD",
+ "bcu": "bcu-Latn-ZZ",
+ "bcv": "bcv-Latn-NG",
+ "bcw": "bcw-Latn-CM",
+ "bcy": "bcy-Latn-NG",
+ "bcz": "bcz-Latn-SN",
+ "bda": "bda-Latn-SN",
+ "bdb": "bdb-Latn-ID",
+ "bdc": "bdc-Latn-CO",
+ "bdd": "bdd-Latn-ZZ",
+ "bde": "bde-Latn-NG",
+ "bdf": "bdf-Latn-PG",
+ "bdg": "bdg-Latn-MY",
+ "bdh": "bdh-Latn-SS",
+ "bdi": "bdi-Latn-SD",
+ "bdj": "bdj-Latn-SS",
+ "bdk": "bdk-Latn-AZ",
+ "bdl": "bdl-Latn-ID",
+ "bdm": "bdm-Latn-TD",
+ "bdn": "bdn-Latn-CM",
+ "bdo": "bdo-Latn-TD",
+ "bdp": "bdp-Latn-TZ",
+ "bdq": "bdq-Latn-VN",
+ "bdr": "bdr-Latn-MY",
+ "bds": "bds-Latn-TZ",
+ "bdt": "bdt-Latn-CF",
+ "bdu": "bdu-Latn-CM",
+ "bdv": "bdv-Orya-IN",
+ "bdw": "bdw-Latn-ID",
+ "bdx": "bdx-Latn-ID",
+ "bdy": "bdy-Latn-AU",
+ "bdz": "bdz-Arab-PK",
+ "be": "be-Cyrl-BY",
+ "bea": "bea-Latn-CA",
+ "bea-Cans": "bea-Cans-CA",
+ "beb": "beb-Latn-CM",
+ "bec": "bec-Latn-CM",
+ "bed": "bed-Latn-ID",
+ "bee": "bee-Deva-IN",
+ "bef": "bef-Latn-ZZ",
+ "beh": "beh-Latn-ZZ",
+ "bei": "bei-Latn-ID",
+ "bej": "bej-Arab-SD",
+ "bek": "bek-Latn-PG",
+ "bem": "bem-Latn-ZM",
+ "beo": "beo-Latn-PG",
+ "bep": "bep-Latn-ID",
+ "beq": "beq-Latn-CG",
+ "bes": "bes-Latn-TD",
+ "bet": "bet-Latn-ZZ",
+ "beu": "beu-Latn-ID",
+ "bev": "bev-Latn-CI",
+ "bew": "bew-Latn-ID",
+ "bex": "bex-Latn-ZZ",
+ "bey": "bey-Latn-PG",
+ "bez": "bez-Latn-TZ",
+ "bfa": "bfa-Latn-SS",
+ "bfa-Arab": "bfa-Arab-SS",
+ "bfb": "bfb-Deva-IN",
+ "bfc": "bfc-Latn-CN",
+ "bfd": "bfd-Latn-CM",
+ "bfe": "bfe-Latn-ID",
+ "bff": "bff-Latn-CF",
+ "bfg": "bfg-Latn-ID",
+ "bfh": "bfh-Latn-PG",
+ "bfj": "bfj-Latn-CM",
+ "bfl": "bfl-Latn-CF",
+ "bfm": "bfm-Latn-CM",
+ "bfn": "bfn-Latn-TL",
+ "bfo": "bfo-Latn-BF",
+ "bfp": "bfp-Latn-CM",
+ "bfq": "bfq-Taml-IN",
+ "bfs": "bfs-Latn-CN",
+ "bfs-Hani": "bfs-Hani-CN",
+ "bft": "bft-Arab-PK",
+ "bfu": "bfu-Tibt-IN",
+ "bfu-Takr": "bfu-Takr-IN",
+ "bfw": "bfw-Orya-IN",
+ "bfx": "bfx-Latn-PH",
+ "bfy": "bfy-Deva-IN",
+ "bfz": "bfz-Deva-IN",
+ "bg": "bg-Cyrl-BG",
+ "bga": "bga-Latn-NG",
+ "bgb": "bgb-Latn-ID",
+ "bgc": "bgc-Deva-IN",
+ "bgd": "bgd-Deva-IN",
+ "bgf": "bgf-Latn-CM",
+ "bgg": "bgg-Latn-IN",
+ "bgi": "bgi-Latn-PH",
+ "bgj": "bgj-Latn-CM",
+ "bgn": "bgn-Arab-PK",
+ "bgo": "bgo-Latn-GN",
+ "bgp": "bgp-Arab-PK",
+ "bgq": "bgq-Deva-IN",
+ "bgr": "bgr-Latn-IN",
+ "bgs": "bgs-Latn-PH",
+ "bgt": "bgt-Latn-SB",
+ "bgu": "bgu-Latn-NG",
+ "bgv": "bgv-Latn-ID",
+ "bgw": "bgw-Deva-IN",
+ "bgx": "bgx-Grek-TR",
+ "bgy": "bgy-Latn-ID",
+ "bgz": "bgz-Latn-ID",
+ "bha": "bha-Deva-IN",
+ "bhb": "bhb-Deva-IN",
+ "bhc": "bhc-Latn-ID",
+ "bhd": "bhd-Deva-IN",
+ "bhd-Arab": "bhd-Arab-IN",
+ "bhd-Takr": "bhd-Takr-IN",
+ "bhe": "bhe-Arab-PK",
+ "bhf": "bhf-Latn-PG",
+ "bhg": "bhg-Latn-ZZ",
+ "bhh": "bhh-Cyrl-IL",
+ "bhh-Hebr": "bhh-Hebr-IL",
+ "bhh-Latn": "bhh-Latn-IL",
+ "bhi": "bhi-Deva-IN",
+ "bhj": "bhj-Deva-NP",
+ "bhl": "bhl-Latn-ZZ",
+ "bhm": "bhm-Arab-OM",
+ "bhn": "bhn-Syrc-GE",
+ "bho": "bho-Deva-IN",
+ "bhp": "bhp-Latn-ID",
+ "bhq": "bhq-Latn-ID",
+ "bhr": "bhr-Latn-MG",
+ "bhs": "bhs-Latn-CM",
+ "bht": "bht-Takr-IN",
+ "bht-Deva": "bht-Deva-IN",
+ "bht-Latn": "bht-Latn-IN",
+ "bhu": "bhu-Deva-IN",
+ "bhv": "bhv-Latn-ID",
+ "bhw": "bhw-Latn-ID",
+ "bhy": "bhy-Latn-ZZ",
+ "bhz": "bhz-Latn-ID",
+ "bi": "bi-Latn-VU",
+ "bia": "bia-Latn-AU",
+ "bib": "bib-Latn-ZZ",
+ "bid": "bid-Latn-TD",
+ "bie": "bie-Latn-PG",
+ "bif": "bif-Latn-GW",
+ "big": "big-Latn-ZZ",
+ "bik": "bik-Latn-PH",
+ "bil": "bil-Latn-NG",
+ "bim": "bim-Latn-ZZ",
+ "bin": "bin-Latn-NG",
+ "bio": "bio-Latn-ZZ",
+ "bip": "bip-Latn-CD",
+ "biq": "biq-Latn-ZZ",
+ "bir": "bir-Latn-PG",
+ "bit": "bit-Latn-PG",
+ "biu": "biu-Latn-IN",
+ "biv": "biv-Latn-GH",
+ "biw": "biw-Latn-CM",
+ "biy": "biy-Deva-IN",
+ "biz": "biz-Latn-CD",
+ "bja": "bja-Latn-CD",
+ "bjb": "bjb-Latn-AU",
+ "bjc": "bjc-Latn-PG",
+ "bjf": "bjf-Syrc-IL",
+ "bjg": "bjg-Latn-GW",
+ "bjh": "bjh-Latn-ZZ",
+ "bji": "bji-Ethi-ZZ",
+ "bjj": "bjj-Deva-IN",
+ "bjk": "bjk-Latn-PG",
+ "bjl": "bjl-Latn-PG",
+ "bjm": "bjm-Arab-IQ",
+ "bjn": "bjn-Latn-ID",
+ "bjo": "bjo-Latn-ZZ",
+ "bjp": "bjp-Latn-PG",
+ "bjr": "bjr-Latn-ZZ",
+ "bjs": "bjs-Latn-BB",
+ "bjt": "bjt-Latn-SN",
+ "bju": "bju-Latn-CM",
+ "bjv": "bjv-Latn-TD",
+ "bjw": "bjw-Latn-CI",
+ "bjx": "bjx-Latn-PH",
+ "bjy": "bjy-Latn-AU",
+ "bjz": "bjz-Latn-ZZ",
+ "bka": "bka-Latn-NG",
+ "bkc": "bkc-Latn-ZZ",
+ "bkd": "bkd-Latn-PH",
+ "bkf": "bkf-Latn-CD",
+ "bkg": "bkg-Latn-CF",
+ "bkh": "bkh-Latn-CM",
+ "bki": "bki-Latn-VU",
+ "bkj": "bkj-Latn-CF",
+ "bkl": "bkl-Latn-ID",
+ "bkm": "bkm-Latn-CM",
+ "bkn": "bkn-Latn-ID",
+ "bko": "bko-Latn-CM",
+ "bkp": "bkp-Latn-CD",
+ "bkq": "bkq-Latn-ZZ",
+ "bkr": "bkr-Latn-ID",
+ "bks": "bks-Latn-PH",
+ "bkt": "bkt-Latn-CD",
+ "bku": "bku-Latn-PH",
+ "bkv": "bkv-Latn-ZZ",
+ "bkw": "bkw-Latn-CG",
+ "bkx": "bkx-Latn-TL",
+ "bky": "bky-Latn-NG",
+ "bkz": "bkz-Latn-ID",
+ "bla": "bla-Latn-CA",
+ "blb": "blb-Latn-SB",
+ "blc": "blc-Latn-CA",
+ "bld": "bld-Latn-ID",
+ "ble": "ble-Latn-GW",
+ "blf": "blf-Latn-ID",
+ "blg": "iba-Latn-MY",
+ "blh": "blh-Latn-LR",
+ "bli": "bli-Latn-CD",
+ "blj": "blj-Latn-ID",
+ "blk": "blk-Mymr-MM",
+ "blm": "blm-Latn-SS",
+ "bln": "bln-Latn-PH",
+ "blo": "blo-Latn-BJ",
+ "blp": "blp-Latn-SB",
+ "blq": "blq-Latn-PG",
+ "blr": "blr-Latn-CN",
+ "blr-Tale": "blr-Tale-CN",
+ "blr-Thai": "blr-Thai-TH",
+ "bls": "bls-Latn-ID",
+ "blt": "blt-Tavt-VN",
+ "blv": "blv-Latn-AO",
+ "blw": "blw-Latn-PH",
+ "blx": "blx-Latn-PH",
+ "bly": "bly-Latn-BJ",
+ "blz": "blz-Latn-ID",
+ "bm": "bm-Latn-ML",
+ "bma": "bma-Latn-NG",
+ "bmb": "bmb-Latn-CD",
+ "bmc": "bmc-Latn-PG",
+ "bmd": "bmd-Latn-GN",
+ "bme": "bme-Latn-CF",
+ "bmf": "bmf-Latn-SL",
+ "bmg": "bmg-Latn-CD",
+ "bmh": "bmh-Latn-ZZ",
+ "bmi": "bmi-Latn-TD",
+ "bmj": "bmj-Deva-NP",
+ "bmk": "bmk-Latn-ZZ",
+ "bml": "bml-Latn-CD",
+ "bmm": "bmm-Latn-MG",
+ "bmn": "bmn-Latn-PG",
+ "bmo": "bmo-Latn-CM",
+ "bmp": "bmp-Latn-PG",
+ "bmq": "bmq-Latn-ML",
+ "bmr": "bmr-Latn-CO",
+ "bms": "bms-Latn-NE",
+ "bmu": "bmu-Latn-ZZ",
+ "bmv": "bmv-Latn-CM",
+ "bmw": "bmw-Latn-CG",
+ "bmx": "bmx-Latn-PG",
+ "bmz": "bmz-Latn-PG",
+ "bn": "bn-Beng-BD",
+ "bna": "bna-Latn-ID",
+ "bnb": "bnb-Latn-MY",
+ "bnc": "bnc-Latn-PH",
+ "bnd": "bnd-Latn-ID",
+ "bne": "bne-Latn-ID",
+ "bnf": "bnf-Latn-ID",
+ "bng": "bng-Latn-ZZ",
+ "bni": "bni-Latn-CD",
+ "bnj": "bnj-Latn-PH",
+ "bnk": "bnk-Latn-VU",
+ "bnm": "bnm-Latn-ZZ",
+ "bnn": "bnn-Latn-TW",
+ "bno": "bno-Latn-PH",
+ "bnp": "bnp-Latn-ZZ",
+ "bnq": "bnq-Latn-ID",
+ "bnr": "bnr-Latn-VU",
+ "bns": "bns-Deva-IN",
+ "bnu": "bnu-Latn-ID",
+ "bnv": "bnv-Latn-ID",
+ "bnw": "bnw-Latn-PG",
+ "bnx": "bnx-Latn-CD",
+ "bny": "bny-Latn-MY",
+ "bnz": "bnz-Latn-CM",
+ "bo": "bo-Tibt-CN",
+ "boa": "boa-Latn-PE",
+ "bob": "bob-Latn-KE",
+ "boe": "boe-Latn-CM",
+ "bof": "bof-Latn-BF",
+ "boh": "boh-Latn-CD",
+ "boj": "boj-Latn-ZZ",
+ "bok": "bok-Latn-CG",
+ "bol": "bol-Latn-NG",
+ "bom": "bom-Latn-ZZ",
+ "bon": "bon-Latn-ZZ",
+ "boo": "boo-Latn-ML",
+ "bop": "bop-Latn-PG",
+ "boq": "boq-Latn-PG",
+ "bor": "bor-Latn-BR",
+ "bot": "bot-Latn-SS",
+ "bou": "bou-Latn-TZ",
+ "bov": "bov-Latn-GH",
+ "bow": "bow-Latn-PG",
+ "box": "box-Latn-BF",
+ "boy": "boy-Latn-CF",
+ "boz": "boz-Latn-ML",
+ "boz-Arab": "boz-Arab-ML",
+ "bpa": "bpa-Latn-VU",
+ "bpc": "bpc-Latn-CM",
+ "bpd": "bpd-Latn-CF",
+ "bpe": "bpe-Latn-PG",
+ "bpg": "bpg-Latn-ID",
+ "bph": "bph-Cyrl-RU",
+ "bpi": "bpi-Latn-PG",
+ "bpj": "bpj-Latn-CD",
+ "bpk": "bpk-Latn-NC",
+ "bpl": "bpl-Latn-AU",
+ "bpm": "bpm-Latn-PG",
+ "bpo": "bpo-Latn-ID",
+ "bpp": "bpp-Latn-ID",
+ "bpq": "bpq-Latn-ID",
+ "bpr": "bpr-Latn-PH",
+ "bps": "bps-Latn-PH",
+ "bpt": "bpt-Latn-AU",
+ "bpu": "bpu-Latn-PG",
+ "bpv": "bpv-Latn-ID",
+ "bpw": "bpw-Latn-PG",
+ "bpx": "bpx-Deva-IN",
+ "bpy": "bpy-Beng-IN",
+ "bpz": "bpz-Latn-ID",
+ "bqa": "bqa-Latn-BJ",
+ "bqb": "bqb-Latn-ID",
+ "bqc": "bqc-Latn-ZZ",
+ "bqd": "bqd-Latn-CM",
+ "bqf": "bqf-Latn-GN",
+ "bqf-Arab": "bqf-Arab-GN",
+ "bqg": "bqg-Latn-TG",
+ "bqi": "bqi-Arab-IR",
+ "bqj": "bqj-Latn-SN",
+ "bqk": "bqk-Latn-CF",
+ "bql": "bql-Latn-PG",
+ "bqm": "bqm-Latn-CM",
+ "bqo": "bqo-Latn-CM",
+ "bqp": "bqp-Latn-ZZ",
+ "bqq": "bqq-Latn-ID",
+ "bqr": "bqr-Latn-ID",
+ "bqs": "bqs-Latn-PG",
+ "bqt": "bqt-Latn-CM",
+ "bqu": "bqu-Latn-CD",
+ "bqv": "bqv-Latn-CI",
+ "bqw": "bqw-Latn-NG",
+ "bqx": "bqx-Latn-NG",
+ "bqz": "bqz-Latn-CM",
+ "br": "br-Latn-FR",
+ "bra": "bra-Deva-IN",
+ "brb": "brb-Khmr-KH",
+ "brb-Laoo": "brb-Laoo-LA",
+ "brb-Latn": "brb-Latn-VN",
+ "brc": "brc-Latn-GY",
+ "brd": "brd-Deva-NP",
+ "brf": "brf-Latn-CD",
+ "brg": "brg-Latn-BO",
+ "brh": "brh-Arab-PK",
+ "bri": "bri-Latn-CM",
+ "brj": "brj-Latn-VU",
+ "brk": "brk-Arab-SD",
+ "brl": "brl-Latn-BW",
+ "brm": "brm-Latn-CD",
+ "brn": "brn-Latn-CR",
+ "brp": "brp-Latn-ID",
+ "brq": "brq-Latn-PG",
+ "brr": "brr-Latn-SB",
+ "brs": "brs-Latn-ID",
+ "brt": "brt-Latn-NG",
+ "bru": "bru-Latn-VN",
+ "bru-Laoo": "bru-Laoo-LA",
+ "bru-Thai": "bru-Thai-LA",
+ "brv": "brv-Laoo-LA",
+ "brx": "brx-Deva-IN",
+ "bry": "bry-Latn-PG",
+ "brz": "brz-Latn-ZZ",
+ "bs": "bs-Latn-BA",
+ "bsa": "bsa-Latn-ID",
+ "bsb": "bsb-Latn-BN",
+ "bsc": "bsc-Latn-SN",
+ "bse": "bse-Latn-CM",
+ "bsf": "bsf-Latn-NG",
+ "bsh": "bsh-Arab-AF",
+ "bsi": "bsi-Latn-CM",
+ "bsj": "bsj-Latn-ZZ",
+ "bsk": "bsk-Arab-PK",
+ "bsk-Latn": "bsk-Latn-PK",
+ "bsl": "bsl-Latn-NG",
+ "bsm": "bsm-Latn-ID",
+ "bsn": "bsn-Latn-CO",
+ "bso": "bso-Latn-TD",
+ "bsp": "bsp-Latn-GN",
+ "bsq": "bsq-Bass-LR",
+ "bsr": "bsr-Latn-NG",
+ "bss": "bss-Latn-CM",
+ "bst": "bst-Ethi-ZZ",
+ "bsu": "bsu-Latn-ID",
+ "bsv": "bsv-Latn-GN",
+ "bsv-Arab": "bsv-Arab-GN",
+ "bsw": "bsw-Latn-ET",
+ "bsw-Ethi": "bsw-Ethi-ET",
+ "bsx": "bsx-Latn-NG",
+ "bsy": "bsy-Latn-MY",
+ "bta": "bta-Latn-NG",
+ "btc": "btc-Latn-CM",
+ "btd": "btd-Batk-ID",
+ "bte": "bte-Latn-NG",
+ "btf": "btf-Latn-TD",
+ "btg": "btg-Latn-CI",
+ "bth": "bth-Latn-MY",
+ "bti": "bti-Latn-ID",
+ "btj": "btj-Latn-ID",
+ "btm": "btm-Batk-ID",
+ "btn": "btn-Latn-PH",
+ "bto": "bto-Latn-PH",
+ "btp": "btp-Latn-PG",
+ "btq": "btq-Latn-MY",
+ "btr": "btr-Latn-VU",
+ "bts": "bts-Latn-ID",
+ "bts-Batk": "bts-Batk-ID",
+ "btt": "btt-Latn-ZZ",
+ "btu": "btu-Latn-NG",
+ "btv": "btv-Deva-PK",
+ "btw": "btw-Latn-PH",
+ "btx": "btx-Latn-ID",
+ "btx-Batk": "btx-Batk-ID",
+ "bty": "bty-Latn-ID",
+ "btz": "btz-Latn-ID",
+ "bua": "bua-Cyrl-RU",
+ "bub": "bub-Latn-TD",
+ "buc": "buc-Latn-YT",
+ "bud": "bud-Latn-ZZ",
+ "bue": "bue-Latn-CA",
+ "buf": "buf-Latn-CD",
+ "bug": "bug-Latn-ID",
+ "buh": "buh-Latn-CN",
+ "bui": "bui-Latn-CG",
+ "buj": "buj-Latn-NG",
+ "buk": "buk-Latn-ZZ",
+ "bum": "bum-Latn-CM",
+ "bun": "bun-Latn-SL",
+ "buo": "buo-Latn-ZZ",
+ "bup": "bup-Latn-ID",
+ "buq": "buq-Latn-PG",
+ "bus": "bus-Latn-ZZ",
+ "but": "but-Latn-PG",
+ "buu": "buu-Latn-ZZ",
+ "buv": "buv-Latn-PG",
+ "buw": "buw-Latn-GA",
+ "bux": "bux-Latn-NG",
+ "buy": "buy-Latn-SL",
+ "buz": "buz-Latn-NG",
+ "bva": "bva-Latn-TD",
+ "bvb": "bvb-Latn-GQ",
+ "bvc": "bvc-Latn-SB",
+ "bvd": "bvd-Latn-SB",
+ "bve": "bve-Latn-ID",
+ "bvf": "bvf-Latn-TD",
+ "bvg": "bvg-Latn-CM",
+ "bvh": "bvh-Latn-NG",
+ "bvi": "bvi-Latn-SS",
+ "bvj": "bvj-Latn-NG",
+ "bvk": "bvk-Latn-ID",
+ "bvm": "bvm-Latn-CM",
+ "bvn": "bvn-Latn-PG",
+ "bvo": "bvo-Latn-TD",
+ "bvq": "bvq-Latn-CF",
+ "bvr": "bvr-Latn-AU",
+ "bvt": "bvt-Latn-ID",
+ "bvu": "bvu-Latn-ID",
+ "bvv": "bvv-Latn-VE",
+ "bvw": "bvw-Latn-NG",
+ "bvx": "bvx-Latn-CG",
+ "bvy": "bvy-Latn-PH",
+ "bvz": "bvz-Latn-ID",
+ "bwa": "bwa-Latn-NC",
+ "bwb": "bwb-Latn-FJ",
+ "bwc": "bwc-Latn-ZM",
+ "bwd": "bwd-Latn-ZZ",
+ "bwe": "bwe-Mymr-MM",
+ "bwe-Latn": "bwe-Latn-MM",
+ "bwf": "bwf-Latn-PG",
+ "bwg": "bwg-Latn-MZ",
+ "bwh": "bwh-Latn-CM",
+ "bwi": "bwi-Latn-VE",
+ "bwj": "bwj-Latn-BF",
+ "bwk": "bwk-Latn-PG",
+ "bwl": "bwl-Latn-CD",
+ "bwm": "bwm-Latn-PG",
+ "bwo": "bwo-Latn-ET",
+ "bwo-Ethi": "bwo-Ethi-ET",
+ "bwp": "bwp-Latn-ID",
+ "bwq": "bwq-Latn-BF",
+ "bwr": "bwr-Latn-ZZ",
+ "bws": "bws-Latn-CD",
+ "bwt": "bwt-Latn-CM",
+ "bwu": "bwu-Latn-GH",
+ "bww": "bww-Latn-CD",
+ "bwx": "bwx-Latn-CN",
+ "bwy": "bwy-Latn-BF",
+ "bwz": "bwz-Latn-CG",
+ "bxa": "bxa-Latn-SB",
+ "bxb": "bxb-Latn-SS",
+ "bxc": "bxc-Latn-GQ",
+ "bxf": "bxf-Latn-PG",
+ "bxg": "bxg-Latn-CD",
+ "bxh": "bxh-Latn-ZZ",
+ "bxi": "bxi-Latn-AU",
+ "bxj": "bxj-Latn-AU",
+ "bxl": "bxl-Latn-BF",
+ "bxm": "bxm-Cyrl-MN",
+ "bxm-Latn": "bxm-Latn-MN",
+ "bxm-Mong": "bxm-Mong-MN",
+ "bxn": "bxn-Latn-AU",
+ "bxo": "bxo-Latn-NG",
+ "bxp": "bxp-Latn-CM",
+ "bxq": "bxq-Latn-NG",
+ "bxs": "bxs-Latn-CM",
+ "bxu": "bxu-Mong-CN",
+ "bxu-Cyrl": "bxu-Cyrl-CN",
+ "bxu-Latn": "bxu-Latn-CN",
+ "bxv": "bxv-Latn-TD",
+ "bxw": "bxw-Latn-ML",
+ "bxz": "bxz-Latn-PG",
+ "bya": "bya-Latn-PH",
+ "byb": "byb-Latn-CM",
+ "byc": "byc-Latn-NG",
+ "byd": "byd-Latn-ID",
+ "bye": "bye-Latn-ZZ",
+ "byf": "byf-Latn-NG",
+ "byh": "byh-Deva-NP",
+ "byi": "byi-Latn-CD",
+ "byj": "byj-Latn-NG",
+ "byk": "byk-Latn-CN",
+ "byl": "byl-Latn-ID",
+ "bym": "bym-Latn-AU",
+ "byn": "byn-Ethi-ER",
+ "byp": "byp-Latn-NG",
+ "byr": "byr-Latn-ZZ",
+ "bys": "bys-Latn-ZZ",
+ "byv": "byv-Latn-CM",
+ "byw": "byw-Deva-NP",
+ "byx": "byx-Latn-ZZ",
+ "byz": "byz-Latn-PG",
+ "bza": "bza-Latn-ZZ",
+ "bzb": "bzb-Latn-ID",
+ "bzc": "bzc-Latn-MG",
+ "bzd": "bzd-Latn-CR",
+ "bze": "bze-Latn-ML",
+ "bzf": "bzf-Latn-ZZ",
+ "bzh": "bzh-Latn-ZZ",
+ "bzi": "bzi-Thai-TH",
+ "bzj": "bzj-Latn-BZ",
+ "bzk": "bzk-Latn-NI",
+ "bzl": "bzl-Latn-ID",
+ "bzm": "bzm-Latn-CD",
+ "bzn": "bzn-Latn-ID",
+ "bzo": "bzo-Latn-CD",
+ "bzp": "bzp-Latn-ID",
+ "bzq": "bzq-Latn-ID",
+ "bzr": "bzr-Latn-AU",
+ "bzt": "bzt-Latn-001",
+ "bzu": "bzu-Latn-ID",
+ "bzv": "bzv-Latn-CM",
+ "bzw": "bzw-Latn-ZZ",
+ "bzx": "bzx-Latn-ML",
+ "bzy": "bzy-Latn-NG",
+ "bzz": "bzz-Latn-NG",
+ "ca": "ca-Latn-ES",
+ "caa": "caa-Latn-GT",
+ "cab": "cab-Latn-HN",
+ "cac": "cac-Latn-GT",
+ "cad": "cad-Latn-US",
+ "cae": "cae-Latn-SN",
+ "caf": "caf-Latn-CA",
+ "caf-Cans": "caf-Cans-CA",
+ "cag": "cag-Latn-PY",
+ "cah": "cah-Latn-PE",
+ "caj": "caj-Latn-AR",
+ "cak": "cak-Latn-GT",
+ "cal": "cal-Latn-MP",
+ "cam": "cam-Latn-NC",
+ "can": "can-Latn-ZZ",
+ "cao": "cao-Latn-BO",
+ "cap": "cap-Latn-BO",
+ "caq": "caq-Latn-IN",
+ "car": "car-Latn-VE",
+ "cas": "cas-Latn-BO",
+ "cav": "cav-Latn-BO",
+ "caw": "caw-Latn-BO",
+ "cax": "cax-Latn-BO",
+ "cay": "cay-Latn-CA",
+ "caz": "caz-Latn-BO",
+ "cbb": "cbb-Latn-CO",
+ "cbc": "cbc-Latn-CO",
+ "cbd": "cbd-Latn-CO",
+ "cbg": "cbg-Latn-CO",
+ "cbi": "cbi-Latn-EC",
+ "cbj": "cbj-Latn-ZZ",
+ "cbk": "cbk-Latn-PH",
+ "cbk-Brai": "cbk-Brai-PH",
+ "cbl": "cbl-Latn-MM",
+ "cbn": "cbn-Thai-TH",
+ "cbo": "cbo-Latn-NG",
+ "cbq": "cbq-Latn-NG",
+ "cbr": "cbr-Latn-PE",
+ "cbs": "cbs-Latn-PE",
+ "cbt": "cbt-Latn-PE",
+ "cbu": "cbu-Latn-PE",
+ "cbv": "cbv-Latn-CO",
+ "cbw": "cbw-Latn-PH",
+ "cby": "cby-Latn-CO",
+ "ccc": "ccc-Latn-PE",
+ "ccd": "ccd-Latn-BR",
+ "cce": "cce-Latn-MZ",
+ "ccg": "ccg-Latn-NG",
+ "cch": "cch-Latn-NG",
+ "ccj": "ccj-Latn-GW",
+ "ccl": "ccl-Latn-TZ",
+ "ccm": "ccm-Latn-MY",
+ "cco": "cco-Latn-MX",
+ "ccp": "ccp-Cakm-BD",
+ "ccr": "ccr-Latn-SV",
+ "cde": "cde-Telu-IN",
+ "cdf": "cdf-Latn-IN",
+ "cdf-Beng": "cdf-Beng-IN",
+ "cdh": "cdh-Deva-IN",
+ "cdh-Takr": "cdh-Takr-IN",
+ "cdi": "cdi-Gujr-IN",
+ "cdj": "cdj-Deva-IN",
+ "cdm": "cdm-Deva-NP",
+ "cdm-Latn": "cdm-Latn-NP",
+ "cdo": "cdo-Hans-CN",
+ "cdo-Hant": "cdo-Hant-CN",
+ "cdo-Latn": "cdo-Latn-CN",
+ "cdr": "cdr-Latn-NG",
+ "cdz": "cdz-Beng-IN",
+ "ce": "ce-Cyrl-RU",
+ "cea": "cea-Latn-US",
+ "ceb": "ceb-Latn-PH",
+ "ceg": "ceg-Latn-PY",
+ "cek": "cek-Latn-MM",
+ "cen": "cen-Latn-NG",
+ "cet": "cet-Latn-NG",
+ "cey": "cey-Latn-MM",
+ "cfa": "cfa-Latn-ZZ",
+ "cfd": "cfd-Latn-NG",
+ "cfg": "cfg-Latn-NG",
+ "cfm": "cfm-Latn-MM",
+ "cfm-Beng": "cfm-Beng-IN",
+ "cga": "cga-Latn-PG",
+ "cgc": "cgc-Latn-PH",
+ "cgg": "cgg-Latn-UG",
+ "cgk": "cgk-Tibt-BT",
+ "ch": "ch-Latn-GU",
+ "chb": "chb-Latn-CO",
+ "chd": "chd-Latn-MX",
+ "chf": "chf-Latn-MX",
+ "chg": "chg-Arab-TM",
+ "chh": "chh-Latn-US",
+ "chj": "chj-Latn-MX",
+ "chk": "chk-Latn-FM",
+ "chl": "chl-Latn-US",
+ "chm": "chm-Cyrl-RU",
+ "chn": "chn-Latn-US",
+ "chn-Dupl": "chn-Dupl-US",
+ "cho": "cho-Latn-US",
+ "chp": "chp-Latn-CA",
+ "chq": "chq-Latn-MX",
+ "chr": "chr-Cher-US",
+ "cht": "cht-Latn-PE",
+ "chw": "chw-Latn-MZ",
+ "chx": "chx-Deva-NP",
+ "chy": "chy-Latn-US",
+ "chz": "chz-Latn-MX",
+ "cia": "cia-Latn-ID",
+ "cia-Arab": "cia-Arab-ID",
+ "cia-Hang": "cia-Hang-ID",
+ "cib": "cib-Latn-BJ",
+ "cic": "cic-Latn-US",
+ "cie": "cie-Latn-NG",
+ "cih": "cih-Deva-IN",
+ "cim": "cim-Latn-IT",
+ "cin": "cin-Latn-BR",
+ "cip": "cip-Latn-MX",
+ "cir": "cir-Latn-NC",
+ "ciw": "ciw-Latn-US",
+ "ciw-Cans": "ciw-Cans-US",
+ "ciy": "ciy-Latn-VE",
+ "cja": "cja-Arab-KH",
+ "cje": "cje-Latn-VN",
+ "cjh": "cjh-Latn-US",
+ "cji": "cji-Cyrl-RU",
+ "cjk": "cjk-Latn-AO",
+ "cjm": "cjm-Cham-VN",
+ "cjn": "cjn-Latn-PG",
+ "cjo": "cjo-Latn-PE",
+ "cjp": "cjp-Latn-CR",
+ "cjs": "cjs-Latn-RU",
+ "cjs-Cyrl": "cjs-Cyrl-RU",
+ "cjv": "cjv-Latn-ZZ",
+ "cjy": "cjy-Hans-CN",
+ "cjy-Hant": "cjy-Hant-CN",
+ "ckb": "ckb-Arab-IQ",
+ "ckl": "ckl-Latn-ZZ",
+ "ckm": "ckm-Latn-HR",
+ "ckm-Glag": "ckm-Glag-HR",
+ "ckn": "ckn-Latn-MM",
+ "cko": "cko-Latn-ZZ",
+ "ckq": "ckq-Latn-TD",
+ "ckr": "ckr-Latn-PG",
+ "cks": "cks-Latn-NC",
+ "ckt": "ckt-Cyrl-RU",
+ "cku": "cku-Latn-US",
+ "ckv": "ckv-Latn-TW",
+ "ckx": "ckx-Latn-CM",
+ "cky": "cky-Latn-ZZ",
+ "ckz": "ckz-Latn-GT",
+ "cla": "cla-Latn-ZZ",
+ "clc": "clc-Latn-CA",
+ "cle": "cle-Latn-MX",
+ "clh": "clh-Arab-PK",
+ "cli": "cli-Latn-GH",
+ "clj": "clj-Latn-MM",
+ "clk": "clk-Latn-IN",
+ "clk-Tibt": "clk-Tibt-CN",
+ "cll": "cll-Latn-GH",
+ "clm": "clm-Latn-US",
+ "clo": "clo-Latn-MX",
+ "clt": "clt-Latn-MM",
+ "clu": "clu-Latn-PH",
+ "clw": "clw-Cyrl-RU",
+ "cly": "cly-Latn-MX",
+ "cma": "cma-Latn-VN",
+ "cme": "cme-Latn-ZZ",
+ "cmg": "cmg-Soyo-MN",
+ "cmi": "cmi-Latn-CO",
+ "cml": "cml-Latn-ID",
+ "cmo": "cmo-Latn-VN",
+ "cmo-KH": "cmo-Latn-KH",
+ "cmo-Khmr": "cmo-Khmr-KH",
+ "cmr": "cmr-Latn-MM",
+ "cms": "cms-Latn-IT",
+ "cmt": "cmt-Latn-ZA",
+ "cna": "cna-Tibt-IN",
+ "cnb": "cnb-Latn-MM",
+ "cnc": "cnc-Latn-VN",
+ "cng": "cng-Latn-CN",
+ "cnh": "cnh-Latn-MM",
+ "cni": "cni-Latn-PE",
+ "cnk": "cnk-Latn-MM",
+ "cnl": "cnl-Latn-MX",
+ "cnp": "cnp-Hans-CN",
+ "cnp-Hant": "cnp-Hant-CN",
+ "cnq": "cnq-Latn-CM",
+ "cns": "cns-Latn-ID",
+ "cnt": "cnt-Latn-MX",
+ "cnw": "cnw-Latn-MM",
+ "cnx": "cnx-Latn-GB",
+ "co": "co-Latn-FR",
+ "coa": "coa-Latn-AU",
+ "cob": "cob-Latn-MX",
+ "coc": "coc-Latn-MX",
+ "cod": "cod-Latn-PE",
+ "coe": "coe-Latn-CO",
+ "cof": "cof-Latn-EC",
+ "cog": "cog-Thai-TH",
+ "coh": "coh-Latn-KE",
+ "coj": "coj-Latn-MX",
+ "cok": "cok-Latn-MX",
+ "col": "col-Latn-US",
+ "com": "com-Latn-US",
+ "coo": "coo-Latn-CA",
+ "cop": "cop-Copt-EG",
+ "coq": "coq-Latn-US",
+ "cot": "cot-Latn-PE",
+ "cou": "cou-Latn-SN",
+ "cox": "cox-Latn-PE",
+ "coz": "coz-Latn-MX",
+ "cpa": "cpa-Latn-MX",
+ "cpb": "cpb-Latn-PE",
+ "cpc": "cpc-Latn-PE",
+ "cpg": "cpg-Grek-GR",
+ "cpi": "cpi-Latn-NR",
+ "cpn": "cpn-Latn-GH",
+ "cpo": "cpo-Latn-BF",
+ "cps": "cps-Latn-PH",
+ "cpu": "cpu-Latn-PE",
+ "cpx": "cpx-Latn-CN",
+ "cpy": "cpy-Latn-PE",
+ "cqd": "cqd-Latn-CN",
+ "cr": "cr-Cans-CA",
+ "crb": "crb-Latn-VC",
+ "crc": "crc-Latn-VU",
+ "crd": "crd-Latn-US",
+ "crf": "crf-Latn-CO",
+ "crg": "crg-Latn-CA",
+ "crh": "crh-Cyrl-UA",
+ "cri": "cri-Latn-ST",
+ "crj": "crj-Cans-CA",
+ "crj-Latn": "crj-Latn-CA",
+ "crk": "crk-Cans-CA",
+ "crl": "crl-Cans-CA",
+ "crm": "crm-Cans-CA",
+ "crn": "crn-Latn-MX",
+ "cro": "cro-Latn-US",
+ "crq": "crq-Latn-AR",
+ "crs": "crs-Latn-SC",
+ "crt": "crt-Latn-AR",
+ "crv": "crv-Latn-IN",
+ "crw": "crw-Latn-VN",
+ "crx": "crx-Latn-CA",
+ "crx-Cans": "crx-Cans-CA",
+ "cry": "cry-Latn-NG",
+ "crz": "crz-Latn-US",
+ "cs": "cs-Latn-CZ",
+ "csa": "csa-Latn-MX",
+ "csb": "csb-Latn-PL",
+ "csh": "csh-Mymr-MM",
+ "csh-Latn": "csh-Latn-MM",
+ "csj": "csj-Latn-MM",
+ "csk": "csk-Latn-SN",
+ "csm": "csm-Latn-US",
+ "cso": "cso-Latn-MX",
+ "csp": "csp-Hans-CN",
+ "csp-Hant": "csp-Hant-CN",
+ "css": "css-Latn-US",
+ "cst": "cst-Latn-US",
+ "csv": "csv-Latn-MM",
+ "csw": "csw-Cans-CA",
+ "csy": "csy-Latn-MM",
+ "csz": "csz-Latn-US",
+ "cta": "cta-Latn-MX",
+ "ctc": "ctc-Latn-US",
+ "ctd": "ctd-Pauc-MM",
+ "cte": "cte-Latn-MX",
+ "ctg": "ctg-Beng-BD",
+ "ctg-Arab": "ctg-Arab-BD",
+ "ctg-Latn": "ctg-Latn-BD",
+ "cth": "cth-Latn-MM",
+ "ctl": "ctl-Latn-MX",
+ "ctm": "ctm-Latn-US",
+ "ctn": "ctn-Deva-NP",
+ "cto": "cto-Latn-CO",
+ "ctp": "ctp-Latn-MX",
+ "cts": "cts-Latn-PH",
+ "ctt": "ctt-Taml-IN",
+ "ctu": "ctu-Latn-MX",
+ "ctz": "ctz-Latn-MX",
+ "cu": "cu-Cyrl-RU",
+ "cu-Glag": "cu-Glag-BG",
+ "cua": "cua-Latn-VN",
+ "cub": "cub-Latn-CO",
+ "cuc": "cuc-Latn-MX",
+ "cuh": "cuh-Latn-KE",
+ "cui": "cui-Latn-CO",
+ "cuj": "cuj-Latn-PE",
+ "cuk": "cuk-Latn-PA",
+ "cul": "cul-Latn-BR",
+ "cuo": "cuo-Latn-VE",
+ "cup": "cup-Latn-US",
+ "cut": "cut-Latn-MX",
+ "cuu": "cuu-Lana-CN",
+ "cuv": "cuv-Latn-CM",
+ "cux": "cux-Latn-MX",
+ "cv": "cv-Cyrl-RU",
+ "cvg": "cvg-Latn-IN",
+ "cvg-Tibt": "cvg-Tibt-IN",
+ "cvn": "cvn-Latn-MX",
+ "cwa": "cwa-Latn-TZ",
+ "cwb": "cwb-Latn-MZ",
+ "cwe": "cwe-Latn-TZ",
+ "cwg": "cwg-Latn-MY",
+ "cwt": "cwt-Latn-SN",
+ "cy": "cy-Latn-GB",
+ "cya": "cya-Latn-MX",
+ "cyb": "cyb-Latn-BO",
+ "cyo": "cyo-Latn-PH",
+ "czh": "czh-Hans-CN",
+ "czh-Hant": "czh-Hant-CN",
+ "czk": "czk-Hebr-CZ",
+ "czn": "czn-Latn-MX",
+ "czt": "czt-Latn-MM",
+ "da": "da-Latn-DK",
+ "daa": "daa-Latn-TD",
+ "dac": "dac-Latn-PG",
+ "dad": "dad-Latn-ZZ",
+ "dae": "dae-Latn-CM",
+ "daf": "dnj-Latn-CI",
+ "dag": "dag-Latn-ZZ",
+ "dah": "dah-Latn-ZZ",
+ "dai": "dai-Latn-TD",
+ "daj": "daj-Latn-SD",
+ "dak": "dak-Latn-US",
+ "dal": "dal-Latn-KE",
+ "dam": "dam-Latn-NG",
+ "dao": "dao-Latn-MM",
+ "daq": "daq-Deva-IN",
+ "dar": "dar-Cyrl-RU",
+ "das": "das-Latn-CI",
+ "dau": "dau-Latn-TD",
+ "dav": "dav-Latn-KE",
+ "daw": "daw-Latn-PH",
+ "dax": "dax-Latn-AU",
+ "daz": "daz-Latn-ID",
+ "dba": "dba-Latn-ML",
+ "dbb": "dbb-Latn-NG",
+ "dbd": "dbd-Latn-ZZ",
+ "dbe": "dbe-Latn-ID",
+ "dbf": "dbf-Latn-ID",
+ "dbg": "dbg-Latn-ML",
+ "dbi": "dbi-Latn-NG",
+ "dbj": "dbj-Latn-MY",
+ "dbj-Arab": "dbj-Arab-MY",
+ "dbl": "dbl-Latn-AU",
+ "dbm": "dbm-Latn-NG",
+ "dbn": "dbn-Latn-ID",
+ "dbo": "dbo-Latn-NG",
+ "dbp": "dbp-Latn-NG",
+ "dbq": "dbq-Latn-ZZ",
+ "dbt": "dbt-Latn-ML",
+ "dbu": "dbu-Latn-ML",
+ "dbv": "dbv-Latn-NG",
+ "dbw": "dbw-Latn-ML",
+ "dby": "dby-Latn-PG",
+ "dcc": "dcc-Arab-IN",
+ "dcr": "dcr-Latn-VI",
+ "dda": "dda-Latn-AU",
+ "ddd": "ddd-Latn-SS",
+ "dde": "dde-Latn-CG",
+ "ddg": "ddg-Latn-TL",
+ "ddi": "ddi-Latn-PG",
+ "ddj": "ddj-Latn-AU",
+ "ddn": "ddn-Latn-ZZ",
+ "ddo": "ddo-Cyrl-RU",
+ "ddr": "ddr-Latn-AU",
+ "dds": "dds-Latn-ML",
+ "ddw": "ddw-Latn-ID",
+ "de": "de-Latn-DE",
+ "dec": "dec-Latn-SD",
+ "ded": "ded-Latn-ZZ",
+ "dee": "dee-Latn-LR",
+ "def": "def-Arab-IR",
+ "deg": "deg-Latn-NG",
+ "deh": "deh-Arab-PK",
+ "dei": "dei-Latn-ID",
+ "dek": "dek-Latn-CM",
+ "del": "del-Latn-US",
+ "dem": "dem-Latn-ID",
+ "den": "den-Latn-CA",
+ "deq": "deq-Latn-CF",
+ "der": "der-Beng-IN",
+ "der-Latn": "der-Latn-IN",
+ "des": "des-Latn-BR",
+ "dev": "dev-Latn-PG",
+ "dez": "dez-Latn-CD",
+ "dga": "dga-Latn-ZZ",
+ "dgb": "dgb-Latn-ML",
+ "dgc": "dgc-Latn-PH",
+ "dgd": "dgd-Latn-BF",
+ "dge": "dge-Latn-PG",
+ "dgg": "dgg-Latn-PG",
+ "dgh": "dgh-Latn-ZZ",
+ "dgi": "dgi-Latn-ZZ",
+ "dgk": "dgk-Latn-CF",
+ "dgl": "dgl-Arab-ZZ",
+ "dgn": "dgn-Latn-AU",
+ "dgr": "dgr-Latn-CA",
+ "dgs": "dgs-Latn-BF",
+ "dgt": "dgt-Latn-AU",
+ "dgw": "dgw-Latn-AU",
+ "dgx": "dgx-Latn-PG",
+ "dgz": "dgz-Latn-ZZ",
+ "dhg": "dhg-Latn-AU",
+ "dhi": "dhi-Deva-NP",
+ "dhl": "dhl-Latn-AU",
+ "dhm": "dhm-Latn-AO",
+ "dhn": "dhn-Gujr-IN",
+ "dho": "dho-Deva-IN",
+ "dhr": "dhr-Latn-AU",
+ "dhs": "dhs-Latn-TZ",
+ "dhu": "dhu-Latn-AU",
+ "dhv": "dhv-Latn-NC",
+ "dhw": "dhw-Deva-NP",
+ "dhx": "dhx-Latn-AU",
+ "dia": "dia-Latn-ZZ",
+ "dib": "dib-Latn-SS",
+ "dic": "dic-Latn-CI",
+ "did": "did-Latn-SS",
+ "dif": "dif-Latn-AU",
+ "dig": "dig-Latn-KE",
+ "dih": "dih-Latn-MX",
+ "dii": "dii-Latn-CM",
+ "dij": "dij-Latn-ID",
+ "dil": "dil-Latn-SD",
+ "din": "din-Latn-SS",
+ "din-Arab": "din-Arab-SS",
+ "dio": "dio-Latn-NG",
+ "dip": "dip-Latn-SS",
+ "dir": "dir-Latn-NG",
+ "dis": "dis-Latn-IN",
+ "dis-Beng": "dis-Beng-IN",
+ "diu": "diu-Latn-NA",
+ "diw": "diw-Latn-SS",
+ "dix": "dix-Latn-VU",
+ "diy": "diy-Latn-ID",
+ "diz": "diz-Latn-CD",
+ "dja": "dja-Latn-AU",
+ "djb": "djb-Latn-AU",
+ "djc": "djc-Latn-TD",
+ "djd": "djd-Latn-AU",
+ "dje": "dje-Latn-NE",
+ "djf": "djf-Latn-AU",
+ "dji": "dji-Latn-AU",
+ "djj": "djj-Latn-AU",
+ "djk": "djk-Latn-SR",
+ "djm": "djm-Latn-ML",
+ "djn": "djn-Latn-AU",
+ "djo": "djo-Latn-ID",
+ "djr": "djr-Latn-AU",
+ "dju": "dju-Latn-PG",
+ "djw": "djw-Latn-AU",
+ "dka": "dka-Tibt-BT",
+ "dkg": "dkg-Latn-NG",
+ "dkk": "dkk-Latn-ID",
+ "dkr": "dkr-Latn-MY",
+ "dks": "dks-Latn-SS",
+ "dkx": "dkx-Latn-CM",
+ "dlg": "dlg-Cyrl-RU",
+ "dlm": "dlm-Latn-HR",
+ "dln": "dln-Latn-IN",
+ "dma": "dma-Latn-GA",
+ "dmb": "dmb-Latn-ML",
+ "dmc": "dmc-Latn-PG",
+ "dmd": "dmd-Latn-AU",
+ "dme": "dme-Latn-CM",
+ "dmf": "dmf-Medf-NG",
+ "dmg": "dmg-Latn-MY",
+ "dmk": "dmk-Arab-PK",
+ "dml": "dml-Arab-PK",
+ "dmm": "dmm-Latn-CM",
+ "dmo": "dmo-Latn-CM",
+ "dmr": "dmr-Latn-ID",
+ "dms": "dms-Latn-ID",
+ "dmu": "dmu-Latn-ID",
+ "dmv": "dmv-Latn-MY",
+ "dmw": "dmw-Latn-AU",
+ "dmx": "dmx-Latn-MZ",
+ "dmy": "dmy-Latn-ID",
+ "dna": "dna-Latn-ID",
+ "dnd": "dnd-Latn-PG",
+ "dne": "dne-Latn-TZ",
+ "dng": "dng-Cyrl-KG",
+ "dng-Arab": "dng-Arab-KG",
+ "dni": "dni-Latn-ID",
+ "dnj": "dnj-Latn-CI",
+ "dnk": "dnk-Latn-ID",
+ "dnn": "dnn-Latn-BF",
+ "dno": "dno-Latn-CD",
+ "dnr": "dnr-Latn-PG",
+ "dnt": "dnt-Latn-ID",
+ "dnu": "dnu-Mymr-MM",
+ "dnv": "dnv-Mymr-MM",
+ "dnw": "dnw-Latn-ID",
+ "dny": "dny-Latn-BR",
+ "doa": "doa-Latn-PG",
+ "dob": "dob-Latn-ZZ",
+ "doc": "doc-Latn-CN",
+ "doe": "doe-Latn-TZ",
+ "dof": "dof-Latn-PG",
+ "doh": "doh-Latn-NG",
+ "doi": "doi-Deva-IN",
+ "dok": "dok-Latn-ID",
+ "dol": "dol-Latn-PG",
+ "don": "don-Latn-PG",
+ "doo": "doo-Latn-CD",
+ "dop": "dop-Latn-ZZ",
+ "dor": "dor-Latn-SB",
+ "dos": "dos-Latn-BF",
+ "dot": "dot-Latn-NG",
+ "dov": "dov-Latn-ZW",
+ "dow": "dow-Latn-ZZ",
+ "dox": "dox-Ethi-ET",
+ "doy": "doy-Latn-GH",
+ "dpp": "dpp-Latn-MY",
+ "drc": "drc-Latn-PT",
+ "dre": "dre-Tibt-NP",
+ "drg": "drg-Latn-MY",
+ "drh": "mn-Cyrl-MN",
+ "dri": "dri-Latn-ZZ",
+ "drl": "drl-Latn-AU",
+ "drn": "drn-Latn-ID",
+ "dro": "dro-Latn-MY",
+ "drq": "drq-Deva-NP",
+ "drs": "drs-Ethi-ZZ",
+ "drt": "drt-Latn-NL",
+ "dru": "dru-Latn-TW",
+ "dry": "dry-Deva-NP",
+ "dsb": "dsb-Latn-DE",
+ "dsh": "dsh-Latn-KE",
+ "dsi": "dsi-Latn-TD",
+ "dsn": "dsn-Latn-ID",
+ "dso": "dso-Orya-IN",
+ "dsq": "dsq-Latn-ML",
+ "dsq-Arab": "dsq-Arab-ML",
+ "dta": "dta-Latn-CN",
+ "dta-Cyrl": "dta-Cyrl-CN",
+ "dta-Hans": "dta-Hans-CN",
+ "dtb": "dtb-Latn-MY",
+ "dtd": "dtd-Latn-CA",
+ "dth": "dth-Latn-AU",
+ "dti": "dti-Latn-ML",
+ "dtk": "dtk-Latn-ML",
+ "dtm": "dtm-Latn-ML",
+ "dto": "dto-Latn-ML",
+ "dtp": "dtp-Latn-MY",
+ "dtr": "dtr-Latn-MY",
+ "dts": "dts-Latn-ZZ",
+ "dtt": "dtt-Latn-ML",
+ "dtu": "dtu-Latn-ML",
+ "dty": "dty-Deva-NP",
+ "dua": "dua-Latn-CM",
+ "dub": "dub-Gujr-IN",
+ "duc": "duc-Latn-ZZ",
+ "dud": "uth-Latn-ZZ",
+ "due": "due-Latn-PH",
+ "duf": "duf-Latn-NC",
+ "dug": "dug-Latn-ZZ",
+ "duh": "duh-Deva-IN",
+ "duh-Gujr": "duh-Gujr-IN",
+ "dui": "dui-Latn-PG",
+ "duk": "duk-Latn-PG",
+ "dul": "dul-Latn-PH",
+ "dum": "dum-Latn-NL",
+ "dun": "dun-Latn-ID",
+ "duo": "duo-Latn-PH",
+ "dup": "dup-Latn-ID",
+ "duq": "duq-Latn-ID",
+ "dur": "dur-Latn-CM",
+ "dus": "dus-Deva-NP",
+ "duu": "duu-Latn-CN",
+ "duv": "duv-Latn-ID",
+ "duw": "duw-Latn-ID",
+ "dux": "dux-Latn-ML",
+ "duy": "duy-Latn-PH",
+ "duz": "duz-Latn-CM",
+ "dv": "dv-Thaa-MV",
+ "dva": "dva-Latn-ZZ",
+ "dwa": "dwa-Latn-NG",
+ "dwk": "dwk-Orya-IN",
+ "dwr": "dwr-Latn-ET",
+ "dwr-Ethi": "dwr-Ethi-ET",
+ "dws": "dws-Latn-001",
+ "dwu": "dwu-Latn-AU",
+ "dww": "dww-Latn-ZZ",
+ "dwy": "dwy-Latn-AU",
+ "dwz": "dwz-Deva-NP",
+ "dya": "dya-Latn-BF",
+ "dyb": "dyb-Latn-AU",
+ "dyd": "dyd-Latn-AU",
+ "dyg": "dyg-Latn-PH",
+ "dyi": "dyi-Latn-CI",
+ "dym": "dym-Latn-ML",
+ "dyn": "dyn-Latn-AU",
+ "dyo": "dyo-Latn-SN",
+ "dyu": "dyu-Latn-BF",
+ "dyy": "dyy-Latn-AU",
+ "dz": "dz-Tibt-BT",
+ "dza": "dza-Latn-NG",
+ "dze": "dze-Latn-AU",
+ "dzg": "dzg-Latn-ZZ",
+ "dzl": "dzl-Tibt-BT",
+ "dzn": "dzn-Latn-CD",
+ "eaa": "eaa-Latn-AU",
+ "ebc": "ebc-Latn-ID",
+ "ebg": "ebg-Latn-NG",
+ "ebk": "ebk-Latn-PH",
+ "ebo": "ebo-Latn-CG",
+ "ebr": "ebr-Latn-CI",
+ "ebu": "ebu-Latn-KE",
+ "ecr": "ecr-Grek-GR",
+ "ecy": "ecy-Cprt-CY",
+ "ee": "ee-Latn-GH",
+ "efa": "efa-Latn-NG",
+ "efe": "efe-Latn-CD",
+ "efi": "efi-Latn-NG",
+ "ega": "ega-Latn-CI",
+ "egl": "egl-Latn-IT",
+ "egm": "egm-Latn-TZ",
+ "ego": "ego-Latn-NG",
+ "egy": "egy-Egyp-EG",
+ "ehu": "ehu-Latn-NG",
+ "eip": "eip-Latn-ID",
+ "eit": "eit-Latn-PG",
+ "eiv": "eiv-Latn-PG",
+ "eja": "eja-Latn-GW",
+ "eka": "eka-Latn-ZZ",
+ "eke": "eke-Latn-NG",
+ "ekg": "ekg-Latn-ID",
+ "eki": "eki-Latn-NG",
+ "ekl": "ekl-Latn-BD",
+ "ekm": "ekm-Latn-CM",
+ "eko": "eko-Latn-MZ",
+ "eko-Arab": "eko-Arab-MZ",
+ "ekp": "ekp-Latn-NG",
+ "ekr": "ekr-Latn-NG",
+ "eky": "eky-Kali-MM",
+ "el": "el-Grek-GR",
+ "ele": "ele-Latn-PG",
+ "elk": "elk-Latn-PG",
+ "elm": "elm-Latn-NG",
+ "elo": "elo-Latn-KE",
+ "elu": "elu-Latn-PG",
+ "ema": "ema-Latn-ZZ",
+ "emb": "emb-Latn-ID",
+ "eme": "eme-Latn-GF",
+ "emg": "emg-Deva-NP",
+ "emi": "emi-Latn-ZZ",
+ "emm": "emm-Latn-MX",
+ "emn": "emn-Latn-CM",
+ "emp": "emp-Latn-PA",
+ "ems": "ems-Latn-US",
+ "ems-Cyrl": "ems-Cyrl-US",
+ "emu": "emu-Deva-IN",
+ "emw": "emw-Latn-ID",
+ "emx": "emx-Latn-FR",
+ "emz": "emz-Latn-CM",
+ "en": "en-Latn-US",
+ "en-Shaw": "en-Shaw-GB",
+ "ena": "ena-Latn-PG",
+ "enb": "enb-Latn-KE",
+ "enc": "enc-Latn-VN",
+ "end": "end-Latn-ID",
+ "enf": "enf-Cyrl-RU",
+ "enh": "enh-Cyrl-RU",
+ "enl": "enl-Latn-PY",
+ "enm": "enm-Latn-GB",
+ "enn": "enn-Latn-ZZ",
+ "eno": "eno-Latn-ID",
+ "enq": "enq-Latn-ZZ",
+ "enr": "enr-Latn-ID",
+ "env": "env-Latn-NG",
+ "enw": "enw-Latn-NG",
+ "enx": "enx-Latn-PY",
+ "eo": "eo-Latn-001",
+ "eot": "eot-Latn-CI",
+ "epi": "epi-Latn-NG",
+ "era": "era-Taml-IN",
+ "erg": "erg-Latn-VU",
+ "erh": "erh-Latn-NG",
+ "eri": "eri-Latn-ZZ",
+ "erk": "erk-Latn-VU",
+ "err": "err-Latn-AU",
+ "ert": "ert-Latn-ID",
+ "erw": "erw-Latn-ID",
+ "es": "es-Latn-ES",
+ "ese": "ese-Latn-BO",
+ "esg": "esg-Gonm-IN",
+ "esh": "esh-Arab-IR",
+ "esi": "esi-Latn-US",
+ "esm": "esm-Latn-CI",
+ "ess": "ess-Latn-US",
+ "ess-Cyrl": "ess-Cyrl-US",
+ "esu": "esu-Latn-US",
+ "esy": "esy-Latn-PH",
+ "et": "et-Latn-EE",
+ "etb": "etb-Latn-NG",
+ "etn": "etn-Latn-VU",
+ "eto": "eto-Latn-CM",
+ "etr": "etr-Latn-ZZ",
+ "ets": "ets-Latn-NG",
+ "ett": "ett-Ital-IT",
+ "etu": "etu-Latn-ZZ",
+ "etx": "etx-Latn-ZZ",
+ "etz": "etz-Latn-ID",
+ "eu": "eu-Latn-ES",
+ "eve": "eve-Cyrl-RU",
+ "evh": "evh-Latn-NG",
+ "evn": "evn-Cyrl-RU",
+ "evn-Latn": "evn-Latn-CN",
+ "evn-Mong": "evn-Mong-CN",
+ "ewo": "ewo-Latn-CM",
+ "ext": "ext-Latn-ES",
+ "eya": "eya-Latn-US",
+ "eyo": "eyo-Latn-KE",
+ "eza": "eza-Latn-ZZ",
+ "eze": "eze-Latn-NG",
+ "fa": "fa-Arab-IR",
+ "faa": "faa-Latn-ZZ",
+ "fab": "fab-Latn-ZZ",
+ "fad": "fad-Latn-PG",
+ "faf": "faf-Latn-SB",
+ "fag": "fag-Latn-ZZ",
+ "fah": "fah-Latn-NG",
+ "fai": "fai-Latn-ZZ",
+ "faj": "faj-Latn-PG",
+ "fak": "fak-Latn-CM",
+ "fal": "fal-Latn-CM",
+ "fam": "fam-Latn-NG",
+ "fan": "fan-Latn-GQ",
+ "fap": "fap-Latn-SN",
+ "far": "far-Latn-SB",
+ "fau": "fau-Latn-ID",
+ "fax": "fax-Latn-ES",
+ "fay": "fay-Arab-IR",
+ "faz": "faz-Arab-IR",
+ "fbl": "fbl-Latn-PH",
+ "fer": "fer-Latn-SS",
+ "ff": "ff-Latn-SN",
+ "ff-Adlm": "ff-Adlm-GN",
+ "ffi": "ffi-Latn-ZZ",
+ "ffm": "ffm-Latn-ML",
+ "fgr": "fgr-Latn-TD",
+ "fi": "fi-Latn-FI",
+ "fia": "fia-Arab-SD",
+ "fie": "fie-Latn-NG",
+ "fif": "fif-Latn-SA",
+ "fil": "fil-Latn-PH",
+ "fip": "fip-Latn-TZ",
+ "fir": "fir-Latn-NG",
+ "fit": "fit-Latn-SE",
+ "fiw": "fiw-Latn-PG",
+ "fj": "fj-Latn-FJ",
+ "fkk": "fkk-Latn-NG",
+ "fkv": "fkv-Latn-NO",
+ "fla": "fla-Latn-US",
+ "flh": "flh-Latn-ID",
+ "fli": "fli-Latn-NG",
+ "fll": "fll-Latn-CM",
+ "fln": "fln-Latn-AU",
+ "flr": "flr-Latn-ZZ",
+ "fly": "fly-Latn-ZA",
+ "fmp": "fmp-Latn-ZZ",
+ "fmu": "fmu-Deva-IN",
+ "fnb": "fnb-Latn-VU",
+ "fng": "fng-Latn-ZA",
+ "fni": "fni-Latn-TD",
+ "fo": "fo-Latn-FO",
+ "fod": "fod-Latn-ZZ",
+ "foi": "foi-Latn-PG",
+ "fom": "fom-Latn-CD",
+ "fon": "fon-Latn-BJ",
+ "for": "for-Latn-ZZ",
+ "fos": "fos-Latn-TW",
+ "fpe": "fpe-Latn-ZZ",
+ "fqs": "fqs-Latn-ZZ",
+ "fr": "fr-Latn-FR",
+ "frc": "frc-Latn-US",
+ "frd": "frd-Latn-ID",
+ "frk": "frk-Latn-DE",
+ "frm": "frm-Latn-FR",
+ "fro": "fro-Latn-FR",
+ "frp": "frp-Latn-FR",
+ "frq": "frq-Latn-PG",
+ "frr": "frr-Latn-DE",
+ "frs": "frs-Latn-DE",
+ "frt": "frt-Latn-VU",
+ "fub": "fub-Arab-CM",
+ "fud": "fud-Latn-WF",
+ "fue": "fue-Latn-ZZ",
+ "fuf": "fuf-Latn-GN",
+ "fuh": "fuh-Latn-ZZ",
+ "fui": "fui-Latn-TD",
+ "fum": "fum-Latn-NG",
+ "fun": "fun-Latn-BR",
+ "fuq": "fuq-Latn-NE",
+ "fur": "fur-Latn-IT",
+ "fut": "fut-Latn-VU",
+ "fuu": "fuu-Latn-CD",
+ "fuv": "fuv-Latn-NG",
+ "fuy": "fuy-Latn-ZZ",
+ "fvr": "fvr-Latn-SD",
+ "fwa": "fwa-Latn-NC",
+ "fwe": "fwe-Latn-NA",
+ "fy": "fy-Latn-NL",
+ "ga": "ga-Latn-IE",
+ "gaa": "gaa-Latn-GH",
+ "gab": "gab-Latn-TD",
+ "gac": "gac-Latn-IN",
+ "gac-Deva": "gac-Deva-IN",
+ "gad": "gad-Latn-PH",
+ "gae": "gae-Latn-VE",
+ "gaf": "gaf-Latn-ZZ",
+ "gag": "gag-Latn-MD",
+ "gah": "gah-Latn-ZZ",
+ "gai": "gai-Latn-PG",
+ "gaj": "gaj-Latn-ZZ",
+ "gak": "gak-Latn-ID",
+ "gal": "gal-Latn-TL",
+ "gam": "gam-Latn-ZZ",
+ "gan": "gan-Hans-CN",
+ "gao": "gao-Latn-PG",
+ "gap": "gap-Latn-PG",
+ "gaq": "gaq-Orya-IN",
+ "gar": "gar-Latn-PG",
+ "gas": "gas-Gujr-IN",
+ "gat": "gat-Latn-PG",
+ "gau": "gau-Telu-IN",
+ "gaw": "gaw-Latn-ZZ",
+ "gax": "gax-Latn-ET",
+ "gax-Ethi": "gax-Ethi-ET",
+ "gay": "gay-Latn-ID",
+ "gba": "gba-Latn-ZZ",
+ "gbb": "gbb-Latn-AU",
+ "gbd": "gbd-Latn-AU",
+ "gbe": "gbe-Latn-PG",
+ "gbf": "gbf-Latn-ZZ",
+ "gbg": "gbg-Latn-CF",
+ "gbh": "gbh-Latn-BJ",
+ "gbi": "gbi-Latn-ID",
+ "gbj": "gbj-Orya-IN",
+ "gbk": "gbk-Deva-IN",
+ "gbk-Takr": "gbk-Takr-IN",
+ "gbl": "gbl-Gujr-IN",
+ "gbl-Deva": "gbl-Deva-IN",
+ "gbm": "gbm-Deva-IN",
+ "gbn": "gbn-Latn-SS",
+ "gbp": "gbp-Latn-CF",
+ "gbq": "gbq-Latn-CF",
+ "gbr": "gbr-Latn-NG",
+ "gbs": "gbs-Latn-BJ",
+ "gbu": "gbu-Latn-AU",
+ "gbv": "gbv-Latn-CF",
+ "gbw": "gbw-Latn-AU",
+ "gbx": "gbx-Latn-BJ",
+ "gby": "gby-Latn-ZZ",
+ "gbz": "gbz-Arab-IR",
+ "gcc": "gcc-Latn-PG",
+ "gcd": "gcd-Latn-AU",
+ "gcf": "gcf-Latn-GP",
+ "gcl": "gcl-Latn-GD",
+ "gcn": "gcn-Latn-PG",
+ "gcr": "gcr-Latn-GF",
+ "gct": "gct-Latn-VE",
+ "gd": "gd-Latn-GB",
+ "gdb": "gdb-Orya-IN",
+ "gdb-Telu": "gdb-Telu-IN",
+ "gdc": "gdc-Latn-AU",
+ "gdd": "gdd-Latn-PG",
+ "gde": "gde-Latn-ZZ",
+ "gdf": "gdf-Latn-NG",
+ "gdg": "gdg-Latn-PH",
+ "gdh": "gdh-Latn-AU",
+ "gdi": "gdi-Latn-CF",
+ "gdj": "gdj-Latn-AU",
+ "gdk": "gdk-Latn-TD",
+ "gdl": "gdl-Latn-ET",
+ "gdl-Ethi": "gdl-Ethi-ET",
+ "gdm": "gdm-Latn-TD",
+ "gdn": "gdn-Latn-ZZ",
+ "gdo": "gdo-Cyrl-RU",
+ "gdq": "gdq-Latn-YE",
+ "gdr": "gdr-Latn-ZZ",
+ "gdt": "gdt-Latn-AU",
+ "gdu": "gdu-Latn-NG",
+ "gdx": "gdx-Deva-IN",
+ "gea": "gea-Latn-NG",
+ "geb": "geb-Latn-ZZ",
+ "gec": "gec-Latn-LR",
+ "ged": "ged-Latn-NG",
+ "gef": "gef-Latn-ID",
+ "geg": "geg-Latn-NG",
+ "geh": "geh-Latn-CA",
+ "gei": "gei-Latn-ID",
+ "gej": "gej-Latn-ZZ",
+ "gek": "gek-Latn-NG",
+ "gel": "gel-Latn-ZZ",
+ "geq": "geq-Latn-CF",
+ "ges": "ges-Latn-ID",
+ "gev": "gev-Latn-GA",
+ "gew": "gew-Latn-NG",
+ "gex": "gex-Latn-SO",
+ "gey": "gey-Latn-CD",
+ "gez": "gez-Ethi-ET",
+ "gfk": "gfk-Latn-ZZ",
+ "gga": "gga-Latn-SB",
+ "ggb": "ggb-Latn-LR",
+ "ggd": "ggd-Latn-AU",
+ "gge": "gge-Latn-AU",
+ "ggg": "ggg-Arab-PK",
+ "ggk": "ggk-Latn-AU",
+ "ggl": "ggl-Latn-PG",
+ "ggn": "gvr-Deva-NP",
+ "ggt": "ggt-Latn-PG",
+ "ggu": "ggu-Latn-CI",
+ "ggw": "ggw-Latn-PG",
+ "gha": "gha-Arab-LY",
+ "gha-Latn": "gha-Latn-LY",
+ "gha-Tfng": "gha-Tfng-LY",
+ "ghc": "ghc-Latn-GB",
+ "ghe": "ghe-Deva-NP",
+ "ghk": "ghk-Latn-MM",
+ "ghn": "ghn-Latn-SB",
+ "ghr": "ghr-Arab-PK",
+ "ghs": "ghs-Latn-ZZ",
+ "ght": "ght-Tibt-NP",
+ "gia": "gia-Latn-AU",
+ "gib": "gib-Latn-NG",
+ "gic": "gic-Latn-ZA",
+ "gid": "gid-Latn-CM",
+ "gie": "gie-Latn-CI",
+ "gig": "gig-Arab-PK",
+ "gih": "gih-Latn-AU",
+ "gil": "gil-Latn-KI",
+ "gim": "gim-Latn-ZZ",
+ "gin": "gin-Cyrl-RU",
+ "gip": "gip-Latn-PG",
+ "giq": "giq-Latn-VN",
+ "gir": "gir-Latn-VN",
+ "gis": "gis-Latn-CM",
+ "git": "git-Latn-CA",
+ "gix": "gix-Latn-CD",
+ "giy": "giy-Latn-AU",
+ "giz": "giz-Latn-CM",
+ "gjk": "gjk-Arab-PK",
+ "gjm": "gjm-Latn-AU",
+ "gjn": "gjn-Latn-ZZ",
+ "gjr": "gjr-Latn-AU",
+ "gju": "gju-Arab-PK",
+ "gka": "gka-Latn-PG",
+ "gkd": "gkd-Latn-PG",
+ "gke": "gke-Latn-CM",
+ "gkn": "gkn-Latn-ZZ",
+ "gko": "gko-Latn-AU",
+ "gkp": "gkp-Latn-ZZ",
+ "gku": "gku-Latn-ZA",
+ "gl": "gl-Latn-ES",
+ "glb": "glb-Latn-NG",
+ "glc": "glc-Latn-TD",
+ "gld": "gld-Cyrl-RU",
+ "glh": "glh-Arab-AF",
+ "glj": "glj-Latn-TD",
+ "glk": "glk-Arab-IR",
+ "gll": "gll-Latn-AU",
+ "glo": "glo-Latn-NG",
+ "glr": "glr-Latn-LR",
+ "glu": "glu-Latn-TD",
+ "glw": "glw-Latn-NG",
+ "gma": "gma-Latn-AU",
+ "gmb": "gmb-Latn-SB",
+ "gmd": "gmd-Latn-NG",
+ "gmg": "gmg-Latn-PG",
+ "gmh": "gmh-Latn-DE",
+ "gmm": "gmm-Latn-ZZ",
+ "gmn": "gmn-Latn-CM",
+ "gmr": "gmr-Latn-AU",
+ "gmu": "gmu-Latn-PG",
+ "gmv": "gmv-Ethi-ZZ",
+ "gmx": "gmx-Latn-TZ",
+ "gmy": "gmy-Linb-GR",
+ "gmz": "gmz-Latn-NG",
+ "gn": "gn-Latn-PY",
+ "gna": "gna-Latn-BF",
+ "gnb": "gnb-Latn-IN",
+ "gnc": "gnc-Latn-ES",
+ "gnd": "gnd-Latn-ZZ",
+ "gne": "gne-Latn-NG",
+ "gng": "gng-Latn-ZZ",
+ "gnh": "gnh-Latn-NG",
+ "gni": "gni-Latn-AU",
+ "gnj": "gnj-Latn-CI",
+ "gnk": "gnk-Latn-BW",
+ "gnl": "gnl-Latn-AU",
+ "gnm": "gnm-Latn-PG",
+ "gnn": "gnn-Latn-AU",
+ "gnq": "gnq-Latn-MY",
+ "gnr": "gnr-Latn-AU",
+ "gnt": "gnt-Latn-PG",
+ "gnu": "gnu-Latn-PG",
+ "gnw": "gnw-Latn-BO",
+ "gnz": "gnz-Latn-CF",
+ "goa": "goa-Latn-CI",
+ "gob": "gob-Latn-CO",
+ "goc": "goc-Latn-PG",
+ "god": "god-Latn-ZZ",
+ "goe": "goe-Tibt-BT",
+ "gof": "gof-Ethi-ZZ",
+ "gog": "gog-Latn-TZ",
+ "goh": "goh-Latn-DE",
+ "goi": "goi-Latn-ZZ",
+ "gok": "gok-Deva-IN",
+ "gol": "gol-Latn-LR",
+ "gom": "gom-Deva-IN",
+ "gon": "gon-Telu-IN",
+ "goo": "goo-Latn-FJ",
+ "gop": "gop-Latn-ID",
+ "goq": "goq-Latn-ID",
+ "gor": "gor-Latn-ID",
+ "gos": "gos-Latn-NL",
+ "got": "got-Goth-UA",
+ "gou": "gou-Latn-CM",
+ "gov": "gov-Latn-CI",
+ "gow": "gow-Latn-TZ",
+ "gox": "gox-Latn-CD",
+ "goy": "goy-Latn-TD",
+ "gpa": "gpa-Latn-NG",
+ "gpe": "gpe-Latn-GH",
+ "gpn": "gpn-Latn-PG",
+ "gqa": "gqa-Latn-NG",
+ "gqn": "gqn-Latn-BR",
+ "gqr": "gqr-Latn-TD",
+ "gra": "gra-Deva-IN",
+ "gra-Gujr": "gra-Gujr-IN",
+ "grb": "grb-Latn-ZZ",
+ "grc": "grc-Cprt-CY",
+ "grc-Linb": "grc-Linb-GR",
+ "grd": "grd-Latn-NG",
+ "grg": "grg-Latn-PG",
+ "grh": "grh-Latn-NG",
+ "gri": "gri-Latn-SB",
+ "grj": "grj-Latn-LR",
+ "grm": "grm-Latn-MY",
+ "grq": "grq-Latn-PG",
+ "grs": "grs-Latn-ID",
+ "grt": "grt-Beng-IN",
+ "gru": "gru-Ethi-ET",
+ "gru-Latn": "gru-Latn-ET",
+ "grv": "grv-Latn-LR",
+ "grw": "grw-Latn-ZZ",
+ "grx": "grx-Latn-PG",
+ "gry": "gry-Latn-LR",
+ "grz": "grz-Latn-PG",
+ "gsl": "gsl-Latn-SN",
+ "gsn": "gsn-Latn-PG",
+ "gso": "gso-Latn-CF",
+ "gsp": "gsp-Latn-PG",
+ "gsw": "gsw-Latn-CH",
+ "gta": "gta-Latn-BR",
+ "gtu": "gtu-Latn-AU",
+ "gu": "gu-Gujr-IN",
+ "gua": "gua-Latn-NG",
+ "gub": "gub-Latn-BR",
+ "guc": "guc-Latn-CO",
+ "gud": "gud-Latn-ZZ",
+ "gue": "gue-Latn-AU",
+ "guf": "guf-Latn-AU",
+ "guh": "guh-Latn-CO",
+ "gui": "gui-Latn-BO",
+ "guk": "guk-Latn-ET",
+ "guk-Ethi": "guk-Ethi-ET",
+ "gul": "gul-Latn-US",
+ "gum": "gum-Latn-CO",
+ "gun": "gun-Latn-BR",
+ "guo": "guo-Latn-CO",
+ "gup": "gup-Latn-AU",
+ "guq": "guq-Latn-PY",
+ "gur": "gur-Latn-GH",
+ "gut": "gut-Latn-CR",
+ "guu": "guu-Latn-VE",
+ "guw": "guw-Latn-ZZ",
+ "gux": "gux-Latn-ZZ",
+ "guz": "guz-Latn-KE",
+ "gv": "gv-Latn-IM",
+ "gva": "gva-Latn-PY",
+ "gvc": "gvc-Latn-BR",
+ "gve": "gve-Latn-PG",
+ "gvf": "gvf-Latn-ZZ",
+ "gvj": "gvj-Latn-BR",
+ "gvl": "gvl-Latn-TD",
+ "gvm": "gvm-Latn-NG",
+ "gvn": "gvn-Latn-AU",
+ "gvo": "gvo-Latn-BR",
+ "gvp": "gvp-Latn-BR",
+ "gvr": "gvr-Deva-NP",
+ "gvs": "gvs-Latn-ZZ",
+ "gvy": "gvy-Latn-AU",
+ "gwa": "gwa-Latn-CI",
+ "gwb": "gwb-Latn-NG",
+ "gwc": "gwc-Arab-ZZ",
+ "gwd": "gwd-Latn-ET",
+ "gwe": "gwe-Latn-TZ",
+ "gwf": "gwf-Arab-PK",
+ "gwg": "gwg-Latn-NG",
+ "gwi": "gwi-Latn-CA",
+ "gwj": "gwj-Latn-BW",
+ "gwm": "gwm-Latn-AU",
+ "gwn": "gwn-Latn-NG",
+ "gwr": "gwr-Latn-UG",
+ "gwt": "gwt-Arab-ZZ",
+ "gwu": "gwu-Latn-AU",
+ "gww": "gww-Latn-AU",
+ "gwx": "gwx-Latn-GH",
+ "gxx": "gxx-Latn-CI",
+ "gyb": "gyb-Latn-PG",
+ "gyd": "gyd-Latn-AU",
+ "gye": "gye-Latn-NG",
+ "gyf": "gyf-Latn-AU",
+ "gyg": "gyg-Latn-CF",
+ "gyi": "gyi-Latn-ZZ",
+ "gyl": "gyl-Latn-ET",
+ "gyl-Ethi": "gyl-Ethi-ET",
+ "gym": "gym-Latn-PA",
+ "gyn": "gyn-Latn-GY",
+ "gyo": "gyo-Deva-NP",
+ "gyr": "gyr-Latn-BO",
+ "gyy": "gyy-Latn-AU",
+ "gyz": "gyz-Latn-NG",
+ "gza": "gza-Latn-SD",
+ "gzi": "gzi-Arab-IR",
+ "gzn": "gzn-Latn-ID",
+ "ha": "ha-Latn-NG",
+ "ha-CM": "ha-Arab-CM",
+ "ha-SD": "ha-Arab-SD",
+ "haa": "haa-Latn-US",
+ "hac": "hac-Arab-IR",
+ "had": "had-Latn-ID",
+ "hae": "hae-Latn-ET",
+ "hag": "hag-Latn-ZZ",
+ "hah": "hah-Latn-PG",
+ "hai": "hai-Latn-CA",
+ "haj": "haj-Latn-IN",
+ "haj-Beng": "haj-Beng-IN",
+ "hak": "hak-Hans-CN",
+ "hal": "hal-Latn-VN",
+ "ham": "ham-Latn-ZZ",
+ "han": "han-Latn-TZ",
+ "hao": "hao-Latn-PG",
+ "hap": "hap-Latn-ID",
+ "haq": "haq-Latn-TZ",
+ "har": "har-Ethi-ET",
+ "har-Arab": "har-Arab-ET",
+ "har-Latn": "har-Latn-ET",
+ "has": "has-Latn-CA",
+ "hav": "hav-Latn-CD",
+ "haw": "haw-Latn-US",
+ "hax": "hax-Latn-CA",
+ "hay": "hay-Latn-TZ",
+ "haz": "haz-Arab-AF",
+ "hba": "hba-Latn-CD",
+ "hbb": "hbb-Latn-ZZ",
+ "hbn": "hbn-Latn-SD",
+ "hbo": "hbo-Hebr-IL",
+ "hbu": "hbu-Latn-TL",
+ "hch": "hch-Latn-MX",
+ "hdy": "hdy-Ethi-ZZ",
+ "he": "he-Hebr-IL",
+ "hed": "hed-Latn-TD",
+ "heg": "heg-Latn-ID",
+ "heh": "heh-Latn-TZ",
+ "hei": "hei-Latn-CA",
+ "hem": "hem-Latn-CD",
+ "hgm": "hgm-Latn-NA",
+ "hgw": "hgw-Latn-PG",
+ "hhi": "hhi-Latn-PG",
+ "hhr": "hhr-Latn-SN",
+ "hhy": "hhy-Latn-ZZ",
+ "hi": "hi-Deva-IN",
+ "hi-Latn": "hi-Latn-IN",
+ "hia": "hia-Latn-ZZ",
+ "hib": "hib-Latn-PE",
+ "hid": "hid-Latn-US",
+ "hif": "hif-Latn-FJ",
+ "hig": "hig-Latn-ZZ",
+ "hih": "hih-Latn-ZZ",
+ "hii": "hii-Takr-IN",
+ "hii-Deva": "hii-Deva-IN",
+ "hij": "hij-Latn-CM",
+ "hik": "hik-Latn-ID",
+ "hil": "hil-Latn-PH",
+ "hio": "hio-Latn-BW",
+ "hir": "hir-Latn-BR",
+ "hit": "hit-Xsux-TR",
+ "hiw": "hiw-Latn-VU",
+ "hix": "hix-Latn-BR",
+ "hji": "hji-Latn-ID",
+ "hka": "hka-Latn-TZ",
+ "hke": "hke-Latn-CD",
+ "hkh": "hkh-Arab-IN",
+ "hkh-Deva": "hkh-Deva-IN",
+ "hkh-Latn": "hkh-Latn-IN",
+ "hkk": "hkk-Latn-PG",
+ "hla": "hla-Latn-ZZ",
+ "hlb": "hlb-Deva-IN",
+ "hld": "hld-Latn-VN",
+ "hlt": "hlt-Latn-MM",
+ "hlu": "hlu-Hluw-TR",
+ "hma": "hma-Latn-CN",
+ "hmb": "hmb-Latn-ML",
+ "hmd": "hmd-Plrd-CN",
+ "hmf": "hmf-Latn-VN",
+ "hmj": "hmj-Bopo-CN",
+ "hmm": "hmm-Latn-CN",
+ "hmn": "hmn-Latn-CN",
+ "hmn-Bopo": "hmn-Bopo-CN",
+ "hmn-Hmng": "hmn-Hmng-CN",
+ "hmp": "hmp-Latn-CN",
+ "hmq": "hmq-Bopo-CN",
+ "hmr": "hmr-Latn-IN",
+ "hms": "hms-Latn-CN",
+ "hmt": "hmt-Latn-ZZ",
+ "hmu": "hmu-Latn-ID",
+ "hmv": "hmv-Latn-VN",
+ "hmw": "hmw-Latn-CN",
+ "hmy": "hmy-Latn-CN",
+ "hmz": "hmz-Latn-CN",
+ "hmz-Plrd": "hmz-Plrd-CN",
+ "hna": "hna-Latn-CM",
+ "hnd": "hnd-Arab-PK",
+ "hne": "hne-Deva-IN",
+ "hng": "hng-Latn-AO",
+ "hnh": "hnh-Latn-BW",
+ "hni": "hni-Latn-CN",
+ "hnj": "hnj-Hmnp-US",
+ "hnj-AU": "hnj-Laoo-AU",
+ "hnj-CN": "hnj-Laoo-CN",
+ "hnj-FR": "hnj-Laoo-FR",
+ "hnj-GF": "hnj-Laoo-GF",
+ "hnj-LA": "hnj-Laoo-LA",
+ "hnj-Laoo": "hnj-Laoo-LA",
+ "hnj-MM": "hnj-Laoo-MM",
+ "hnj-SR": "hnj-Laoo-SR",
+ "hnj-TH": "hnj-Laoo-TH",
+ "hnj-US": "hnj-Hmnp-US",
+ "hnj-VN": "hnj-Laoo-VN",
+ "hnn": "hnn-Latn-PH",
+ "hno": "hno-Arab-PK",
+ "hns": "hns-Latn-SR",
+ "ho": "ho-Latn-PG",
+ "hoa": "hoa-Latn-SB",
+ "hob": "hob-Latn-PG",
+ "hoc": "hoc-Deva-IN",
+ "hod": "hod-Latn-NG",
+ "hoe": "hoe-Latn-NG",
+ "hoh": "hoh-Arab-OM",
+ "hoi": "hoi-Latn-US",
+ "hoj": "hoj-Deva-IN",
+ "hol": "hol-Latn-AO",
+ "hom": "hom-Latn-SS",
+ "hoo": "hoo-Latn-CD",
+ "hop": "hop-Latn-US",
+ "hor": "hor-Latn-TD",
+ "hot": "hot-Latn-ZZ",
+ "hov": "hov-Latn-ID",
+ "how": "how-Hani-CN",
+ "hoy": "hoy-Deva-IN",
+ "hpo": "hpo-Mymr-MM",
+ "hr": "hr-Latn-HR",
+ "hra": "hra-Latn-IN",
+ "hrc": "hrc-Latn-PG",
+ "hre": "hre-Latn-VN",
+ "hrk": "hrk-Latn-ID",
+ "hrm": "hrm-Latn-CN",
+ "hrm-Hmng": "hrm-Hmng-CN",
+ "hro": "hro-Latn-VN",
+ "hrp": "hrp-Latn-AU",
+ "hrt": "hrt-Syrc-TR",
+ "hru": "hru-Latn-IN",
+ "hrw": "hrw-Latn-PG",
+ "hrx": "hrx-Latn-BR",
+ "hrz": "hrz-Arab-IR",
+ "hsb": "hsb-Latn-DE",
+ "hsn": "hsn-Hans-CN",
+ "hss": "hss-Arab-OM",
+ "ht": "ht-Latn-HT",
+ "hti": "hti-Latn-ID",
+ "hto": "hto-Latn-CO",
+ "hts": "hts-Latn-TZ",
+ "htu": "htu-Latn-ID",
+ "htx": "htx-Xsux-TR",
+ "hu": "hu-Latn-HU",
+ "hub": "hub-Latn-PE",
+ "huc": "huc-Latn-BW",
+ "hud": "hud-Latn-ID",
+ "hue": "hue-Latn-MX",
+ "huf": "huf-Latn-PG",
+ "hug": "hug-Latn-PE",
+ "huh": "huh-Latn-CL",
+ "hui": "hui-Latn-ZZ",
+ "huk": "huk-Latn-ID",
+ "hul": "hul-Latn-PG",
+ "hum": "hum-Latn-CD",
+ "hup": "hup-Latn-US",
+ "hur": "hur-Latn-CA",
+ "hus": "hus-Latn-MX",
+ "hut": "hut-Deva-NP",
+ "hut-Tibt": "hut-Tibt-NP",
+ "huu": "huu-Latn-PE",
+ "huv": "huv-Latn-MX",
+ "huw": "huw-Latn-ID",
+ "hux": "hux-Latn-PE",
+ "huy": "huy-Hebr-IL",
+ "huz": "huz-Cyrl-RU",
+ "hvc": "hvc-Latn-HT",
+ "hve": "hve-Latn-MX",
+ "hvk": "hvk-Latn-NC",
+ "hvn": "hvn-Latn-ID",
+ "hvv": "hvv-Latn-MX",
+ "hwa": "hwa-Latn-CI",
+ "hwc": "hwc-Latn-US",
+ "hwo": "hwo-Latn-NG",
+ "hy": "hy-Armn-AM",
+ "hya": "hya-Latn-CM",
+ "hyw": "hyw-Armn-AM",
+ "hz": "hz-Latn-NA",
+ "ia": "ia-Latn-001",
+ "iai": "iai-Latn-NC",
+ "ian": "ian-Latn-ZZ",
+ "iar": "iar-Latn-ZZ",
+ "iba": "iba-Latn-MY",
+ "ibb": "ibb-Latn-NG",
+ "ibd": "ibd-Latn-AU",
+ "ibe": "ibe-Latn-NG",
+ "ibg": "ibg-Latn-PH",
+ "ibh": "ibh-Latn-VN",
+ "ibl": "ibl-Latn-PH",
+ "ibm": "ibm-Latn-NG",
+ "ibn": "ibn-Latn-NG",
+ "ibr": "ibr-Latn-NG",
+ "ibu": "ibu-Latn-ID",
+ "iby": "iby-Latn-ZZ",
+ "ica": "ica-Latn-ZZ",
+ "ich": "ich-Latn-ZZ",
+ "icr": "icr-Latn-CO",
+ "id": "id-Latn-ID",
+ "ida": "ida-Latn-KE",
+ "idb": "idb-Latn-IN",
+ "idc": "idc-Latn-NG",
+ "idd": "idd-Latn-ZZ",
+ "ide": "ide-Latn-NG",
+ "idi": "idi-Latn-ZZ",
+ "idr": "idr-Latn-SS",
+ "ids": "ids-Latn-NG",
+ "idt": "idt-Latn-TL",
+ "idu": "idu-Latn-ZZ",
+ "ie": "ie-Latn-001",
+ "ifa": "ifa-Latn-PH",
+ "ifb": "ifb-Latn-PH",
+ "ife": "ife-Latn-TG",
+ "iff": "iff-Latn-VU",
+ "ifk": "ifk-Latn-PH",
+ "ifm": "ifm-Latn-CG",
+ "ifu": "ifu-Latn-PH",
+ "ify": "ify-Latn-PH",
+ "ig": "ig-Latn-NG",
+ "igb": "igb-Latn-ZZ",
+ "ige": "ige-Latn-ZZ",
+ "igg": "igg-Latn-PG",
+ "igl": "igl-Latn-NG",
+ "igm": "igm-Latn-PG",
+ "ign": "ign-Latn-BO",
+ "igo": "igo-Latn-PG",
+ "igs": "igs-Latn-001",
+ "igs-Grek": "igs-Grek-001",
+ "igw": "igw-Latn-NG",
+ "ihb": "ihb-Latn-ID",
+ "ihi": "ihi-Latn-NG",
+ "ihp": "ihp-Latn-ID",
+ "ihw": "ihw-Latn-AU",
+ "ii": "ii-Yiii-CN",
+ "iin": "iin-Latn-AU",
+ "ijc": "ijc-Latn-NG",
+ "ije": "ije-Latn-NG",
+ "ijj": "ijj-Latn-ZZ",
+ "ijn": "ijn-Latn-NG",
+ "ijs": "ijs-Latn-NG",
+ "ik": "ik-Latn-US",
+ "iki": "iki-Latn-NG",
+ "ikk": "ikk-Latn-ZZ",
+ "ikl": "ikl-Latn-NG",
+ "iko": "iko-Latn-NG",
+ "ikp": "ikp-Latn-NG",
+ "ikr": "ikr-Latn-AU",
+ "ikt": "ikt-Latn-CA",
+ "ikt-Cans": "ikt-Cans-CA",
+ "ikv": "ikv-Latn-NG",
+ "ikw": "ikw-Latn-ZZ",
+ "ikx": "ikx-Latn-ZZ",
+ "ikz": "ikz-Latn-TZ",
+ "ila": "ila-Latn-ID",
+ "ilb": "ilb-Latn-ZM",
+ "ilg": "ilg-Latn-AU",
+ "ili": "ili-Latn-CN",
+ "ili-Arab": "ili-Arab-CN",
+ "ili-Cyrl": "ili-Cyrl-KZ",
+ "ilk": "ilk-Latn-PH",
+ "ilm": "ilm-Latn-MY",
+ "ilo": "ilo-Latn-PH",
+ "ilp": "ilp-Latn-PH",
+ "ilu": "ilu-Latn-ID",
+ "ilv": "ilv-Latn-NG",
+ "imi": "imi-Latn-PG",
+ "iml": "iml-Latn-US",
+ "imn": "imn-Latn-PG",
+ "imo": "imo-Latn-ZZ",
+ "imr": "imr-Latn-ID",
+ "ims": "ims-Latn-IT",
+ "imt": "imt-Latn-SS",
+ "imy": "imy-Lyci-TR",
+ "in": "id-Latn-ID",
+ "inb": "inb-Latn-CO",
+ "ing": "ing-Latn-US",
+ "inh": "inh-Cyrl-RU",
+ "inj": "inj-Latn-CO",
+ "inn": "inn-Latn-PH",
+ "ino": "ino-Latn-PG",
+ "inp": "inp-Latn-PE",
+ "int": "int-Mymr-MM",
+ "io": "io-Latn-001",
+ "ior": "ior-Ethi-ET",
+ "iou": "iou-Latn-ZZ",
+ "iow": "iow-Latn-US",
+ "ipi": "ipi-Latn-PG",
+ "ipo": "ipo-Latn-PG",
+ "iqu": "iqu-Latn-PE",
+ "iqw": "iqw-Latn-NG",
+ "ire": "ire-Latn-ID",
+ "irh": "irh-Latn-ID",
+ "iri": "iri-Latn-ZZ",
+ "irk": "irk-Latn-TZ",
+ "irn": "irn-Latn-BR",
+ "iru": "iru-Taml-IN",
+ "iru-Mlym": "iru-Mlym-IN",
+ "irx": "irx-Latn-ID",
+ "iry": "iry-Latn-PH",
+ "is": "is-Latn-IS",
+ "isa": "isa-Latn-PG",
+ "isc": "isc-Latn-PE",
+ "isd": "isd-Latn-PH",
+ "ish": "ish-Latn-NG",
+ "isi": "isi-Latn-NG",
+ "isk": "isk-Arab-AF",
+ "isk-Cyrl": "isk-Cyrl-TJ",
+ "ism": "ism-Latn-ID",
+ "isn": "isn-Latn-TZ",
+ "iso": "iso-Latn-NG",
+ "ist": "ist-Latn-HR",
+ "isu": "isu-Latn-CM",
+ "it": "it-Latn-IT",
+ "itb": "itb-Latn-PH",
+ "itd": "itd-Latn-ID",
+ "ite": "ite-Latn-BO",
+ "iti": "iti-Latn-PH",
+ "itk": "itk-Hebr-IT",
+ "itl": "itl-Cyrl-RU",
+ "itm": "itm-Latn-NG",
+ "ito": "ito-Latn-BO",
+ "itr": "itr-Latn-PG",
+ "its": "its-Latn-NG",
+ "itt": "itt-Latn-PH",
+ "itv": "itv-Latn-PH",
+ "itw": "itw-Latn-NG",
+ "itx": "itx-Latn-ID",
+ "ity": "ity-Latn-PH",
+ "itz": "itz-Latn-GT",
+ "iu": "iu-Cans-CA",
+ "ium": "ium-Latn-CN",
+ "ium-Hani": "ium-Hani-CN",
+ "ium-Laoo": "ium-Laoo-LA",
+ "ium-Thai": "ium-Thai-TH",
+ "ivb": "ivb-Latn-PH",
+ "ivv": "ivv-Latn-PH",
+ "iw": "he-Hebr-IL",
+ "iwk": "iwk-Latn-PH",
+ "iwm": "iwm-Latn-ZZ",
+ "iwo": "iwo-Latn-ID",
+ "iws": "iws-Latn-ZZ",
+ "ixc": "ixc-Latn-MX",
+ "ixl": "ixl-Latn-GT",
+ "iya": "iya-Latn-NG",
+ "iyo": "iyo-Latn-CM",
+ "iyx": "iyx-Latn-CG",
+ "izh": "izh-Latn-RU",
+ "izi": "eza-Latn-ZZ",
+ "izr": "izr-Latn-NG",
+ "izz": "izz-Latn-NG",
+ "ja": "ja-Jpan-JP",
+ "jaa": "jaa-Latn-BR",
+ "jab": "jab-Latn-ZZ",
+ "jac": "jac-Latn-GT",
+ "jad": "jad-Arab-GN",
+ "jae": "jae-Latn-PG",
+ "jaf": "jaf-Latn-NG",
+ "jah": "jah-Latn-MY",
+ "jaj": "jaj-Latn-SB",
+ "jak": "jak-Latn-MY",
+ "jal": "jal-Latn-ID",
+ "jam": "jam-Latn-JM",
+ "jan": "jan-Latn-AU",
+ "jao": "jao-Latn-AU",
+ "jaq": "jaq-Latn-ID",
+ "jar": "jgk-Latn-ZZ",
+ "jas": "jas-Latn-NC",
+ "jat": "jat-Arab-AF",
+ "jau": "jau-Latn-ID",
+ "jax": "jax-Latn-ID",
+ "jay": "jay-Latn-AU",
+ "jaz": "jaz-Latn-NC",
+ "jbe": "jbe-Hebr-IL",
+ "jbi": "jbi-Latn-AU",
+ "jbj": "jbj-Latn-ID",
+ "jbk": "jbk-Latn-PG",
+ "jbm": "jbm-Latn-NG",
+ "jbn": "jbn-Arab-LY",
+ "jbo": "jbo-Latn-001",
+ "jbr": "jbr-Latn-ID",
+ "jbt": "jbt-Latn-BR",
+ "jbu": "jbu-Latn-ZZ",
+ "jbw": "jbw-Latn-AU",
+ "jct": "jct-Cyrl-UA",
+ "jct-Latn": "jct-Latn-UA",
+ "jda": "jda-Tibt-IN",
+ "jdg": "jdg-Arab-PK",
+ "jdt": "jdt-Cyrl-RU",
+ "jdt-Hebr": "jdt-Hebr-RU",
+ "jdt-Latn": "jdt-Latn-AZ",
+ "jeb": "jeb-Latn-PE",
+ "jee": "jee-Deva-NP",
+ "jeh": "jeh-Latn-VN",
+ "jeh-Laoo": "jeh-Laoo-LA",
+ "jei": "jei-Latn-ID",
+ "jek": "jek-Latn-CI",
+ "jel": "jel-Latn-ID",
+ "jen": "jen-Latn-ZZ",
+ "jer": "jer-Latn-NG",
+ "jet": "jet-Latn-PG",
+ "jeu": "jeu-Latn-TD",
+ "jgb": "jgb-Latn-CD",
+ "jge": "jge-Geor-GE",
+ "jge-Hebr": "jge-Hebr-IL",
+ "jgk": "jgk-Latn-ZZ",
+ "jgo": "jgo-Latn-CM",
+ "jhi": "jhi-Latn-MY",
+ "ji": "yi-Hebr-001",
+ "jia": "jia-Latn-CM",
+ "jib": "jib-Latn-ZZ",
+ "jic": "jic-Latn-HN",
+ "jid": "jid-Latn-NG",
+ "jie": "jie-Latn-NG",
+ "jig": "jig-Latn-AU",
+ "jil": "jil-Latn-PG",
+ "jim": "jim-Latn-CM",
+ "jit": "jit-Latn-TZ",
+ "jiu": "jiu-Latn-CN",
+ "jiv": "jiv-Latn-EC",
+ "jiy": "jiy-Latn-CN",
+ "jje": "jje-Hang-KR",
+ "jjr": "jjr-Latn-NG",
+ "jka": "jka-Latn-ID",
+ "jkm": "jkm-Mymr-MM",
+ "jkm-Brai": "jkm-Brai-MM",
+ "jkm-Latn": "jkm-Latn-MM",
+ "jko": "jko-Latn-PG",
+ "jku": "jku-Latn-NG",
+ "jle": "jle-Latn-SD",
+ "jma": "jma-Latn-PG",
+ "jmb": "jmb-Latn-NG",
+ "jmc": "jmc-Latn-TZ",
+ "jmd": "jmd-Latn-ID",
+ "jmi": "jmi-Latn-NG",
+ "jml": "jml-Deva-NP",
+ "jmn": "jmn-Latn-MM",
+ "jmr": "jmr-Latn-GH",
+ "jms": "jms-Latn-NG",
+ "jmw": "jmw-Latn-PG",
+ "jmx": "jmx-Latn-MX",
+ "jna": "jna-Takr-IN",
+ "jnd": "jnd-Arab-PK",
+ "jng": "jng-Latn-AU",
+ "jni": "jni-Latn-NG",
+ "jnj": "jnj-Latn-ET",
+ "jnj-Ethi": "jnj-Ethi-ET",
+ "jnl": "jnl-Deva-IN",
+ "jns": "jns-Deva-IN",
+ "jns-Latn": "jns-Latn-IN",
+ "jns-Takr": "jns-Takr-IN",
+ "job": "job-Latn-CD",
+ "jod": "jod-Latn-CI",
+ "jog": "jog-Arab-PK",
+ "jor": "jor-Latn-BO",
+ "jow": "jow-Latn-ML",
+ "jpa": "jpa-Hebr-PS",
+ "jpr": "jpr-Hebr-IL",
+ "jqr": "jqr-Latn-PE",
+ "jra": "jra-Latn-ZZ",
+ "jrr": "jrr-Latn-NG",
+ "jrt": "jrt-Latn-NG",
+ "jru": "jru-Latn-VE",
+ "jua": "jua-Latn-BR",
+ "jub": "jub-Latn-NG",
+ "jud": "jud-Latn-CI",
+ "juh": "juh-Latn-NG",
+ "jui": "jui-Latn-AU",
+ "juk": "juk-Latn-NG",
+ "jul": "jul-Deva-NP",
+ "jum": "jum-Latn-SD",
+ "jun": "jun-Orya-IN",
+ "juo": "juo-Latn-NG",
+ "jup": "jup-Latn-BR",
+ "jur": "jur-Latn-BR",
+ "jut": "jut-Latn-DK",
+ "juu": "juu-Latn-NG",
+ "juw": "juw-Latn-NG",
+ "juy": "juy-Orya-IN",
+ "jv": "jv-Latn-ID",
+ "jvd": "jvd-Latn-ID",
+ "jvn": "jvn-Latn-SR",
+ "jw": "jv-Latn-ID",
+ "jwi": "jwi-Latn-GH",
+ "jya": "jya-Tibt-CN",
+ "jye": "jye-Hebr-IL",
+ "jyy": "jyy-Latn-TD",
+ "ka": "ka-Geor-GE",
+ "kaa": "kaa-Cyrl-UZ",
+ "kab": "kab-Latn-DZ",
+ "kac": "kac-Latn-MM",
+ "kad": "kad-Latn-ZZ",
+ "kag": "kag-Latn-MY",
+ "kah": "kah-Latn-CF",
+ "kai": "kai-Latn-ZZ",
+ "kaj": "kaj-Latn-NG",
+ "kak": "kak-Latn-PH",
+ "kam": "kam-Latn-KE",
+ "kao": "kao-Latn-ML",
+ "kap": "kap-Cyrl-RU",
+ "kaq": "kaq-Latn-PE",
+ "kav": "kav-Latn-BR",
+ "kaw": "kaw-Kawi-ID",
+ "kax": "kax-Latn-ID",
+ "kay": "kay-Latn-BR",
+ "kba": "kba-Latn-AU",
+ "kbb": "kbb-Latn-BR",
+ "kbc": "kbc-Latn-BR",
+ "kbd": "kbd-Cyrl-RU",
+ "kbe": "kbe-Latn-AU",
+ "kbh": "kbh-Latn-CO",
+ "kbi": "kbi-Latn-ID",
+ "kbj": "kbj-Latn-CD",
+ "kbk": "kbk-Latn-PG",
+ "kbl": "kbl-Latn-TD",
+ "kbm": "kbm-Latn-ZZ",
+ "kbn": "kbn-Latn-CF",
+ "kbo": "kbo-Latn-SS",
+ "kbp": "kbp-Latn-ZZ",
+ "kbq": "kbq-Latn-ZZ",
+ "kbr": "kbr-Latn-ET",
+ "kbr-Ethi": "kbr-Ethi-ET",
+ "kbs": "kbs-Latn-GA",
+ "kbt": "kbt-Latn-PG",
+ "kbu": "kbu-Arab-PK",
+ "kbv": "kbv-Latn-ID",
+ "kbw": "kbw-Latn-PG",
+ "kbx": "kbx-Latn-ZZ",
+ "kby": "kby-Arab-NE",
+ "kbz": "kbz-Latn-NG",
+ "kca": "kca-Cyrl-RU",
+ "kcb": "kcb-Latn-PG",
+ "kcc": "kcc-Latn-NG",
+ "kcd": "kcd-Latn-ID",
+ "kce": "kce-Latn-NG",
+ "kcf": "kcf-Latn-NG",
+ "kcg": "kcg-Latn-NG",
+ "kch": "kch-Latn-NG",
+ "kci": "kci-Latn-NG",
+ "kcj": "kcj-Latn-GW",
+ "kck": "kck-Latn-ZW",
+ "kcl": "kcl-Latn-ZZ",
+ "kcm": "kcm-Latn-CF",
+ "kcn": "kcn-Latn-UG",
+ "kco": "kco-Latn-PG",
+ "kcp": "kcp-Latn-SD",
+ "kcq": "kcq-Latn-NG",
+ "kcs": "kcs-Latn-NG",
+ "kct": "kct-Latn-ZZ",
+ "kcu": "kcu-Latn-TZ",
+ "kcv": "kcv-Latn-CD",
+ "kcw": "kcw-Latn-CD",
+ "kcz": "kcz-Latn-TZ",
+ "kda": "kda-Latn-AU",
+ "kdc": "kdc-Latn-TZ",
+ "kdd": "kdd-Latn-AU",
+ "kde": "kde-Latn-TZ",
+ "kdf": "kdf-Latn-PG",
+ "kdg": "kdg-Latn-CD",
+ "kdh": "kdh-Latn-TG",
+ "kdi": "kdi-Latn-UG",
+ "kdj": "kdj-Latn-UG",
+ "kdk": "kdk-Latn-NC",
+ "kdl": "kdl-Latn-ZZ",
+ "kdm": "kdm-Latn-NG",
+ "kdn": "kdn-Latn-ZW",
+ "kdp": "kdp-Latn-NG",
+ "kdq": "kdq-Beng-IN",
+ "kdr": "kdr-Latn-LT",
+ "kdr-Cyrl": "kdr-Cyrl-UA",
+ "kdt": "kdt-Thai-TH",
+ "kdw": "kdw-Latn-ID",
+ "kdx": "kdx-Latn-NG",
+ "kdy": "kdy-Latn-ID",
+ "kdz": "kdz-Latn-CM",
+ "kea": "kea-Latn-CV",
+ "keb": "keb-Latn-GA",
+ "kec": "kec-Latn-SD",
+ "ked": "ked-Latn-TZ",
+ "kee": "kee-Latn-US",
+ "kef": "kef-Latn-TG",
+ "keg": "keg-Latn-SD",
+ "keh": "keh-Latn-PG",
+ "kei": "kei-Latn-ID",
+ "kek": "kek-Latn-GT",
+ "kel": "kel-Latn-CD",
+ "kem": "kem-Latn-TL",
+ "ken": "ken-Latn-CM",
+ "keo": "keo-Latn-UG",
+ "ker": "ker-Latn-TD",
+ "kes": "kes-Latn-NG",
+ "ket": "ket-Cyrl-RU",
+ "keu": "keu-Latn-TG",
+ "kew": "kew-Latn-PG",
+ "kex": "kex-Deva-IN",
+ "kex-Gujr": "kex-Gujr-IN",
+ "key": "key-Telu-IN",
+ "kez": "kez-Latn-ZZ",
+ "kfa": "kfa-Knda-IN",
+ "kfb": "kfb-Deva-IN",
+ "kfc": "kfc-Telu-IN",
+ "kfd": "kfd-Knda-IN",
+ "kfe": "kfe-Taml-IN",
+ "kff": "kff-Latn-IN",
+ "kff-Deva": "kff-Deva-IN",
+ "kff-Orya": "kff-Orya-IN",
+ "kff-Telu": "kff-Telu-IN",
+ "kfh": "kfh-Mlym-IN",
+ "kfi": "kfi-Taml-IN",
+ "kfi-Knda": "kfi-Knda-IN",
+ "kfk": "kfk-Deva-IN",
+ "kfk-Takr": "kfk-Takr-IN",
+ "kfl": "kfl-Latn-CM",
+ "kfm": "kfm-Arab-IR",
+ "kfn": "kfn-Latn-CM",
+ "kfo": "kfo-Latn-CI",
+ "kfp": "kfp-Deva-IN",
+ "kfq": "kfq-Deva-IN",
+ "kfr": "kfr-Deva-IN",
+ "kfs": "kfs-Deva-IN",
+ "kfv": "kfv-Latn-IN",
+ "kfw": "kfw-Latn-IN",
+ "kfx": "kfx-Deva-IN",
+ "kfx-Takr": "kfx-Takr-IN",
+ "kfy": "kfy-Deva-IN",
+ "kfz": "kfz-Latn-BF",
+ "kg": "kg-Latn-CD",
+ "kga": "kga-Latn-CI",
+ "kgb": "kgb-Latn-ID",
+ "kge": "kge-Latn-ID",
+ "kgf": "kgf-Latn-ZZ",
+ "kgj": "kgj-Deva-NP",
+ "kgk": "kgk-Latn-BR",
+ "kgl": "kgl-Latn-AU",
+ "kgm": "kgm-Latn-BR",
+ "kgo": "kgo-Latn-SD",
+ "kgp": "kgp-Latn-BR",
+ "kgq": "kgq-Latn-ID",
+ "kgr": "kgr-Latn-ID",
+ "kgs": "kgs-Latn-AU",
+ "kgt": "kgt-Latn-NG",
+ "kgu": "kgu-Latn-PG",
+ "kgv": "kgv-Latn-ID",
+ "kgw": "kgw-Latn-ID",
+ "kgx": "kgx-Latn-ID",
+ "kgy": "kgy-Deva-NP",
+ "kha": "kha-Latn-IN",
+ "khb": "khb-Talu-CN",
+ "khc": "khc-Latn-ID",
+ "khd": "khd-Latn-ID",
+ "khe": "khe-Latn-ID",
+ "khf": "khf-Thai-LA",
+ "khg": "khg-Tibt-CN",
+ "khh": "khh-Latn-ID",
+ "khj": "khj-Latn-NG",
+ "khl": "khl-Latn-PG",
+ "khn": "khn-Deva-IN",
+ "khp": "khp-Latn-ID",
+ "khq": "khq-Latn-ML",
+ "khr": "khr-Latn-IN",
+ "khr-Deva": "khr-Deva-IN",
+ "khs": "khs-Latn-ZZ",
+ "kht": "kht-Mymr-IN",
+ "khu": "khu-Latn-AO",
+ "khv": "khv-Cyrl-RU",
+ "khw": "khw-Arab-PK",
+ "khx": "khx-Latn-CD",
+ "khy": "khy-Latn-CD",
+ "khz": "khz-Latn-ZZ",
+ "ki": "ki-Latn-KE",
+ "kia": "kia-Latn-TD",
+ "kib": "kib-Latn-SD",
+ "kic": "kic-Latn-US",
+ "kid": "kid-Latn-CM",
+ "kie": "kie-Latn-TD",
+ "kif": "kif-Deva-NP",
+ "kig": "kig-Latn-ID",
+ "kih": "kih-Latn-PG",
+ "kij": "kij-Latn-ZZ",
+ "kil": "kil-Latn-NG",
+ "kim": "kim-Cyrl-RU",
+ "kio": "kio-Latn-US",
+ "kip": "kip-Deva-NP",
+ "kiq": "kiq-Latn-ID",
+ "kis": "kis-Latn-PG",
+ "kit": "kit-Latn-PG",
+ "kiu": "kiu-Latn-TR",
+ "kiv": "kiv-Latn-TZ",
+ "kiw": "kiw-Latn-ZZ",
+ "kix": "kix-Latn-IN",
+ "kiy": "kiy-Latn-ID",
+ "kiz": "kiz-Latn-TZ",
+ "kj": "kj-Latn-NA",
+ "kja": "kja-Latn-ID",
+ "kjb": "kjb-Latn-GT",
+ "kjc": "kjc-Latn-ID",
+ "kjd": "kjd-Latn-ZZ",
+ "kje": "kje-Latn-ID",
+ "kjg": "kjg-Laoo-LA",
+ "kjh": "kjh-Cyrl-RU",
+ "kji": "kji-Latn-SB",
+ "kjj": "kjj-Latn-AZ",
+ "kjk": "kjk-Latn-ID",
+ "kjl": "kjl-Deva-NP",
+ "kjm": "kjm-Latn-VN",
+ "kjn": "kjn-Latn-AU",
+ "kjo": "kjo-Deva-IN",
+ "kjp": "kjp-Mymr-MM",
+ "kjp-Thai": "kjp-Thai-TH",
+ "kjq": "kjq-Latn-US",
+ "kjr": "kjr-Latn-ID",
+ "kjs": "kjs-Latn-ZZ",
+ "kjt": "kjt-Thai-TH",
+ "kju": "kju-Latn-US",
+ "kjx": "kjx-Latn-PG",
+ "kjy": "kjy-Latn-ZZ",
+ "kk": "kk-Cyrl-KZ",
+ "kk-AF": "kk-Arab-AF",
+ "kk-Arab": "kk-Arab-CN",
+ "kk-CN": "kk-Arab-CN",
+ "kk-IR": "kk-Arab-IR",
+ "kk-MN": "kk-Arab-MN",
+ "kka": "kka-Latn-NG",
+ "kkb": "kkb-Latn-ID",
+ "kkc": "kkc-Latn-ZZ",
+ "kkd": "kkd-Latn-NG",
+ "kke": "kke-Latn-GN",
+ "kke-Arab": "kke-Arab-GN",
+ "kkf": "kkf-Tibt-IN",
+ "kkg": "kkg-Latn-PH",
+ "kkh": "kkh-Lana-MM",
+ "kki": "kki-Latn-TZ",
+ "kkj": "kkj-Latn-CM",
+ "kkk": "kkk-Latn-SB",
+ "kkl": "kkl-Latn-ID",
+ "kkm": "kkm-Latn-NG",
+ "kko": "kko-Latn-SD",
+ "kkp": "kkp-Latn-AU",
+ "kkq": "kkq-Latn-CD",
+ "kkr": "kkr-Latn-NG",
+ "kks": "kks-Latn-NG",
+ "kkt": "kkt-Deva-NP",
+ "kku": "kku-Latn-NG",
+ "kkv": "kkv-Latn-ID",
+ "kkw": "kkw-Latn-CG",
+ "kkx": "kkx-Latn-ID",
+ "kky": "kky-Latn-AU",
+ "kkz": "kkz-Latn-CA",
+ "kl": "kl-Latn-GL",
+ "kla": "kla-Latn-US",
+ "klb": "klb-Latn-MX",
+ "klc": "klc-Latn-CM",
+ "kld": "kld-Latn-AU",
+ "kle": "kle-Deva-NP",
+ "klf": "klf-Latn-TD",
+ "klg": "klg-Latn-PH",
+ "klh": "klh-Latn-PG",
+ "kli": "kli-Latn-ID",
+ "klj": "klj-Arab-IR",
+ "klk": "klk-Latn-NG",
+ "kll": "kll-Latn-PH",
+ "klm": "klm-Latn-PG",
+ "kln": "kln-Latn-KE",
+ "klo": "klo-Latn-NG",
+ "klp": "klp-Latn-PG",
+ "klq": "klq-Latn-ZZ",
+ "klr": "klr-Deva-NP",
+ "kls": "kls-Latn-PK",
+ "kls-Arab": "kls-Arab-PK",
+ "klt": "klt-Latn-ZZ",
+ "klu": "klu-Latn-LR",
+ "klv": "klv-Latn-VU",
+ "klw": "klw-Latn-ID",
+ "klx": "klx-Latn-ZZ",
+ "kly": "kly-Latn-ID",
+ "klz": "klz-Latn-ID",
+ "km": "km-Khmr-KH",
+ "kma": "kma-Latn-GH",
+ "kmb": "kmb-Latn-AO",
+ "kmc": "kmc-Latn-CN",
+ "kmc-Hani": "kmc-Hani-CN",
+ "kmd": "kmd-Latn-PH",
+ "kme": "kme-Latn-CM",
+ "kmf": "kmf-Latn-PG",
+ "kmg": "kmg-Latn-PG",
+ "kmh": "kmh-Latn-ZZ",
+ "kmi": "kmi-Latn-NG",
+ "kmj": "kmj-Deva-IN",
+ "kmk": "kmk-Latn-PH",
+ "kml": "kml-Latn-PH",
+ "kmm": "kmm-Latn-IN",
+ "kmn": "kmn-Latn-PG",
+ "kmo": "kmo-Latn-ZZ",
+ "kmp": "kmp-Latn-CM",
+ "kmq": "kmq-Latn-ET",
+ "kms": "kms-Latn-ZZ",
+ "kmt": "kmt-Latn-ID",
+ "kmu": "kmu-Latn-ZZ",
+ "kmv": "kmv-Latn-BR",
+ "kmw": "kmw-Latn-ZZ",
+ "kmx": "kmx-Latn-PG",
+ "kmy": "kmy-Latn-NG",
+ "kmz": "kmz-Arab-IR",
+ "kn": "kn-Knda-IN",
+ "kna": "kna-Latn-NG",
+ "knb": "knb-Latn-PH",
+ "knd": "knd-Latn-ID",
+ "kne": "kne-Latn-PH",
+ "knf": "knf-Latn-GW",
+ "kni": "kni-Latn-NG",
+ "knj": "knj-Latn-GT",
+ "knk": "knk-Latn-SL",
+ "knk-Arab": "knk-Arab-SL",
+ "knl": "knl-Latn-ID",
+ "knm": "knm-Latn-BR",
+ "kno": "kno-Latn-SL",
+ "knp": "knp-Latn-ZZ",
+ "knq": "knq-Latn-MY",
+ "knr": "knr-Latn-PG",
+ "kns": "kns-Latn-MY",
+ "kns-Thai": "kns-Thai-TH",
+ "knt": "knt-Latn-BR",
+ "knu": "knu-Latn-GN",
+ "knv": "knv-Latn-PG",
+ "knw": "knw-Latn-NA",
+ "knx": "knx-Latn-ID",
+ "kny": "kny-Latn-CD",
+ "knz": "knz-Latn-BF",
+ "ko": "ko-Kore-KR",
+ "koa": "koa-Latn-PG",
+ "koc": "koc-Latn-NG",
+ "kod": "kod-Latn-ID",
+ "koe": "koe-Latn-SS",
+ "kof": "kof-Latn-NG",
+ "kog": "kog-Latn-CO",
+ "koh": "koh-Latn-CG",
+ "koi": "koi-Cyrl-RU",
+ "kok": "kok-Deva-IN",
+ "kol": "kol-Latn-ZZ",
+ "koo": "koo-Latn-UG",
+ "kop": "kop-Latn-PG",
+ "koq": "koq-Latn-GA",
+ "kos": "kos-Latn-FM",
+ "kot": "kot-Latn-CM",
+ "kou": "kou-Latn-TD",
+ "kov": "kov-Latn-NG",
+ "kow": "kow-Latn-NG",
+ "koy": "koy-Latn-US",
+ "koz": "koz-Latn-ZZ",
+ "kpa": "kpa-Latn-NG",
+ "kpc": "kpc-Latn-CO",
+ "kpd": "kpd-Latn-ID",
+ "kpe": "kpe-Latn-LR",
+ "kpf": "kpf-Latn-ZZ",
+ "kpg": "kpg-Latn-FM",
+ "kph": "kph-Latn-GH",
+ "kpi": "kpi-Latn-ID",
+ "kpj": "kpj-Latn-BR",
+ "kpk": "kpk-Latn-NG",
+ "kpl": "kpl-Latn-CD",
+ "kpm": "kpm-Latn-VN",
+ "kpn": "kpn-Latn-BR",
+ "kpo": "kpo-Latn-ZZ",
+ "kpq": "kpq-Latn-ID",
+ "kpr": "kpr-Latn-ZZ",
+ "kps": "kps-Latn-ID",
+ "kpt": "kpt-Cyrl-RU",
+ "kpu": "kpu-Latn-ID",
+ "kpw": "kpw-Latn-PG",
+ "kpx": "kpx-Latn-ZZ",
+ "kpy": "kpy-Cyrl-RU",
+ "kpz": "kpz-Latn-UG",
+ "kqa": "kqa-Latn-PG",
+ "kqb": "kqb-Latn-ZZ",
+ "kqc": "kqc-Latn-PG",
+ "kqd": "kqd-Syrc-IQ",
+ "kqe": "kqe-Latn-PH",
+ "kqf": "kqf-Latn-ZZ",
+ "kqg": "kqg-Latn-BF",
+ "kqh": "kqh-Latn-TZ",
+ "kqi": "kqi-Latn-PG",
+ "kqj": "kqj-Latn-PG",
+ "kqk": "kqk-Latn-BJ",
+ "kql": "kql-Latn-PG",
+ "kqm": "kqm-Latn-CI",
+ "kqn": "kqn-Latn-ZM",
+ "kqo": "kqo-Latn-LR",
+ "kqp": "kqp-Latn-TD",
+ "kqq": "kqq-Latn-BR",
+ "kqr": "kqr-Latn-MY",
+ "kqs": "kqs-Latn-ZZ",
+ "kqt": "kqt-Latn-MY",
+ "kqu": "kqu-Latn-ZA",
+ "kqv": "kqv-Latn-ID",
+ "kqw": "kqw-Latn-PG",
+ "kqx": "kqx-Latn-CM",
+ "kqy": "kqy-Ethi-ZZ",
+ "kqz": "kqz-Latn-ZA",
+ "kr": "kr-Latn-ZZ",
+ "kra": "kra-Deva-NP",
+ "krb": "krb-Latn-US",
+ "krc": "krc-Cyrl-RU",
+ "krd": "krd-Latn-TL",
+ "kre": "kre-Latn-BR",
+ "krf": "krf-Latn-VU",
+ "krh": "krh-Latn-NG",
+ "kri": "kri-Latn-SL",
+ "krj": "krj-Latn-PH",
+ "krk": "krk-Cyrl-RU",
+ "krl": "krl-Latn-RU",
+ "krn": "krn-Latn-LR",
+ "krp": "krp-Latn-NG",
+ "krr": "krr-Khmr-KH",
+ "krs": "krs-Latn-ZZ",
+ "krt": "krt-Latn-NE",
+ "kru": "kru-Deva-IN",
+ "krv": "krv-Khmr-KH",
+ "krw": "krw-Latn-LR",
+ "krx": "krx-Latn-SN",
+ "kry": "kry-Latn-AZ",
+ "krz": "krz-Latn-ID",
+ "ks": "ks-Arab-IN",
+ "ksa": "ksa-Latn-NG",
+ "ksb": "ksb-Latn-TZ",
+ "ksc": "ksc-Latn-PH",
+ "ksd": "ksd-Latn-ZZ",
+ "kse": "kse-Latn-PG",
+ "ksf": "ksf-Latn-CM",
+ "ksg": "ksg-Latn-SB",
+ "ksh": "ksh-Latn-DE",
+ "ksi": "ksi-Latn-PG",
+ "ksj": "ksj-Latn-ZZ",
+ "ksk": "ksk-Latn-US",
+ "ksl": "ksl-Latn-PG",
+ "ksm": "ksm-Latn-NG",
+ "ksn": "ksn-Latn-PH",
+ "kso": "kso-Latn-NG",
+ "ksp": "ksp-Latn-CF",
+ "ksq": "ksq-Latn-NG",
+ "ksr": "ksr-Latn-ZZ",
+ "kss": "kss-Latn-LR",
+ "kst": "kst-Latn-BF",
+ "ksu": "ksu-Mymr-IN",
+ "ksv": "ksv-Latn-CD",
+ "ksw": "ksw-Mymr-MM",
+ "ksw-Latn": "ksw-Latn-MM",
+ "ksx": "ksx-Latn-ID",
+ "ksz": "ksz-Deva-IN",
+ "kta": "kta-Latn-VN",
+ "ktb": "ktb-Ethi-ZZ",
+ "ktc": "ktc-Latn-NG",
+ "ktd": "ktd-Latn-AU",
+ "ktf": "ktf-Latn-CD",
+ "ktg": "ktg-Latn-AU",
+ "kth": "kth-Latn-TD",
+ "kti": "kti-Latn-ID",
+ "ktj": "ktj-Latn-CI",
+ "ktk": "ktk-Latn-PG",
+ "ktl": "ktl-Arab-IR",
+ "ktm": "ktm-Latn-ZZ",
+ "ktn": "ktn-Latn-BR",
+ "kto": "kto-Latn-ZZ",
+ "ktp": "ktp-Plrd-CN",
+ "ktq": "ktq-Latn-PH",
+ "ktr": "dtp-Latn-MY",
+ "kts": "kts-Latn-ID",
+ "ktt": "ktt-Latn-ID",
+ "ktu": "ktu-Latn-CD",
+ "ktv": "ktv-Latn-VN",
+ "ktw": "ktw-Latn-US",
+ "ktx": "ktx-Latn-BR",
+ "kty": "kty-Latn-CD",
+ "ktz": "ktz-Latn-NA",
+ "ku": "ku-Latn-TR",
+ "ku-Arab": "ku-Arab-IQ",
+ "ku-LB": "ku-Arab-LB",
+ "ku-Yezi": "ku-Yezi-GE",
+ "kub": "kub-Latn-ZZ",
+ "kuc": "kuc-Latn-ID",
+ "kud": "kud-Latn-ZZ",
+ "kue": "kue-Latn-ZZ",
+ "kuf": "kuf-Laoo-LA",
+ "kug": "kug-Latn-NG",
+ "kuh": "kuh-Latn-NG",
+ "kui": "kui-Latn-BR",
+ "kuj": "kuj-Latn-ZZ",
+ "kuk": "kuk-Latn-ID",
+ "kul": "kul-Latn-NG",
+ "kum": "kum-Cyrl-RU",
+ "kun": "kun-Latn-ZZ",
+ "kuo": "kuo-Latn-PG",
+ "kup": "kup-Latn-ZZ",
+ "kuq": "kuq-Latn-BR",
+ "kus": "kus-Latn-ZZ",
+ "kut": "kut-Latn-CA",
+ "kuu": "kuu-Latn-US",
+ "kuv": "kuv-Latn-ID",
+ "kuw": "kuw-Latn-CF",
+ "kux": "kux-Latn-AU",
+ "kuy": "kuy-Latn-AU",
+ "kuz": "kuz-Latn-CL",
+ "kv": "kv-Cyrl-RU",
+ "kva": "kva-Cyrl-RU",
+ "kvb": "kvb-Latn-ID",
+ "kvc": "kvc-Latn-PG",
+ "kvd": "kvd-Latn-ID",
+ "kve": "kve-Latn-MY",
+ "kvf": "kvf-Latn-TD",
+ "kvg": "kvg-Latn-ZZ",
+ "kvh": "kvh-Latn-ID",
+ "kvi": "kvi-Latn-TD",
+ "kvj": "kvj-Latn-CM",
+ "kvl": "kvl-Latn-MM",
+ "kvm": "kvm-Latn-CM",
+ "kvn": "kvn-Latn-CO",
+ "kvo": "kvo-Latn-ID",
+ "kvp": "kvp-Latn-ID",
+ "kvq": "kvq-Mymr-MM",
+ "kvq-Latn": "kvq-Latn-MM",
+ "kvr": "kvr-Latn-ID",
+ "kvt": "kvt-Mymr-MM",
+ "kvv": "kvv-Latn-ID",
+ "kvw": "kvw-Latn-ID",
+ "kvx": "kvx-Arab-PK",
+ "kvy": "kvy-Kali-MM",
+ "kvz": "kvz-Latn-ID",
+ "kw": "kw-Latn-GB",
+ "kwa": "kwa-Latn-BR",
+ "kwb": "kwb-Latn-NG",
+ "kwc": "kwc-Latn-CG",
+ "kwd": "kwd-Latn-SB",
+ "kwe": "kwe-Latn-ID",
+ "kwf": "kwf-Latn-SB",
+ "kwg": "kwg-Latn-TD",
+ "kwh": "kwh-Latn-ID",
+ "kwi": "kwi-Latn-CO",
+ "kwj": "kwj-Latn-ZZ",
+ "kwk": "kwk-Latn-CA",
+ "kwl": "kwl-Latn-NG",
+ "kwm": "kwm-Latn-NA",
+ "kwn": "kwn-Latn-NA",
+ "kwo": "kwo-Latn-ZZ",
+ "kwp": "kwp-Latn-CI",
+ "kwq": "yam-Latn-ZZ",
+ "kwr": "kwr-Latn-ID",
+ "kws": "kws-Latn-CD",
+ "kwt": "kwt-Latn-ID",
+ "kwu": "kwu-Latn-CM",
+ "kwv": "kwv-Latn-TD",
+ "kww": "kww-Latn-SR",
+ "kwy": "kwy-Latn-CD",
+ "kwz": "kwz-Latn-AO",
+ "kxa": "kxa-Latn-ZZ",
+ "kxb": "kxb-Latn-CI",
+ "kxc": "kxc-Ethi-ZZ",
+ "kxd": "kxd-Latn-BN",
+ "kxd-Arab": "kxd-Arab-BN",
+ "kxe": "tvd-Latn-ZZ",
+ "kxf": "kxf-Mymr-MM",
+ "kxf-Latn": "kxf-Latn-MM",
+ "kxi": "kxi-Latn-MY",
+ "kxj": "kxj-Latn-TD",
+ "kxk": "kxk-Mymr-MM",
+ "kxl": "kru-Deva-IN",
+ "kxm": "kxm-Thai-TH",
+ "kxn": "kxn-Latn-MY",
+ "kxo": "kxo-Latn-BR",
+ "kxp": "kxp-Arab-PK",
+ "kxq": "kxq-Latn-ID",
+ "kxr": "kxr-Latn-PG",
+ "kxt": "kxt-Latn-PG",
+ "kxv": "kxv-Orya-IN",
+ "kxv-Latn": "kxv-Latn-IN",
+ "kxv-Telu": "kxv-Telu-IN",
+ "kxw": "kxw-Latn-ZZ",
+ "kxx": "kxx-Latn-CG",
+ "kxy": "kxy-Latn-VN",
+ "kxz": "kxz-Latn-ZZ",
+ "ky": "ky-Cyrl-KG",
+ "ky-Arab": "ky-Arab-CN",
+ "ky-CN": "ky-Arab-CN",
+ "ky-Latn": "ky-Latn-TR",
+ "ky-TR": "ky-Latn-TR",
+ "kya": "kya-Latn-TZ",
+ "kyb": "kyb-Latn-PH",
+ "kyc": "kyc-Latn-PG",
+ "kyd": "kyd-Latn-ID",
+ "kye": "kye-Latn-ZZ",
+ "kyf": "kyf-Latn-CI",
+ "kyg": "kyg-Latn-PG",
+ "kyh": "kyh-Latn-US",
+ "kyi": "kyi-Latn-MY",
+ "kyj": "kyj-Latn-PH",
+ "kyk": "kyk-Latn-PH",
+ "kyl": "kyl-Latn-US",
+ "kym": "kym-Latn-CF",
+ "kyn": "kyn-Latn-PH",
+ "kyo": "kyo-Latn-ID",
+ "kyq": "kyq-Latn-TD",
+ "kyr": "kyr-Latn-BR",
+ "kys": "kys-Latn-MY",
+ "kyt": "kyt-Latn-ID",
+ "kyu": "kyu-Kali-MM",
+ "kyu-Latn": "kyu-Latn-MM",
+ "kyu-Mymr": "kyu-Mymr-MM",
+ "kyv": "kyv-Deva-NP",
+ "kyw": "kyw-Deva-IN",
+ "kyw-Beng": "kyw-Beng-IN",
+ "kyw-Orya": "kyw-Orya-IN",
+ "kyx": "kyx-Latn-ZZ",
+ "kyy": "kyy-Latn-PG",
+ "kyz": "kyz-Latn-BR",
+ "kza": "kza-Latn-BF",
+ "kzb": "kzb-Latn-ID",
+ "kzc": "kzc-Latn-CI",
+ "kzd": "kzd-Latn-ID",
+ "kze": "kze-Latn-PG",
+ "kzf": "kzf-Latn-ID",
+ "kzh": "dgl-Arab-ZZ",
+ "kzi": "kzi-Latn-MY",
+ "kzj": "dtp-Latn-MY",
+ "kzk": "kzk-Latn-SB",
+ "kzl": "kzl-Latn-ID",
+ "kzm": "kzm-Latn-ID",
+ "kzn": "kzn-Latn-MW",
+ "kzo": "kzo-Latn-GA",
+ "kzp": "kzp-Latn-ID",
+ "kzr": "kzr-Latn-ZZ",
+ "kzs": "kzs-Latn-MY",
+ "kzt": "dtp-Latn-MY",
+ "kzu": "kzu-Latn-ID",
+ "kzv": "kzv-Latn-ID",
+ "kzw": "kzw-Latn-BR",
+ "kzx": "kzx-Latn-ID",
+ "kzy": "kzy-Latn-CD",
+ "kzz": "kzz-Latn-ID",
+ "la": "la-Latn-VA",
+ "laa": "laa-Latn-PH",
+ "lab": "lab-Lina-GR",
+ "lac": "lac-Latn-MX",
+ "lad": "lad-Hebr-IL",
+ "lae": "lae-Deva-IN",
+ "lae-Tibt": "lae-Tibt-IN",
+ "lag": "lag-Latn-TZ",
+ "lah": "lah-Arab-PK",
+ "lai": "lai-Latn-MW",
+ "laj": "laj-Latn-UG",
+ "lal": "lal-Latn-CD",
+ "lam": "lam-Latn-ZM",
+ "lan": "lan-Latn-NG",
+ "lap": "lap-Latn-TD",
+ "laq": "laq-Latn-VN",
+ "lar": "lar-Latn-GH",
+ "las": "las-Latn-ZZ",
+ "lau": "lau-Latn-ID",
+ "law": "law-Latn-ID",
+ "lax": "lax-Latn-IN",
+ "lax-Beng": "lax-Beng-IN",
+ "laz": "laz-Latn-PG",
+ "lb": "lb-Latn-LU",
+ "lbb": "lbb-Latn-PG",
+ "lbc": "lbc-Lisu-CN",
+ "lbe": "lbe-Cyrl-RU",
+ "lbf": "lbf-Deva-IN",
+ "lbf-Tibt": "lbf-Tibt-CN",
+ "lbi": "lbi-Latn-CM",
+ "lbj": "lbj-Tibt-IN",
+ "lbj-Arab": "lbj-Arab-IN",
+ "lbl": "lbl-Latn-PH",
+ "lbm": "lbm-Deva-IN",
+ "lbn": "lbn-Latn-LA",
+ "lbn-Laoo": "lbn-Laoo-LA",
+ "lbo": "lbo-Laoo-LA",
+ "lbo-Latn": "lbo-Latn-US",
+ "lbq": "lbq-Latn-PG",
+ "lbr": "lbr-Deva-NP",
+ "lbt": "lbt-Latn-VN",
+ "lbu": "lbu-Latn-ZZ",
+ "lbv": "lbv-Latn-PG",
+ "lbw": "lbw-Latn-ID",
+ "lbx": "lbx-Latn-ID",
+ "lby": "lby-Latn-AU",
+ "lbz": "lbz-Latn-AU",
+ "lcc": "lcc-Latn-ID",
+ "lcd": "lcd-Latn-ID",
+ "lce": "lce-Latn-ID",
+ "lcf": "lcf-Latn-ID",
+ "lch": "lch-Latn-AO",
+ "lcl": "lcl-Latn-ID",
+ "lcm": "lcm-Latn-ZZ",
+ "lcp": "lcp-Thai-CN",
+ "lcq": "lcq-Latn-ID",
+ "lcs": "lcs-Latn-ID",
+ "lda": "lda-Latn-CI",
+ "ldb": "ldb-Latn-ZZ",
+ "ldd": "ldd-Latn-NG",
+ "ldg": "ldg-Latn-NG",
+ "ldh": "ldh-Latn-NG",
+ "ldi": "ldi-Latn-CG",
+ "ldj": "ldj-Latn-NG",
+ "ldk": "ldk-Latn-NG",
+ "ldl": "ldl-Latn-NG",
+ "ldm": "ldm-Latn-GN",
+ "ldn": "ldn-Latn-001",
+ "ldo": "ldo-Latn-NG",
+ "ldp": "ldp-Latn-NG",
+ "ldq": "ldq-Latn-NG",
+ "lea": "lea-Latn-CD",
+ "leb": "leb-Latn-ZM",
+ "lec": "lec-Latn-BO",
+ "led": "led-Latn-ZZ",
+ "lee": "lee-Latn-ZZ",
+ "lef": "lef-Latn-GH",
+ "leh": "leh-Latn-ZM",
+ "lei": "lei-Latn-PG",
+ "lej": "lej-Latn-CD",
+ "lek": "lek-Latn-PG",
+ "lel": "lel-Latn-CD",
+ "lem": "lem-Latn-ZZ",
+ "len": "len-Latn-HN",
+ "leo": "leo-Latn-CM",
+ "lep": "lep-Lepc-IN",
+ "leq": "leq-Latn-ZZ",
+ "ler": "ler-Latn-PG",
+ "les": "les-Latn-CD",
+ "let": "let-Latn-PG",
+ "leu": "leu-Latn-ZZ",
+ "lev": "lev-Latn-ID",
+ "lew": "lew-Latn-ID",
+ "lex": "lex-Latn-ID",
+ "ley": "ley-Latn-ID",
+ "lez": "lez-Cyrl-RU",
+ "lfa": "lfa-Latn-CM",
+ "lfn": "lfn-Latn-001",
+ "lfn-Cyrl": "lfn-Cyrl-001",
+ "lg": "lg-Latn-UG",
+ "lga": "lga-Latn-SB",
+ "lgb": "lgb-Latn-SB",
+ "lgg": "lgg-Latn-ZZ",
+ "lgh": "lgh-Latn-VN",
+ "lgi": "lgi-Latn-ID",
+ "lgk": "lgk-Latn-VU",
+ "lgl": "lgl-Latn-SB",
+ "lgm": "lgm-Latn-CD",
+ "lgn": "lgn-Latn-ET",
+ "lgo": "lgo-Latn-SS",
+ "lgq": "lgq-Latn-GH",
+ "lgr": "lgr-Latn-SB",
+ "lgt": "lgt-Latn-PG",
+ "lgu": "lgu-Latn-SB",
+ "lgz": "lgz-Latn-CD",
+ "lha": "lha-Latn-VN",
+ "lhh": "lhh-Latn-ID",
+ "lhi": "lhi-Latn-CN",
+ "lhm": "lhm-Deva-NP",
+ "lhn": "lhn-Latn-MY",
+ "lhs": "lhs-Syrc-SY",
+ "lht": "lht-Latn-VU",
+ "lhu": "lhu-Latn-CN",
+ "li": "li-Latn-NL",
+ "lia": "lia-Latn-ZZ",
+ "lib": "lib-Latn-PG",
+ "lic": "lic-Latn-CN",
+ "lid": "lid-Latn-ZZ",
+ "lie": "lie-Latn-CD",
+ "lif": "lif-Deva-NP",
+ "lif-Limb": "lif-Limb-IN",
+ "lig": "lig-Latn-ZZ",
+ "lih": "lih-Latn-ZZ",
+ "lij": "lij-Latn-IT",
+ "lik": "lik-Latn-CD",
+ "lil": "lil-Latn-CA",
+ "lio": "lio-Latn-ID",
+ "lip": "lip-Latn-GH",
+ "liq": "liq-Latn-ET",
+ "lir": "lir-Latn-LR",
+ "lis": "lis-Lisu-CN",
+ "liu": "liu-Latn-SD",
+ "liv": "liv-Latn-LV",
+ "liw": "liw-Latn-ID",
+ "lix": "lix-Latn-ID",
+ "liy": "liy-Latn-CF",
+ "liz": "liz-Latn-CD",
+ "lja": "lja-Latn-AU",
+ "lje": "lje-Latn-ID",
+ "lji": "lji-Latn-ID",
+ "ljl": "ljl-Latn-ID",
+ "ljp": "ljp-Latn-ID",
+ "ljw": "ljw-Latn-AU",
+ "ljx": "ljx-Latn-AU",
+ "lka": "lka-Latn-TL",
+ "lkb": "lkb-Latn-KE",
+ "lkc": "lkc-Latn-VN",
+ "lkd": "lkd-Latn-BR",
+ "lke": "lke-Latn-UG",
+ "lkh": "lkh-Tibt-BT",
+ "lki": "lki-Arab-IR",
+ "lkj": "lkj-Latn-MY",
+ "lkl": "lkl-Latn-PG",
+ "lkm": "lkm-Latn-AU",
+ "lkn": "lkn-Latn-VU",
+ "lko": "lko-Latn-KE",
+ "lkr": "lkr-Latn-SS",
+ "lks": "lks-Latn-KE",
+ "lkt": "lkt-Latn-US",
+ "lku": "lku-Latn-AU",
+ "lky": "lky-Latn-SS",
+ "lla": "lla-Latn-NG",
+ "llb": "llb-Latn-MZ",
+ "llc": "llc-Latn-GN",
+ "lld": "lld-Latn-IT",
+ "lle": "lle-Latn-ZZ",
+ "llf": "llf-Latn-PG",
+ "llg": "llg-Latn-ID",
+ "lli": "lli-Latn-CG",
+ "llj": "llj-Latn-AU",
+ "llk": "llk-Latn-MY",
+ "lll": "lll-Latn-PG",
+ "llm": "llm-Latn-ID",
+ "lln": "lln-Latn-ZZ",
+ "llp": "llp-Latn-VU",
+ "llq": "llq-Latn-ID",
+ "llu": "llu-Latn-SB",
+ "llx": "llx-Latn-FJ",
+ "lma": "lma-Latn-GN",
+ "lmb": "lmb-Latn-VU",
+ "lmc": "lmc-Latn-AU",
+ "lmd": "lmd-Latn-SD",
+ "lme": "lme-Latn-TD",
+ "lmf": "lmf-Latn-ID",
+ "lmg": "lmg-Latn-PG",
+ "lmh": "lmh-Deva-NP",
+ "lmi": "lmi-Latn-CD",
+ "lmj": "lmj-Latn-ID",
+ "lmk": "lmk-Latn-IN",
+ "lmk-Mymr": "lmk-Mymr-IN",
+ "lml": "lml-Latn-VU",
+ "lmn": "lmn-Telu-IN",
+ "lmo": "lmo-Latn-IT",
+ "lmp": "lmp-Latn-ZZ",
+ "lmq": "lmq-Latn-ID",
+ "lmr": "lmr-Latn-ID",
+ "lmu": "lmu-Latn-VU",
+ "lmv": "lmv-Latn-FJ",
+ "lmw": "lmw-Latn-US",
+ "lmx": "lmx-Latn-CM",
+ "lmy": "lmy-Latn-ID",
+ "ln": "ln-Latn-CD",
+ "lna": "lna-Latn-CF",
+ "lnb": "lnb-Latn-NA",
+ "lnd": "lnd-Latn-ID",
+ "lnh": "lnh-Latn-MY",
+ "lni": "lni-Latn-PG",
+ "lnj": "lnj-Latn-AU",
+ "lnl": "lnl-Latn-CF",
+ "lnm": "lnm-Latn-PG",
+ "lnn": "lnn-Latn-VU",
+ "lns": "lns-Latn-ZZ",
+ "lnu": "lnu-Latn-ZZ",
+ "lnw": "lnw-Latn-AU",
+ "lnz": "lnz-Latn-CD",
+ "lo": "lo-Laoo-LA",
+ "loa": "loa-Latn-ID",
+ "lob": "lob-Latn-BF",
+ "loc": "loc-Latn-PH",
+ "loe": "loe-Latn-ID",
+ "log": "log-Latn-CD",
+ "loh": "loh-Latn-SS",
+ "loi": "loi-Latn-CI",
+ "loj": "loj-Latn-ZZ",
+ "lok": "lok-Latn-ZZ",
+ "lol": "lol-Latn-CD",
+ "lom": "lom-Latn-LR",
+ "lon": "lon-Latn-MW",
+ "loo": "loo-Latn-CD",
+ "lop": "lop-Latn-NG",
+ "loq": "loq-Latn-CD",
+ "lor": "lor-Latn-ZZ",
+ "los": "los-Latn-ZZ",
+ "lot": "lot-Latn-SS",
+ "lot-Arab": "lot-Arab-SS",
+ "lou": "lou-Latn-US",
+ "low": "low-Latn-MY",
+ "lox": "lox-Latn-ID",
+ "loy": "loy-Deva-NP",
+ "loy-Tibt": "loy-Tibt-NP",
+ "loz": "loz-Latn-ZM",
+ "lpa": "lpa-Latn-VU",
+ "lpe": "lpe-Latn-ID",
+ "lpn": "lpn-Latn-MM",
+ "lpo": "lpo-Plrd-CN",
+ "lpo-Lisu": "lpo-Lisu-CN",
+ "lpx": "lpx-Latn-SS",
+ "lqr": "lqr-Latn-SS",
+ "lra": "lra-Latn-MY",
+ "lrc": "lrc-Arab-IR",
+ "lrg": "lrg-Latn-AU",
+ "lri": "lri-Latn-KE",
+ "lrk": "lrk-Arab-PK",
+ "lrl": "lrl-Arab-IR",
+ "lrm": "lrm-Latn-KE",
+ "lrn": "lrn-Latn-ID",
+ "lro": "lro-Latn-SD",
+ "lrt": "lrt-Latn-ID",
+ "lrv": "lrv-Latn-VU",
+ "lrz": "lrz-Latn-VU",
+ "lsa": "lsa-Arab-IR",
+ "lsd": "lsd-Hebr-IL",
+ "lse": "lse-Latn-CD",
+ "lsi": "lsi-Latn-MM",
+ "lsm": "lsm-Latn-UG",
+ "lsr": "lsr-Latn-PG",
+ "lss": "lss-Arab-PK",
+ "lt": "lt-Latn-LT",
+ "ltg": "ltg-Latn-LV",
+ "lth": "lth-Latn-UG",
+ "lti": "lti-Latn-ID",
+ "ltn": "ltn-Latn-BR",
+ "lto": "lto-Latn-KE",
+ "lts": "lts-Latn-KE",
+ "ltu": "ltu-Latn-ID",
+ "lu": "lu-Latn-CD",
+ "lua": "lua-Latn-CD",
+ "luc": "luc-Latn-UG",
+ "lud": "lud-Latn-RU",
+ "lue": "lue-Latn-ZM",
+ "luf": "luf-Latn-PG",
+ "lui": "lui-Latn-US",
+ "luj": "luj-Latn-CD",
+ "luk": "luk-Tibt-BT",
+ "lul": "lul-Latn-SS",
+ "lum": "lum-Latn-AO",
+ "lun": "lun-Latn-ZM",
+ "luo": "luo-Latn-KE",
+ "lup": "lup-Latn-GA",
+ "luq": "luq-Latn-CU",
+ "lur": "lur-Latn-ID",
+ "lus": "lus-Latn-IN",
+ "lus-Beng": "lus-Beng-BD",
+ "lus-Brai": "lus-Brai-IN",
+ "lut": "lut-Latn-US",
+ "luu": "luu-Deva-NP",
+ "luv": "luv-Arab-OM",
+ "luw": "luw-Latn-CM",
+ "luy": "luy-Latn-KE",
+ "luz": "luz-Arab-IR",
+ "lv": "lv-Latn-LV",
+ "lva": "lva-Latn-TL",
+ "lvi": "lvi-Latn-LA",
+ "lvk": "lvk-Latn-SB",
+ "lvu": "lvu-Latn-ID",
+ "lwa": "lwa-Latn-CD",
+ "lwe": "lwe-Latn-ID",
+ "lwg": "lwg-Latn-KE",
+ "lwh": "lwh-Latn-VN",
+ "lwl": "lwl-Thai-TH",
+ "lwm": "lwm-Thai-CN",
+ "lwo": "lwo-Latn-SS",
+ "lwo-ZA": "lwo-Latn-ZA",
+ "lwt": "lwt-Latn-ID",
+ "lww": "lww-Latn-VU",
+ "lxm": "lxm-Latn-PG",
+ "lya": "lya-Tibt-BT",
+ "lyn": "lyn-Latn-ZM",
+ "lzh": "lzh-Hans-CN",
+ "lzl": "lzl-Latn-VU",
+ "lzn": "lzn-Latn-MM",
+ "lzz": "lzz-Latn-TR",
+ "maa": "maa-Latn-MX",
+ "mab": "mab-Latn-MX",
+ "mad": "mad-Latn-ID",
+ "mae": "mae-Latn-NG",
+ "maf": "maf-Latn-CM",
+ "mag": "mag-Deva-IN",
+ "mai": "mai-Deva-IN",
+ "maj": "maj-Latn-MX",
+ "mak": "mak-Latn-ID",
+ "mam": "mam-Latn-GT",
+ "man": "man-Latn-GM",
+ "man-GN": "man-Nkoo-GN",
+ "man-Nkoo": "man-Nkoo-GN",
+ "maq": "maq-Latn-MX",
+ "mas": "mas-Latn-KE",
+ "mat": "mat-Latn-MX",
+ "mau": "mau-Latn-MX",
+ "mav": "mav-Latn-BR",
+ "maw": "maw-Latn-ZZ",
+ "max": "max-Latn-ID",
+ "maz": "maz-Latn-MX",
+ "mba": "mba-Latn-PH",
+ "mbb": "mbb-Latn-PH",
+ "mbc": "mbc-Latn-BR",
+ "mbd": "mbd-Latn-PH",
+ "mbf": "mbf-Latn-SG",
+ "mbh": "mbh-Latn-ZZ",
+ "mbi": "mbi-Latn-PH",
+ "mbj": "mbj-Latn-BR",
+ "mbk": "mbk-Latn-PG",
+ "mbl": "mbl-Latn-BR",
+ "mbm": "mbm-Latn-CG",
+ "mbn": "mbn-Latn-CO",
+ "mbo": "mbo-Latn-ZZ",
+ "mbp": "mbp-Latn-CO",
+ "mbq": "mbq-Latn-ZZ",
+ "mbr": "mbr-Latn-CO",
+ "mbs": "mbs-Latn-PH",
+ "mbt": "mbt-Latn-PH",
+ "mbu": "mbu-Latn-ZZ",
+ "mbv": "mbv-Latn-GN",
+ "mbw": "mbw-Latn-ZZ",
+ "mbx": "mbx-Latn-PG",
+ "mby": "mby-Arab-PK",
+ "mbz": "mbz-Latn-MX",
+ "mca": "mca-Latn-PY",
+ "mcb": "mcb-Latn-PE",
+ "mcc": "mcc-Latn-PG",
+ "mcd": "mcd-Latn-PE",
+ "mce": "mce-Latn-MX",
+ "mcf": "mcf-Latn-PE",
+ "mcg": "mcg-Latn-VE",
+ "mch": "mch-Latn-VE",
+ "mci": "mci-Latn-ZZ",
+ "mcj": "mcj-Latn-NG",
+ "mck": "mck-Latn-AO",
+ "mcl": "mcl-Latn-CO",
+ "mcm": "mcm-Latn-MY",
+ "mcn": "mcn-Latn-TD",
+ "mco": "mco-Latn-MX",
+ "mcp": "mcp-Latn-ZZ",
+ "mcq": "mcq-Latn-ZZ",
+ "mcr": "mcr-Latn-ZZ",
+ "mcs": "mcs-Latn-CM",
+ "mct": "mct-Latn-CM",
+ "mcu": "mcu-Latn-ZZ",
+ "mcv": "mcv-Latn-PG",
+ "mcw": "mcw-Latn-TD",
+ "mcx": "mcx-Latn-CF",
+ "mcy": "mcy-Latn-PG",
+ "mcz": "mcz-Latn-PG",
+ "mda": "mda-Latn-ZZ",
+ "mdb": "mdb-Latn-PG",
+ "mdc": "mdc-Latn-PG",
+ "mdd": "mdd-Latn-CM",
+ "mde": "mde-Arab-ZZ",
+ "mdf": "mdf-Cyrl-RU",
+ "mdg": "mdg-Latn-TD",
+ "mdh": "mdh-Latn-PH",
+ "mdi": "mdi-Latn-CD",
+ "mdj": "mdj-Latn-ZZ",
+ "mdk": "mdk-Latn-CD",
+ "mdm": "mdm-Latn-CD",
+ "mdn": "mdn-Latn-CF",
+ "mdp": "mdp-Latn-CD",
+ "mdq": "mdq-Latn-CD",
+ "mdr": "mdr-Latn-ID",
+ "mds": "mds-Latn-PG",
+ "mdt": "mdt-Latn-CG",
+ "mdu": "mdu-Latn-CG",
+ "mdv": "mdv-Latn-MX",
+ "mdw": "mdw-Latn-CG",
+ "mdx": "mdx-Ethi-ZZ",
+ "mdy": "mdy-Ethi-ET",
+ "mdy-Latn": "mdy-Latn-ET",
+ "mdz": "mdz-Latn-BR",
+ "mea": "mea-Latn-CM",
+ "meb": "meb-Latn-PG",
+ "mec": "mec-Latn-AU",
+ "med": "med-Latn-ZZ",
+ "mee": "mee-Latn-ZZ",
+ "meh": "meh-Latn-MX",
+ "mej": "mej-Latn-ID",
+ "mek": "mek-Latn-ZZ",
+ "mel": "mel-Latn-MY",
+ "mem": "mem-Latn-AU",
+ "men": "men-Latn-SL",
+ "meo": "meo-Latn-MY",
+ "meo-Arab": "meo-Arab-MY",
+ "mep": "mep-Latn-AU",
+ "meq": "meq-Latn-CM",
+ "mer": "mer-Latn-KE",
+ "mes": "mes-Latn-TD",
+ "met": "met-Latn-ZZ",
+ "meu": "meu-Latn-ZZ",
+ "mev": "mev-Latn-LR",
+ "mew": "mew-Latn-NG",
+ "mey": "mey-Latn-MR",
+ "mey-Arab": "mey-Arab-MR",
+ "mez": "mez-Latn-US",
+ "mfa": "mfa-Arab-TH",
+ "mfb": "mfb-Latn-ID",
+ "mfc": "mfc-Latn-CD",
+ "mfd": "mfd-Latn-CM",
+ "mfe": "mfe-Latn-MU",
+ "mff": "mff-Latn-CM",
+ "mfg": "mfg-Latn-GN",
+ "mfg-Arab": "mfg-Arab-GN",
+ "mfh": "mfh-Latn-CM",
+ "mfi": "mfi-Arab-CM",
+ "mfi-Latn": "mfi-Latn-CM",
+ "mfj": "mfj-Latn-CM",
+ "mfk": "mfk-Latn-CM",
+ "mfl": "mfl-Latn-NG",
+ "mfm": "mfm-Latn-NG",
+ "mfn": "mfn-Latn-ZZ",
+ "mfo": "mfo-Latn-ZZ",
+ "mfp": "mfp-Latn-ID",
+ "mfq": "mfq-Latn-ZZ",
+ "mfr": "mfr-Latn-AU",
+ "mft": "mft-Latn-PG",
+ "mfu": "mfu-Latn-AO",
+ "mfv": "mfv-Latn-GW",
+ "mfw": "mfw-Latn-PG",
+ "mfx": "mfx-Latn-ET",
+ "mfx-Ethi": "mfx-Ethi-ET",
+ "mfy": "mfy-Latn-MX",
+ "mfz": "mfz-Latn-SS",
+ "mg": "mg-Latn-MG",
+ "mgb": "mgb-Latn-TD",
+ "mgc": "mgc-Latn-SS",
+ "mgd": "mgd-Latn-SS",
+ "mgd-Arab": "mgd-Arab-SS",
+ "mge": "mge-Latn-TD",
+ "mgf": "mgf-Latn-ID",
+ "mgg": "mgg-Latn-CM",
+ "mgh": "mgh-Latn-MZ",
+ "mgi": "mgi-Latn-NG",
+ "mgj": "mgj-Latn-NG",
+ "mgk": "mgk-Latn-ID",
+ "mgl": "mgl-Latn-ZZ",
+ "mgm": "mgm-Latn-TL",
+ "mgn": "mgn-Latn-CF",
+ "mgo": "mgo-Latn-CM",
+ "mgp": "mgp-Deva-NP",
+ "mgq": "mgq-Latn-TZ",
+ "mgr": "mgr-Latn-ZM",
+ "mgs": "mgs-Latn-TZ",
+ "mgt": "mgt-Latn-PG",
+ "mgu": "mgu-Latn-PG",
+ "mgv": "mgv-Latn-TZ",
+ "mgw": "mgw-Latn-TZ",
+ "mgy": "mgy-Latn-TZ",
+ "mgz": "mgz-Latn-TZ",
+ "mh": "mh-Latn-MH",
+ "mhb": "mhb-Latn-GA",
+ "mhc": "mhc-Latn-MX",
+ "mhd": "mhd-Latn-TZ",
+ "mhe": "mhe-Latn-MY",
+ "mhf": "mhf-Latn-PG",
+ "mhg": "mhg-Latn-AU",
+ "mhi": "mhi-Latn-ZZ",
+ "mhj": "mhj-Arab-AF",
+ "mhk": "mhk-Latn-CM",
+ "mhl": "mhl-Latn-ZZ",
+ "mhm": "mhm-Latn-MZ",
+ "mhn": "mhn-Latn-IT",
+ "mho": "mho-Latn-ZM",
+ "mhp": "mhp-Latn-ID",
+ "mhq": "mhq-Latn-US",
+ "mhs": "mhs-Latn-ID",
+ "mht": "mht-Latn-VE",
+ "mhu": "mhu-Latn-IN",
+ "mhw": "mhw-Latn-BW",
+ "mhx": "mhx-Latn-MM",
+ "mhy": "mhy-Latn-ID",
+ "mhz": "mhz-Latn-ID",
+ "mi": "mi-Latn-NZ",
+ "mia": "mia-Latn-US",
+ "mib": "mib-Latn-MX",
+ "mic": "mic-Latn-CA",
+ "mid": "mid-Mand-IQ",
+ "mie": "mie-Latn-MX",
+ "mif": "mif-Latn-ZZ",
+ "mig": "mig-Latn-MX",
+ "mih": "mih-Latn-MX",
+ "mii": "mii-Latn-MX",
+ "mij": "mij-Latn-CM",
+ "mik": "mik-Latn-US",
+ "mil": "mil-Latn-MX",
+ "mim": "mim-Latn-MX",
+ "min": "min-Latn-ID",
+ "mio": "mio-Latn-MX",
+ "mip": "mip-Latn-MX",
+ "miq": "miq-Latn-NI",
+ "mir": "mir-Latn-MX",
+ "mit": "mit-Latn-MX",
+ "miu": "miu-Latn-MX",
+ "miw": "miw-Latn-ZZ",
+ "mix": "mix-Latn-MX",
+ "miy": "miy-Latn-MX",
+ "miz": "miz-Latn-MX",
+ "mjb": "mjb-Latn-TL",
+ "mjc": "mjc-Latn-MX",
+ "mjd": "mjd-Latn-US",
+ "mje": "mje-Latn-TD",
+ "mjg": "mjg-Latn-CN",
+ "mjh": "mjh-Latn-TZ",
+ "mji": "mji-Latn-CN",
+ "mjj": "mjj-Latn-PG",
+ "mjk": "mjk-Latn-PG",
+ "mjl": "mjl-Deva-IN",
+ "mjl-Takr": "mjl-Takr-IN",
+ "mjm": "mjm-Latn-PG",
+ "mjn": "mjn-Latn-PG",
+ "mjq": "mjq-Mlym-IN",
+ "mjr": "mjr-Mlym-IN",
+ "mjs": "mjs-Latn-NG",
+ "mjt": "mjt-Deva-IN",
+ "mjt-Beng": "mjt-Beng-BD",
+ "mju": "mju-Telu-IN",
+ "mjv": "mjv-Mlym-IN",
+ "mjw": "mjw-Latn-IN",
+ "mjx": "mjx-Latn-BD",
+ "mjx-Beng": "mjx-Beng-BD",
+ "mjy": "mjy-Latn-US",
+ "mjz": "mjz-Deva-NP",
+ "mk": "mk-Cyrl-MK",
+ "mka": "mka-Latn-CI",
+ "mkb": "mkb-Deva-IN",
+ "mkc": "mkc-Latn-PG",
+ "mke": "mke-Deva-IN",
+ "mkf": "mkf-Latn-NG",
+ "mki": "mki-Arab-ZZ",
+ "mkj": "mkj-Latn-FM",
+ "mkk": "mkk-Latn-CM",
+ "mkl": "mkl-Latn-ZZ",
+ "mkm": "mkm-Thai-TH",
+ "mkn": "mkn-Latn-ID",
+ "mko": "mko-Latn-NG",
+ "mkp": "mkp-Latn-ZZ",
+ "mkr": "mkr-Latn-PG",
+ "mks": "mks-Latn-MX",
+ "mkt": "mkt-Latn-NC",
+ "mku": "mku-Latn-GN",
+ "mkv": "mkv-Latn-VU",
+ "mkw": "mkw-Latn-ZZ",
+ "mkx": "mkx-Latn-PH",
+ "mky": "mky-Latn-ID",
+ "mkz": "mkz-Latn-TL",
+ "ml": "ml-Mlym-IN",
+ "mla": "mla-Latn-VU",
+ "mlb": "mlb-Latn-CM",
+ "mlc": "mlc-Latn-VN",
+ "mle": "mle-Latn-ZZ",
+ "mlf": "mlf-Thai-LA",
+ "mlf-Latn": "mlf-Latn-LA",
+ "mlh": "mlh-Latn-PG",
+ "mli": "mli-Latn-ID",
+ "mlj": "mlj-Latn-TD",
+ "mlk": "mlk-Latn-KE",
+ "mll": "mll-Latn-VU",
+ "mln": "mln-Latn-SB",
+ "mlo": "mlo-Latn-SN",
+ "mlp": "mlp-Latn-ZZ",
+ "mlq": "mlq-Latn-SN",
+ "mlq-Arab": "mlq-Arab-SN",
+ "mlr": "mlr-Latn-CM",
+ "mls": "mls-Latn-SD",
+ "mlu": "mlu-Latn-SB",
+ "mlv": "mlv-Latn-VU",
+ "mlw": "mlw-Latn-CM",
+ "mlx": "mlx-Latn-VU",
+ "mlz": "mlz-Latn-PH",
+ "mma": "mma-Latn-NG",
+ "mmb": "mmb-Latn-ID",
+ "mmc": "mmc-Latn-MX",
+ "mmd": "mmd-Latn-CN",
+ "mmd-Hans": "mmd-Hans-CN",
+ "mmd-Hant": "mmd-Hant-CN",
+ "mme": "mme-Latn-VU",
+ "mmf": "mmf-Latn-NG",
+ "mmg": "mmg-Latn-VU",
+ "mmh": "mmh-Latn-BR",
+ "mmi": "mmi-Latn-PG",
+ "mmm": "mmm-Latn-VU",
+ "mmn": "mmn-Latn-PH",
+ "mmo": "mmo-Latn-ZZ",
+ "mmp": "mmp-Latn-PG",
+ "mmq": "mmq-Latn-PG",
+ "mmr": "mmr-Latn-CN",
+ "mmt": "mmt-Latn-PG",
+ "mmu": "mmu-Latn-ZZ",
+ "mmv": "mmv-Latn-BR",
+ "mmw": "mmw-Latn-VU",
+ "mmx": "mmx-Latn-ZZ",
+ "mmy": "mmy-Latn-TD",
+ "mmz": "mmz-Latn-CD",
+ "mn": "mn-Cyrl-MN",
+ "mn-CN": "mn-Mong-CN",
+ "mn-Mong": "mn-Mong-CN",
+ "mna": "mna-Latn-ZZ",
+ "mnb": "mnb-Latn-ID",
+ "mnd": "mnd-Latn-BR",
+ "mne": "mne-Latn-TD",
+ "mnf": "mnf-Latn-ZZ",
+ "mng": "mng-Latn-VN",
+ "mnh": "mnh-Latn-CD",
+ "mni": "mni-Beng-IN",
+ "mnj": "mnj-Arab-AF",
+ "mnl": "mnl-Latn-VU",
+ "mnm": "mnm-Latn-PG",
+ "mnn": "mnn-Latn-VN",
+ "mnp": "mnp-Latn-CN",
+ "mnq": "mnq-Latn-MY",
+ "mnr": "mnr-Latn-US",
+ "mns": "mns-Cyrl-RU",
+ "mnu": "mnu-Latn-ID",
+ "mnv": "mnv-Latn-SB",
+ "mnw": "mnw-Mymr-MM",
+ "mnx": "mnx-Latn-ID",
+ "mny": "mny-Latn-MZ",
+ "mnz": "mnz-Latn-ID",
+ "mo": "ro-Latn-RO",
+ "moa": "moa-Latn-ZZ",
+ "moc": "moc-Latn-AR",
+ "mod": "mod-Latn-US",
+ "moe": "moe-Latn-CA",
+ "mog": "mog-Latn-ID",
+ "moh": "moh-Latn-CA",
+ "moi": "moi-Latn-NG",
+ "moj": "moj-Latn-CG",
+ "mok": "mok-Latn-ID",
+ "mom": "mom-Latn-NI",
+ "moo": "moo-Latn-VN",
+ "mop": "mop-Latn-BZ",
+ "moq": "moq-Latn-ID",
+ "mor": "mor-Latn-SD",
+ "mos": "mos-Latn-BF",
+ "mot": "mot-Latn-CO",
+ "mou": "mou-Latn-TD",
+ "mov": "mov-Latn-US",
+ "mow": "mow-Latn-CG",
+ "mox": "mox-Latn-ZZ",
+ "moy": "moy-Latn-ET",
+ "moy-Ethi": "moy-Ethi-ET",
+ "moz": "moz-Latn-TD",
+ "mpa": "mpa-Latn-TZ",
+ "mpb": "mpb-Latn-AU",
+ "mpc": "mpc-Latn-AU",
+ "mpd": "mpd-Latn-BR",
+ "mpe": "mpe-Latn-ET",
+ "mpe-Ethi": "mpe-Ethi-ET",
+ "mpg": "mpg-Latn-TD",
+ "mph": "mph-Latn-AU",
+ "mpi": "mpi-Latn-CM",
+ "mpj": "mpj-Latn-AU",
+ "mpk": "mpk-Latn-TD",
+ "mpl": "mpl-Latn-PG",
+ "mpm": "mpm-Latn-MX",
+ "mpn": "mpn-Latn-PG",
+ "mpo": "mpo-Latn-PG",
+ "mpp": "mpp-Latn-ZZ",
+ "mpq": "mpq-Latn-BR",
+ "mpr": "mpr-Latn-SB",
+ "mps": "mps-Latn-ZZ",
+ "mpt": "mpt-Latn-ZZ",
+ "mpu": "mpu-Latn-BR",
+ "mpv": "mpv-Latn-PG",
+ "mpw": "mpw-Latn-BR",
+ "mpx": "mpx-Latn-ZZ",
+ "mpy": "mpy-Latn-ID",
+ "mpz": "mpz-Thai-TH",
+ "mqa": "mqa-Latn-ID",
+ "mqb": "mqb-Latn-CM",
+ "mqc": "mqc-Latn-ID",
+ "mqe": "mqe-Latn-PG",
+ "mqf": "mqf-Latn-ID",
+ "mqg": "mqg-Latn-ID",
+ "mqh": "mqh-Latn-MX",
+ "mqi": "mqi-Latn-ID",
+ "mqj": "mqj-Latn-ID",
+ "mqk": "mqk-Latn-PH",
+ "mql": "mql-Latn-ZZ",
+ "mqm": "mqm-Latn-PF",
+ "mqn": "mqn-Latn-ID",
+ "mqo": "mqo-Latn-ID",
+ "mqp": "mqp-Latn-ID",
+ "mqq": "mqq-Latn-MY",
+ "mqr": "mqr-Latn-ID",
+ "mqs": "mqs-Latn-ID",
+ "mqu": "mqu-Latn-SS",
+ "mqv": "mqv-Latn-PG",
+ "mqw": "mqw-Latn-PG",
+ "mqx": "mqx-Latn-ID",
+ "mqx-Bugi": "mqx-Bugi-ID",
+ "mqy": "mqy-Latn-ID",
+ "mqz": "mqz-Latn-PG",
+ "mr": "mr-Deva-IN",
+ "mra": "mra-Thai-TH",
+ "mrb": "mrb-Latn-VU",
+ "mrc": "mrc-Latn-US",
+ "mrd": "mrd-Deva-NP",
+ "mrf": "mrf-Latn-ID",
+ "mrg": "mrg-Latn-IN",
+ "mrg-Beng": "mrg-Beng-IN",
+ "mrg-Deva": "mrg-Deva-IN",
+ "mrh": "mrh-Latn-IN",
+ "mrj": "mrj-Cyrl-RU",
+ "mrk": "mrk-Latn-NC",
+ "mrl": "mrl-Latn-FM",
+ "mrm": "mrm-Latn-VU",
+ "mrn": "mrn-Latn-SB",
+ "mro": "mro-Mroo-BD",
+ "mrp": "mrp-Latn-VU",
+ "mrq": "mrq-Latn-PF",
+ "mrr": "mrr-Deva-IN",
+ "mrs": "mrs-Latn-VU",
+ "mrt": "mrt-Latn-NG",
+ "mru": "mru-Latn-CM",
+ "mrv": "mrv-Latn-PF",
+ "mrw": "mrw-Latn-PH",
+ "mrw-Arab": "mrw-Arab-PH",
+ "mrx": "mrx-Latn-ID",
+ "mry": "mry-Latn-PH",
+ "mrz": "mrz-Latn-ID",
+ "ms": "ms-Latn-MY",
+ "ms-CC": "ms-Arab-CC",
+ "msb": "msb-Latn-PH",
+ "msc": "msc-Latn-GN",
+ "mse": "mse-Latn-TD",
+ "msf": "msf-Latn-ID",
+ "msg": "msg-Latn-ID",
+ "msh": "msh-Latn-MG",
+ "msi": "msi-Latn-MY",
+ "msj": "msj-Latn-CD",
+ "msk": "msk-Latn-PH",
+ "msl": "msl-Latn-ID",
+ "msm": "msm-Latn-PH",
+ "msn": "msn-Latn-VU",
+ "mso": "mso-Latn-ID",
+ "msp": "msp-Latn-BR",
+ "msq": "msq-Latn-NC",
+ "mss": "mss-Latn-ID",
+ "msu": "msu-Latn-PG",
+ "msv": "msv-Latn-CM",
+ "msw": "msw-Latn-GW",
+ "msx": "msx-Latn-PG",
+ "msy": "msy-Latn-PG",
+ "msz": "msz-Latn-PG",
+ "mt": "mt-Latn-MT",
+ "mta": "mta-Latn-PH",
+ "mtb": "mtb-Latn-CI",
+ "mtc": "mtc-Latn-ZZ",
+ "mtd": "mtd-Latn-ID",
+ "mte": "mte-Latn-SB",
+ "mtf": "mtf-Latn-ZZ",
+ "mtg": "mtg-Latn-ID",
+ "mth": "mth-Latn-ID",
+ "mti": "mti-Latn-ZZ",
+ "mtj": "mtj-Latn-ID",
+ "mtk": "mtk-Latn-CM",
+ "mtl": "mtl-Latn-NG",
+ "mtm": "mtm-Cyrl-RU",
+ "mtn": "mtn-Latn-NI",
+ "mto": "mto-Latn-MX",
+ "mtp": "mtp-Latn-BO",
+ "mtq": "mtq-Latn-VN",
+ "mtr": "mtr-Deva-IN",
+ "mts": "mts-Latn-PE",
+ "mtt": "mtt-Latn-VU",
+ "mtu": "mtu-Latn-MX",
+ "mtv": "mtv-Latn-PG",
+ "mtw": "mtw-Latn-PH",
+ "mtx": "mtx-Latn-MX",
+ "mty": "mty-Latn-PG",
+ "mua": "mua-Latn-CM",
+ "mub": "mub-Latn-TD",
+ "muc": "muc-Latn-CM",
+ "mud": "mud-Cyrl-RU",
+ "mue": "mue-Latn-EC",
+ "mug": "mug-Latn-CM",
+ "muh": "muh-Latn-SS",
+ "mui": "mui-Latn-ID",
+ "muj": "muj-Latn-TD",
+ "muk": "muk-Tibt-NP",
+ "mum": "mum-Latn-PG",
+ "muo": "muo-Latn-CM",
+ "muq": "muq-Latn-CN",
+ "mur": "mur-Latn-ZZ",
+ "mus": "mus-Latn-US",
+ "mut": "mut-Deva-IN",
+ "muu": "muu-Latn-KE",
+ "muv": "muv-Taml-IN",
+ "mux": "mux-Latn-PG",
+ "muy": "muy-Latn-CM",
+ "muz": "muz-Ethi-ET",
+ "muz-Latn": "muz-Latn-ET",
+ "mva": "mva-Latn-ZZ",
+ "mvd": "mvd-Latn-ID",
+ "mvf": "mvf-Mong-CN",
+ "mvf-Phag": "mvf-Phag-CN",
+ "mvg": "mvg-Latn-MX",
+ "mvh": "mvh-Latn-TD",
+ "mvk": "mvk-Latn-PG",
+ "mvl": "mvl-Latn-AU",
+ "mvn": "mvn-Latn-ZZ",
+ "mvo": "mvo-Latn-SB",
+ "mvp": "mvp-Latn-ID",
+ "mvq": "mvq-Latn-PG",
+ "mvr": "mvr-Latn-ID",
+ "mvs": "mvs-Latn-ID",
+ "mvt": "mvt-Latn-VU",
+ "mvu": "mvu-Latn-TD",
+ "mvv": "mvv-Latn-MY",
+ "mvw": "mvw-Latn-TZ",
+ "mvx": "mvx-Latn-ID",
+ "mvy": "mvy-Arab-PK",
+ "mvz": "mvz-Ethi-ET",
+ "mvz-Arab": "mvz-Arab-ET",
+ "mwa": "mwa-Latn-PG",
+ "mwb": "mwb-Latn-PG",
+ "mwc": "mwc-Latn-PG",
+ "mwe": "mwe-Latn-TZ",
+ "mwf": "mwf-Latn-AU",
+ "mwg": "mwg-Latn-PG",
+ "mwh": "mwh-Latn-PG",
+ "mwi": "mwi-Latn-VU",
+ "mwk": "mwk-Latn-ML",
+ "mwl": "mwl-Latn-PT",
+ "mwm": "mwm-Latn-TD",
+ "mwn": "mwn-Latn-ZM",
+ "mwo": "mwo-Latn-VU",
+ "mwp": "mwp-Latn-AU",
+ "mwq": "mwq-Latn-MM",
+ "mwr": "mwr-Deva-IN",
+ "mws": "mws-Latn-KE",
+ "mwt": "mwt-Mymr-MM",
+ "mwt-Thai": "mwt-Thai-TH",
+ "mwu": "mwu-Latn-SS",
+ "mwv": "mwv-Latn-ID",
+ "mww": "mww-Hmnp-US",
+ "mwz": "mwz-Latn-CD",
+ "mxa": "mxa-Latn-MX",
+ "mxb": "mxb-Latn-MX",
+ "mxc": "mxc-Latn-ZW",
+ "mxd": "mxd-Latn-ID",
+ "mxe": "mxe-Latn-VU",
+ "mxf": "mxf-Latn-CM",
+ "mxg": "mxg-Latn-AO",
+ "mxh": "mxh-Latn-CD",
+ "mxi": "mxi-Latn-ES",
+ "mxj": "mxj-Latn-IN",
+ "mxk": "mxk-Latn-PG",
+ "mxl": "mxl-Latn-BJ",
+ "mxm": "mxm-Latn-ZZ",
+ "mxn": "mxn-Latn-ID",
+ "mxo": "mxo-Latn-ZM",
+ "mxp": "mxp-Latn-MX",
+ "mxq": "mxq-Latn-MX",
+ "mxr": "mxr-Latn-MY",
+ "mxs": "mxs-Latn-MX",
+ "mxt": "mxt-Latn-MX",
+ "mxu": "mxu-Latn-CM",
+ "mxv": "mxv-Latn-MX",
+ "mxw": "mxw-Latn-PG",
+ "mxx": "mxx-Latn-CI",
+ "mxy": "mxy-Latn-MX",
+ "mxz": "mxz-Latn-ID",
+ "my": "my-Mymr-MM",
+ "myb": "myb-Latn-TD",
+ "myc": "myc-Latn-CD",
+ "mye": "mye-Latn-GA",
+ "myf": "myf-Latn-ET",
+ "myg": "myg-Latn-CM",
+ "myh": "myh-Latn-US",
+ "myj": "myj-Latn-SS",
+ "myk": "myk-Latn-ZZ",
+ "myl": "myl-Latn-ID",
+ "mym": "mym-Ethi-ZZ",
+ "myp": "myp-Latn-BR",
+ "myr": "myr-Latn-PE",
+ "myu": "myu-Latn-BR",
+ "myv": "myv-Cyrl-RU",
+ "myw": "myw-Latn-ZZ",
+ "myx": "myx-Latn-UG",
+ "myy": "myy-Latn-CO",
+ "myz": "myz-Mand-IR",
+ "mza": "mza-Latn-MX",
+ "mzd": "mzd-Latn-CM",
+ "mze": "mze-Latn-PG",
+ "mzh": "mzh-Latn-AR",
+ "mzi": "mzi-Latn-MX",
+ "mzj": "mzj-Latn-LR",
+ "mzk": "mzk-Latn-ZZ",
+ "mzl": "mzl-Latn-MX",
+ "mzm": "mzm-Latn-ZZ",
+ "mzn": "mzn-Arab-IR",
+ "mzo": "mzo-Latn-BR",
+ "mzp": "mzp-Latn-ZZ",
+ "mzq": "mzq-Latn-ID",
+ "mzr": "mzr-Latn-BR",
+ "mzt": "mzt-Latn-MY",
+ "mzu": "mzu-Latn-PG",
+ "mzv": "mzv-Latn-CF",
+ "mzw": "mzw-Latn-ZZ",
+ "mzx": "mzx-Latn-GY",
+ "mzz": "mzz-Latn-ZZ",
+ "na": "na-Latn-NR",
+ "naa": "naa-Latn-ID",
+ "nab": "nab-Latn-BR",
+ "nac": "nac-Latn-ZZ",
+ "nae": "nae-Latn-ID",
+ "naf": "naf-Latn-ZZ",
+ "nag": "nag-Latn-IN",
+ "naj": "naj-Latn-GN",
+ "nak": "nak-Latn-ZZ",
+ "nal": "nal-Latn-PG",
+ "nam": "nam-Latn-AU",
+ "nan": "nan-Hans-CN",
+ "nao": "nao-Deva-NP",
+ "nap": "nap-Latn-IT",
+ "naq": "naq-Latn-NA",
+ "nar": "nar-Latn-NG",
+ "nas": "nas-Latn-ZZ",
+ "nat": "nat-Latn-NG",
+ "naw": "naw-Latn-GH",
+ "nax": "nax-Latn-PG",
+ "nay": "nay-Latn-AU",
+ "naz": "naz-Latn-MX",
+ "nb": "nb-Latn-NO",
+ "nba": "nba-Latn-AO",
+ "nbb": "nbb-Latn-NG",
+ "nbc": "nbc-Latn-IN",
+ "nbd": "nbd-Latn-CD",
+ "nbe": "nbe-Latn-IN",
+ "nbh": "nbh-Latn-NG",
+ "nbi": "nbi-Latn-IN",
+ "nbj": "nbj-Latn-AU",
+ "nbk": "nbk-Latn-PG",
+ "nbm": "nbm-Latn-CF",
+ "nbn": "nbn-Latn-ID",
+ "nbo": "nbo-Latn-NG",
+ "nbp": "nbp-Latn-NG",
+ "nbq": "nbq-Latn-ID",
+ "nbr": "nbr-Latn-NG",
+ "nbt": "nbt-Latn-IN",
+ "nbt-Deva": "nbt-Deva-IN",
+ "nbu": "nbu-Latn-IN",
+ "nbv": "nbv-Latn-CM",
+ "nbw": "nbw-Latn-CD",
+ "nby": "nby-Latn-PG",
+ "nca": "nca-Latn-ZZ",
+ "ncb": "ncb-Latn-IN",
+ "ncb-Deva": "ncb-Deva-IN",
+ "ncc": "ncc-Latn-PG",
+ "ncd": "ncd-Deva-NP",
+ "nce": "nce-Latn-ZZ",
+ "ncf": "ncf-Latn-ZZ",
+ "ncg": "ncg-Latn-CA",
+ "nch": "nch-Latn-MX",
+ "nci": "nci-Latn-MX",
+ "ncj": "ncj-Latn-MX",
+ "nck": "nck-Latn-AU",
+ "ncl": "ncl-Latn-MX",
+ "ncm": "ncm-Latn-PG",
+ "ncn": "ncn-Latn-PG",
+ "nco": "nco-Latn-ZZ",
+ "ncq": "ncq-Laoo-LA",
+ "ncq-Thai": "ncq-Thai-LA",
+ "ncr": "ncr-Latn-CM",
+ "nct": "nct-Latn-IN",
+ "nct-Beng": "nct-Beng-IN",
+ "ncu": "ncu-Latn-ZZ",
+ "ncx": "ncx-Latn-MX",
+ "ncz": "ncz-Latn-US",
+ "nd": "nd-Latn-ZW",
+ "nda": "nda-Latn-CG",
+ "ndb": "ndb-Latn-CM",
+ "ndc": "ndc-Latn-MZ",
+ "ndd": "ndd-Latn-NG",
+ "ndf": "ndf-Cyrl-RU",
+ "ndg": "ndg-Latn-TZ",
+ "ndh": "ndh-Latn-TZ",
+ "ndi": "ndi-Latn-NG",
+ "ndj": "ndj-Latn-TZ",
+ "ndk": "ndk-Latn-CD",
+ "ndl": "ndl-Latn-CD",
+ "ndm": "ndm-Latn-TD",
+ "ndn": "ndn-Latn-CG",
+ "ndp": "ndp-Latn-UG",
+ "ndq": "ndq-Latn-AO",
+ "ndr": "ndr-Latn-NG",
+ "nds": "nds-Latn-DE",
+ "ndt": "ndt-Latn-CD",
+ "ndu": "ndu-Latn-CM",
+ "ndv": "ndv-Latn-SN",
+ "ndw": "ndw-Latn-CD",
+ "ndx": "ndx-Latn-ID",
+ "ndy": "ndy-Latn-CF",
+ "ndy-TD": "ndy-Latn-TD",
+ "ndz": "ndz-Latn-SS",
+ "ne": "ne-Deva-NP",
+ "nea": "nea-Latn-ID",
+ "neb": "neb-Latn-ZZ",
+ "nec": "nec-Latn-ID",
+ "ned": "ned-Latn-NG",
+ "nee": "nee-Latn-NC",
+ "neg": "neg-Cyrl-RU",
+ "neh": "neh-Tibt-BT",
+ "nei": "nei-Xsux-TR",
+ "nej": "nej-Latn-PG",
+ "nek": "nek-Latn-NC",
+ "nem": "nem-Latn-NC",
+ "nen": "nen-Latn-NC",
+ "neo": "neo-Latn-VN",
+ "neq": "neq-Latn-MX",
+ "ner": "ner-Latn-ID",
+ "net": "net-Latn-PG",
+ "neu": "neu-Latn-001",
+ "new": "new-Deva-NP",
+ "nex": "nex-Latn-ZZ",
+ "ney": "ney-Latn-CI",
+ "nez": "nez-Latn-US",
+ "nfa": "nfa-Latn-ID",
+ "nfd": "nfd-Latn-NG",
+ "nfl": "nfl-Latn-SB",
+ "nfr": "nfr-Latn-ZZ",
+ "nfu": "nfu-Latn-CM",
+ "ng": "ng-Latn-NA",
+ "nga": "nga-Latn-ZZ",
+ "ngb": "ngb-Latn-ZZ",
+ "ngc": "ngc-Latn-CD",
+ "ngd": "ngd-Latn-CF",
+ "nge": "nge-Latn-CM",
+ "ngg": "ngg-Latn-CF",
+ "ngh": "ngh-Latn-ZA",
+ "ngi": "ngi-Latn-NG",
+ "ngj": "ngj-Latn-CM",
+ "ngk": "ngk-Latn-AU",
+ "ngl": "ngl-Latn-MZ",
+ "ngm": "ngm-Latn-FM",
+ "ngn": "ngn-Latn-CM",
+ "ngp": "ngp-Latn-TZ",
+ "ngq": "ngq-Latn-TZ",
+ "ngr": "ngr-Latn-SB",
+ "ngs": "ngs-Latn-NG",
+ "ngt": "ngt-Laoo-LA",
+ "ngu": "ngu-Latn-MX",
+ "ngv": "ngv-Latn-CM",
+ "ngw": "ngw-Latn-NG",
+ "ngx": "ngx-Latn-NG",
+ "ngy": "ngy-Latn-CM",
+ "ngz": "ngz-Latn-CG",
+ "nha": "nha-Latn-AU",
+ "nhb": "nhb-Latn-ZZ",
+ "nhc": "nhc-Latn-MX",
+ "nhd": "nhd-Latn-PY",
+ "nhe": "nhe-Latn-MX",
+ "nhf": "nhf-Latn-AU",
+ "nhg": "nhg-Latn-MX",
+ "nhi": "nhi-Latn-MX",
+ "nhk": "nhk-Latn-MX",
+ "nhm": "nhm-Latn-MX",
+ "nhn": "nhn-Latn-MX",
+ "nho": "nho-Latn-PG",
+ "nhp": "nhp-Latn-MX",
+ "nhq": "nhq-Latn-MX",
+ "nhr": "nhr-Latn-BW",
+ "nht": "nht-Latn-MX",
+ "nhu": "nhu-Latn-CM",
+ "nhv": "nhv-Latn-MX",
+ "nhw": "nhw-Latn-MX",
+ "nhx": "nhx-Latn-MX",
+ "nhy": "nhy-Latn-MX",
+ "nhz": "nhz-Latn-MX",
+ "nia": "nia-Latn-ID",
+ "nib": "nib-Latn-PG",
+ "nid": "nid-Latn-AU",
+ "nie": "nie-Latn-TD",
+ "nif": "nif-Latn-ZZ",
+ "nig": "nig-Latn-AU",
+ "nih": "nih-Latn-TZ",
+ "nii": "nii-Latn-ZZ",
+ "nij": "nij-Latn-ID",
+ "nil": "nil-Latn-ID",
+ "nim": "nim-Latn-TZ",
+ "nin": "nin-Latn-ZZ",
+ "nio": "nio-Cyrl-RU",
+ "niq": "niq-Latn-KE",
+ "nir": "nir-Latn-ID",
+ "nis": "nis-Latn-PG",
+ "nit": "nit-Telu-IN",
+ "niu": "niu-Latn-NU",
+ "niv": "niv-Cyrl-RU",
+ "niv-Latn": "niv-Latn-RU",
+ "niw": "niw-Latn-PG",
+ "nix": "nix-Latn-CD",
+ "niy": "niy-Latn-ZZ",
+ "niz": "niz-Latn-ZZ",
+ "nja": "nja-Latn-NG",
+ "njb": "njb-Latn-IN",
+ "njd": "njd-Latn-TZ",
+ "njh": "njh-Latn-IN",
+ "nji": "nji-Latn-AU",
+ "njj": "njj-Latn-CM",
+ "njl": "njl-Latn-SS",
+ "njm": "njm-Latn-IN",
+ "njn": "njn-Latn-IN",
+ "njo": "njo-Latn-IN",
+ "njr": "njr-Latn-NG",
+ "njs": "njs-Latn-ID",
+ "njt": "njt-Latn-SR",
+ "nju": "nju-Latn-AU",
+ "njx": "njx-Latn-CG",
+ "njy": "njy-Latn-CM",
+ "njz": "njz-Latn-IN",
+ "njz-Beng": "njz-Beng-IN",
+ "nka": "nka-Latn-ZM",
+ "nkb": "nkb-Latn-IN",
+ "nkc": "nkc-Latn-CM",
+ "nkd": "nkd-Latn-IN",
+ "nke": "nke-Latn-SB",
+ "nkf": "nkf-Latn-IN",
+ "nkg": "nkg-Latn-ZZ",
+ "nkh": "nkh-Latn-IN",
+ "nki": "nki-Latn-IN",
+ "nki-Beng": "nki-Beng-IN",
+ "nkj": "nkj-Latn-ID",
+ "nkk": "nkk-Latn-VU",
+ "nkm": "nkm-Latn-PG",
+ "nkn": "nkn-Latn-AO",
+ "nko": "nko-Latn-ZZ",
+ "nkq": "nkq-Latn-GH",
+ "nkr": "nkr-Latn-FM",
+ "nks": "nks-Latn-ID",
+ "nkt": "nkt-Latn-TZ",
+ "nku": "nku-Latn-CI",
+ "nkv": "nkv-Latn-MW",
+ "nkw": "nkw-Latn-CD",
+ "nkx": "nkx-Latn-NG",
+ "nkz": "nkz-Latn-NG",
+ "nl": "nl-Latn-NL",
+ "nla": "nla-Latn-CM",
+ "nlc": "nlc-Latn-ID",
+ "nle": "nle-Latn-KE",
+ "nlg": "nlg-Latn-SB",
+ "nli": "nli-Arab-AF",
+ "nlj": "nlj-Latn-CD",
+ "nlk": "nlk-Latn-ID",
+ "nlm": "nlm-Arab-PK",
+ "nlo": "nlo-Latn-CD",
+ "nlq": "nlq-Latn-MM",
+ "nlu": "nlu-Latn-GH",
+ "nlv": "nlv-Latn-MX",
+ "nlw": "nlw-Latn-AU",
+ "nlx": "nlx-Deva-IN",
+ "nly": "nly-Latn-AU",
+ "nlz": "nlz-Latn-SB",
+ "nma": "nma-Latn-IN",
+ "nmb": "nmb-Latn-VU",
+ "nmc": "nmc-Latn-TD",
+ "nmd": "nmd-Latn-GA",
+ "nme": "nme-Latn-IN",
+ "nmf": "nmf-Latn-IN",
+ "nmg": "nmg-Latn-CM",
+ "nmh": "nmh-Latn-IN",
+ "nmi": "nmi-Latn-NG",
+ "nmj": "nmj-Latn-CF",
+ "nmk": "nmk-Latn-VU",
+ "nml": "nml-Latn-CM",
+ "nmm": "nmm-Deva-NP",
+ "nmm-Tibt": "nmm-Tibt-NP",
+ "nmn": "nmn-Latn-BW",
+ "nmo": "nmo-Latn-IN",
+ "nmo-Beng": "nmo-Beng-IN",
+ "nmp": "nmp-Latn-AU",
+ "nmq": "nmq-Latn-ZW",
+ "nmr": "nmr-Latn-CM",
+ "nms": "nms-Latn-VU",
+ "nmt": "nmt-Latn-FM",
+ "nmu": "nmu-Latn-US",
+ "nmv": "nmv-Latn-AU",
+ "nmw": "nmw-Latn-PG",
+ "nmx": "nmx-Latn-PG",
+ "nmz": "nmz-Latn-ZZ",
+ "nn": "nn-Latn-NO",
+ "nna": "nna-Latn-AU",
+ "nnb": "nnb-Latn-CD",
+ "nnc": "nnc-Latn-TD",
+ "nnd": "nnd-Latn-VU",
+ "nne": "nne-Latn-AO",
+ "nnf": "nnf-Latn-ZZ",
+ "nng": "nng-Latn-IN",
+ "nng-Beng": "nng-Beng-IN",
+ "nnh": "nnh-Latn-CM",
+ "nni": "nni-Latn-ID",
+ "nnj": "nnj-Latn-ET",
+ "nnk": "nnk-Latn-ZZ",
+ "nnl": "nnl-Latn-IN",
+ "nnm": "nnm-Latn-ZZ",
+ "nnn": "nnn-Latn-TD",
+ "nnp": "nnp-Wcho-IN",
+ "nnq": "nnq-Latn-TZ",
+ "nnr": "nnr-Latn-AU",
+ "nnt": "nnt-Latn-US",
+ "nnu": "nnu-Latn-GH",
+ "nnv": "nnv-Latn-AU",
+ "nnw": "nnw-Latn-BF",
+ "nny": "nny-Latn-AU",
+ "nnz": "nnz-Latn-CM",
+ "no": "no-Latn-NO",
+ "noa": "noa-Latn-CO",
+ "noc": "noc-Latn-PG",
+ "nod": "nod-Lana-TH",
+ "noe": "noe-Deva-IN",
+ "nof": "nof-Latn-PG",
+ "nog": "nog-Cyrl-RU",
+ "noh": "noh-Latn-PG",
+ "noi": "noi-Deva-IN",
+ "noj": "noj-Latn-CO",
+ "nok": "nok-Latn-US",
+ "nom": "nom-Latn-PE",
+ "non": "non-Runr-SE",
+ "nop": "nop-Latn-ZZ",
+ "noq": "noq-Latn-CD",
+ "nos": "nos-Yiii-CN",
+ "not": "not-Latn-PE",
+ "nou": "nou-Latn-ZZ",
+ "nov": "nov-Latn-001",
+ "now": "now-Latn-TZ",
+ "noy": "noy-Latn-TD",
+ "npb": "npb-Tibt-BT",
+ "npg": "npg-Latn-MM",
+ "nph": "nph-Latn-IN",
+ "npl": "npl-Latn-MX",
+ "npn": "npn-Latn-PG",
+ "npo": "npo-Latn-IN",
+ "nps": "nps-Latn-ID",
+ "npu": "npu-Latn-IN",
+ "npx": "npx-Latn-SB",
+ "npy": "npy-Latn-ID",
+ "nqg": "nqg-Latn-BJ",
+ "nqk": "nqk-Latn-BJ",
+ "nql": "nql-Latn-AO",
+ "nqm": "nqm-Latn-ID",
+ "nqn": "nqn-Latn-PG",
+ "nqo": "nqo-Nkoo-GN",
+ "nqq": "nqq-Latn-MM",
+ "nqt": "nqt-Latn-NG",
+ "nqy": "nqy-Latn-MM",
+ "nr": "nr-Latn-ZA",
+ "nra": "nra-Latn-GA",
+ "nrb": "nrb-Latn-ZZ",
+ "nre": "nre-Latn-IN",
+ "nrf": "nrf-Latn-JE",
+ "nrg": "nrg-Latn-VU",
+ "nri": "nri-Latn-IN",
+ "nrk": "nrk-Latn-AU",
+ "nrl": "nrl-Latn-AU",
+ "nrm": "nrm-Latn-MY",
+ "nrp": "nrp-Latn-IT",
+ "nru": "nru-Latn-CN",
+ "nru-Hans": "nru-Hans-CN",
+ "nru-Hant": "nru-Hant-CN",
+ "nrx": "nrx-Latn-AU",
+ "nrz": "nrz-Latn-PG",
+ "nsa": "nsa-Latn-IN",
+ "nsb": "nsb-Latn-ZA",
+ "nsc": "nsc-Latn-NG",
+ "nsd": "nsd-Yiii-CN",
+ "nse": "nse-Latn-ZM",
+ "nsf": "nsf-Yiii-CN",
+ "nsg": "nsg-Latn-TZ",
+ "nsh": "nsh-Latn-CM",
+ "nsk": "nsk-Cans-CA",
+ "nsm": "nsm-Latn-IN",
+ "nsn": "nsn-Latn-ZZ",
+ "nso": "nso-Latn-ZA",
+ "nsq": "nsq-Latn-US",
+ "nss": "nss-Latn-ZZ",
+ "nst": "nst-Tnsa-IN",
+ "nsu": "nsu-Latn-MX",
+ "nsv": "nsv-Yiii-CN",
+ "nsw": "nsw-Latn-VU",
+ "nsx": "nsx-Latn-AO",
+ "nsy": "nsy-Latn-ID",
+ "nsz": "nsz-Latn-US",
+ "ntd": "ntd-Latn-MY",
+ "nte": "nte-Latn-MZ",
+ "ntg": "ntg-Latn-AU",
+ "nti": "nti-Latn-BF",
+ "ntj": "ntj-Latn-AU",
+ "ntk": "ntk-Latn-TZ",
+ "ntm": "ntm-Latn-ZZ",
+ "nto": "nto-Latn-CD",
+ "ntp": "ntp-Latn-MX",
+ "ntr": "ntr-Latn-ZZ",
+ "ntu": "ntu-Latn-SB",
+ "ntx": "ntx-Latn-MM",
+ "nty": "nty-Yiii-VN",
+ "ntz": "ntz-Arab-IR",
+ "nua": "nua-Latn-NC",
+ "nuc": "nuc-Latn-BR",
+ "nud": "nud-Latn-PG",
+ "nue": "nue-Latn-CD",
+ "nuf": "nuf-Latn-CN",
+ "nug": "nug-Latn-AU",
+ "nuh": "nuh-Latn-NG",
+ "nui": "nui-Latn-ZZ",
+ "nuj": "nuj-Latn-UG",
+ "nuk": "nuk-Latn-CA",
+ "num": "num-Latn-TO",
+ "nun": "nun-Latn-MM",
+ "nuo": "nuo-Latn-VN",
+ "nup": "nup-Latn-ZZ",
+ "nuq": "nuq-Latn-PG",
+ "nur": "nur-Latn-PG",
+ "nus": "nus-Latn-SS",
+ "nut": "nut-Latn-VN",
+ "nuu": "nuu-Latn-CD",
+ "nuv": "nuv-Latn-ZZ",
+ "nuw": "nuw-Latn-FM",
+ "nux": "nux-Latn-ZZ",
+ "nuy": "nuy-Latn-AU",
+ "nuz": "nuz-Latn-MX",
+ "nv": "nv-Latn-US",
+ "nvh": "nvh-Latn-VU",
+ "nvm": "nvm-Latn-PG",
+ "nvo": "nvo-Latn-CM",
+ "nwb": "nwb-Latn-ZZ",
+ "nwc": "nwc-Newa-NP",
+ "nwc-Brah": "nwc-Brah-NP",
+ "nwc-Deva": "nwc-Deva-NP",
+ "nwc-Sidd": "nwc-Sidd-NP",
+ "nwe": "nwe-Latn-CM",
+ "nwg": "nwg-Latn-AU",
+ "nwi": "nwi-Latn-VU",
+ "nwm": "nwm-Latn-SS",
+ "nwo": "nwo-Latn-AU",
+ "nwr": "nwr-Latn-PG",
+ "nww": "nww-Latn-TZ",
+ "nwx": "nwx-Deva-NP",
+ "nxa": "nxa-Latn-TL",
+ "nxd": "nxd-Latn-CD",
+ "nxe": "nxe-Latn-ID",
+ "nxg": "nxg-Latn-ID",
+ "nxi": "nxi-Latn-TZ",
+ "nxl": "nxl-Latn-ID",
+ "nxn": "nxn-Latn-AU",
+ "nxo": "nxo-Latn-GA",
+ "nxq": "nxq-Latn-CN",
+ "nxr": "nxr-Latn-ZZ",
+ "nxx": "nxx-Latn-ID",
+ "ny": "ny-Latn-MW",
+ "nyb": "nyb-Latn-GH",
+ "nyc": "nyc-Latn-CD",
+ "nyd": "nyd-Latn-KE",
+ "nye": "nye-Latn-AO",
+ "nyf": "nyf-Latn-KE",
+ "nyg": "nyg-Latn-CD",
+ "nyh": "nyh-Latn-AU",
+ "nyi": "nyi-Latn-SD",
+ "nyj": "nyj-Latn-CD",
+ "nyk": "nyk-Latn-AO",
+ "nyl": "nyl-Thai-TH",
+ "nym": "nym-Latn-TZ",
+ "nyn": "nyn-Latn-UG",
+ "nyo": "nyo-Latn-UG",
+ "nyp": "nyp-Latn-UG",
+ "nyq": "nyq-Arab-IR",
+ "nyr": "nyr-Latn-MW",
+ "nys": "nys-Latn-AU",
+ "nyt": "nyt-Latn-AU",
+ "nyu": "nyu-Latn-MZ",
+ "nyv": "nyv-Latn-AU",
+ "nyx": "nyx-Latn-AU",
+ "nyy": "nyy-Latn-TZ",
+ "nza": "nza-Latn-CM",
+ "nzb": "nzb-Latn-GA",
+ "nzd": "nzd-Latn-CD",
+ "nzi": "nzi-Latn-GH",
+ "nzk": "nzk-Latn-CF",
+ "nzm": "nzm-Latn-IN",
+ "nzu": "nzu-Latn-CG",
+ "nzy": "nzy-Latn-TD",
+ "nzz": "nzz-Latn-ML",
+ "oaa": "oaa-Cyrl-RU",
+ "oac": "oac-Cyrl-RU",
+ "oar": "oar-Syrc-SY",
+ "oav": "oav-Geor-GE",
+ "obi": "obi-Latn-US",
+ "obk": "obk-Latn-PH",
+ "obl": "obl-Latn-CM",
+ "obm": "obm-Phnx-JO",
+ "obo": "obo-Latn-PH",
+ "obr": "obr-Mymr-MM",
+ "obt": "obt-Latn-FR",
+ "obu": "obu-Latn-NG",
+ "oc": "oc-Latn-FR",
+ "oca": "oca-Latn-PE",
+ "oco": "oco-Latn-GB",
+ "ocu": "ocu-Latn-MX",
+ "oda": "oda-Latn-NG",
+ "odk": "odk-Arab-PK",
+ "odt": "odt-Latn-NL",
+ "odu": "odu-Latn-NG",
+ "ofu": "ofu-Latn-NG",
+ "ogb": "ogb-Latn-NG",
+ "ogc": "ogc-Latn-ZZ",
+ "ogg": "ogg-Latn-NG",
+ "ogo": "ogo-Latn-NG",
+ "ogu": "ogu-Latn-NG",
+ "oht": "oht-Xsux-TR",
+ "oia": "oia-Latn-ID",
+ "oie": "oie-Latn-SS",
+ "oin": "oin-Latn-PG",
+ "oj": "oj-Cans-CA",
+ "ojb": "ojb-Latn-CA",
+ "ojb-Cans": "ojb-Cans-CA",
+ "ojc": "ojc-Latn-CA",
+ "ojs": "ojs-Cans-CA",
+ "ojv": "ojv-Latn-SB",
+ "ojw": "ojw-Latn-CA",
+ "ojw-Cans": "ojw-Cans-CA",
+ "oka": "oka-Latn-CA",
+ "okb": "okb-Latn-NG",
+ "okc": "okc-Latn-CD",
+ "okd": "okd-Latn-NG",
+ "oke": "oke-Latn-NG",
+ "okg": "okg-Latn-AU",
+ "oki": "oki-Latn-KE",
+ "okk": "okk-Latn-PG",
+ "okm": "okm-Hang-KR",
+ "oko": "oko-Hani-KR",
+ "okr": "okr-Latn-ZZ",
+ "oks": "oks-Latn-NG",
+ "oku": "oku-Latn-CM",
+ "okv": "okv-Latn-ZZ",
+ "okx": "okx-Latn-NG",
+ "okz": "okz-Khmr-KH",
+ "ola": "ola-Deva-NP",
+ "ola-Tibt": "ola-Tibt-CN",
+ "old": "old-Latn-TZ",
+ "ole": "ole-Tibt-BT",
+ "olk": "olk-Latn-AU",
+ "olm": "olm-Latn-NG",
+ "olo": "olo-Latn-RU",
+ "olr": "olr-Latn-VU",
+ "olt": "olt-Latn-LT",
+ "olu": "olu-Latn-AO",
+ "om": "om-Latn-ET",
+ "oma": "oma-Latn-US",
+ "omb": "omb-Latn-VU",
+ "omc": "omc-Latn-PE",
+ "omg": "omg-Latn-PE",
+ "omi": "omi-Latn-CD",
+ "omk": "omk-Cyrl-RU",
+ "oml": "oml-Latn-CD",
+ "omo": "omo-Latn-PG",
+ "omp": "omp-Mtei-IN",
+ "omr": "omr-Modi-IN",
+ "omt": "omt-Latn-KE",
+ "omu": "omu-Latn-PE",
+ "omw": "omw-Latn-PG",
+ "ona": "ona-Latn-AR",
+ "one": "one-Latn-CA",
+ "ong": "ong-Latn-ZZ",
+ "oni": "oni-Latn-ID",
+ "onj": "onj-Latn-PG",
+ "onk": "onk-Latn-PG",
+ "onn": "onn-Latn-ZZ",
+ "ono": "ono-Latn-CA",
+ "onp": "onp-Latn-IN",
+ "onp-Deva": "onp-Deva-IN",
+ "onr": "onr-Latn-PG",
+ "ons": "ons-Latn-ZZ",
+ "ont": "ont-Latn-PG",
+ "onu": "onu-Latn-VU",
+ "onx": "onx-Latn-ID",
+ "ood": "ood-Latn-US",
+ "oon": "oon-Deva-IN",
+ "oor": "oor-Latn-ZA",
+ "opa": "opa-Latn-NG",
+ "opk": "opk-Latn-ID",
+ "opm": "opm-Latn-ZZ",
+ "opo": "opo-Latn-PG",
+ "opt": "opt-Latn-MX",
+ "opy": "opy-Latn-BR",
+ "or": "or-Orya-IN",
+ "ora": "ora-Latn-SB",
+ "orc": "orc-Latn-KE",
+ "ore": "ore-Latn-PE",
+ "org": "org-Latn-NG",
+ "orn": "orn-Latn-MY",
+ "oro": "oro-Latn-ZZ",
+ "orr": "orr-Latn-NG",
+ "ors": "ors-Latn-MY",
+ "ort": "ort-Telu-IN",
+ "oru": "oru-Arab-ZZ",
+ "orv": "orv-Cyrl-RU",
+ "orw": "orw-Latn-BR",
+ "orx": "orx-Latn-NG",
+ "orz": "orz-Latn-ID",
+ "os": "os-Cyrl-GE",
+ "osa": "osa-Osge-US",
+ "osc": "osc-Ital-IT",
+ "osc-Latn": "osc-Latn-IT",
+ "osi": "osi-Java-ID",
+ "oso": "oso-Latn-NG",
+ "osp": "osp-Latn-ES",
+ "ost": "ost-Latn-CM",
+ "osu": "osu-Latn-PG",
+ "osx": "osx-Latn-DE",
+ "ota": "ota-Arab-ZZ",
+ "otb": "otb-Tibt-CN",
+ "otd": "otd-Latn-ID",
+ "ote": "ote-Latn-MX",
+ "oti": "oti-Latn-BR",
+ "otk": "otk-Orkh-MN",
+ "otl": "otl-Latn-MX",
+ "otm": "otm-Latn-MX",
+ "otn": "otn-Latn-MX",
+ "otq": "otq-Latn-MX",
+ "otr": "otr-Latn-SD",
+ "ots": "ots-Latn-MX",
+ "ott": "ott-Latn-MX",
+ "otu": "otu-Latn-BR",
+ "otw": "otw-Latn-CA",
+ "otx": "otx-Latn-MX",
+ "oty": "oty-Gran-IN",
+ "otz": "otz-Latn-MX",
+ "oub": "oub-Latn-LR",
+ "oue": "oue-Latn-PG",
+ "oui": "oui-Ougr-143",
+ "oum": "oum-Latn-PG",
+ "ovd": "ovd-Latn-SE",
+ "owi": "owi-Latn-PG",
+ "owl": "owl-Latn-GB",
+ "oyd": "oyd-Latn-ET",
+ "oym": "oym-Latn-BR",
+ "oyy": "oyy-Latn-PG",
+ "ozm": "ozm-Latn-ZZ",
+ "pa": "pa-Guru-IN",
+ "pa-Arab": "pa-Arab-PK",
+ "pa-PK": "pa-Arab-PK",
+ "pab": "pab-Latn-BR",
+ "pac": "pac-Latn-VN",
+ "pad": "pad-Latn-BR",
+ "pae": "pae-Latn-CD",
+ "paf": "paf-Latn-BR",
+ "pag": "pag-Latn-PH",
+ "pah": "pah-Latn-BR",
+ "pai": "pai-Latn-NG",
+ "pak": "pak-Latn-BR",
+ "pal": "pal-Phli-IR",
+ "pal-Phlp": "pal-Phlp-CN",
+ "pam": "pam-Latn-PH",
+ "pao": "pao-Latn-US",
+ "pap": "pap-Latn-CW",
+ "paq": "paq-Cyrl-TJ",
+ "par": "par-Latn-US",
+ "pas": "pas-Latn-ID",
+ "pau": "pau-Latn-PW",
+ "pav": "pav-Latn-BR",
+ "paw": "paw-Latn-US",
+ "pax": "pax-Latn-BR",
+ "pay": "pay-Latn-HN",
+ "paz": "paz-Latn-BR",
+ "pbb": "pbb-Latn-CO",
+ "pbc": "pbc-Latn-GY",
+ "pbe": "pbe-Latn-MX",
+ "pbf": "pbf-Latn-MX",
+ "pbg": "pbg-Latn-VE",
+ "pbh": "pbh-Latn-VE",
+ "pbi": "pbi-Latn-ZZ",
+ "pbl": "pbl-Latn-NG",
+ "pbm": "pbm-Latn-MX",
+ "pbn": "pbn-Latn-NG",
+ "pbo": "pbo-Latn-GW",
+ "pbp": "pbp-Latn-GN",
+ "pbr": "pbr-Latn-TZ",
+ "pbs": "pbs-Latn-MX",
+ "pbt": "pbt-Arab-AF",
+ "pbv": "pbv-Latn-IN",
+ "pby": "pby-Latn-PG",
+ "pca": "pca-Latn-MX",
+ "pcb": "pcb-Khmr-KH",
+ "pcc": "pcc-Latn-CN",
+ "pcc-Hani": "pcc-Hani-CN",
+ "pcd": "pcd-Latn-FR",
+ "pce": "pce-Mymr-MM",
+ "pce-Thai": "pce-Thai-TH",
+ "pcf": "pcf-Mlym-IN",
+ "pcg": "pcg-Mlym-IN",
+ "pcg-Knda": "pcg-Knda-IN",
+ "pcg-Taml": "pcg-Taml-IN",
+ "pch": "pch-Deva-IN",
+ "pci": "pci-Deva-IN",
+ "pci-Orya": "pci-Orya-IN",
+ "pcj": "pcj-Telu-IN",
+ "pck": "pck-Latn-IN",
+ "pcm": "pcm-Latn-NG",
+ "pcn": "pcn-Latn-NG",
+ "pcp": "pcp-Latn-BO",
+ "pcw": "pcw-Latn-NG",
+ "pda": "pda-Latn-PG",
+ "pdc": "pdc-Latn-US",
+ "pdn": "pdn-Latn-ID",
+ "pdo": "pdo-Latn-ID",
+ "pdt": "pdt-Latn-CA",
+ "pdu": "pdu-Latn-MM",
+ "pdu-Mymr": "pdu-Mymr-MM",
+ "pea": "pea-Latn-ID",
+ "peb": "peb-Latn-US",
+ "ped": "ped-Latn-ZZ",
+ "pee": "pee-Latn-ID",
+ "peg": "peg-Orya-IN",
+ "pei": "pei-Latn-MX",
+ "pek": "pek-Latn-PG",
+ "pel": "pel-Latn-ID",
+ "pem": "pem-Latn-CD",
+ "peo": "peo-Xpeo-IR",
+ "pep": "pep-Latn-PG",
+ "peq": "peq-Latn-US",
+ "pev": "pev-Latn-VE",
+ "pex": "pex-Latn-ZZ",
+ "pey": "pey-Latn-ID",
+ "pez": "pez-Latn-MY",
+ "pfa": "pfa-Latn-FM",
+ "pfe": "pfe-Latn-CM",
+ "pfl": "pfl-Latn-DE",
+ "pga": "pga-Latn-SS",
+ "pgd": "pgd-Khar-PK",
+ "pgg": "pgg-Deva-IN",
+ "pgi": "pgi-Latn-PG",
+ "pgk": "pgk-Latn-VU",
+ "pgl": "pgl-Ogam-IE",
+ "pgn": "pgn-Ital-IT",
+ "pgs": "pgs-Latn-NG",
+ "pgu": "pgu-Latn-ID",
+ "phd": "phd-Deva-IN",
+ "phg": "phg-Latn-VN",
+ "phh": "phh-Latn-VN",
+ "phk": "phk-Mymr-IN",
+ "phl": "phl-Arab-ZZ",
+ "phm": "phm-Latn-MZ",
+ "phn": "phn-Phnx-LB",
+ "pho": "pho-Laoo-LA",
+ "phr": "phr-Arab-PK",
+ "pht": "pht-Thai-TH",
+ "phv": "phv-Arab-AF",
+ "phw": "phw-Deva-NP",
+ "pi": "pi-Sinh-IN",
+ "pi-Brah": "pi-Brah-IN",
+ "pi-Deva": "pi-Deva-IN",
+ "pi-Khar": "pi-Khar-IN",
+ "pi-Khmr": "pi-Khmr-IN",
+ "pi-Mymr": "pi-Mymr-IN",
+ "pi-Thai": "pi-Thai-IN",
+ "pia": "pia-Latn-MX",
+ "pib": "pib-Latn-PE",
+ "pic": "pic-Latn-GA",
+ "pid": "pid-Latn-VE",
+ "pif": "pif-Latn-FM",
+ "pig": "pig-Latn-PE",
+ "pih": "pih-Latn-NF",
+ "pij": "pij-Latn-CO",
+ "pil": "pil-Latn-ZZ",
+ "pim": "pim-Latn-US",
+ "pin": "pin-Latn-PG",
+ "pio": "pio-Latn-CO",
+ "pip": "pip-Latn-ZZ",
+ "pir": "pir-Latn-BR",
+ "pis": "pis-Latn-SB",
+ "pit": "pit-Latn-AU",
+ "piu": "piu-Latn-AU",
+ "piv": "piv-Latn-SB",
+ "piw": "piw-Latn-TZ",
+ "pix": "pix-Latn-PG",
+ "piy": "piy-Latn-NG",
+ "piz": "piz-Latn-NC",
+ "pjt": "pjt-Latn-AU",
+ "pka": "pka-Brah-IN",
+ "pkb": "pkb-Latn-KE",
+ "pkg": "pkg-Latn-PG",
+ "pkh": "pkh-Latn-BD",
+ "pkh-Deva": "pkh-Deva-BD",
+ "pkn": "pkn-Latn-AU",
+ "pko": "pko-Latn-KE",
+ "pkp": "pkp-Latn-CK",
+ "pkr": "pkr-Mlym-IN",
+ "pku": "pku-Latn-ID",
+ "pl": "pl-Latn-PL",
+ "pla": "pla-Latn-ZZ",
+ "plb": "plb-Latn-VU",
+ "plc": "plc-Latn-PH",
+ "pld": "pld-Latn-GB",
+ "ple": "ple-Latn-ID",
+ "plg": "plg-Latn-AR",
+ "plh": "plh-Latn-ID",
+ "plj": "plj-Latn-NG",
+ "plk": "plk-Arab-PK",
+ "pll": "pll-Mymr-MM",
+ "pln": "pln-Latn-CO",
+ "plo": "plo-Latn-MX",
+ "plr": "plr-Latn-CI",
+ "pls": "pls-Latn-MX",
+ "plu": "plu-Latn-BR",
+ "plv": "plv-Latn-PH",
+ "plw": "plw-Latn-PH",
+ "plz": "plz-Latn-MY",
+ "pma": "pma-Latn-VU",
+ "pmb": "pmb-Latn-CD",
+ "pmd": "pmd-Latn-AU",
+ "pme": "pme-Latn-NC",
+ "pmf": "pmf-Latn-ID",
+ "pmh": "pmh-Brah-IN",
+ "pmi": "pmi-Latn-CN",
+ "pmj": "pmj-Latn-CN",
+ "pml": "pml-Latn-TN",
+ "pmm": "pmm-Latn-CM",
+ "pmn": "pmn-Latn-CM",
+ "pmo": "pmo-Latn-ID",
+ "pmq": "pmq-Latn-MX",
+ "pmr": "pmr-Latn-PG",
+ "pms": "pms-Latn-IT",
+ "pmt": "pmt-Latn-PF",
+ "pmw": "pmw-Latn-US",
+ "pmx": "pmx-Latn-IN",
+ "pmy": "pmy-Latn-ID",
+ "pmz": "pmz-Latn-MX",
+ "pna": "pna-Latn-MY",
+ "pnc": "pnc-Latn-ID",
+ "pnd": "pnd-Latn-AO",
+ "pne": "pne-Latn-MY",
+ "png": "png-Latn-ZZ",
+ "pnh": "pnh-Latn-CK",
+ "pni": "pni-Latn-ID",
+ "pnj": "pnj-Latn-AU",
+ "pnk": "pnk-Latn-BO",
+ "pnl": "pnl-Latn-BF",
+ "pnm": "pnm-Latn-MY",
+ "pnn": "pnn-Latn-ZZ",
+ "pno": "pno-Latn-PE",
+ "pnp": "pnp-Latn-ID",
+ "pnq": "pnq-Latn-BF",
+ "pnr": "pnr-Latn-PG",
+ "pns": "pns-Latn-ID",
+ "pnt": "pnt-Grek-GR",
+ "pnv": "pnv-Latn-AU",
+ "pnw": "pnw-Latn-AU",
+ "pny": "pny-Latn-CM",
+ "pnz": "pnz-Latn-CF",
+ "poc": "poc-Latn-GT",
+ "poe": "poe-Latn-MX",
+ "pof": "pof-Latn-CD",
+ "pog": "pog-Latn-BR",
+ "poh": "poh-Latn-GT",
+ "poi": "poi-Latn-MX",
+ "pok": "pok-Latn-BR",
+ "pom": "pom-Latn-US",
+ "pon": "pon-Latn-FM",
+ "poo": "poo-Latn-US",
+ "pop": "pop-Latn-NC",
+ "poq": "poq-Latn-MX",
+ "pos": "pos-Latn-MX",
+ "pot": "pot-Latn-US",
+ "pov": "pov-Latn-GW",
+ "pow": "pow-Latn-MX",
+ "poy": "poy-Latn-TZ",
+ "ppa": "bfy-Deva-IN",
+ "ppe": "ppe-Latn-PG",
+ "ppi": "ppi-Latn-MX",
+ "ppk": "ppk-Latn-ID",
+ "ppl": "ppl-Latn-SV",
+ "ppm": "ppm-Latn-ID",
+ "ppn": "ppn-Latn-PG",
+ "ppo": "ppo-Latn-ZZ",
+ "ppp": "ppp-Latn-CD",
+ "ppq": "ppq-Latn-PG",
+ "pps": "pps-Latn-MX",
+ "ppt": "ppt-Latn-PG",
+ "pqa": "pqa-Latn-NG",
+ "pqm": "pqm-Latn-CA",
+ "pra": "pra-Khar-PK",
+ "prc": "prc-Arab-AF",
+ "prd": "prd-Arab-IR",
+ "pre": "pre-Latn-ST",
+ "prf": "prf-Latn-PH",
+ "prg": "prg-Latn-001",
+ "prh": "prh-Latn-PH",
+ "pri": "pri-Latn-NC",
+ "prk": "prk-Latn-MM",
+ "prm": "prm-Latn-PG",
+ "pro": "pro-Latn-FR",
+ "prp": "prp-Gujr-IN",
+ "prq": "prq-Latn-PE",
+ "prr": "prr-Latn-BR",
+ "prt": "prt-Thai-TH",
+ "pru": "pru-Latn-ID",
+ "prw": "prw-Latn-PG",
+ "prx": "prx-Arab-IN",
+ "prx-Tibt": "prx-Tibt-IN",
+ "ps": "ps-Arab-AF",
+ "psa": "psa-Latn-ID",
+ "pse": "pse-Latn-ID",
+ "psh": "psh-Arab-AF",
+ "psi": "psi-Arab-AF",
+ "psm": "psm-Latn-BO",
+ "psn": "psn-Latn-ID",
+ "psq": "psq-Latn-PG",
+ "pss": "pss-Latn-ZZ",
+ "pst": "pst-Arab-PK",
+ "psw": "psw-Latn-VU",
+ "pt": "pt-Latn-BR",
+ "pta": "pta-Latn-PY",
+ "pth": "pth-Latn-BR",
+ "pti": "pti-Latn-AU",
+ "ptn": "ptn-Latn-ID",
+ "pto": "pto-Latn-BR",
+ "ptp": "ptp-Latn-ZZ",
+ "ptr": "ptr-Latn-VU",
+ "ptt": "ptt-Latn-ID",
+ "ptu": "ptu-Latn-ID",
+ "ptv": "ptv-Latn-VU",
+ "pua": "pua-Latn-MX",
+ "pub": "pub-Latn-IN",
+ "puc": "puc-Latn-ID",
+ "pud": "pud-Latn-ID",
+ "pue": "pue-Latn-AR",
+ "puf": "puf-Latn-ID",
+ "pug": "pug-Latn-BF",
+ "pui": "pui-Latn-CO",
+ "puj": "puj-Latn-ID",
+ "pum": "pum-Deva-NP",
+ "puo": "puo-Latn-VN",
+ "pup": "pup-Latn-PG",
+ "puq": "puq-Latn-PE",
+ "pur": "pur-Latn-BR",
+ "put": "put-Latn-ID",
+ "puu": "puu-Latn-GA",
+ "puw": "puw-Latn-FM",
+ "pux": "pux-Latn-PG",
+ "puy": "puy-Latn-US",
+ "pwa": "pwa-Latn-ZZ",
+ "pwb": "pwb-Latn-NG",
+ "pwg": "pwg-Latn-PG",
+ "pwm": "pwm-Latn-PH",
+ "pwn": "pwn-Latn-TW",
+ "pwo": "pwo-Mymr-MM",
+ "pwr": "pwr-Deva-IN",
+ "pww": "pww-Thai-TH",
+ "pxm": "pxm-Latn-MX",
+ "pye": "pye-Latn-CI",
+ "pym": "pym-Latn-NG",
+ "pyn": "pyn-Latn-BR",
+ "pyu": "pyu-Latn-TW",
+ "pyu-Hani": "pyu-Hani-TW",
+ "pyx": "pyx-Mymr-MM",
+ "pyy": "pyy-Latn-MM",
+ "pzh": "pzh-Latn-TW",
+ "pzn": "pzn-Latn-MM",
+ "qu": "qu-Latn-PE",
+ "qua": "qua-Latn-US",
+ "qub": "qub-Latn-PE",
+ "quc": "quc-Latn-GT",
+ "qud": "qud-Latn-EC",
+ "quf": "quf-Latn-PE",
+ "qug": "qug-Latn-EC",
+ "qui": "qui-Latn-US",
+ "quk": "quk-Latn-PE",
+ "qul": "qul-Latn-BO",
+ "qum": "qum-Latn-GT",
+ "qun": "qun-Latn-US",
+ "qup": "qup-Latn-PE",
+ "quq": "quq-Latn-ES",
+ "qur": "qur-Latn-PE",
+ "qus": "qus-Latn-AR",
+ "quv": "quv-Latn-GT",
+ "quw": "quw-Latn-EC",
+ "qux": "qux-Latn-PE",
+ "quy": "quy-Latn-PE",
+ "qva": "qva-Latn-PE",
+ "qvc": "qvc-Latn-PE",
+ "qve": "qve-Latn-PE",
+ "qvh": "qvh-Latn-PE",
+ "qvi": "qvi-Latn-EC",
+ "qvj": "qvj-Latn-EC",
+ "qvl": "qvl-Latn-PE",
+ "qvm": "qvm-Latn-PE",
+ "qvn": "qvn-Latn-PE",
+ "qvo": "qvo-Latn-PE",
+ "qvp": "qvp-Latn-PE",
+ "qvs": "qvs-Latn-PE",
+ "qvw": "qvw-Latn-PE",
+ "qvz": "qvz-Latn-EC",
+ "qwa": "qwa-Latn-PE",
+ "qwc": "qwc-Latn-PE",
+ "qwh": "qwh-Latn-PE",
+ "qwm": "qwm-Latn-RU",
+ "qwm-Cyrl": "qwm-Cyrl-RU",
+ "qwm-Runr": "qwm-Runr-RU",
+ "qws": "qws-Latn-PE",
+ "qwt": "qwt-Latn-US",
+ "qxa": "qxa-Latn-PE",
+ "qxc": "qxc-Latn-PE",
+ "qxh": "qxh-Latn-PE",
+ "qxl": "qxl-Latn-EC",
+ "qxn": "qxn-Latn-PE",
+ "qxo": "qxo-Latn-PE",
+ "qxp": "qxp-Latn-PE",
+ "qxq": "qxq-Arab-IR",
+ "qxr": "qxr-Latn-EC",
+ "qxt": "qxt-Latn-PE",
+ "qxu": "qxu-Latn-PE",
+ "qxw": "qxw-Latn-PE",
+ "qya": "qya-Latn-001",
+ "qyp": "qyp-Latn-US",
+ "raa": "raa-Deva-NP",
+ "rab": "rab-Deva-NP",
+ "rac": "rac-Latn-ID",
+ "rad": "rad-Latn-VN",
+ "raf": "raf-Deva-NP",
+ "rag": "rag-Latn-KE",
+ "rah": "rah-Beng-IN",
+ "rah-Latn": "rah-Latn-IN",
+ "rai": "rai-Latn-ZZ",
+ "raj": "raj-Deva-IN",
+ "rak": "rak-Latn-PG",
+ "ram": "ram-Latn-BR",
+ "ran": "ran-Latn-ID",
+ "rao": "rao-Latn-ZZ",
+ "rap": "rap-Latn-CL",
+ "rar": "rar-Latn-CK",
+ "rav": "rav-Deva-NP",
+ "raw": "raw-Latn-MM",
+ "rax": "rax-Latn-NG",
+ "ray": "ray-Latn-PF",
+ "raz": "raz-Latn-ID",
+ "rbb": "rbb-Mymr-MM",
+ "rbk": "rbk-Latn-PH",
+ "rbl": "rbl-Latn-PH",
+ "rbp": "rbp-Latn-AU",
+ "rcf": "rcf-Latn-RE",
+ "rdb": "rdb-Arab-IR",
+ "rea": "rea-Latn-PG",
+ "reb": "reb-Latn-ID",
+ "ree": "ree-Latn-MY",
+ "reg": "reg-Latn-TZ",
+ "rei": "rei-Orya-IN",
+ "rei-Telu": "rei-Telu-IN",
+ "rej": "rej-Latn-ID",
+ "rel": "rel-Latn-ZZ",
+ "rem": "rem-Latn-PE",
+ "ren": "ren-Latn-VN",
+ "res": "res-Latn-ZZ",
+ "ret": "ret-Latn-ID",
+ "rey": "rey-Latn-BO",
+ "rga": "rga-Latn-VU",
+ "rgn": "rgn-Latn-IT",
+ "rgr": "rgr-Latn-PE",
+ "rgs": "rgs-Latn-VN",
+ "rgu": "rgu-Latn-ID",
+ "rhg": "rhg-Rohg-MM",
+ "rhp": "rhp-Latn-PG",
+ "ria": "ria-Latn-IN",
+ "rif": "rif-Latn-MA",
+ "ril": "ril-Latn-MM",
+ "rim": "rim-Latn-TZ",
+ "rin": "rin-Latn-NG",
+ "rir": "rir-Latn-ID",
+ "rit": "rit-Latn-AU",
+ "riu": "riu-Latn-ID",
+ "rjg": "rjg-Latn-ID",
+ "rji": "rji-Deva-NP",
+ "rjs": "rjs-Deva-NP",
+ "rka": "rka-Khmr-KH",
+ "rkb": "rkb-Latn-BR",
+ "rkh": "rkh-Latn-CK",
+ "rki": "rki-Mymr-MM",
+ "rkm": "rkm-Latn-BF",
+ "rkt": "rkt-Beng-BD",
+ "rkw": "rkw-Latn-AU",
+ "rm": "rm-Latn-CH",
+ "rma": "rma-Latn-NI",
+ "rmb": "rmb-Latn-AU",
+ "rmc": "rmc-Latn-SK",
+ "rmd": "rmd-Latn-DK",
+ "rme": "rme-Latn-GB",
+ "rmf": "rmf-Latn-FI",
+ "rmg": "rmg-Latn-NO",
+ "rmh": "rmh-Latn-ID",
+ "rmi": "rmi-Armn-AM",
+ "rmk": "rmk-Latn-PG",
+ "rml": "rml-Latn-PL",
+ "rml-Cyrl": "rml-Cyrl-BY",
+ "rmm": "rmm-Latn-ID",
+ "rmn": "rmn-Latn-RS",
+ "rmn-Cyrl": "rmn-Cyrl-BG",
+ "rmn-Grek": "rmn-Grek-GR",
+ "rmo": "rmo-Latn-CH",
+ "rmp": "rmp-Latn-PG",
+ "rmq": "rmq-Latn-ES",
+ "rmt": "rmt-Arab-IR",
+ "rmu": "rmu-Latn-SE",
+ "rmw": "rmw-Latn-GB",
+ "rmx": "rmx-Latn-VN",
+ "rmz": "rmz-Mymr-IN",
+ "rn": "rn-Latn-BI",
+ "rna": "rna-Latn-ZZ",
+ "rnd": "rnd-Latn-CD",
+ "rng": "rng-Latn-MZ",
+ "rnl": "rnl-Latn-IN",
+ "rnn": "rnn-Latn-ID",
+ "rnr": "rnr-Latn-AU",
+ "rnw": "rnw-Latn-TZ",
+ "ro": "ro-Latn-RO",
+ "rob": "rob-Latn-ID",
+ "roc": "roc-Latn-VN",
+ "rod": "rod-Latn-NG",
+ "roe": "roe-Latn-PG",
+ "rof": "rof-Latn-TZ",
+ "rog": "rog-Latn-VN",
+ "rol": "rol-Latn-PH",
+ "rom": "rom-Latn-RO",
+ "rom-Cyrl": "rom-Cyrl-RO",
+ "roo": "roo-Latn-ZZ",
+ "rop": "rop-Latn-AU",
+ "ror": "ror-Latn-ID",
+ "rou": "rou-Latn-TD",
+ "row": "row-Latn-ID",
+ "rpn": "rpn-Latn-VU",
+ "rpt": "rpt-Latn-PG",
+ "rri": "rri-Latn-SB",
+ "rro": "rro-Latn-ZZ",
+ "rrt": "rrt-Latn-AU",
+ "rsk": "rsk-Cyrl-RS",
+ "rtc": "rtc-Latn-MM",
+ "rth": "rth-Latn-ID",
+ "rtm": "rtm-Latn-FJ",
+ "rtw": "rtw-Deva-IN",
+ "ru": "ru-Cyrl-RU",
+ "rub": "rub-Latn-UG",
+ "ruc": "ruc-Latn-UG",
+ "rue": "rue-Cyrl-UA",
+ "ruf": "ruf-Latn-TZ",
+ "rug": "rug-Latn-SB",
+ "rui": "rui-Latn-TZ",
+ "ruk": "ruk-Latn-NG",
+ "ruo": "ruo-Latn-HR",
+ "rup": "rup-Latn-RO",
+ "rup-Grek": "rup-Grek-GR",
+ "ruq": "ruq-Latn-GR",
+ "rut": "rut-Cyrl-RU",
+ "rut-Latn": "rut-Latn-AZ",
+ "ruu": "ruu-Latn-MY",
+ "ruy": "ruy-Latn-NG",
+ "ruz": "ruz-Latn-NG",
+ "rw": "rw-Latn-RW",
+ "rwa": "rwa-Latn-PG",
+ "rwk": "rwk-Latn-TZ",
+ "rwl": "rwl-Latn-TZ",
+ "rwm": "rwm-Latn-UG",
+ "rwo": "rwo-Latn-ZZ",
+ "rwr": "rwr-Deva-IN",
+ "rxd": "rxd-Latn-AU",
+ "rxw": "rxw-Latn-AU",
+ "ryu": "ryu-Kana-JP",
+ "sa": "sa-Deva-IN",
+ "saa": "saa-Latn-TD",
+ "sab": "sab-Latn-PA",
+ "sac": "sac-Latn-US",
+ "sad": "sad-Latn-TZ",
+ "sae": "sae-Latn-BR",
+ "saf": "saf-Latn-GH",
+ "sah": "sah-Cyrl-RU",
+ "saj": "saj-Latn-ID",
+ "sak": "sak-Latn-GA",
+ "sam": "sam-Samr-PS",
+ "sam-Hebr": "sam-Hebr-PS",
+ "sam-Syrc": "sam-Syrc-PS",
+ "sao": "sao-Latn-ID",
+ "saq": "saq-Latn-KE",
+ "sar": "sar-Latn-BO",
+ "sas": "sas-Latn-ID",
+ "sat": "sat-Olck-IN",
+ "sau": "sau-Latn-ID",
+ "sav": "sav-Latn-SN",
+ "saw": "saw-Latn-ID",
+ "sax": "sax-Latn-VU",
+ "say": "say-Latn-NG",
+ "saz": "saz-Saur-IN",
+ "sba": "sba-Latn-ZZ",
+ "sbb": "sbb-Latn-SB",
+ "sbc": "sbc-Latn-PG",
+ "sbd": "sbd-Latn-BF",
+ "sbe": "sbe-Latn-ZZ",
+ "sbg": "sbg-Latn-ID",
+ "sbh": "sbh-Latn-PG",
+ "sbi": "sbi-Latn-PG",
+ "sbj": "sbj-Latn-TD",
+ "sbk": "sbk-Latn-TZ",
+ "sbl": "sbl-Latn-PH",
+ "sbm": "sbm-Latn-TZ",
+ "sbn": "sbn-Arab-PK",
+ "sbo": "sbo-Latn-MY",
+ "sbp": "sbp-Latn-TZ",
+ "sbq": "sbq-Latn-PG",
+ "sbr": "sbr-Latn-ID",
+ "sbs": "sbs-Latn-NA",
+ "sbt": "sbt-Latn-ID",
+ "sbu": "sbu-Tibt-IN",
+ "sbu-Deva": "sbu-Deva-IN",
+ "sbv": "sbv-Latn-IT",
+ "sbw": "sbw-Latn-GA",
+ "sbx": "sbx-Latn-ID",
+ "sby": "sby-Latn-ZM",
+ "sbz": "sbz-Latn-CF",
+ "sc": "sc-Latn-IT",
+ "scb": "scb-Latn-VN",
+ "sce": "sce-Latn-CN",
+ "sce-Arab": "sce-Arab-CN",
+ "scf": "scf-Latn-PA",
+ "scg": "scg-Latn-ID",
+ "sch": "sch-Latn-IN",
+ "sci": "sci-Latn-LK",
+ "sck": "sck-Deva-IN",
+ "scl": "scl-Arab-ZZ",
+ "scn": "scn-Latn-IT",
+ "sco": "sco-Latn-GB",
+ "scp": "scp-Deva-NP",
+ "scs": "scs-Latn-CA",
+ "scs-Cans": "scs-Cans-CA",
+ "sct": "sct-Laoo-LA",
+ "scu": "scu-Takr-IN",
+ "scv": "scv-Latn-NG",
+ "scw": "scw-Latn-NG",
+ "scx": "scx-Grek-IT",
+ "sd": "sd-Arab-PK",
+ "sd-Deva": "sd-Deva-IN",
+ "sd-IN": "sd-Deva-IN",
+ "sd-Khoj": "sd-Khoj-IN",
+ "sd-Sind": "sd-Sind-IN",
+ "sda": "sda-Latn-ID",
+ "sdb": "sdb-Arab-IQ",
+ "sdc": "sdc-Latn-IT",
+ "sde": "sde-Latn-NG",
+ "sdf": "sdf-Arab-IQ",
+ "sdg": "sdg-Arab-AF",
+ "sdh": "sdh-Arab-IR",
+ "sdj": "sdj-Latn-CG",
+ "sdk": "sdk-Latn-PG",
+ "sdn": "sdn-Latn-IT",
+ "sdo": "sdo-Latn-MY",
+ "sdq": "sdq-Latn-ID",
+ "sds": "sds-Arab-TN",
+ "sdu": "sdu-Latn-ID",
+ "sdx": "sdx-Latn-MY",
+ "se": "se-Latn-NO",
+ "sea": "sea-Latn-MY",
+ "seb": "seb-Latn-CI",
+ "sec": "sec-Latn-CA",
+ "sed": "sed-Latn-VN",
+ "see": "see-Latn-US",
+ "sef": "sef-Latn-CI",
+ "seg": "seg-Latn-TZ",
+ "seh": "seh-Latn-MZ",
+ "sei": "sei-Latn-MX",
+ "sej": "sej-Latn-PG",
+ "sek": "sek-Latn-CA",
+ "sek-Cans": "sek-Cans-CA",
+ "sel": "sel-Cyrl-RU",
+ "sen": "sen-Latn-BF",
+ "seo": "seo-Latn-PG",
+ "sep": "sep-Latn-BF",
+ "seq": "seq-Latn-BF",
+ "ser": "ser-Latn-US",
+ "ses": "ses-Latn-ML",
+ "set": "set-Latn-ID",
+ "seu": "seu-Latn-ID",
+ "sev": "sev-Latn-CI",
+ "sew": "sew-Latn-PG",
+ "sey": "sey-Latn-EC",
+ "sez": "sez-Latn-MM",
+ "sfe": "sfe-Latn-PH",
+ "sfm": "sfm-Plrd-CN",
+ "sfw": "sfw-Latn-GH",
+ "sg": "sg-Latn-CF",
+ "sga": "sga-Ogam-IE",
+ "sgb": "sgb-Latn-PH",
+ "sgc": "sgc-Latn-KE",
+ "sgd": "sgd-Latn-PH",
+ "sge": "sge-Latn-ID",
+ "sgh": "sgh-Cyrl-TJ",
+ "sgh-Arab": "sgh-Arab-AF",
+ "sgh-Latn": "sgh-Latn-TJ",
+ "sgi": "sgi-Latn-CM",
+ "sgj": "sgj-Deva-IN",
+ "sgm": "sgm-Latn-KE",
+ "sgp": "sgp-Latn-IN",
+ "sgr": "sgr-Arab-IR",
+ "sgs": "sgs-Latn-LT",
+ "sgt": "sgt-Tibt-BT",
+ "sgu": "sgu-Latn-ID",
+ "sgw": "sgw-Ethi-ZZ",
+ "sgy": "sgy-Arab-AF",
+ "sgz": "sgz-Latn-ZZ",
+ "sha": "sha-Latn-NG",
+ "shb": "shb-Latn-BR",
+ "shc": "shc-Latn-CD",
+ "shd": "shd-Arab-PK",
+ "she": "she-Latn-ET",
+ "shg": "shg-Latn-BW",
+ "shh": "shh-Latn-US",
+ "shi": "shi-Tfng-MA",
+ "shj": "shj-Latn-SD",
+ "shk": "shk-Latn-ZZ",
+ "shm": "shm-Arab-IR",
+ "shn": "shn-Mymr-MM",
+ "sho": "sho-Latn-NG",
+ "shp": "shp-Latn-PE",
+ "shq": "shq-Latn-ZM",
+ "shr": "shr-Latn-CD",
+ "shs": "shs-Latn-CA",
+ "sht": "sht-Latn-US",
+ "shu": "shu-Arab-ZZ",
+ "shv": "shv-Arab-OM",
+ "shw": "shw-Latn-SD",
+ "shy": "shy-Latn-DZ",
+ "shy-Arab": "shy-Arab-DZ",
+ "shy-Tfng": "shy-Tfng-DZ",
+ "shz": "shz-Latn-ML",
+ "si": "si-Sinh-LK",
+ "sia": "sia-Cyrl-RU",
+ "sib": "sib-Latn-MY",
+ "sid": "sid-Latn-ET",
+ "sie": "sie-Latn-ZM",
+ "sif": "sif-Latn-BF",
+ "sig": "sig-Latn-ZZ",
+ "sih": "sih-Latn-NC",
+ "sii": "sii-Latn-IN",
+ "sij": "sij-Latn-PG",
+ "sik": "sik-Latn-BR",
+ "sil": "sil-Latn-ZZ",
+ "sim": "sim-Latn-ZZ",
+ "sip": "sip-Tibt-IN",
+ "siq": "siq-Latn-PG",
+ "sir": "sir-Latn-NG",
+ "sis": "sis-Latn-US",
+ "siu": "siu-Latn-PG",
+ "siv": "siv-Latn-PG",
+ "siw": "siw-Latn-PG",
+ "six": "six-Latn-PG",
+ "siy": "siy-Arab-IR",
+ "siz": "siz-Arab-EG",
+ "sja": "sja-Latn-CO",
+ "sjb": "sjb-Latn-ID",
+ "sjd": "sjd-Cyrl-RU",
+ "sje": "sje-Latn-SE",
+ "sjg": "sjg-Latn-TD",
+ "sjl": "sjl-Latn-IN",
+ "sjm": "sjm-Latn-PH",
+ "sjp": "sjp-Deva-IN",
+ "sjp-Beng": "sjp-Beng-IN",
+ "sjr": "sjr-Latn-ZZ",
+ "sjt": "sjt-Cyrl-RU",
+ "sju": "sju-Latn-SE",
+ "sjw": "sjw-Latn-US",
+ "sk": "sk-Latn-SK",
+ "ska": "ska-Latn-US",
+ "skb": "skb-Thai-TH",
+ "skc": "skc-Latn-ZZ",
+ "skd": "skd-Latn-US",
+ "ske": "ske-Latn-VU",
+ "skf": "skf-Latn-BR",
+ "skg": "skg-Latn-MG",
+ "skh": "skh-Latn-ID",
+ "ski": "ski-Latn-ID",
+ "skj": "skj-Deva-NP",
+ "skm": "skm-Latn-PG",
+ "skn": "skn-Latn-PH",
+ "sko": "sko-Latn-ID",
+ "skp": "skp-Latn-MY",
+ "skq": "skq-Latn-BF",
+ "skr": "skr-Arab-PK",
+ "sks": "sks-Latn-ZZ",
+ "skt": "skt-Latn-CD",
+ "sku": "sku-Latn-VU",
+ "skv": "skv-Latn-ID",
+ "skw": "skw-Latn-GY",
+ "skx": "skx-Latn-ID",
+ "sky": "sky-Latn-SB",
+ "skz": "skz-Latn-ID",
+ "sl": "sl-Latn-SI",
+ "slc": "slc-Latn-CO",
+ "sld": "sld-Latn-ZZ",
+ "slg": "slg-Latn-ID",
+ "slh": "slh-Latn-US",
+ "sli": "sli-Latn-PL",
+ "slj": "slj-Latn-BR",
+ "sll": "sll-Latn-ZZ",
+ "slm": "slm-Latn-PH",
+ "sln": "sln-Latn-US",
+ "slp": "slp-Latn-ID",
+ "slq": "slq-Arab-IR",
+ "slr": "slr-Latn-CN",
+ "slu": "slu-Latn-ID",
+ "slw": "slw-Latn-PG",
+ "slx": "slx-Latn-CD",
+ "sly": "sly-Latn-ID",
+ "slz": "slz-Latn-ID",
+ "sm": "sm-Latn-WS",
+ "sma": "sma-Latn-SE",
+ "smb": "smb-Latn-PG",
+ "smc": "smc-Latn-PG",
+ "smd": "kmb-Latn-AO",
+ "smf": "smf-Latn-PG",
+ "smg": "smg-Latn-PG",
+ "smh": "smh-Yiii-CN",
+ "smj": "smj-Latn-SE",
+ "smk": "smk-Latn-PH",
+ "sml": "sml-Latn-PH",
+ "smn": "smn-Latn-FI",
+ "smp": "smp-Samr-IL",
+ "smq": "smq-Latn-ZZ",
+ "smr": "smr-Latn-ID",
+ "sms": "sms-Latn-FI",
+ "smt": "smt-Latn-IN",
+ "smu": "smu-Khmr-KH",
+ "smw": "smw-Latn-ID",
+ "smx": "smx-Latn-CD",
+ "smy": "smy-Arab-IR",
+ "smz": "smz-Latn-PG",
+ "sn": "sn-Latn-ZW",
+ "snb": "iba-Latn-MY",
+ "snc": "snc-Latn-ZZ",
+ "sne": "sne-Latn-MY",
+ "snf": "snf-Latn-SN",
+ "sng": "sng-Latn-CD",
+ "sng-Brai": "sng-Brai-CD",
+ "sni": "sni-Latn-PE",
+ "snj": "snj-Latn-CF",
+ "snk": "snk-Latn-ML",
+ "snl": "snl-Latn-PH",
+ "snm": "snm-Latn-UG",
+ "snn": "snn-Latn-CO",
+ "sno": "sno-Latn-US",
+ "snp": "snp-Latn-ZZ",
+ "snq": "snq-Latn-GA",
+ "snr": "snr-Latn-PG",
+ "sns": "sns-Latn-VU",
+ "snu": "snu-Latn-ID",
+ "snv": "snv-Latn-MY",
+ "snw": "snw-Latn-GH",
+ "snx": "snx-Latn-ZZ",
+ "sny": "sny-Latn-ZZ",
+ "snz": "snz-Latn-PG",
+ "so": "so-Latn-SO",
+ "soa": "soa-Tavt-TH",
+ "soa-Thai": "soa-Thai-TH",
+ "sob": "sob-Latn-ID",
+ "soc": "soc-Latn-CD",
+ "sod": "sod-Latn-CD",
+ "soe": "soe-Latn-CD",
+ "sog": "sog-Sogd-UZ",
+ "soi": "soi-Deva-NP",
+ "sok": "sok-Latn-ZZ",
+ "sol": "sol-Latn-PG",
+ "soo": "soo-Latn-CD",
+ "sop": "sop-Latn-CD",
+ "soq": "soq-Latn-ZZ",
+ "sor": "sor-Latn-TD",
+ "sos": "sos-Latn-BF",
+ "sou": "sou-Thai-TH",
+ "sov": "sov-Latn-PW",
+ "sow": "sow-Latn-PG",
+ "sox": "sox-Latn-CM",
+ "soy": "soy-Latn-ZZ",
+ "soz": "soz-Latn-TZ",
+ "spb": "spb-Latn-ID",
+ "spc": "spc-Latn-VE",
+ "spd": "spd-Latn-ZZ",
+ "spe": "spe-Latn-PG",
+ "spg": "spg-Latn-MY",
+ "spi": "spi-Latn-ID",
+ "spk": "spk-Latn-PG",
+ "spl": "spl-Latn-ZZ",
+ "spm": "spm-Latn-PG",
+ "spn": "spn-Latn-PY",
+ "spo": "spo-Latn-US",
+ "spp": "spp-Latn-ML",
+ "spq": "spq-Latn-PE",
+ "spr": "spr-Latn-ID",
+ "sps": "sps-Latn-ZZ",
+ "spt": "spt-Tibt-IN",
+ "spv": "spv-Orya-IN",
+ "sq": "sq-Latn-AL",
+ "sqa": "sqa-Latn-NG",
+ "sqh": "sqh-Latn-NG",
+ "sqm": "sqm-Latn-CF",
+ "sqo": "sqo-Arab-IR",
+ "sqq": "sqq-Laoo-LA",
+ "sqt": "sqt-Arab-YE",
+ "sqt-Latn": "sqt-Latn-YE",
+ "squ": "squ-Latn-CA",
+ "sr": "sr-Cyrl-RS",
+ "sr-ME": "sr-Latn-ME",
+ "sr-RO": "sr-Latn-RO",
+ "sr-RU": "sr-Latn-RU",
+ "sr-TR": "sr-Latn-TR",
+ "sra": "sra-Latn-PG",
+ "srb": "srb-Sora-IN",
+ "sre": "sre-Latn-ID",
+ "srf": "srf-Latn-PG",
+ "srg": "srg-Latn-PH",
+ "srh": "srh-Arab-CN",
+ "sri": "sri-Latn-CO",
+ "srk": "srk-Latn-MY",
+ "srl": "srl-Latn-ID",
+ "srm": "srm-Latn-SR",
+ "srn": "srn-Latn-SR",
+ "sro": "sro-Latn-IT",
+ "srq": "srq-Latn-BO",
+ "srr": "srr-Latn-SN",
+ "srs": "srs-Latn-CA",
+ "srt": "srt-Latn-ID",
+ "sru": "sru-Latn-BR",
+ "srv": "srv-Latn-PH",
+ "srw": "srw-Latn-ID",
+ "srx": "srx-Deva-IN",
+ "sry": "sry-Latn-PG",
+ "srz": "srz-Arab-IR",
+ "ss": "ss-Latn-ZA",
+ "ssb": "ssb-Latn-PH",
+ "ssc": "ssc-Latn-TZ",
+ "ssd": "ssd-Latn-ZZ",
+ "sse": "sse-Latn-PH",
+ "sse-Arab": "sse-Arab-PH",
+ "ssf": "ssf-Latn-TW",
+ "ssg": "ssg-Latn-ZZ",
+ "ssh": "ssh-Arab-AE",
+ "ssj": "ssj-Latn-PG",
+ "ssl": "ssl-Latn-GH",
+ "ssm": "ssm-Latn-MY",
+ "ssn": "ssn-Latn-KE",
+ "sso": "sso-Latn-PG",
+ "ssq": "ssq-Latn-ID",
+ "sss": "sss-Laoo-LA",
+ "sss-Thai": "sss-Thai-TH",
+ "sst": "sst-Latn-PG",
+ "ssu": "ssu-Latn-PG",
+ "ssv": "ssv-Latn-VU",
+ "ssx": "ssx-Latn-PG",
+ "ssy": "ssy-Latn-ER",
+ "ssz": "ssz-Latn-PG",
+ "st": "st-Latn-ZA",
+ "sta": "sta-Latn-ZM",
+ "stb": "stb-Latn-PH",
+ "ste": "ste-Latn-ID",
+ "stf": "stf-Latn-PG",
+ "stg": "stg-Latn-VN",
+ "sth": "sth-Latn-IE",
+ "sti": "sti-Latn-VN",
+ "sti-KH": "sti-Latn-KH",
+ "stj": "stj-Latn-BF",
+ "stk": "stk-Latn-ZZ",
+ "stl": "stl-Latn-NL",
+ "stm": "stm-Latn-PG",
+ "stn": "stn-Latn-SB",
+ "sto": "sto-Latn-CA",
+ "stp": "stp-Latn-MX",
+ "stq": "stq-Latn-DE",
+ "str": "str-Latn-CA",
+ "sts": "sts-Arab-AF",
+ "stt": "stt-Latn-VN",
+ "stv": "stv-Ethi-ET",
+ "stv-Arab": "stv-Arab-ET",
+ "stw": "stw-Latn-FM",
+ "sty": "sty-Cyrl-RU",
+ "su": "su-Latn-ID",
+ "sua": "sua-Latn-ZZ",
+ "sub": "sub-Latn-CD",
+ "suc": "suc-Latn-PH",
+ "sue": "sue-Latn-ZZ",
+ "sug": "sug-Latn-PG",
+ "sui": "sui-Latn-PG",
+ "suj": "suj-Latn-TZ",
+ "suk": "suk-Latn-TZ",
+ "suo": "suo-Latn-PG",
+ "suq": "suq-Latn-ET",
+ "suq-Ethi": "suq-Ethi-ET",
+ "sur": "sur-Latn-ZZ",
+ "sus": "sus-Latn-GN",
+ "sut": "sut-Latn-NI",
+ "suv": "suv-Latn-IN",
+ "suv-Beng": "suv-Beng-IN",
+ "suv-Deva": "suv-Deva-IN",
+ "suw": "suw-Latn-TZ",
+ "suy": "suy-Latn-BR",
+ "suz": "suz-Deva-NP",
+ "sv": "sv-Latn-SE",
+ "sva": "sva-Geor-GE",
+ "sva-Cyrl": "sva-Cyrl-GE",
+ "sva-Latn": "sva-Latn-GE",
+ "svb": "svb-Latn-PG",
+ "svc": "svc-Latn-VC",
+ "sve": "sve-Latn-ID",
+ "svm": "svm-Latn-IT",
+ "svs": "svs-Latn-SB",
+ "sw": "sw-Latn-TZ",
+ "swb": "swb-Arab-YT",
+ "swc": "sw-Latn-CD",
+ "swf": "swf-Latn-CD",
+ "swg": "swg-Latn-DE",
+ "swi": "swi-Hani-CN",
+ "swj": "swj-Latn-GA",
+ "swk": "swk-Latn-MW",
+ "swm": "swm-Latn-PG",
+ "swo": "swo-Latn-BR",
+ "swp": "swp-Latn-ZZ",
+ "swq": "swq-Latn-CM",
+ "swr": "swr-Latn-ID",
+ "sws": "sws-Latn-ID",
+ "swt": "swt-Latn-ID",
+ "swu": "swu-Latn-ID",
+ "swv": "swv-Deva-IN",
+ "sww": "sww-Latn-VU",
+ "swx": "swx-Latn-BR",
+ "swy": "swy-Latn-TD",
+ "sxb": "sxb-Latn-KE",
+ "sxe": "sxe-Latn-GA",
+ "sxn": "sxn-Latn-ID",
+ "sxr": "sxr-Latn-TW",
+ "sxs": "sxs-Latn-NG",
+ "sxu": "sxu-Latn-DE",
+ "sxu-Runr": "sxu-Runr-DE",
+ "sxw": "sxw-Latn-ZZ",
+ "sya": "sya-Latn-ID",
+ "syb": "syb-Latn-PH",
+ "syc": "syc-Syrc-TR",
+ "syi": "syi-Latn-GA",
+ "syk": "syk-Latn-NG",
+ "syl": "syl-Beng-BD",
+ "sym": "sym-Latn-BF",
+ "syn": "syn-Syrc-IR",
+ "syo": "syo-Latn-KH",
+ "syr": "syr-Syrc-IQ",
+ "sys": "sys-Latn-TD",
+ "syw": "syw-Deva-NP",
+ "syx": "syx-Latn-GA",
+ "sza": "sza-Latn-MY",
+ "szb": "szb-Latn-ID",
+ "szc": "szc-Latn-MY",
+ "szd": "szd-Latn-MY",
+ "szg": "szg-Latn-CD",
+ "szl": "szl-Latn-PL",
+ "szn": "szn-Latn-ID",
+ "szp": "szp-Latn-ID",
+ "szv": "szv-Latn-CM",
+ "szw": "szw-Latn-ID",
+ "szy": "szy-Latn-TW",
+ "ta": "ta-Taml-IN",
+ "taa": "taa-Latn-US",
+ "tab": "tab-Cyrl-RU",
+ "tac": "tac-Latn-MX",
+ "tad": "tad-Latn-ID",
+ "tae": "tae-Latn-BR",
+ "taf": "taf-Latn-BR",
+ "tag": "tag-Latn-SD",
+ "taj": "taj-Deva-NP",
+ "tak": "tak-Latn-NG",
+ "tal": "tal-Latn-ZZ",
+ "tan": "tan-Latn-ZZ",
+ "tao": "tao-Latn-TW",
+ "tap": "tap-Latn-CD",
+ "taq": "taq-Latn-ZZ",
+ "tar": "tar-Latn-MX",
+ "tas": "tas-Latn-VN",
+ "tau": "tau-Latn-US",
+ "tav": "tav-Latn-CO",
+ "taw": "taw-Latn-PG",
+ "tax": "tax-Latn-TD",
+ "tay": "tay-Latn-TW",
+ "tay-Hans": "tay-Hans-TW",
+ "tay-Hant": "tay-Hant-TW",
+ "taz": "taz-Latn-SD",
+ "tba": "tba-Latn-BR",
+ "tbc": "tbc-Latn-ZZ",
+ "tbd": "tbd-Latn-ZZ",
+ "tbe": "tbe-Latn-SB",
+ "tbf": "tbf-Latn-ZZ",
+ "tbg": "tbg-Latn-ZZ",
+ "tbh": "tbh-Latn-AU",
+ "tbi": "tbi-Latn-SD",
+ "tbj": "tbj-Latn-PG",
+ "tbk": "tbk-Tagb-PH",
+ "tbk-Hano": "tbk-Hano-PH",
+ "tbk-Latn": "tbk-Latn-PH",
+ "tbl": "tbl-Latn-PH",
+ "tbm": "tbm-Latn-CD",
+ "tbn": "tbn-Latn-CO",
+ "tbo": "tbo-Latn-ZZ",
+ "tbp": "tbp-Latn-ID",
+ "tbs": "tbs-Latn-PG",
+ "tbt": "tbt-Latn-CD",
+ "tbu": "tbu-Latn-MX",
+ "tbv": "tbv-Latn-PG",
+ "tbw": "tbw-Latn-PH",
+ "tbx": "tbx-Latn-PG",
+ "tby": "tby-Latn-ID",
+ "tbz": "tbz-Latn-ZZ",
+ "tca": "tca-Latn-BR",
+ "tcb": "tcb-Latn-US",
+ "tcc": "tcc-Latn-TZ",
+ "tcd": "tcd-Latn-GH",
+ "tce": "tce-Latn-CA",
+ "tcf": "tcf-Latn-MX",
+ "tcg": "tcg-Latn-ID",
+ "tch": "tch-Latn-TC",
+ "tci": "tci-Latn-ZZ",
+ "tck": "tck-Latn-GA",
+ "tcm": "tcm-Latn-ID",
+ "tcn": "tcn-Tibt-NP",
+ "tco": "tco-Mymr-MM",
+ "tcp": "tcp-Latn-MM",
+ "tcq": "tcq-Latn-ID",
+ "tcs": "tcs-Latn-AU",
+ "tcu": "tcu-Latn-MX",
+ "tcw": "tcw-Latn-MX",
+ "tcx": "tcx-Taml-IN",
+ "tcy": "tcy-Knda-IN",
+ "tcz": "tcz-Latn-IN",
+ "tda": "tda-Tfng-NE",
+ "tda-Arab": "tda-Arab-NE",
+ "tda-Latn": "tda-Latn-NE",
+ "tdb": "tdb-Deva-IN",
+ "tdb-Beng": "tdb-Beng-IN",
+ "tdb-Kthi": "tdb-Kthi-IN",
+ "tdc": "tdc-Latn-CO",
+ "tdd": "tdd-Tale-CN",
+ "tde": "tde-Latn-ML",
+ "tdg": "tdg-Deva-NP",
+ "tdh": "tdh-Deva-NP",
+ "tdi": "tdi-Latn-ID",
+ "tdj": "tdj-Latn-ID",
+ "tdk": "tdk-Latn-NG",
+ "tdl": "tdl-Latn-NG",
+ "tdm": "tdm-Latn-GY",
+ "tdn": "tdn-Latn-ID",
+ "tdo": "tdo-Latn-NG",
+ "tdq": "tdq-Latn-NG",
+ "tdr": "tdr-Latn-VN",
+ "tds": "tds-Latn-ID",
+ "tdt": "tdt-Latn-TL",
+ "tdu": "dtp-Latn-MY",
+ "tdv": "tdv-Latn-NG",
+ "tdx": "tdx-Latn-MG",
+ "tdy": "tdy-Latn-PH",
+ "te": "te-Telu-IN",
+ "tea": "tea-Latn-MY",
+ "teb": "teb-Latn-EC",
+ "tec": "tec-Latn-KE",
+ "ted": "ted-Latn-ZZ",
+ "tee": "tee-Latn-MX",
+ "teg": "teg-Latn-GA",
+ "teh": "teh-Latn-AR",
+ "tei": "tei-Latn-PG",
+ "tek": "tek-Latn-CD",
+ "tem": "tem-Latn-SL",
+ "ten": "ten-Latn-CO",
+ "teo": "teo-Latn-UG",
+ "tep": "tep-Latn-MX",
+ "teq": "teq-Latn-SD",
+ "ter": "ter-Latn-BR",
+ "tes": "tes-Java-ID",
+ "tet": "tet-Latn-TL",
+ "teu": "teu-Latn-UG",
+ "tev": "tev-Latn-ID",
+ "tew": "tew-Latn-US",
+ "tex": "tex-Latn-SS",
+ "tey": "tey-Latn-SD",
+ "tfi": "tfi-Latn-ZZ",
+ "tfn": "tfn-Latn-US",
+ "tfo": "tfo-Latn-ID",
+ "tfr": "tfr-Latn-PA",
+ "tft": "tft-Latn-ID",
+ "tg": "tg-Cyrl-TJ",
+ "tg-Arab": "tg-Arab-PK",
+ "tg-PK": "tg-Arab-PK",
+ "tga": "tga-Latn-KE",
+ "tgb": "tgb-Latn-MY",
+ "tgc": "tgc-Latn-ZZ",
+ "tgd": "tgd-Latn-NG",
+ "tge": "tge-Deva-NP",
+ "tgf": "tgf-Tibt-BT",
+ "tgh": "tgh-Latn-TT",
+ "tgi": "tgi-Latn-PG",
+ "tgj": "tgj-Latn-IN",
+ "tgn": "tgn-Latn-PH",
+ "tgo": "tgo-Latn-ZZ",
+ "tgp": "tgp-Latn-VU",
+ "tgq": "tgq-Latn-MY",
+ "tgs": "tgs-Latn-VU",
+ "tgt": "tgt-Latn-PH",
+ "tgt-Hano": "tgt-Hano-PH",
+ "tgt-Tagb": "tgt-Tagb-PH",
+ "tgu": "tgu-Latn-ZZ",
+ "tgv": "tgv-Latn-BR",
+ "tgw": "tgw-Latn-CI",
+ "tgx": "tgx-Latn-CA",
+ "tgy": "tgy-Latn-SS",
+ "tgz": "tgz-Latn-AU",
+ "th": "th-Thai-TH",
+ "thd": "thd-Latn-AU",
+ "the": "the-Deva-NP",
+ "thf": "thf-Deva-NP",
+ "thh": "thh-Latn-MX",
+ "thi": "thi-Tale-LA",
+ "thk": "thk-Latn-KE",
+ "thl": "thl-Deva-NP",
+ "thm": "thm-Thai-TH",
+ "thp": "thp-Latn-CA",
+ "thp-Dupl": "thp-Dupl-CA",
+ "thq": "thq-Deva-NP",
+ "thr": "thr-Deva-NP",
+ "ths": "ths-Deva-NP",
+ "tht": "tht-Latn-CA",
+ "thu": "thu-Latn-SS",
+ "thv": "thv-Latn-DZ",
+ "thv-Arab": "thv-Arab-DZ",
+ "thv-Tfng": "thv-Tfng-DZ",
+ "thy": "thy-Latn-NG",
+ "thz": "thz-Latn-NE",
+ "thz-Tfng": "thz-Tfng-NE",
+ "ti": "ti-Ethi-ET",
+ "tic": "tic-Latn-SD",
+ "tif": "tif-Latn-ZZ",
+ "tig": "tig-Ethi-ER",
+ "tih": "tih-Latn-MY",
+ "tii": "tii-Latn-CD",
+ "tij": "tij-Deva-NP",
+ "tik": "tik-Latn-ZZ",
+ "til": "til-Latn-US",
+ "tim": "tim-Latn-ZZ",
+ "tin": "tin-Cyrl-RU",
+ "tio": "tio-Latn-ZZ",
+ "tip": "tip-Latn-ID",
+ "tiq": "tiq-Latn-BF",
+ "tis": "tis-Latn-PH",
+ "tit": "tit-Latn-CO",
+ "tiu": "tiu-Latn-PH",
+ "tiv": "tiv-Latn-NG",
+ "tiw": "tiw-Latn-AU",
+ "tix": "tix-Latn-US",
+ "tiy": "tiy-Latn-PH",
+ "tja": "tja-Latn-LR",
+ "tjg": "tjg-Latn-ID",
+ "tji": "tji-Latn-CN",
+ "tjj": "tjj-Latn-AU",
+ "tjl": "tjl-Mymr-MM",
+ "tjn": "tjn-Latn-CI",
+ "tjo": "tjo-Arab-DZ",
+ "tjp": "tjp-Latn-AU",
+ "tjs": "tjs-Latn-CN",
+ "tju": "tju-Latn-AU",
+ "tjw": "tjw-Latn-AU",
+ "tk": "tk-Latn-TM",
+ "tka": "tka-Latn-BR",
+ "tkb": "tkb-Deva-IN",
+ "tkd": "tkd-Latn-TL",
+ "tke": "tke-Latn-MZ",
+ "tkf": "tkf-Latn-BR",
+ "tkg": "tkg-Latn-MG",
+ "tkl": "tkl-Latn-TK",
+ "tkp": "tkp-Latn-SB",
+ "tkq": "tkq-Latn-NG",
+ "tkr": "tkr-Latn-AZ",
+ "tks": "tks-Arab-IR",
+ "tkt": "tkt-Deva-NP",
+ "tku": "tku-Latn-MX",
+ "tkv": "tkv-Latn-PG",
+ "tkw": "tkw-Latn-SB",
+ "tkx": "tkx-Latn-ID",
+ "tkz": "tkz-Latn-VN",
+ "tl": "fil-Latn-PH",
+ "tla": "tla-Latn-MX",
+ "tlb": "tlb-Latn-ID",
+ "tlc": "tlc-Latn-MX",
+ "tld": "tld-Latn-ID",
+ "tlf": "tlf-Latn-ZZ",
+ "tlg": "tlg-Latn-ID",
+ "tli": "tli-Latn-US",
+ "tli-Cyrl": "tli-Cyrl-US",
+ "tlj": "tlj-Latn-UG",
+ "tlk": "tlk-Latn-ID",
+ "tll": "tll-Latn-CD",
+ "tlm": "tlm-Latn-VU",
+ "tln": "tln-Latn-ID",
+ "tlp": "tlp-Latn-MX",
+ "tlq": "tlq-Latn-MM",
+ "tlr": "tlr-Latn-SB",
+ "tls": "tls-Latn-VU",
+ "tlt": "tlt-Latn-ID",
+ "tlu": "tlu-Latn-ID",
+ "tlv": "tlv-Latn-ID",
+ "tlx": "tlx-Latn-ZZ",
+ "tly": "tly-Latn-AZ",
+ "tma": "tma-Latn-TD",
+ "tmb": "tmb-Latn-VU",
+ "tmc": "tmc-Latn-TD",
+ "tmd": "tmd-Latn-PG",
+ "tme": "tme-Latn-BR",
+ "tmf": "tmf-Latn-PY",
+ "tmg": "tmg-Latn-ID",
+ "tmh": "tmh-Latn-NE",
+ "tmi": "tmi-Latn-VU",
+ "tmj": "tmj-Latn-ID",
+ "tmk": "tmk-Deva-NP",
+ "tml": "tml-Latn-ID",
+ "tmm": "tmm-Latn-VN",
+ "tmn": "tmn-Latn-ID",
+ "tmo": "tmo-Latn-MY",
+ "tmq": "tmq-Latn-PG",
+ "tmr": "tmr-Syrc-IL",
+ "tmt": "tmt-Latn-VU",
+ "tmu": "tmu-Latn-ID",
+ "tmv": "tmv-Latn-CD",
+ "tmw": "tmw-Latn-MY",
+ "tmy": "tmy-Latn-ZZ",
+ "tmz": "tmz-Latn-VE",
+ "tn": "tn-Latn-ZA",
+ "tna": "tna-Latn-BO",
+ "tnb": "tnb-Latn-CO",
+ "tnc": "tnc-Latn-CO",
+ "tnd": "tnd-Latn-CO",
+ "tng": "tng-Latn-TD",
+ "tnh": "tnh-Latn-ZZ",
+ "tni": "tni-Latn-ID",
+ "tnk": "tnk-Latn-VU",
+ "tnl": "tnl-Latn-VU",
+ "tnm": "tnm-Latn-ID",
+ "tnn": "tnn-Latn-VU",
+ "tno": "tno-Latn-BO",
+ "tnp": "tnp-Latn-VU",
+ "tnq": "tnq-Latn-PR",
+ "tnr": "tnr-Latn-SN",
+ "tns": "tns-Latn-PG",
+ "tnt": "tnt-Latn-ID",
+ "tnv": "tnv-Cakm-BD",
+ "tnw": "tnw-Latn-ID",
+ "tnx": "tnx-Latn-SB",
+ "tny": "tny-Latn-TZ",
+ "to": "to-Latn-TO",
+ "tob": "tob-Latn-AR",
+ "toc": "toc-Latn-MX",
+ "tod": "tod-Latn-GN",
+ "tof": "tof-Latn-ZZ",
+ "tog": "tog-Latn-MW",
+ "toh": "toh-Latn-MZ",
+ "toi": "toi-Latn-ZM",
+ "toj": "toj-Latn-MX",
+ "tok": "tok-Latn-001",
+ "tol": "tol-Latn-US",
+ "tom": "tom-Latn-ID",
+ "too": "too-Latn-MX",
+ "top": "top-Latn-MX",
+ "toq": "toq-Latn-ZZ",
+ "tor": "tor-Latn-CD",
+ "tos": "tos-Latn-MX",
+ "tou": "tou-Latn-VN",
+ "tov": "tov-Arab-IR",
+ "tow": "tow-Latn-US",
+ "tox": "tox-Latn-PW",
+ "toy": "toy-Latn-ID",
+ "toz": "toz-Latn-CM",
+ "tpa": "tpa-Latn-PG",
+ "tpc": "tpc-Latn-MX",
+ "tpe": "tpe-Latn-BD",
+ "tpe-Beng": "tpe-Beng-BD",
+ "tpf": "tpf-Latn-ID",
+ "tpg": "tpg-Latn-ID",
+ "tpi": "tpi-Latn-PG",
+ "tpj": "tpj-Latn-PY",
+ "tpk": "tpk-Latn-BR",
+ "tpl": "tpl-Latn-MX",
+ "tpm": "tpm-Latn-ZZ",
+ "tpn": "tpn-Latn-BR",
+ "tpp": "tpp-Latn-MX",
+ "tpr": "tpr-Latn-BR",
+ "tpt": "tpt-Latn-MX",
+ "tpu": "tpu-Khmr-KH",
+ "tpv": "tpv-Latn-MP",
+ "tpx": "tpx-Latn-MX",
+ "tpy": "tpy-Latn-BR",
+ "tpz": "tpz-Latn-ZZ",
+ "tqb": "tqb-Latn-BR",
+ "tql": "tql-Latn-VU",
+ "tqm": "tqm-Latn-PG",
+ "tqn": "tqn-Latn-US",
+ "tqo": "tqo-Latn-ZZ",
+ "tqp": "tqp-Latn-PG",
+ "tqt": "tqt-Latn-MX",
+ "tqu": "tqu-Latn-SB",
+ "tqw": "tqw-Latn-US",
+ "tr": "tr-Latn-TR",
+ "tra": "tra-Arab-AF",
+ "trb": "trb-Latn-PG",
+ "trc": "trc-Latn-MX",
+ "tre": "tre-Latn-ID",
+ "trf": "trf-Latn-TT",
+ "trg": "trg-Hebr-IL",
+ "trh": "trh-Latn-PG",
+ "tri": "tri-Latn-SR",
+ "trj": "trj-Latn-TD",
+ "trl": "trl-Latn-GB",
+ "trm": "trm-Arab-AF",
+ "trn": "trn-Latn-BO",
+ "tro": "tro-Latn-IN",
+ "trp": "trp-Latn-IN",
+ "trp-Beng": "trp-Beng-IN",
+ "trq": "trq-Latn-MX",
+ "trr": "trr-Latn-PE",
+ "trs": "trs-Latn-MX",
+ "trt": "trt-Latn-ID",
+ "tru": "tru-Latn-TR",
+ "trv": "trv-Latn-TW",
+ "trw": "trw-Arab-PK",
+ "trx": "trx-Latn-MY",
+ "try": "try-Latn-IN",
+ "trz": "trz-Latn-BR",
+ "ts": "ts-Latn-ZA",
+ "tsa": "tsa-Latn-CG",
+ "tsb": "tsb-Latn-ET",
+ "tsc": "tsc-Latn-MZ",
+ "tsd": "tsd-Grek-GR",
+ "tsf": "taj-Deva-NP",
+ "tsg": "tsg-Latn-PH",
+ "tsh": "tsh-Latn-CM",
+ "tsi": "tsi-Latn-CA",
+ "tsj": "tsj-Tibt-BT",
+ "tsl": "tsl-Latn-VN",
+ "tsp": "tsp-Latn-BF",
+ "tsr": "tsr-Latn-VU",
+ "tst": "tst-Latn-ML",
+ "tsu": "tsu-Latn-TW",
+ "tsv": "tsv-Latn-GA",
+ "tsw": "tsw-Latn-ZZ",
+ "tsx": "tsx-Latn-PG",
+ "tsz": "tsz-Latn-MX",
+ "tt": "tt-Cyrl-RU",
+ "ttb": "ttb-Latn-NG",
+ "ttc": "ttc-Latn-GT",
+ "ttd": "ttd-Latn-ZZ",
+ "tte": "tte-Latn-ZZ",
+ "ttf": "ttf-Latn-CM",
+ "tth": "tth-Laoo-LA",
+ "tti": "tti-Latn-ID",
+ "ttj": "ttj-Latn-UG",
+ "ttk": "ttk-Latn-CO",
+ "ttl": "ttl-Latn-ZM",
+ "ttm": "ttm-Latn-CA",
+ "ttn": "ttn-Latn-ID",
+ "tto": "tto-Laoo-LA",
+ "ttp": "ttp-Latn-ID",
+ "ttr": "ttr-Latn-ZZ",
+ "tts": "tts-Thai-TH",
+ "ttt": "ttt-Latn-AZ",
+ "ttu": "ttu-Latn-PG",
+ "ttv": "ttv-Latn-PG",
+ "ttw": "ttw-Latn-MY",
+ "tty": "tty-Latn-ID",
+ "tua": "tua-Latn-PG",
+ "tub": "tub-Latn-US",
+ "tuc": "tuc-Latn-PG",
+ "tud": "tud-Latn-BR",
+ "tue": "tue-Latn-CO",
+ "tuf": "tuf-Latn-CO",
+ "tug": "tug-Latn-TD",
+ "tuh": "tuh-Latn-ZZ",
+ "tui": "tui-Latn-CM",
+ "tuj": "tuj-Latn-ID",
+ "tul": "tul-Latn-ZZ",
+ "tum": "tum-Latn-MW",
+ "tun": "tun-Latn-US",
+ "tuo": "tuo-Latn-BR",
+ "tuq": "tuq-Latn-ZZ",
+ "tus": "tus-Latn-CA",
+ "tuu": "tuu-Latn-US",
+ "tuv": "tuv-Latn-KE",
+ "tux": "tux-Latn-BR",
+ "tuy": "tuy-Latn-KE",
+ "tuz": "tuz-Latn-BF",
+ "tva": "tva-Latn-SB",
+ "tvd": "tvd-Latn-ZZ",
+ "tve": "tve-Latn-ID",
+ "tvk": "tvk-Latn-VU",
+ "tvl": "tvl-Latn-TV",
+ "tvm": "tvm-Latn-ID",
+ "tvn": "tvn-Mymr-MM",
+ "tvo": "tvo-Latn-ID",
+ "tvs": "tvs-Latn-KE",
+ "tvt": "tvt-Latn-IN",
+ "tvu": "tvu-Latn-ZZ",
+ "tvw": "tvw-Latn-ID",
+ "tvx": "tvx-Latn-TW",
+ "twa": "twa-Latn-US",
+ "twb": "twb-Latn-PH",
+ "twd": "twd-Latn-NL",
+ "twe": "twe-Latn-ID",
+ "twf": "twf-Latn-US",
+ "twg": "twg-Latn-ID",
+ "twh": "twh-Latn-ZZ",
+ "twl": "twl-Latn-MZ",
+ "twm": "twm-Deva-IN",
+ "twn": "twn-Latn-CM",
+ "two": "two-Latn-BW",
+ "twp": "twp-Latn-PG",
+ "twq": "twq-Latn-NE",
+ "twr": "twr-Latn-MX",
+ "twt": "twt-Latn-BR",
+ "twu": "twu-Latn-ID",
+ "tww": "tww-Latn-PG",
+ "twx": "twx-Latn-MZ",
+ "twy": "twy-Latn-ID",
+ "txa": "txa-Latn-MY",
+ "txe": "txe-Latn-ID",
+ "txg": "txg-Tang-CN",
+ "txi": "txi-Latn-BR",
+ "txj": "txj-Latn-NG",
+ "txm": "txm-Latn-ID",
+ "txn": "txn-Latn-ID",
+ "txo": "txo-Toto-IN",
+ "txq": "txq-Latn-ID",
+ "txs": "txs-Latn-ID",
+ "txt": "txt-Latn-ID",
+ "txu": "txu-Latn-BR",
+ "txx": "txx-Latn-MY",
+ "txy": "txy-Latn-MG",
+ "ty": "ty-Latn-PF",
+ "tya": "tya-Latn-ZZ",
+ "tye": "tye-Latn-NG",
+ "tyh": "tyh-Latn-VN",
+ "tyi": "tyi-Latn-CG",
+ "tyj": "tyj-Latn-VN",
+ "tyl": "tyl-Latn-VN",
+ "tyn": "tyn-Latn-ID",
+ "typ": "typ-Latn-AU",
+ "tyr": "tyr-Tavt-VN",
+ "tys": "tys-Latn-VN",
+ "tyt": "tyt-Latn-VN",
+ "tyt-Tavt": "tyt-Tavt-VN",
+ "tyu": "tyu-Latn-BW",
+ "tyv": "tyv-Cyrl-RU",
+ "tyx": "tyx-Latn-CG",
+ "tyy": "tyy-Latn-NG",
+ "tyz": "tyz-Latn-VN",
+ "tzh": "tzh-Latn-MX",
+ "tzj": "tzj-Latn-GT",
+ "tzl": "tzl-Latn-001",
+ "tzm": "tzm-Latn-MA",
+ "tzn": "tzn-Latn-ID",
+ "tzo": "tzo-Latn-MX",
+ "tzx": "tzx-Latn-PG",
+ "uam": "uam-Latn-BR",
+ "uar": "uar-Latn-PG",
+ "uba": "uba-Latn-NG",
+ "ubi": "ubi-Latn-TD",
+ "ubl": "ubl-Latn-PH",
+ "ubr": "ubr-Latn-PG",
+ "ubu": "ubu-Latn-ZZ",
+ "uda": "uda-Latn-NG",
+ "ude": "ude-Cyrl-RU",
+ "udg": "udg-Mlym-IN",
+ "udi": "udi-Aghb-RU",
+ "udj": "udj-Latn-ID",
+ "udl": "udl-Latn-CM",
+ "udm": "udm-Cyrl-RU",
+ "udu": "udu-Latn-SD",
+ "ues": "ues-Latn-ID",
+ "ufi": "ufi-Latn-PG",
+ "ug": "ug-Arab-CN",
+ "ug-Cyrl": "ug-Cyrl-KZ",
+ "ug-KZ": "ug-Cyrl-KZ",
+ "ug-MN": "ug-Cyrl-MN",
+ "uga": "uga-Ugar-SY",
+ "ugb": "ugb-Latn-AU",
+ "uge": "uge-Latn-SB",
+ "ugh": "ugh-Cyrl-RU",
+ "ugo": "ugo-Thai-TH",
+ "uha": "uha-Latn-NG",
+ "uhn": "uhn-Latn-ID",
+ "uis": "uis-Latn-PG",
+ "uiv": "uiv-Latn-CM",
+ "uji": "uji-Latn-NG",
+ "uk": "uk-Cyrl-UA",
+ "uka": "uka-Latn-ID",
+ "ukg": "ukg-Latn-PG",
+ "ukh": "ukh-Latn-CF",
+ "uki": "uki-Orya-IN",
+ "ukk": "ukk-Latn-MM",
+ "ukp": "ukp-Latn-NG",
+ "ukq": "ukq-Latn-NG",
+ "uku": "uku-Latn-NG",
+ "ukv": "ukv-Latn-SS",
+ "ukw": "ukw-Latn-NG",
+ "uky": "uky-Latn-AU",
+ "ula": "ula-Latn-NG",
+ "ulb": "ulb-Latn-NG",
+ "ulc": "ulc-Cyrl-RU",
+ "ule": "ule-Latn-AR",
+ "ulf": "ulf-Latn-ID",
+ "uli": "uli-Latn-FM",
+ "ulk": "ulk-Latn-AU",
+ "ulm": "ulm-Latn-ID",
+ "uln": "uln-Latn-PG",
+ "ulu": "ulu-Latn-ID",
+ "ulw": "ulw-Latn-NI",
+ "uma": "uma-Latn-US",
+ "umb": "umb-Latn-AO",
+ "umd": "umd-Latn-AU",
+ "umg": "umg-Latn-AU",
+ "umi": "umi-Latn-MY",
+ "umm": "umm-Latn-NG",
+ "umn": "umn-Latn-MM",
+ "umo": "umo-Latn-BR",
+ "ump": "ump-Latn-AU",
+ "umr": "umr-Latn-AU",
+ "ums": "ums-Latn-ID",
+ "una": "una-Latn-PG",
+ "und": "en-Latn-US",
+ "und-002": "en-Latn-NG",
+ "und-003": "en-Latn-US",
+ "und-005": "pt-Latn-BR",
+ "und-009": "en-Latn-AU",
+ "und-011": "en-Latn-NG",
+ "und-013": "es-Latn-MX",
+ "und-014": "sw-Latn-TZ",
+ "und-015": "ar-Arab-EG",
+ "und-017": "sw-Latn-CD",
+ "und-018": "en-Latn-ZA",
+ "und-019": "en-Latn-US",
+ "und-021": "en-Latn-US",
+ "und-029": "es-Latn-CU",
+ "und-030": "zh-Hans-CN",
+ "und-034": "hi-Deva-IN",
+ "und-035": "id-Latn-ID",
+ "und-039": "it-Latn-IT",
+ "und-053": "en-Latn-AU",
+ "und-054": "en-Latn-PG",
+ "und-057": "en-Latn-GU",
+ "und-061": "sm-Latn-WS",
+ "und-142": "zh-Hans-CN",
+ "und-143": "uz-Latn-UZ",
+ "und-145": "ar-Arab-SA",
+ "und-150": "ru-Cyrl-RU",
+ "und-151": "ru-Cyrl-RU",
+ "und-154": "en-Latn-GB",
+ "und-155": "de-Latn-DE",
+ "und-202": "en-Latn-NG",
+ "und-419": "es-Latn-419",
+ "und-AD": "ca-Latn-AD",
+ "und-AE": "ar-Arab-AE",
+ "und-AF": "fa-Arab-AF",
+ "und-AL": "sq-Latn-AL",
+ "und-AM": "hy-Armn-AM",
+ "und-AO": "pt-Latn-AO",
+ "und-AQ": "und-Latn-AQ",
+ "und-AR": "es-Latn-AR",
+ "und-AS": "sm-Latn-AS",
+ "und-AT": "de-Latn-AT",
+ "und-AW": "nl-Latn-AW",
+ "und-AX": "sv-Latn-AX",
+ "und-AZ": "az-Latn-AZ",
+ "und-Adlm": "ff-Adlm-GN",
+ "und-Aghb": "udi-Aghb-RU",
+ "und-Ahom": "aho-Ahom-IN",
+ "und-Arab": "ar-Arab-EG",
+ "und-Arab-CC": "ms-Arab-CC",
+ "und-Arab-CN": "ug-Arab-CN",
+ "und-Arab-GB": "ur-Arab-GB",
+ "und-Arab-ID": "ms-Arab-ID",
+ "und-Arab-IN": "ur-Arab-IN",
+ "und-Arab-KH": "cja-Arab-KH",
+ "und-Arab-MM": "rhg-Arab-MM",
+ "und-Arab-MN": "kk-Arab-MN",
+ "und-Arab-MU": "ur-Arab-MU",
+ "und-Arab-NG": "ha-Arab-NG",
+ "und-Arab-PK": "ur-Arab-PK",
+ "und-Arab-TG": "apd-Arab-TG",
+ "und-Arab-TH": "mfa-Arab-TH",
+ "und-Arab-TJ": "fa-Arab-TJ",
+ "und-Arab-TR": "apc-Arab-TR",
+ "und-Arab-YT": "swb-Arab-YT",
+ "und-Armi": "arc-Armi-IR",
+ "und-Armn": "hy-Armn-AM",
+ "und-Avst": "ae-Avst-IR",
+ "und-BA": "bs-Latn-BA",
+ "und-BD": "bn-Beng-BD",
+ "und-BE": "nl-Latn-BE",
+ "und-BF": "fr-Latn-BF",
+ "und-BG": "bg-Cyrl-BG",
+ "und-BH": "ar-Arab-BH",
+ "und-BI": "rn-Latn-BI",
+ "und-BJ": "fr-Latn-BJ",
+ "und-BL": "fr-Latn-BL",
+ "und-BN": "ms-Latn-BN",
+ "und-BO": "es-Latn-BO",
+ "und-BQ": "pap-Latn-BQ",
+ "und-BR": "pt-Latn-BR",
+ "und-BT": "dz-Tibt-BT",
+ "und-BV": "und-Latn-BV",
+ "und-BY": "be-Cyrl-BY",
+ "und-Bali": "ban-Bali-ID",
+ "und-Bamu": "bax-Bamu-CM",
+ "und-Bass": "bsq-Bass-LR",
+ "und-Batk": "bbc-Batk-ID",
+ "und-Beng": "bn-Beng-BD",
+ "und-Bhks": "sa-Bhks-IN",
+ "und-Bopo": "zh-Bopo-TW",
+ "und-Brah": "pka-Brah-IN",
+ "und-Brai": "fr-Brai-FR",
+ "und-Bugi": "bug-Bugi-ID",
+ "und-Buhd": "bku-Buhd-PH",
+ "und-CD": "sw-Latn-CD",
+ "und-CF": "fr-Latn-CF",
+ "und-CG": "fr-Latn-CG",
+ "und-CH": "de-Latn-CH",
+ "und-CI": "fr-Latn-CI",
+ "und-CL": "es-Latn-CL",
+ "und-CM": "fr-Latn-CM",
+ "und-CN": "zh-Hans-CN",
+ "und-CO": "es-Latn-CO",
+ "und-CP": "und-Latn-CP",
+ "und-CR": "es-Latn-CR",
+ "und-CU": "es-Latn-CU",
+ "und-CV": "pt-Latn-CV",
+ "und-CW": "pap-Latn-CW",
+ "und-CY": "el-Grek-CY",
+ "und-CZ": "cs-Latn-CZ",
+ "und-Cakm": "ccp-Cakm-BD",
+ "und-Cans": "iu-Cans-CA",
+ "und-Cari": "xcr-Cari-TR",
+ "und-Cham": "cjm-Cham-VN",
+ "und-Cher": "chr-Cher-US",
+ "und-Chrs": "xco-Chrs-UZ",
+ "und-Copt": "cop-Copt-EG",
+ "und-Cpmn": "und-Cpmn-CY",
+ "und-Cpmn-CY": "und-Cpmn-CY",
+ "und-Cprt": "grc-Cprt-CY",
+ "und-Cyrl": "ru-Cyrl-RU",
+ "und-Cyrl-AL": "mk-Cyrl-AL",
+ "und-Cyrl-BA": "sr-Cyrl-BA",
+ "und-Cyrl-GE": "ab-Cyrl-GE",
+ "und-Cyrl-GR": "mk-Cyrl-GR",
+ "und-Cyrl-MD": "uk-Cyrl-MD",
+ "und-Cyrl-RO": "bg-Cyrl-RO",
+ "und-Cyrl-SK": "uk-Cyrl-SK",
+ "und-Cyrl-TR": "kbd-Cyrl-TR",
+ "und-Cyrl-XK": "sr-Cyrl-XK",
+ "und-DE": "de-Latn-DE",
+ "und-DJ": "aa-Latn-DJ",
+ "und-DK": "da-Latn-DK",
+ "und-DO": "es-Latn-DO",
+ "und-DZ": "ar-Arab-DZ",
+ "und-Deva": "hi-Deva-IN",
+ "und-Deva-BT": "ne-Deva-BT",
+ "und-Deva-FJ": "hif-Deva-FJ",
+ "und-Deva-MU": "bho-Deva-MU",
+ "und-Deva-PK": "btv-Deva-PK",
+ "und-Diak": "dv-Diak-MV",
+ "und-Dogr": "doi-Dogr-IN",
+ "und-Dupl": "fr-Dupl-FR",
+ "und-EA": "es-Latn-EA",
+ "und-EC": "es-Latn-EC",
+ "und-EE": "et-Latn-EE",
+ "und-EG": "ar-Arab-EG",
+ "und-EH": "ar-Arab-EH",
+ "und-ER": "ti-Ethi-ER",
+ "und-ES": "es-Latn-ES",
+ "und-ET": "am-Ethi-ET",
+ "und-EU": "en-Latn-IE",
+ "und-EZ": "de-Latn-EZ",
+ "und-Egyp": "egy-Egyp-EG",
+ "und-Elba": "sq-Elba-AL",
+ "und-Elym": "arc-Elym-IR",
+ "und-Ethi": "am-Ethi-ET",
+ "und-FI": "fi-Latn-FI",
+ "und-FO": "fo-Latn-FO",
+ "und-FR": "fr-Latn-FR",
+ "und-GA": "fr-Latn-GA",
+ "und-GE": "ka-Geor-GE",
+ "und-GF": "fr-Latn-GF",
+ "und-GH": "ak-Latn-GH",
+ "und-GL": "kl-Latn-GL",
+ "und-GN": "fr-Latn-GN",
+ "und-GP": "fr-Latn-GP",
+ "und-GQ": "es-Latn-GQ",
+ "und-GR": "el-Grek-GR",
+ "und-GS": "und-Latn-GS",
+ "und-GT": "es-Latn-GT",
+ "und-GW": "pt-Latn-GW",
+ "und-Geor": "ka-Geor-GE",
+ "und-Glag": "cu-Glag-BG",
+ "und-Gong": "wsg-Gong-IN",
+ "und-Gonm": "esg-Gonm-IN",
+ "und-Goth": "got-Goth-UA",
+ "und-Gran": "sa-Gran-IN",
+ "und-Grek": "el-Grek-GR",
+ "und-Grek-TR": "bgx-Grek-TR",
+ "und-Gujr": "gu-Gujr-IN",
+ "und-Guru": "pa-Guru-IN",
+ "und-HK": "zh-Hant-HK",
+ "und-HM": "und-Latn-HM",
+ "und-HN": "es-Latn-HN",
+ "und-HR": "hr-Latn-HR",
+ "und-HT": "ht-Latn-HT",
+ "und-HU": "hu-Latn-HU",
+ "und-Hanb": "zh-Hanb-TW",
+ "und-Hang": "ko-Hang-KR",
+ "und-Hani": "zh-Hani-CN",
+ "und-Hano": "hnn-Hano-PH",
+ "und-Hans": "zh-Hans-CN",
+ "und-Hant": "zh-Hant-TW",
+ "und-Hant-CA": "yue-Hant-CA",
+ "und-Hebr": "he-Hebr-IL",
+ "und-Hebr-SE": "yi-Hebr-SE",
+ "und-Hebr-UA": "yi-Hebr-UA",
+ "und-Hebr-US": "yi-Hebr-US",
+ "und-Hira": "ja-Hira-JP",
+ "und-Hluw": "hlu-Hluw-TR",
+ "und-Hmng": "hnj-Hmng-LA",
+ "und-Hmnp": "hnj-Hmnp-US",
+ "und-Hung": "hu-Hung-HU",
+ "und-IC": "es-Latn-IC",
+ "und-ID": "id-Latn-ID",
+ "und-IL": "he-Hebr-IL",
+ "und-IN": "hi-Deva-IN",
+ "und-IQ": "ar-Arab-IQ",
+ "und-IR": "fa-Arab-IR",
+ "und-IS": "is-Latn-IS",
+ "und-IT": "it-Latn-IT",
+ "und-Ital": "ett-Ital-IT",
+ "und-JO": "ar-Arab-JO",
+ "und-JP": "ja-Jpan-JP",
+ "und-Jamo": "ko-Jamo-KR",
+ "und-Java": "jv-Java-ID",
+ "und-Jpan": "ja-Jpan-JP",
+ "und-KE": "sw-Latn-KE",
+ "und-KG": "ky-Cyrl-KG",
+ "und-KH": "km-Khmr-KH",
+ "und-KM": "ar-Arab-KM",
+ "und-KP": "ko-Kore-KP",
+ "und-KR": "ko-Kore-KR",
+ "und-KW": "ar-Arab-KW",
+ "und-KZ": "ru-Cyrl-KZ",
+ "und-Kali": "eky-Kali-MM",
+ "und-Kana": "ja-Kana-JP",
+ "und-Kawi": "kaw-Kawi-ID",
+ "und-Khar": "pra-Khar-PK",
+ "und-Khmr": "km-Khmr-KH",
+ "und-Khoj": "sd-Khoj-IN",
+ "und-Kits": "zkt-Kits-CN",
+ "und-Knda": "kn-Knda-IN",
+ "und-Kore": "ko-Kore-KR",
+ "und-Kthi": "bho-Kthi-IN",
+ "und-LA": "lo-Laoo-LA",
+ "und-LB": "ar-Arab-LB",
+ "und-LI": "de-Latn-LI",
+ "und-LK": "si-Sinh-LK",
+ "und-LS": "st-Latn-LS",
+ "und-LT": "lt-Latn-LT",
+ "und-LU": "fr-Latn-LU",
+ "und-LV": "lv-Latn-LV",
+ "und-LY": "ar-Arab-LY",
+ "und-Lana": "nod-Lana-TH",
+ "und-Laoo": "lo-Laoo-LA",
+ "und-Laoo-AU": "hnj-Laoo-AU",
+ "und-Laoo-CN": "hnj-Laoo-CN",
+ "und-Laoo-FR": "hnj-Laoo-FR",
+ "und-Laoo-GF": "hnj-Laoo-GF",
+ "und-Laoo-MM": "hnj-Laoo-MM",
+ "und-Laoo-SR": "hnj-Laoo-SR",
+ "und-Laoo-TH": "hnj-Laoo-TH",
+ "und-Laoo-US": "hnj-Laoo-US",
+ "und-Laoo-VN": "hnj-Laoo-VN",
+ "und-Latn-AF": "tk-Latn-AF",
+ "und-Latn-AM": "ku-Latn-AM",
+ "und-Latn-CN": "za-Latn-CN",
+ "und-Latn-CY": "tr-Latn-CY",
+ "und-Latn-DZ": "fr-Latn-DZ",
+ "und-Latn-ET": "en-Latn-ET",
+ "und-Latn-GE": "ku-Latn-GE",
+ "und-Latn-IR": "tk-Latn-IR",
+ "und-Latn-KM": "fr-Latn-KM",
+ "und-Latn-MA": "fr-Latn-MA",
+ "und-Latn-MK": "sq-Latn-MK",
+ "und-Latn-MM": "kac-Latn-MM",
+ "und-Latn-MO": "pt-Latn-MO",
+ "und-Latn-MR": "fr-Latn-MR",
+ "und-Latn-RU": "krl-Latn-RU",
+ "und-Latn-SY": "fr-Latn-SY",
+ "und-Latn-TN": "fr-Latn-TN",
+ "und-Latn-TW": "trv-Latn-TW",
+ "und-Latn-UA": "pl-Latn-UA",
+ "und-Lepc": "lep-Lepc-IN",
+ "und-Limb": "lif-Limb-IN",
+ "und-Lina": "lab-Lina-GR",
+ "und-Linb": "grc-Linb-GR",
+ "und-Lisu": "lis-Lisu-CN",
+ "und-Lyci": "xlc-Lyci-TR",
+ "und-Lydi": "xld-Lydi-TR",
+ "und-MA": "ar-Arab-MA",
+ "und-MC": "fr-Latn-MC",
+ "und-MD": "ro-Latn-MD",
+ "und-ME": "sr-Latn-ME",
+ "und-MF": "fr-Latn-MF",
+ "und-MG": "mg-Latn-MG",
+ "und-MK": "mk-Cyrl-MK",
+ "und-ML": "bm-Latn-ML",
+ "und-MM": "my-Mymr-MM",
+ "und-MN": "mn-Cyrl-MN",
+ "und-MO": "zh-Hant-MO",
+ "und-MQ": "fr-Latn-MQ",
+ "und-MR": "ar-Arab-MR",
+ "und-MT": "mt-Latn-MT",
+ "und-MU": "mfe-Latn-MU",
+ "und-MV": "dv-Thaa-MV",
+ "und-MX": "es-Latn-MX",
+ "und-MY": "ms-Latn-MY",
+ "und-MZ": "pt-Latn-MZ",
+ "und-Mahj": "hi-Mahj-IN",
+ "und-Maka": "mak-Maka-ID",
+ "und-Mand": "myz-Mand-IR",
+ "und-Mani": "xmn-Mani-CN",
+ "und-Marc": "bo-Marc-CN",
+ "und-Medf": "dmf-Medf-NG",
+ "und-Mend": "men-Mend-SL",
+ "und-Merc": "xmr-Merc-SD",
+ "und-Mero": "xmr-Mero-SD",
+ "und-Mlym": "ml-Mlym-IN",
+ "und-Modi": "mr-Modi-IN",
+ "und-Mong": "mn-Mong-CN",
+ "und-Mroo": "mro-Mroo-BD",
+ "und-Mtei": "mni-Mtei-IN",
+ "und-Mult": "skr-Mult-PK",
+ "und-Mymr": "my-Mymr-MM",
+ "und-Mymr-IN": "kht-Mymr-IN",
+ "und-Mymr-TH": "mnw-Mymr-TH",
+ "und-NA": "af-Latn-NA",
+ "und-NC": "fr-Latn-NC",
+ "und-NE": "ha-Latn-NE",
+ "und-NI": "es-Latn-NI",
+ "und-NL": "nl-Latn-NL",
+ "und-NO": "nb-Latn-NO",
+ "und-NP": "ne-Deva-NP",
+ "und-Nagm": "unr-Nagm-IN",
+ "und-Nand": "sa-Nand-IN",
+ "und-Narb": "xna-Narb-SA",
+ "und-Nbat": "arc-Nbat-JO",
+ "und-Newa": "new-Newa-NP",
+ "und-Nkoo": "man-Nkoo-GN",
+ "und-Nshu": "zhx-Nshu-CN",
+ "und-OM": "ar-Arab-OM",
+ "und-Ogam": "sga-Ogam-IE",
+ "und-Olck": "sat-Olck-IN",
+ "und-Orkh": "otk-Orkh-MN",
+ "und-Orya": "or-Orya-IN",
+ "und-Osge": "osa-Osge-US",
+ "und-Osma": "so-Osma-SO",
+ "und-Ougr": "oui-Ougr-143",
+ "und-PA": "es-Latn-PA",
+ "und-PE": "es-Latn-PE",
+ "und-PF": "fr-Latn-PF",
+ "und-PG": "tpi-Latn-PG",
+ "und-PH": "fil-Latn-PH",
+ "und-PK": "ur-Arab-PK",
+ "und-PL": "pl-Latn-PL",
+ "und-PM": "fr-Latn-PM",
+ "und-PR": "es-Latn-PR",
+ "und-PS": "ar-Arab-PS",
+ "und-PT": "pt-Latn-PT",
+ "und-PW": "pau-Latn-PW",
+ "und-PY": "gn-Latn-PY",
+ "und-Palm": "arc-Palm-SY",
+ "und-Pauc": "ctd-Pauc-MM",
+ "und-Perm": "kv-Perm-RU",
+ "und-Phag": "lzh-Phag-CN",
+ "und-Phli": "pal-Phli-IR",
+ "und-Phlp": "pal-Phlp-CN",
+ "und-Phnx": "phn-Phnx-LB",
+ "und-Plrd": "hmd-Plrd-CN",
+ "und-Prti": "xpr-Prti-IR",
+ "und-QA": "ar-Arab-QA",
+ "und-QO": "en-Latn-DG",
+ "und-RE": "fr-Latn-RE",
+ "und-RO": "ro-Latn-RO",
+ "und-RS": "sr-Cyrl-RS",
+ "und-RU": "ru-Cyrl-RU",
+ "und-RW": "rw-Latn-RW",
+ "und-Rjng": "rej-Rjng-ID",
+ "und-Rohg": "rhg-Rohg-MM",
+ "und-Runr": "non-Runr-SE",
+ "und-SA": "ar-Arab-SA",
+ "und-SC": "fr-Latn-SC",
+ "und-SD": "ar-Arab-SD",
+ "und-SE": "sv-Latn-SE",
+ "und-SI": "sl-Latn-SI",
+ "und-SJ": "nb-Latn-SJ",
+ "und-SK": "sk-Latn-SK",
+ "und-SM": "it-Latn-SM",
+ "und-SN": "fr-Latn-SN",
+ "und-SO": "so-Latn-SO",
+ "und-SR": "nl-Latn-SR",
+ "und-ST": "pt-Latn-ST",
+ "und-SV": "es-Latn-SV",
+ "und-SY": "ar-Arab-SY",
+ "und-Samr": "smp-Samr-IL",
+ "und-Sarb": "xsa-Sarb-YE",
+ "und-Saur": "saz-Saur-IN",
+ "und-Sgnw": "ase-Sgnw-US",
+ "und-Shaw": "en-Shaw-GB",
+ "und-Shrd": "sa-Shrd-IN",
+ "und-Sidd": "sa-Sidd-IN",
+ "und-Sind": "sd-Sind-IN",
+ "und-Sinh": "si-Sinh-LK",
+ "und-Sogd": "sog-Sogd-UZ",
+ "und-Sogo": "sog-Sogo-UZ",
+ "und-Sora": "srb-Sora-IN",
+ "und-Soyo": "cmg-Soyo-MN",
+ "und-Sund": "su-Sund-ID",
+ "und-Sylo": "syl-Sylo-BD",
+ "und-Syrc": "syr-Syrc-IQ",
+ "und-TD": "fr-Latn-TD",
+ "und-TF": "fr-Latn-TF",
+ "und-TG": "fr-Latn-TG",
+ "und-TH": "th-Thai-TH",
+ "und-TJ": "tg-Cyrl-TJ",
+ "und-TK": "tkl-Latn-TK",
+ "und-TL": "pt-Latn-TL",
+ "und-TM": "tk-Latn-TM",
+ "und-TN": "ar-Arab-TN",
+ "und-TO": "to-Latn-TO",
+ "und-TR": "tr-Latn-TR",
+ "und-TV": "tvl-Latn-TV",
+ "und-TW": "zh-Hant-TW",
+ "und-TZ": "sw-Latn-TZ",
+ "und-Tagb": "tbw-Tagb-PH",
+ "und-Takr": "doi-Takr-IN",
+ "und-Tale": "tdd-Tale-CN",
+ "und-Talu": "khb-Talu-CN",
+ "und-Taml": "ta-Taml-IN",
+ "und-Tang": "txg-Tang-CN",
+ "und-Tavt": "blt-Tavt-VN",
+ "und-Telu": "te-Telu-IN",
+ "und-Tfng": "zgh-Tfng-MA",
+ "und-Tglg": "fil-Tglg-PH",
+ "und-Thaa": "dv-Thaa-MV",
+ "und-Thai": "th-Thai-TH",
+ "und-Thai-CN": "lcp-Thai-CN",
+ "und-Thai-KH": "kdt-Thai-KH",
+ "und-Thai-LA": "kdt-Thai-LA",
+ "und-Tibt": "bo-Tibt-CN",
+ "und-Tirh": "mai-Tirh-IN",
+ "und-Tnsa": "nst-Tnsa-IN",
+ "und-Toto": "txo-Toto-IN",
+ "und-UA": "uk-Cyrl-UA",
+ "und-UG": "sw-Latn-UG",
+ "und-UY": "es-Latn-UY",
+ "und-UZ": "uz-Latn-UZ",
+ "und-Ugar": "uga-Ugar-SY",
+ "und-VA": "it-Latn-VA",
+ "und-VE": "es-Latn-VE",
+ "und-VN": "vi-Latn-VN",
+ "und-VU": "bi-Latn-VU",
+ "und-Vaii": "vai-Vaii-LR",
+ "und-Vith": "sq-Vith-AL",
+ "und-WF": "fr-Latn-WF",
+ "und-WS": "sm-Latn-WS",
+ "und-Wara": "hoc-Wara-IN",
+ "und-Wcho": "nnp-Wcho-IN",
+ "und-XK": "sq-Latn-XK",
+ "und-Xpeo": "peo-Xpeo-IR",
+ "und-Xsux": "akk-Xsux-IQ",
+ "und-YE": "ar-Arab-YE",
+ "und-YT": "fr-Latn-YT",
+ "und-Yezi": "ku-Yezi-GE",
+ "und-Yiii": "ii-Yiii-CN",
+ "und-ZW": "sn-Latn-ZW",
+ "und-Zanb": "cmg-Zanb-MN",
+ "une": "une-Latn-NG",
+ "ung": "ung-Latn-AU",
+ "uni": "uni-Latn-PG",
+ "unk": "unk-Latn-BR",
+ "unm": "unm-Latn-US",
+ "unn": "unn-Latn-AU",
+ "unr": "unr-Beng-IN",
+ "unr-Deva": "unr-Deva-NP",
+ "unr-NP": "unr-Deva-NP",
+ "unu": "unu-Latn-PG",
+ "unx": "unx-Beng-IN",
+ "unz": "unz-Latn-ID",
+ "uok": "ema-Latn-ZZ",
+ "uon": "uon-Latn-TW",
+ "upi": "upi-Latn-PG",
+ "upv": "upv-Latn-VU",
+ "ur": "ur-Arab-PK",
+ "ura": "ura-Latn-PE",
+ "urb": "urb-Latn-BR",
+ "urc": "urc-Latn-AU",
+ "ure": "ure-Latn-BO",
+ "urf": "urf-Latn-AU",
+ "urg": "urg-Latn-PG",
+ "urh": "urh-Latn-NG",
+ "uri": "uri-Latn-ZZ",
+ "urk": "urk-Thai-TH",
+ "urm": "urm-Latn-PG",
+ "urn": "urn-Latn-ID",
+ "uro": "uro-Latn-PG",
+ "urp": "urp-Latn-BR",
+ "urr": "urr-Latn-VU",
+ "urt": "urt-Latn-ZZ",
+ "uru": "uru-Latn-BR",
+ "urv": "urv-Latn-PG",
+ "urw": "urw-Latn-ZZ",
+ "urx": "urx-Latn-PG",
+ "ury": "ury-Latn-ID",
+ "urz": "urz-Latn-BR",
+ "usa": "usa-Latn-ZZ",
+ "ush": "ush-Arab-PK",
+ "usi": "usi-Latn-BD",
+ "usi-Beng": "usi-Beng-BD",
+ "usk": "usk-Latn-CM",
+ "usp": "usp-Latn-GT",
+ "uss": "uss-Latn-NG",
+ "usu": "usu-Latn-PG",
+ "uta": "uta-Latn-NG",
+ "ute": "ute-Latn-US",
+ "uth": "uth-Latn-ZZ",
+ "utp": "utp-Latn-SB",
+ "utr": "utr-Latn-ZZ",
+ "utu": "utu-Latn-PG",
+ "uum": "uum-Grek-GE",
+ "uum-Cyrl": "uum-Cyrl-GE",
+ "uur": "uur-Latn-VU",
+ "uve": "uve-Latn-NC",
+ "uvh": "uvh-Latn-ZZ",
+ "uvl": "uvl-Latn-ZZ",
+ "uwa": "uwa-Latn-AU",
+ "uya": "uya-Latn-NG",
+ "uz": "uz-Latn-UZ",
+ "uz-AF": "uz-Arab-AF",
+ "uz-Arab": "uz-Arab-AF",
+ "uz-CN": "uz-Cyrl-CN",
+ "uzs": "uzs-Arab-AF",
+ "vaa": "vaa-Taml-IN",
+ "vae": "vae-Latn-CF",
+ "vaf": "vaf-Arab-IR",
+ "vag": "vag-Latn-ZZ",
+ "vah": "vah-Deva-IN",
+ "vai": "vai-Vaii-LR",
+ "vaj": "vaj-Latn-NA",
+ "val": "val-Latn-PG",
+ "vam": "vam-Latn-PG",
+ "van": "van-Latn-ZZ",
+ "vao": "vao-Latn-VU",
+ "vap": "vap-Latn-IN",
+ "var": "var-Latn-MX",
+ "vas": "vas-Deva-IN",
+ "vas-Gujr": "vas-Gujr-IN",
+ "vau": "vau-Latn-CD",
+ "vav": "vav-Deva-IN",
+ "vav-Gujr": "vav-Gujr-IN",
+ "vay": "vay-Deva-NP",
+ "vbb": "vbb-Latn-ID",
+ "vbk": "vbk-Latn-PH",
+ "ve": "ve-Latn-ZA",
+ "vec": "vec-Latn-IT",
+ "vem": "vem-Latn-NG",
+ "veo": "veo-Latn-US",
+ "vep": "vep-Latn-RU",
+ "ver": "ver-Latn-NG",
+ "vgr": "vgr-Arab-PK",
+ "vi": "vi-Latn-VN",
+ "vic": "vic-Latn-SX",
+ "vid": "vid-Latn-TZ",
+ "vif": "vif-Latn-CG",
+ "vig": "vig-Latn-BF",
+ "vil": "vil-Latn-AR",
+ "vin": "vin-Latn-TZ",
+ "vit": "vit-Latn-NG",
+ "viv": "viv-Latn-ZZ",
+ "vka": "vka-Latn-AU",
+ "vkj": "vkj-Latn-TD",
+ "vkk": "vkk-Latn-ID",
+ "vkl": "vkl-Latn-ID",
+ "vkm": "vkm-Latn-BR",
+ "vkn": "vkn-Latn-NG",
+ "vko": "vko-Latn-ID",
+ "vkp": "vkp-Latn-IN",
+ "vkp-Deva": "vkp-Deva-IN",
+ "vkt": "vkt-Latn-ID",
+ "vku": "vku-Latn-AU",
+ "vkz": "vkz-Latn-NG",
+ "vlp": "vlp-Latn-VU",
+ "vls": "vls-Latn-BE",
+ "vma": "vma-Latn-AU",
+ "vmb": "vmb-Latn-AU",
+ "vmc": "vmc-Latn-MX",
+ "vmd": "vmd-Knda-IN",
+ "vme": "vme-Latn-ID",
+ "vmf": "vmf-Latn-DE",
+ "vmg": "vmg-Latn-PG",
+ "vmh": "vmh-Arab-IR",
+ "vmi": "vmi-Latn-AU",
+ "vmj": "vmj-Latn-MX",
+ "vmk": "vmk-Latn-MZ",
+ "vml": "vml-Latn-AU",
+ "vmm": "vmm-Latn-MX",
+ "vmp": "vmp-Latn-MX",
+ "vmq": "vmq-Latn-MX",
+ "vmr": "vmr-Latn-MZ",
+ "vms": "vms-Latn-ID",
+ "vmu": "vmu-Latn-AU",
+ "vmw": "vmw-Latn-MZ",
+ "vmx": "vmx-Latn-MX",
+ "vmy": "vmy-Latn-MX",
+ "vmz": "vmz-Latn-MX",
+ "vnk": "vnk-Latn-SB",
+ "vnm": "vnm-Latn-VU",
+ "vnp": "vnp-Latn-VU",
+ "vo": "vo-Latn-001",
+ "vor": "vor-Latn-NG",
+ "vot": "vot-Latn-RU",
+ "vra": "vra-Latn-VU",
+ "vro": "vro-Latn-EE",
+ "vrs": "vrs-Latn-SB",
+ "vrt": "vrt-Latn-VU",
+ "vto": "vto-Latn-ID",
+ "vum": "vum-Latn-GA",
+ "vun": "vun-Latn-TZ",
+ "vut": "vut-Latn-ZZ",
+ "vwa": "vwa-Latn-CN",
+ "vwa-Mymr": "vwa-Mymr-CN",
+ "wa": "wa-Latn-BE",
+ "waa": "waa-Latn-US",
+ "wab": "wab-Latn-PG",
+ "wac": "wac-Latn-US",
+ "wad": "wad-Latn-ID",
+ "wae": "wae-Latn-CH",
+ "waf": "waf-Latn-BR",
+ "wag": "wag-Latn-PG",
+ "wah": "wah-Latn-ID",
+ "wai": "wai-Latn-ID",
+ "waj": "waj-Latn-ZZ",
+ "wal": "wal-Ethi-ET",
+ "wam": "wam-Latn-US",
+ "wan": "wan-Latn-ZZ",
+ "wap": "wap-Latn-GY",
+ "waq": "waq-Latn-AU",
+ "war": "war-Latn-PH",
+ "was": "was-Latn-US",
+ "wat": "wat-Latn-PG",
+ "wau": "wau-Latn-BR",
+ "wav": "wav-Latn-NG",
+ "waw": "waw-Latn-BR",
+ "wax": "wax-Latn-PG",
+ "way": "way-Latn-SR",
+ "waz": "waz-Latn-PG",
+ "wba": "wba-Latn-VE",
+ "wbb": "wbb-Latn-ID",
+ "wbe": "wbe-Latn-ID",
+ "wbf": "wbf-Latn-BF",
+ "wbh": "wbh-Latn-TZ",
+ "wbi": "wbi-Latn-TZ",
+ "wbj": "wbj-Latn-TZ",
+ "wbk": "wbk-Arab-AF",
+ "wbl": "wbl-Latn-PK",
+ "wbl-Arab": "wbl-Arab-AF",
+ "wbl-Cyrl": "wbl-Cyrl-TJ",
+ "wbm": "wbm-Latn-CN",
+ "wbp": "wbp-Latn-AU",
+ "wbq": "wbq-Telu-IN",
+ "wbr": "wbr-Deva-IN",
+ "wbt": "wbt-Latn-AU",
+ "wbv": "wbv-Latn-AU",
+ "wbw": "wbw-Latn-ID",
+ "wca": "wca-Latn-BR",
+ "wci": "wci-Latn-ZZ",
+ "wdd": "wdd-Latn-GA",
+ "wdg": "wdg-Latn-PG",
+ "wdj": "wdj-Latn-AU",
+ "wdk": "wdk-Latn-AU",
+ "wdt": "wdt-Latn-CA",
+ "wdu": "wdu-Latn-AU",
+ "wdy": "wdy-Latn-AU",
+ "wec": "wec-Latn-CI",
+ "wed": "wed-Latn-PG",
+ "weg": "weg-Latn-AU",
+ "weh": "weh-Latn-CM",
+ "wei": "wei-Latn-PG",
+ "wem": "wem-Latn-BJ",
+ "weo": "weo-Latn-ID",
+ "wep": "wep-Latn-DE",
+ "wer": "wer-Latn-ZZ",
+ "wes": "wes-Latn-CM",
+ "wet": "wet-Latn-ID",
+ "weu": "weu-Latn-MM",
+ "wew": "wew-Latn-ID",
+ "wfg": "wfg-Latn-ID",
+ "wga": "wga-Latn-AU",
+ "wgb": "wgb-Latn-PG",
+ "wgg": "wgg-Latn-AU",
+ "wgi": "wgi-Latn-ZZ",
+ "wgo": "wgo-Latn-ID",
+ "wgu": "wgu-Latn-AU",
+ "wgy": "wgy-Latn-AU",
+ "wha": "wha-Latn-ID",
+ "whg": "whg-Latn-ZZ",
+ "whk": "whk-Latn-ID",
+ "whu": "whu-Latn-ID",
+ "wib": "wib-Latn-ZZ",
+ "wic": "wic-Latn-US",
+ "wie": "wie-Latn-AU",
+ "wif": "wif-Latn-AU",
+ "wig": "wig-Latn-AU",
+ "wih": "wih-Latn-AU",
+ "wii": "wii-Latn-PG",
+ "wij": "wij-Latn-AU",
+ "wik": "wik-Latn-AU",
+ "wil": "wil-Latn-AU",
+ "wim": "wim-Latn-AU",
+ "win": "win-Latn-US",
+ "wir": "wir-Latn-BR",
+ "wiu": "wiu-Latn-ZZ",
+ "wiv": "wiv-Latn-ZZ",
+ "wiy": "wiy-Latn-US",
+ "wja": "wja-Latn-ZZ",
+ "wji": "wji-Latn-ZZ",
+ "wka": "wka-Latn-TZ",
+ "wkd": "wkd-Latn-ID",
+ "wkr": "wkr-Latn-AU",
+ "wkw": "wkw-Latn-AU",
+ "wky": "wky-Latn-AU",
+ "wla": "wla-Latn-PG",
+ "wlg": "wlg-Latn-AU",
+ "wlh": "wlh-Latn-TL",
+ "wli": "wli-Latn-ID",
+ "wlm": "wlm-Latn-GB",
+ "wlo": "wlo-Arab-ID",
+ "wlr": "wlr-Latn-VU",
+ "wls": "wls-Latn-WF",
+ "wlu": "wlu-Latn-AU",
+ "wlv": "wlv-Latn-AR",
+ "wlw": "wlw-Latn-ID",
+ "wlx": "wlx-Latn-GH",
+ "wma": "wma-Latn-NG",
+ "wmb": "wmb-Latn-AU",
+ "wmc": "wmc-Latn-PG",
+ "wmd": "wmd-Latn-BR",
+ "wme": "wme-Deva-NP",
+ "wmh": "wmh-Latn-TL",
+ "wmi": "wmi-Latn-AU",
+ "wmm": "wmm-Latn-ID",
+ "wmn": "wmn-Latn-NC",
+ "wmo": "wmo-Latn-ZZ",
+ "wms": "wms-Latn-ID",
+ "wmt": "wmt-Latn-AU",
+ "wmw": "wmw-Latn-MZ",
+ "wmw-Arab": "wmw-Arab-MZ",
+ "wmx": "wmx-Latn-PG",
+ "wnb": "wnb-Latn-PG",
+ "wnc": "wnc-Latn-ZZ",
+ "wnd": "wnd-Latn-AU",
+ "wne": "wne-Arab-PK",
+ "wng": "wng-Latn-ID",
+ "wni": "wni-Arab-KM",
+ "wnk": "wnk-Latn-ID",
+ "wnm": "wnm-Latn-AU",
+ "wnn": "wnn-Latn-AU",
+ "wno": "wno-Latn-ID",
+ "wnp": "wnp-Latn-PG",
+ "wnu": "wnu-Latn-ZZ",
+ "wnw": "wnw-Latn-US",
+ "wny": "wny-Latn-AU",
+ "wo": "wo-Latn-SN",
+ "woa": "woa-Latn-AU",
+ "wob": "wob-Latn-ZZ",
+ "woc": "woc-Latn-PG",
+ "wod": "wod-Latn-ID",
+ "woe": "woe-Latn-FM",
+ "wof": "wof-Latn-GM",
+ "wof-Arab": "wof-Arab-GM",
+ "wog": "wog-Latn-PG",
+ "woi": "woi-Latn-ID",
+ "wok": "wok-Latn-CM",
+ "wom": "wom-Latn-NG",
+ "won": "won-Latn-CD",
+ "woo": "woo-Latn-ID",
+ "wor": "wor-Latn-ID",
+ "wos": "wos-Latn-ZZ",
+ "wow": "wow-Latn-ID",
+ "wpc": "wpc-Latn-VE",
+ "wrb": "wrb-Latn-AU",
+ "wrg": "wrg-Latn-AU",
+ "wrh": "wrh-Latn-AU",
+ "wri": "wri-Latn-AU",
+ "wrk": "wrk-Latn-AU",
+ "wrl": "wrl-Latn-AU",
+ "wrm": "wrm-Latn-AU",
+ "wro": "wro-Latn-AU",
+ "wrp": "wrp-Latn-ID",
+ "wrr": "wrr-Latn-AU",
+ "wrs": "wrs-Latn-ZZ",
+ "wru": "wru-Latn-ID",
+ "wrv": "wrv-Latn-PG",
+ "wrw": "wrw-Latn-AU",
+ "wrx": "wrx-Latn-ID",
+ "wrz": "wrz-Latn-AU",
+ "wsa": "wsa-Latn-ID",
+ "wsg": "wsg-Gong-IN",
+ "wsi": "wsi-Latn-VU",
+ "wsk": "wsk-Latn-ZZ",
+ "wsr": "wsr-Latn-PG",
+ "wss": "wss-Latn-GH",
+ "wsu": "wsu-Latn-BR",
+ "wsv": "wsv-Arab-AF",
+ "wtf": "wtf-Latn-PG",
+ "wth": "wth-Latn-AU",
+ "wti": "wti-Latn-ET",
+ "wtk": "wtk-Latn-PG",
+ "wtm": "wtm-Deva-IN",
+ "wtw": "wtw-Latn-ID",
+ "wtw-Bugi": "wtw-Bugi-ID",
+ "wua": "wua-Latn-AU",
+ "wub": "wub-Latn-AU",
+ "wud": "wud-Latn-TG",
+ "wul": "wul-Latn-ID",
+ "wum": "wum-Latn-GA",
+ "wun": "wun-Latn-TZ",
+ "wur": "wur-Latn-AU",
+ "wut": "wut-Latn-PG",
+ "wuu": "wuu-Hans-CN",
+ "wuv": "wuv-Latn-ZZ",
+ "wux": "wux-Latn-AU",
+ "wuy": "wuy-Latn-ID",
+ "wwa": "wwa-Latn-ZZ",
+ "wwb": "wwb-Latn-AU",
+ "wwo": "wwo-Latn-VU",
+ "wwr": "wwr-Latn-AU",
+ "www": "www-Latn-CM",
+ "wxw": "wxw-Latn-AU",
+ "wyb": "wyb-Latn-AU",
+ "wyi": "wyi-Latn-AU",
+ "wym": "wym-Latn-PL",
+ "wyn": "wyn-Latn-US",
+ "wyr": "wyr-Latn-BR",
+ "wyy": "wyy-Latn-FJ",
+ "xaa": "xaa-Latn-ES",
+ "xab": "xab-Latn-NG",
+ "xai": "xai-Latn-BR",
+ "xaj": "xaj-Latn-BR",
+ "xak": "xak-Latn-VE",
+ "xal": "xal-Cyrl-RU",
+ "xam": "xam-Latn-ZA",
+ "xan": "xan-Ethi-ET",
+ "xao": "xao-Latn-VN",
+ "xar": "xar-Latn-PG",
+ "xas": "xas-Cyrl-RU",
+ "xat": "xat-Latn-BR",
+ "xau": "xau-Latn-ID",
+ "xav": "xav-Latn-BR",
+ "xaw": "xaw-Latn-US",
+ "xay": "xay-Latn-ID",
+ "xbb": "xbb-Latn-AU",
+ "xbd": "xbd-Latn-AU",
+ "xbe": "xbe-Latn-AU",
+ "xbg": "xbg-Latn-AU",
+ "xbi": "xbi-Latn-ZZ",
+ "xbj": "xbj-Latn-AU",
+ "xbm": "xbm-Latn-FR",
+ "xbn": "xbn-Latn-MY",
+ "xbp": "xbp-Latn-AU",
+ "xbr": "xbr-Latn-ID",
+ "xbw": "xbw-Latn-BR",
+ "xby": "xby-Latn-AU",
+ "xch": "xch-Latn-US",
+ "xco": "xco-Chrs-UZ",
+ "xcr": "xcr-Cari-TR",
+ "xda": "xda-Latn-AU",
+ "xdk": "xdk-Latn-AU",
+ "xdo": "xdo-Latn-AO",
+ "xdq": "xdq-Cyrl-RU",
+ "xdy": "xdy-Latn-ID",
+ "xed": "xed-Latn-CM",
+ "xeg": "xeg-Latn-ZA",
+ "xem": "xem-Latn-ID",
+ "xer": "xer-Latn-BR",
+ "xes": "xes-Latn-ZZ",
+ "xet": "xet-Latn-BR",
+ "xeu": "xeu-Latn-PG",
+ "xgb": "xgb-Latn-CI",
+ "xgd": "xgd-Latn-AU",
+ "xgg": "xgg-Latn-AU",
+ "xgi": "xgi-Latn-AU",
+ "xgm": "xgm-Latn-AU",
+ "xgu": "xgu-Latn-AU",
+ "xgw": "xgw-Latn-AU",
+ "xh": "xh-Latn-ZA",
+ "xhe": "xhe-Arab-PK",
+ "xhm": "xhm-Khmr-KH",
+ "xhv": "xhv-Latn-VN",
+ "xii": "xii-Latn-ZA",
+ "xin": "xin-Latn-GT",
+ "xir": "xir-Latn-BR",
+ "xis": "xis-Orya-IN",
+ "xiy": "xiy-Latn-BR",
+ "xjb": "xjb-Latn-AU",
+ "xjt": "xjt-Latn-AU",
+ "xka": "xka-Arab-PK",
+ "xkb": "xkb-Latn-BJ",
+ "xkc": "xkc-Arab-IR",
+ "xkd": "xkd-Latn-ID",
+ "xke": "xke-Latn-ID",
+ "xkg": "xkg-Latn-ML",
+ "xkj": "xkj-Arab-IR",
+ "xkl": "xkl-Latn-ID",
+ "xkn": "xkn-Latn-ID",
+ "xkp": "xkp-Arab-IR",
+ "xkq": "xkq-Latn-ID",
+ "xkr": "xkr-Latn-BR",
+ "xks": "xks-Latn-ID",
+ "xkt": "xkt-Latn-GH",
+ "xku": "xku-Latn-CG",
+ "xkv": "xkv-Latn-BW",
+ "xkw": "xkw-Latn-ID",
+ "xkx": "xkx-Latn-PG",
+ "xky": "xky-Latn-MY",
+ "xkz": "xkz-Latn-BT",
+ "xla": "xla-Latn-ZZ",
+ "xlc": "xlc-Lyci-TR",
+ "xld": "xld-Lydi-TR",
+ "xly": "xly-Elym-IR",
+ "xma": "xma-Latn-SO",
+ "xmb": "xmb-Latn-CM",
+ "xmc": "xmc-Latn-MZ",
+ "xmd": "xmd-Latn-CM",
+ "xmf": "xmf-Geor-GE",
+ "xmg": "xmg-Latn-CM",
+ "xmh": "xmh-Latn-AU",
+ "xmj": "xmj-Latn-CM",
+ "xmm": "xmm-Latn-ID",
+ "xmn": "xmn-Mani-CN",
+ "xmo": "xmo-Latn-BR",
+ "xmp": "xmp-Latn-AU",
+ "xmq": "xmq-Latn-AU",
+ "xmr": "xmr-Merc-SD",
+ "xmt": "xmt-Latn-ID",
+ "xmu": "xmu-Latn-AU",
+ "xmv": "xmv-Latn-MG",
+ "xmw": "xmw-Latn-MG",
+ "xmx": "xmx-Latn-ID",
+ "xmy": "xmy-Latn-AU",
+ "xmz": "xmz-Latn-ID",
+ "xna": "xna-Narb-SA",
+ "xnb": "xnb-Latn-TW",
+ "xni": "xni-Latn-AU",
+ "xnj": "xnj-Latn-TZ",
+ "xnk": "xnk-Latn-AU",
+ "xnm": "xnm-Latn-AU",
+ "xnn": "xnn-Latn-PH",
+ "xnq": "xnq-Latn-MZ",
+ "xnr": "xnr-Deva-IN",
+ "xnt": "xnt-Latn-US",
+ "xnu": "xnu-Latn-AU",
+ "xny": "xny-Latn-AU",
+ "xnz": "xnz-Latn-EG",
+ "xnz-Arab": "xnz-Arab-EG",
+ "xoc": "xoc-Latn-NG",
+ "xod": "xod-Latn-ID",
+ "xog": "xog-Latn-UG",
+ "xoi": "xoi-Latn-PG",
+ "xok": "xok-Latn-BR",
+ "xom": "xom-Latn-SD",
+ "xom-Ethi": "xom-Ethi-ET",
+ "xon": "xon-Latn-ZZ",
+ "xoo": "xoo-Latn-BR",
+ "xop": "xop-Latn-PG",
+ "xor": "xor-Latn-BR",
+ "xow": "xow-Latn-PG",
+ "xpa": "xpa-Latn-AU",
+ "xpb": "xpb-Latn-AU",
+ "xpd": "xpd-Latn-AU",
+ "xpf": "xpf-Latn-AU",
+ "xpg": "xpg-Grek-TR",
+ "xph": "xph-Latn-AU",
+ "xpi": "xpi-Ogam-GB",
+ "xpj": "xpj-Latn-AU",
+ "xpk": "xpk-Latn-BR",
+ "xpl": "xpl-Latn-AU",
+ "xpm": "xpm-Cyrl-RU",
+ "xpn": "xpn-Latn-BR",
+ "xpo": "xpo-Latn-MX",
+ "xpq": "xpq-Latn-US",
+ "xpr": "xpr-Prti-IR",
+ "xpt": "xpt-Latn-AU",
+ "xpv": "xpv-Latn-AU",
+ "xpw": "xpw-Latn-AU",
+ "xpx": "xpx-Latn-AU",
+ "xpz": "xpz-Latn-AU",
+ "xra": "xra-Latn-BR",
+ "xrb": "xrb-Latn-ZZ",
+ "xrd": "xrd-Latn-AU",
+ "xre": "xre-Latn-BR",
+ "xrg": "xrg-Latn-AU",
+ "xri": "xri-Latn-BR",
+ "xrm": "xrm-Cyrl-RU",
+ "xrn": "xrn-Cyrl-RU",
+ "xrr": "xrr-Latn-IT",
+ "xru": "xru-Latn-AU",
+ "xrw": "xrw-Latn-PG",
+ "xsa": "xsa-Sarb-YE",
+ "xsb": "xsb-Latn-PH",
+ "xse": "xse-Latn-ID",
+ "xsh": "xsh-Latn-NG",
+ "xsi": "xsi-Latn-ZZ",
+ "xsm": "xsm-Latn-ZZ",
+ "xsn": "xsn-Latn-NG",
+ "xsp": "xsp-Latn-PG",
+ "xsq": "xsq-Latn-MZ",
+ "xsr": "xsr-Deva-NP",
+ "xss": "xss-Cyrl-RU",
+ "xsu": "xsu-Latn-VE",
+ "xsy": "xsy-Latn-TW",
+ "xta": "xta-Latn-MX",
+ "xtb": "xtb-Latn-MX",
+ "xtc": "xtc-Latn-SD",
+ "xtd": "xtd-Latn-MX",
+ "xte": "xte-Latn-ID",
+ "xth": "xth-Latn-AU",
+ "xti": "xti-Latn-MX",
+ "xtj": "xtj-Latn-MX",
+ "xtl": "xtl-Latn-MX",
+ "xtm": "xtm-Latn-MX",
+ "xtn": "xtn-Latn-MX",
+ "xtp": "xtp-Latn-MX",
+ "xts": "xts-Latn-MX",
+ "xtt": "xtt-Latn-MX",
+ "xtu": "xtu-Latn-MX",
+ "xtv": "xtv-Latn-AU",
+ "xtw": "xtw-Latn-BR",
+ "xty": "xty-Latn-MX",
+ "xub": "xub-Taml-IN",
+ "xub-Knda": "xub-Knda-IN",
+ "xub-Mlym": "xub-Mlym-IN",
+ "xud": "xud-Latn-AU",
+ "xuj": "xuj-Taml-IN",
+ "xul": "xul-Latn-AU",
+ "xum": "xum-Latn-IT",
+ "xum-Ital": "xum-Ital-IT",
+ "xun": "xun-Latn-AU",
+ "xuo": "xuo-Latn-TD",
+ "xut": "xut-Latn-AU",
+ "xuu": "xuu-Latn-NA",
+ "xve": "xve-Ital-IT",
+ "xvi": "xvi-Arab-AF",
+ "xvn": "xvn-Latn-ES",
+ "xvo": "xvo-Latn-IT",
+ "xvs": "xvs-Latn-IT",
+ "xwa": "xwa-Latn-BR",
+ "xwd": "xwd-Latn-AU",
+ "xwe": "xwe-Latn-ZZ",
+ "xwj": "xwj-Latn-AU",
+ "xwk": "xwk-Latn-AU",
+ "xwl": "xwl-Latn-BJ",
+ "xwo": "xwo-Cyrl-RU",
+ "xwr": "xwr-Latn-ID",
+ "xwt": "xwt-Latn-AU",
+ "xww": "xww-Latn-AU",
+ "xxb": "xxb-Latn-GH",
+ "xxk": "xxk-Latn-ID",
+ "xxm": "xxm-Latn-AU",
+ "xxr": "xxr-Latn-BR",
+ "xxt": "xxt-Latn-ID",
+ "xya": "xya-Latn-AU",
+ "xyb": "xyb-Latn-AU",
+ "xyj": "xyj-Latn-AU",
+ "xyk": "xyk-Latn-AU",
+ "xyl": "xyl-Latn-BR",
+ "xyt": "xyt-Latn-AU",
+ "xyy": "xyy-Latn-AU",
+ "xzh": "xzh-Marc-CN",
+ "xzp": "xzp-Latn-MX",
+ "yaa": "yaa-Latn-PE",
+ "yab": "yab-Latn-BR",
+ "yac": "yac-Latn-ID",
+ "yad": "yad-Latn-PE",
+ "yae": "yae-Latn-VE",
+ "yaf": "yaf-Latn-CD",
+ "yag": "yag-Latn-CL",
+ "yai": "yai-Cyrl-TJ",
+ "yaj": "yaj-Latn-CF",
+ "yak": "yak-Latn-US",
+ "yal": "yal-Latn-GN",
+ "yal-Arab": "yal-Arab-GN",
+ "yam": "yam-Latn-ZZ",
+ "yan": "yan-Latn-NI",
+ "yao": "yao-Latn-MZ",
+ "yap": "yap-Latn-FM",
+ "yaq": "yaq-Latn-MX",
+ "yar": "yar-Latn-VE",
+ "yas": "yas-Latn-ZZ",
+ "yat": "yat-Latn-ZZ",
+ "yau": "yau-Latn-VE",
+ "yav": "yav-Latn-CM",
+ "yaw": "yaw-Latn-BR",
+ "yax": "yax-Latn-AO",
+ "yay": "yay-Latn-ZZ",
+ "yaz": "yaz-Latn-ZZ",
+ "yba": "yba-Latn-ZZ",
+ "ybb": "ybb-Latn-CM",
+ "ybe": "ybe-Latn-CN",
+ "ybe-Ougr": "ybe-Ougr-CN",
+ "ybh": "ybh-Deva-NP",
+ "ybi": "ybi-Deva-NP",
+ "ybj": "ybj-Latn-NG",
+ "ybl": "ybl-Latn-NG",
+ "ybm": "ybm-Latn-PG",
+ "ybn": "ybn-Latn-BR",
+ "ybo": "ybo-Latn-PG",
+ "ybx": "ybx-Latn-PG",
+ "yby": "yby-Latn-ZZ",
+ "ycl": "ycl-Latn-CN",
+ "ycn": "ycn-Latn-CO",
+ "yda": "yda-Latn-AU",
+ "yde": "yde-Latn-PG",
+ "ydg": "ydg-Arab-PK",
+ "ydk": "ydk-Latn-PG",
+ "yea": "yea-Mlym-IN",
+ "yea-Knda": "yea-Knda-IN",
+ "yec": "yec-Latn-DE",
+ "yee": "yee-Latn-PG",
+ "yei": "yei-Latn-CM",
+ "yej": "yej-Grek-IL",
+ "yel": "yel-Latn-CD",
+ "yer": "yer-Latn-ZZ",
+ "yes": "yes-Latn-NG",
+ "yet": "yet-Latn-ID",
+ "yeu": "yeu-Telu-IN",
+ "yev": "yev-Latn-PG",
+ "yey": "yey-Latn-BW",
+ "yga": "yga-Latn-AU",
+ "ygi": "ygi-Latn-AU",
+ "ygl": "ygl-Latn-PG",
+ "ygm": "ygm-Latn-PG",
+ "ygp": "ygp-Plrd-CN",
+ "ygr": "ygr-Latn-ZZ",
+ "ygu": "ygu-Latn-AU",
+ "ygw": "ygw-Latn-ZZ",
+ "yhd": "yhd-Hebr-IL",
+ "yi": "yi-Hebr-001",
+ "yia": "yia-Latn-AU",
+ "yig": "yig-Yiii-CN",
+ "yih": "yih-Hebr-DE",
+ "yii": "yii-Latn-AU",
+ "yij": "yij-Latn-AU",
+ "yil": "yil-Latn-AU",
+ "yim": "yim-Latn-IN",
+ "yir": "yir-Latn-ID",
+ "yis": "yis-Latn-PG",
+ "yiv": "yiv-Yiii-CN",
+ "yka": "yka-Latn-PH",
+ "yka-Arab": "yka-Arab-PH",
+ "ykg": "ykg-Cyrl-RU",
+ "yki": "yki-Latn-ID",
+ "ykk": "ykk-Latn-PG",
+ "ykm": "ykm-Latn-PG",
+ "yko": "yko-Latn-ZZ",
+ "ykr": "ykr-Latn-PG",
+ "yky": "yky-Latn-CF",
+ "yla": "yla-Latn-PG",
+ "ylb": "ylb-Latn-PG",
+ "yle": "yle-Latn-ZZ",
+ "ylg": "ylg-Latn-ZZ",
+ "yli": "yli-Latn-ID",
+ "yll": "yll-Latn-ZZ",
+ "ylr": "ylr-Latn-AU",
+ "ylu": "ylu-Latn-PG",
+ "yly": "yly-Latn-NC",
+ "ymb": "ymb-Latn-PG",
+ "yme": "yme-Latn-PE",
+ "ymg": "ymg-Latn-CD",
+ "ymk": "ymk-Latn-MZ",
+ "ymk-Arab": "ymk-Arab-MZ",
+ "yml": "yml-Latn-ZZ",
+ "ymm": "ymm-Latn-SO",
+ "ymn": "ymn-Latn-ID",
+ "ymo": "ymo-Latn-PG",
+ "ymp": "ymp-Latn-PG",
+ "yna": "yna-Plrd-CN",
+ "ynd": "ynd-Latn-AU",
+ "yng": "yng-Latn-CD",
+ "ynk": "ynk-Cyrl-RU",
+ "ynl": "ynl-Latn-PG",
+ "ynq": "ynq-Latn-NG",
+ "yns": "yns-Latn-CD",
+ "ynu": "ynu-Latn-CO",
+ "yo": "yo-Latn-NG",
+ "yob": "yob-Latn-PG",
+ "yog": "yog-Latn-PH",
+ "yoi": "yoi-Jpan-JP",
+ "yok": "yok-Latn-US",
+ "yol": "yol-Latn-GB",
+ "yom": "yom-Latn-CD",
+ "yon": "yon-Latn-ZZ",
+ "yot": "yot-Latn-NG",
+ "yoy": "yoy-Thai-TH",
+ "yra": "yra-Latn-PG",
+ "yrb": "yrb-Latn-ZZ",
+ "yre": "yre-Latn-ZZ",
+ "yrk": "yrk-Cyrl-RU",
+ "yrl": "yrl-Latn-BR",
+ "yrm": "yrm-Latn-AU",
+ "yro": "yro-Latn-BR",
+ "yrs": "yrs-Latn-ID",
+ "yrw": "yrw-Latn-PG",
+ "yry": "yry-Latn-AU",
+ "ysd": "ysd-Yiii-CN",
+ "ysn": "ysn-Yiii-CN",
+ "ysp": "ysp-Yiii-CN",
+ "ysr": "ysr-Cyrl-RU",
+ "yss": "yss-Latn-ZZ",
+ "ysy": "ysy-Plrd-CN",
+ "ytw": "ytw-Latn-PG",
+ "yty": "yty-Latn-AU",
+ "yua": "yua-Latn-MX",
+ "yub": "yub-Latn-AU",
+ "yuc": "yuc-Latn-US",
+ "yud": "yud-Hebr-IL",
+ "yue": "yue-Hant-HK",
+ "yue-CN": "yue-Hans-CN",
+ "yue-Hans": "yue-Hans-CN",
+ "yuf": "yuf-Latn-US",
+ "yug": "yug-Cyrl-RU",
+ "yui": "yui-Latn-CO",
+ "yuj": "yuj-Latn-ZZ",
+ "yul": "yul-Latn-CF",
+ "yum": "yum-Latn-US",
+ "yun": "yun-Latn-NG",
+ "yup": "yup-Latn-CO",
+ "yuq": "yuq-Latn-BO",
+ "yur": "yur-Latn-US",
+ "yut": "yut-Latn-ZZ",
+ "yuw": "yuw-Latn-ZZ",
+ "yux": "yux-Cyrl-RU",
+ "yuz": "yuz-Latn-BO",
+ "yva": "yva-Latn-ID",
+ "yvt": "yvt-Latn-VE",
+ "ywa": "ywa-Latn-PG",
+ "ywg": "ywg-Latn-AU",
+ "ywn": "ywn-Latn-BR",
+ "ywq": "ywq-Plrd-CN",
+ "ywq-Yiii": "ywq-Yiii-CN",
+ "ywr": "ywr-Latn-AU",
+ "ywu": "ywu-Plrd-CN",
+ "ywu-Yiii": "ywu-Yiii-CN",
+ "yww": "yww-Latn-AU",
+ "yxa": "yxa-Latn-AU",
+ "yxg": "yxg-Latn-AU",
+ "yxl": "yxl-Latn-AU",
+ "yxm": "yxm-Latn-AU",
+ "yxu": "yxu-Latn-AU",
+ "yxy": "yxy-Latn-AU",
+ "yyr": "yyr-Latn-AU",
+ "yyu": "yyu-Latn-PG",
+ "za": "za-Latn-CN",
+ "zaa": "zaa-Latn-MX",
+ "zab": "zab-Latn-MX",
+ "zac": "zac-Latn-MX",
+ "zad": "zad-Latn-MX",
+ "zae": "zae-Latn-MX",
+ "zaf": "zaf-Latn-MX",
+ "zag": "zag-Latn-SD",
+ "zah": "zah-Latn-NG",
+ "zaj": "zaj-Latn-TZ",
+ "zak": "zak-Latn-TZ",
+ "zam": "zam-Latn-MX",
+ "zao": "zao-Latn-MX",
+ "zap": "zap-Latn-MX",
+ "zaq": "zaq-Latn-MX",
+ "zar": "zar-Latn-MX",
+ "zas": "zas-Latn-MX",
+ "zat": "zat-Latn-MX",
+ "zau": "zau-Tibt-IN",
+ "zau-Arab": "zau-Arab-IN",
+ "zav": "zav-Latn-MX",
+ "zaw": "zaw-Latn-MX",
+ "zax": "zax-Latn-MX",
+ "zay": "zay-Latn-ET",
+ "zay-Ethi": "zay-Ethi-ET",
+ "zaz": "zaz-Latn-NG",
+ "zba": "zba-Arab-001",
+ "zbc": "zbc-Latn-MY",
+ "zbe": "zbe-Latn-MY",
+ "zbt": "zbt-Latn-ID",
+ "zbu": "zbu-Latn-NG",
+ "zbw": "zbw-Latn-MY",
+ "zca": "zca-Latn-MX",
+ "zch": "zch-Hani-CN",
+ "zdj": "zdj-Arab-KM",
+ "zea": "zea-Latn-NL",
+ "zeg": "zeg-Latn-PG",
+ "zeh": "zeh-Hani-CN",
+ "zen": "zen-Tfng-MR",
+ "zen-Arab": "zen-Arab-MR",
+ "zga": "zga-Latn-TZ",
+ "zgb": "zgb-Hani-CN",
+ "zgh": "zgh-Tfng-MA",
+ "zgm": "zgm-Hani-CN",
+ "zgn": "zgn-Hani-CN",
+ "zgr": "zgr-Latn-PG",
+ "zh": "zh-Hans-CN",
+ "zh-AU": "zh-Hant-AU",
+ "zh-BN": "zh-Hant-BN",
+ "zh-Bopo": "zh-Bopo-TW",
+ "zh-GB": "zh-Hant-GB",
+ "zh-GF": "zh-Hant-GF",
+ "zh-HK": "zh-Hant-HK",
+ "zh-Hanb": "zh-Hanb-TW",
+ "zh-Hant": "zh-Hant-TW",
+ "zh-ID": "zh-Hant-ID",
+ "zh-MO": "zh-Hant-MO",
+ "zh-PA": "zh-Hant-PA",
+ "zh-PF": "zh-Hant-PF",
+ "zh-PH": "zh-Hant-PH",
+ "zh-SR": "zh-Hant-SR",
+ "zh-TH": "zh-Hant-TH",
+ "zh-TW": "zh-Hant-TW",
+ "zh-US": "zh-Hant-US",
+ "zh-VN": "zh-Hant-VN",
+ "zhd": "zhd-Hani-CN",
+ "zhd-Latn": "zhd-Latn-VN",
+ "zhi": "zhi-Latn-NG",
+ "zhn": "zhn-Latn-CN",
+ "zhn-Hani": "zhn-Hani-CN",
+ "zhw": "zhw-Latn-CM",
+ "zhx": "zhx-Nshu-CN",
+ "zia": "zia-Latn-ZZ",
+ "zik": "zik-Latn-PG",
+ "zil": "zil-Latn-GN",
+ "zim": "zim-Latn-TD",
+ "zin": "zin-Latn-TZ",
+ "ziw": "ziw-Latn-TZ",
+ "ziz": "ziz-Latn-NG",
+ "zka": "zka-Latn-ID",
+ "zkb": "zkb-Cyrl-RU",
+ "zkd": "zkd-Latn-MM",
+ "zko": "zko-Cyrl-RU",
+ "zkp": "zkp-Latn-BR",
+ "zkt": "zkt-Kits-CN",
+ "zku": "zku-Latn-AU",
+ "zkz": "zkz-Cyrl-RU",
+ "zla": "zla-Latn-CD",
+ "zlj": "zlj-Hani-CN",
+ "zlj-Latn": "zlj-Latn-CN",
+ "zlm": "zlm-Latn-TG",
+ "zln": "zln-Hani-CN",
+ "zlq": "zlq-Hani-CN",
+ "zma": "zma-Latn-AU",
+ "zmb": "zmb-Latn-CD",
+ "zmc": "zmc-Latn-AU",
+ "zmd": "zmd-Latn-AU",
+ "zme": "zme-Latn-AU",
+ "zmf": "zmf-Latn-CD",
+ "zmg": "zmg-Latn-AU",
+ "zmh": "zmh-Latn-PG",
+ "zmi": "zmi-Latn-MY",
+ "zmj": "zmj-Latn-AU",
+ "zmk": "zmk-Latn-AU",
+ "zml": "zml-Latn-AU",
+ "zmm": "zmm-Latn-AU",
+ "zmn": "zmn-Latn-GA",
+ "zmo": "zmo-Latn-SD",
+ "zmp": "zmp-Latn-CD",
+ "zmq": "zmq-Latn-CD",
+ "zmr": "zmr-Latn-AU",
+ "zms": "zms-Latn-CD",
+ "zmt": "zmt-Latn-AU",
+ "zmu": "zmu-Latn-AU",
+ "zmv": "zmv-Latn-AU",
+ "zmw": "zmw-Latn-CD",
+ "zmx": "zmx-Latn-CG",
+ "zmy": "zmy-Latn-AU",
+ "zmz": "zmz-Latn-CD",
+ "zna": "zna-Latn-TD",
+ "zne": "zne-Latn-ZZ",
+ "zng": "zng-Latn-VN",
+ "znk": "znk-Latn-AU",
+ "zns": "zns-Latn-NG",
+ "zoc": "zoc-Latn-MX",
+ "zoh": "zoh-Latn-MX",
+ "zom": "zom-Latn-IN",
+ "zoo": "zoo-Latn-MX",
+ "zoq": "zoq-Latn-MX",
+ "zor": "zor-Latn-MX",
+ "zos": "zos-Latn-MX",
+ "zpa": "zpa-Latn-MX",
+ "zpb": "zpb-Latn-MX",
+ "zpc": "zpc-Latn-MX",
+ "zpd": "zpd-Latn-MX",
+ "zpe": "zpe-Latn-MX",
+ "zpf": "zpf-Latn-MX",
+ "zpg": "zpg-Latn-MX",
+ "zph": "zph-Latn-MX",
+ "zpi": "zpi-Latn-MX",
+ "zpj": "zpj-Latn-MX",
+ "zpk": "zpk-Latn-MX",
+ "zpl": "zpl-Latn-MX",
+ "zpm": "zpm-Latn-MX",
+ "zpn": "zpn-Latn-MX",
+ "zpo": "zpo-Latn-MX",
+ "zpp": "zpp-Latn-MX",
+ "zpq": "zpq-Latn-MX",
+ "zpr": "zpr-Latn-MX",
+ "zps": "zps-Latn-MX",
+ "zpt": "zpt-Latn-MX",
+ "zpu": "zpu-Latn-MX",
+ "zpv": "zpv-Latn-MX",
+ "zpw": "zpw-Latn-MX",
+ "zpx": "zpx-Latn-MX",
+ "zpy": "zpy-Latn-MX",
+ "zpz": "zpz-Latn-MX",
+ "zqe": "zqe-Hani-CN",
+ "zqe-Latn": "zqe-Latn-CN",
+ "zrn": "zrn-Latn-TD",
+ "zro": "zro-Latn-EC",
+ "zrp": "zrp-Hebr-FR",
+ "zrs": "zrs-Latn-ID",
+ "zsa": "zsa-Latn-PG",
+ "zsr": "zsr-Latn-MX",
+ "zsu": "zsu-Latn-PG",
+ "zte": "zte-Latn-MX",
+ "ztg": "ztg-Latn-MX",
+ "ztl": "ztl-Latn-MX",
+ "ztm": "ztm-Latn-MX",
+ "ztn": "ztn-Latn-MX",
+ "ztp": "ztp-Latn-MX",
+ "ztq": "ztq-Latn-MX",
+ "zts": "zts-Latn-MX",
+ "ztt": "ztt-Latn-MX",
+ "ztu": "ztu-Latn-MX",
+ "ztx": "ztx-Latn-MX",
+ "zty": "zty-Latn-MX",
+ "zu": "zu-Latn-ZA",
+ "zua": "zua-Latn-NG",
+ "zuh": "zuh-Latn-PG",
+ "zum": "zum-Arab-OM",
+ "zun": "zun-Latn-US",
+ "zuy": "zuy-Latn-CM",
+ "zyg": "zyg-Hani-CN",
+ "zyj": "zyj-Latn-CN",
+ "zyj-Hani": "zyj-Hani-CN",
+ "zyn": "zyn-Hani-CN",
+ "zyp": "zyp-Latn-MM",
+ "zza": "zza-Latn-TR",
+ "zzj": "zzj-Hani-CN",
+};
+
+// Extracted from likelySubtags.xml.
+// Derived from CLDR Supplemental Data, version 43.
+// https://unicode.org/Public/cldr/43/cldr-common-43.0.zip
+var minLikelySubtags = {
+ "aa-Latn-DJ": "aa-DJ",
+ "aa-Latn-ET": "aa",
+ "aaa-Latn-NG": "aaa",
+ "aab-Latn-NG": "aab",
+ "aac-Latn-PG": "aac",
+ "aad-Latn-PG": "aad",
+ "aae-Grek-IT": "aae-Grek",
+ "aae-Latn-IT": "aae",
+ "aaf-Arab-IN": "aaf-Arab",
+ "aaf-Mlym-IN": "aaf",
+ "aag-Latn-PG": "aag",
+ "aah-Latn-PG": "aah",
+ "aai-Latn-ZZ": "aai",
+ "aak-Latn-ZZ": "aak",
+ "aal-Latn-CM": "aal",
+ "aan-Latn-BR": "aan",
+ "aao-Arab-DZ": "aao",
+ "aap-Latn-BR": "aap",
+ "aaq-Latn-US": "aaq",
+ "aas-Latn-TZ": "aas",
+ "aat-Grek-GR": "aat",
+ "aau-Latn-ZZ": "aau",
+ "aaw-Latn-PG": "aaw",
+ "aax-Latn-ID": "aax",
+ "aaz-Latn-ID": "aaz",
+ "ab-Cyrl-GE": "ab",
+ "aba-Latn-CI": "aba",
+ "abb-Latn-CM": "abb",
+ "abc-Latn-PH": "abc",
+ "abd-Latn-PH": "abd",
+ "abe-Latn-CA": "abe",
+ "abf-Latn-MY": "abf",
+ "abg-Latn-PG": "abg",
+ "abh-Arab-TJ": "abh",
+ "abi-Latn-ZZ": "abi",
+ "abl-Latn-ID": "abl-Latn",
+ "abl-Rjng-ID": "abl",
+ "abm-Latn-NG": "abm",
+ "abn-Latn-NG": "abn",
+ "abo-Latn-NG": "abo",
+ "abp-Latn-PH": "abp",
+ "abq-Cyrl-ZZ": "abq",
+ "abr-Latn-GH": "abr",
+ "abs-Latn-ID": "abs",
+ "abt-Latn-ZZ": "abt",
+ "abu-Latn-CI": "abu",
+ "abv-Arab-BH": "abv",
+ "abw-Latn-PG": "abw",
+ "abx-Latn-PH": "abx",
+ "aby-Latn-ZZ": "aby",
+ "abz-Latn-ID": "abz",
+ "aca-Latn-CO": "aca",
+ "acb-Latn-NG": "acb",
+ "acd-Latn-ZZ": "acd",
+ "ace-Latn-ID": "ace",
+ "acf-Latn-LC": "acf",
+ "ach-Latn-UG": "ach",
+ "acm-Arab-IQ": "acm",
+ "acn-Latn-CN": "acn",
+ "acp-Latn-NG": "acp",
+ "acq-Arab-YE": "acq",
+ "acr-Latn-GT": "acr",
+ "acs-Latn-BR": "acs",
+ "act-Latn-NL": "act",
+ "acu-Latn-EC": "acu",
+ "acv-Latn-US": "acv",
+ "acw-Arab-SA": "acw",
+ "acx-Arab-OM": "acx",
+ "acy-Arab-CY": "acy-Arab",
+ "acy-Grek-CY": "acy-Grek",
+ "acy-Latn-CY": "acy",
+ "acz-Latn-SD": "acz",
+ "ada-Latn-GH": "ada",
+ "adb-Latn-TL": "adb",
+ "add-Latn-CM": "add",
+ "ade-Latn-ZZ": "ade",
+ "adf-Arab-OM": "adf",
+ "adg-Latn-AU": "adg",
+ "adh-Latn-UG": "adh",
+ "adi-Latn-IN": "adi",
+ "adi-Tibt-CN": "adi-Tibt",
+ "adj-Latn-ZZ": "adj",
+ "adl-Latn-IN": "adl",
+ "adn-Latn-ID": "adn",
+ "ado-Latn-PG": "ado",
+ "adq-Latn-GH": "adq",
+ "adr-Latn-ID": "adr",
+ "adt-Latn-AU": "adt",
+ "adu-Latn-NG": "adu",
+ "adw-Latn-BR": "adw",
+ "adx-Tibt-CN": "adx",
+ "ady-Cyrl-RU": "ady",
+ "adz-Latn-ZZ": "adz",
+ "ae-Avst-IR": "ae",
+ "aea-Latn-AU": "aea",
+ "aeb-Arab-TN": "aeb",
+ "aec-Arab-EG": "aec",
+ "aee-Arab-AF": "aee",
+ "aek-Latn-NC": "aek",
+ "ael-Latn-CM": "ael",
+ "aem-Latn-VN": "aem",
+ "aeq-Arab-PK": "aeq",
+ "aer-Latn-AU": "aer",
+ "aeu-Latn-CN": "aeu",
+ "aew-Latn-PG": "aew",
+ "aey-Latn-ZZ": "aey",
+ "aez-Latn-PG": "aez",
+ "af-Latn-NA": "af-NA",
+ "af-Latn-ZA": "af",
+ "afb-Arab-KW": "afb",
+ "afd-Latn-PG": "afd",
+ "afe-Latn-NG": "afe",
+ "afh-Latn-GH": "afh",
+ "afi-Latn-PG": "afi",
+ "afk-Latn-PG": "afk",
+ "afn-Latn-NG": "afn",
+ "afo-Latn-NG": "afo",
+ "afp-Latn-PG": "afp",
+ "afs-Latn-MX": "afs",
+ "afu-Latn-GH": "afu",
+ "afz-Latn-ID": "afz",
+ "aga-Latn-PE": "aga",
+ "agb-Latn-NG": "agb",
+ "agc-Latn-ZZ": "agc",
+ "agd-Latn-ZZ": "agd",
+ "age-Latn-PG": "age",
+ "agf-Latn-ID": "agf",
+ "agg-Latn-ZZ": "agg",
+ "agh-Latn-CD": "agh",
+ "agi-Deva-IN": "agi",
+ "agj-Arab-ET": "agj-Arab",
+ "agj-Ethi-ET": "agj",
+ "agk-Latn-PH": "agk",
+ "agl-Latn-PG": "agl",
+ "agm-Latn-ZZ": "agm",
+ "agn-Latn-PH": "agn",
+ "ago-Latn-ZZ": "ago",
+ "agq-Latn-CM": "agq",
+ "agr-Latn-PE": "agr",
+ "ags-Latn-CM": "ags",
+ "agt-Latn-PH": "agt",
+ "agu-Latn-GT": "agu",
+ "agv-Latn-PH": "agv",
+ "agw-Latn-SB": "agw",
+ "agx-Cyrl-RU": "agx",
+ "agy-Latn-PH": "agy",
+ "agz-Latn-PH": "agz",
+ "aha-Latn-ZZ": "aha",
+ "ahb-Latn-VU": "ahb",
+ "ahg-Ethi-ET": "ahg",
+ "ahh-Latn-ID": "ahh",
+ "ahi-Latn-CI": "ahi",
+ "ahk-Latn-MM": "ahk",
+ "ahk-Latn-TH": "ahk-TH",
+ "ahk-Mymr-MM": "ahk-Mymr",
+ "ahk-Thai-TH": "ahk-Thai",
+ "ahl-Latn-ZZ": "ahl",
+ "ahm-Latn-CI": "ahm",
+ "ahn-Latn-NG": "ahn",
+ "aho-Ahom-IN": "aho",
+ "ahp-Latn-CI": "ahp",
+ "ahr-Deva-IN": "ahr",
+ "ahs-Latn-NG": "ahs",
+ "aht-Latn-US": "aht",
+ "aia-Latn-SB": "aia",
+ "aib-Arab-CN": "aib",
+ "aic-Latn-PG": "aic",
+ "aid-Latn-AU": "aid",
+ "aie-Latn-PG": "aie",
+ "aif-Latn-PG": "aif",
+ "aig-Latn-AG": "aig",
+ "aij-Hebr-IL": "aij",
+ "aik-Latn-NG": "aik",
+ "ail-Latn-PG": "ail",
+ "aim-Latn-IN": "aim",
+ "ain-Kana-JP": "ain",
+ "ain-Latn-JP": "ain-Latn",
+ "aio-Mymr-IN": "aio",
+ "aip-Latn-ID": "aip",
+ "aiq-Arab-AF": "aiq",
+ "air-Latn-ID": "air",
+ "ait-Latn-BR": "ait",
+ "aiw-Arab-ET": "aiw-Arab",
+ "aiw-Ethi-ET": "aiw-Ethi",
+ "aiw-Latn-ET": "aiw",
+ "aix-Latn-PG": "aix",
+ "aiy-Latn-CF": "aiy",
+ "aja-Latn-SS": "aja",
+ "ajg-Latn-ZZ": "ajg",
+ "aji-Latn-NC": "aji",
+ "ajn-Latn-AU": "ajn",
+ "ajp-Arab-JO": "ajp",
+ "ajw-Latn-NG": "ajw",
+ "ajz-Latn-IN": "ajz",
+ "ak-Latn-GH": "ak",
+ "akb-Batk-ID": "akb-Batk",
+ "akb-Latn-ID": "akb",
+ "akc-Latn-ID": "akc",
+ "akd-Latn-NG": "akd",
+ "ake-Latn-GY": "ake",
+ "akf-Latn-NG": "akf",
+ "akg-Latn-ID": "akg",
+ "akh-Latn-PG": "akh",
+ "aki-Latn-PG": "aki",
+ "akk-Xsux-IQ": "akk",
+ "akl-Latn-PH": "akl",
+ "ako-Latn-SR": "ako",
+ "akp-Latn-GH": "akp",
+ "akq-Latn-PG": "akq",
+ "akr-Latn-VU": "akr",
+ "aks-Latn-TG": "aks",
+ "akt-Latn-PG": "akt",
+ "aku-Latn-CM": "aku",
+ "akv-Cyrl-RU": "akv",
+ "akw-Latn-CG": "akw",
+ "akz-Latn-US": "akz",
+ "ala-Latn-ZZ": "ala",
+ "alc-Latn-CL": "alc",
+ "ald-Latn-CI": "ald",
+ "ale-Latn-US": "ale",
+ "alf-Latn-NG": "alf",
+ "alh-Latn-AU": "alh",
+ "ali-Latn-ZZ": "ali",
+ "alj-Latn-PH": "alj",
+ "alk-Laoo-LA": "alk",
+ "all-Mlym-IN": "all",
+ "alm-Latn-VU": "alm",
+ "aln-Latn-XK": "aln",
+ "alo-Latn-ID": "alo",
+ "alp-Latn-ID": "alp",
+ "alq-Latn-CA": "alq",
+ "alr-Cyrl-RU": "alr",
+ "alt-Cyrl-RU": "alt",
+ "alu-Latn-SB": "alu",
+ "alw-Ethi-ET": "alw",
+ "alx-Latn-PG": "alx",
+ "aly-Latn-AU": "aly",
+ "alz-Latn-CD": "alz",
+ "am-Ethi-ET": "am",
+ "ama-Latn-BR": "ama",
+ "amb-Latn-NG": "amb",
+ "amc-Latn-PE": "amc",
+ "ame-Latn-PE": "ame",
+ "amf-Ethi-ET": "amf-Ethi",
+ "amf-Latn-ET": "amf",
+ "amg-Latn-AU": "amg",
+ "ami-Latn-TW": "ami",
+ "amj-Latn-TD": "amj",
+ "amk-Latn-ID": "amk",
+ "amm-Latn-ZZ": "amm",
+ "amn-Latn-ZZ": "amn",
+ "amo-Latn-NG": "amo",
+ "amp-Latn-ZZ": "amp",
+ "amq-Latn-ID": "amq",
+ "amr-Latn-PE": "amr",
+ "ams-Jpan-JP": "ams",
+ "amt-Latn-PG": "amt",
+ "amu-Latn-MX": "amu",
+ "amv-Latn-ID": "amv",
+ "amw-Arab-SY": "amw-Arab",
+ "amw-Armi-SY": "amw-Armi",
+ "amw-Latn-SY": "amw-Latn",
+ "amw-Syrc-SY": "amw",
+ "amx-Latn-AU": "amx",
+ "amy-Latn-AU": "amy",
+ "amz-Latn-AU": "amz",
+ "an-Latn-ES": "an",
+ "ana-Latn-CO": "ana",
+ "anb-Latn-PE": "anb",
+ "anc-Latn-ZZ": "anc",
+ "and-Latn-ID": "and",
+ "ane-Latn-NC": "ane",
+ "anf-Latn-GH": "anf",
+ "ang-Latn-GB": "ang",
+ "anh-Latn-PG": "anh",
+ "ani-Cyrl-RU": "ani",
+ "anj-Latn-PG": "anj",
+ "ank-Latn-ZZ": "ank",
+ "anl-Latn-MM": "anl",
+ "anm-Latn-IN": "anm",
+ "ann-Latn-NG": "ann",
+ "ano-Latn-CO": "ano",
+ "anp-Deva-IN": "anp",
+ "anr-Deva-IN": "anr",
+ "ans-Latn-CO": "ans",
+ "ant-Latn-AU": "ant",
+ "anu-Arab-SS": "anu-Arab",
+ "anu-Ethi-ET": "anu",
+ "anu-Latn-SS": "anu-Latn",
+ "anv-Latn-CM": "anv",
+ "anw-Latn-NG": "anw",
+ "anx-Latn-PG": "anx",
+ "any-Latn-ZZ": "any",
+ "anz-Latn-PG": "anz",
+ "aoa-Latn-ST": "aoa",
+ "aob-Latn-PG": "aob",
+ "aoc-Latn-VE": "aoc",
+ "aod-Latn-PG": "aod",
+ "aoe-Latn-PG": "aoe",
+ "aof-Latn-PG": "aof",
+ "aog-Latn-PG": "aog",
+ "aoi-Latn-AU": "aoi",
+ "aoj-Latn-ZZ": "aoj",
+ "aok-Latn-NC": "aok",
+ "aol-Latn-ID": "aol",
+ "aom-Latn-ZZ": "aom",
+ "aon-Latn-PG": "aon",
+ "aor-Latn-VU": "aor",
+ "aos-Latn-ID": "aos",
+ "aot-Beng-BD": "aot",
+ "aot-Latn-IN": "aot-Latn",
+ "aox-Latn-GY": "aox",
+ "aoz-Latn-ID": "aoz",
+ "apb-Latn-SB": "apb",
+ "apc-Arab-SY": "apc",
+ "apc-Arab-TR": "apc-TR",
+ "apd-Arab-TG": "apd",
+ "ape-Latn-ZZ": "ape",
+ "apf-Latn-PH": "apf",
+ "apg-Latn-ID": "apg",
+ "aph-Deva-NP": "aph",
+ "api-Latn-BR": "api",
+ "apj-Latn-US": "apj",
+ "apk-Latn-US": "apk",
+ "apl-Latn-US": "apl",
+ "apm-Latn-US": "apm",
+ "apn-Latn-BR": "apn",
+ "apo-Latn-PG": "apo",
+ "app-Latn-VU": "app",
+ "apr-Latn-ZZ": "apr",
+ "aps-Latn-ZZ": "aps",
+ "apt-Latn-IN": "apt",
+ "apu-Latn-BR": "apu",
+ "apv-Latn-BR": "apv",
+ "apw-Latn-US": "apw",
+ "apx-Latn-ID": "apx",
+ "apy-Latn-BR": "apy",
+ "apz-Latn-ZZ": "apz",
+ "aqc-Cyrl-RU": "aqc",
+ "aqd-Latn-ML": "aqd",
+ "aqg-Latn-NG": "aqg",
+ "aqk-Latn-NG": "aqk",
+ "aqm-Latn-ID": "aqm",
+ "aqn-Latn-PH": "aqn",
+ "aqr-Latn-NC": "aqr",
+ "aqt-Latn-PY": "aqt",
+ "aqz-Latn-BR": "aqz",
+ "ar-Arab-AE": "ar-AE",
+ "ar-Arab-BH": "ar-BH",
+ "ar-Arab-DZ": "ar-DZ",
+ "ar-Arab-EG": "ar",
+ "ar-Arab-EH": "ar-EH",
+ "ar-Arab-IQ": "ar-IQ",
+ "ar-Arab-JO": "ar-JO",
+ "ar-Arab-KM": "ar-KM",
+ "ar-Arab-KW": "ar-KW",
+ "ar-Arab-LB": "ar-LB",
+ "ar-Arab-LY": "ar-LY",
+ "ar-Arab-MA": "ar-MA",
+ "ar-Arab-MR": "ar-MR",
+ "ar-Arab-OM": "ar-OM",
+ "ar-Arab-PS": "ar-PS",
+ "ar-Arab-QA": "ar-QA",
+ "ar-Arab-SA": "ar-SA",
+ "ar-Arab-SD": "ar-SD",
+ "ar-Arab-SY": "ar-SY",
+ "ar-Arab-TN": "ar-TN",
+ "ar-Arab-YE": "ar-YE",
+ "arc-Armi-IR": "arc",
+ "arc-Elym-IR": "arc-Elym",
+ "arc-Nbat-JO": "arc-Nbat",
+ "arc-Palm-SY": "arc-Palm",
+ "ard-Latn-AU": "ard",
+ "are-Latn-AU": "are",
+ "arh-Latn-ZZ": "arh",
+ "ari-Latn-US": "ari",
+ "arj-Latn-BR": "arj",
+ "ark-Latn-BR": "ark",
+ "arl-Latn-PE": "arl",
+ "arn-Latn-CL": "arn",
+ "aro-Latn-BO": "aro",
+ "arp-Latn-US": "arp",
+ "arq-Arab-DZ": "arq",
+ "arr-Latn-BR": "arr",
+ "ars-Arab-SA": "ars",
+ "aru-Latn-BR": "aru",
+ "arw-Latn-SR": "arw",
+ "arx-Latn-BR": "arx",
+ "ary-Arab-MA": "ary",
+ "arz-Arab-EG": "arz",
+ "as-Beng-IN": "as",
+ "asa-Latn-TZ": "asa",
+ "asb-Latn-CA": "asb",
+ "asc-Latn-ID": "asc",
+ "ase-Sgnw-US": "ase",
+ "asg-Latn-ZZ": "asg",
+ "ash-Latn-PE": "ash",
+ "asi-Latn-ID": "asi",
+ "asj-Latn-CM": "asj",
+ "ask-Arab-AF": "ask",
+ "asl-Latn-ID": "asl",
+ "asn-Latn-BR": "asn",
+ "aso-Latn-ZZ": "aso",
+ "ass-Latn-CM": "ass",
+ "ast-Latn-ES": "ast",
+ "asu-Latn-BR": "asu",
+ "asv-Latn-CD": "asv",
+ "asx-Latn-PG": "asx",
+ "asy-Latn-ID": "asy",
+ "asz-Latn-ID": "asz",
+ "ata-Latn-ZZ": "ata",
+ "atb-Latn-CN": "atb",
+ "atb-Lisu-CN": "atb-Lisu",
+ "atc-Latn-PE": "atc",
+ "atd-Latn-PH": "atd",
+ "ate-Latn-PG": "ate",
+ "atg-Latn-ZZ": "atg",
+ "ati-Latn-CI": "ati",
+ "atj-Latn-CA": "atj",
+ "atk-Latn-PH": "atk",
+ "atl-Latn-PH": "atl",
+ "atm-Latn-PH": "atm",
+ "atn-Arab-IR": "atn",
+ "ato-Latn-CM": "ato",
+ "atp-Latn-PH": "atp",
+ "atq-Latn-ID": "atq",
+ "atr-Latn-BR": "atr",
+ "ats-Latn-US": "ats",
+ "att-Latn-PH": "att",
+ "atu-Latn-SS": "atu",
+ "atv-Cyrl-RU": "atv",
+ "atw-Latn-US": "atw",
+ "atx-Latn-BR": "atx",
+ "aty-Latn-VU": "aty",
+ "atz-Latn-PH": "atz",
+ "aua-Latn-SB": "aua",
+ "auc-Latn-EC": "auc",
+ "aud-Latn-SB": "aud",
+ "aug-Latn-BJ": "aug",
+ "auh-Latn-ZM": "auh",
+ "aui-Latn-PG": "aui",
+ "auj-Arab-LY": "auj",
+ "auj-Latn-LY": "auj-Latn",
+ "auj-Tfng-LY": "auj-Tfng",
+ "auk-Latn-PG": "auk",
+ "aul-Latn-VU": "aul",
+ "aum-Latn-NG": "aum",
+ "aun-Latn-PG": "aun",
+ "auo-Latn-NG": "auo",
+ "aup-Latn-PG": "aup",
+ "auq-Latn-ID": "auq",
+ "aur-Latn-PG": "aur",
+ "aut-Latn-PF": "aut",
+ "auu-Latn-ID": "auu",
+ "auw-Latn-ID": "auw",
+ "auy-Latn-ZZ": "auy",
+ "auz-Arab-UZ": "auz",
+ "av-Cyrl-RU": "av",
+ "avb-Latn-PG": "avb",
+ "avd-Arab-IR": "avd",
+ "avi-Latn-CI": "avi",
+ "avk-Latn-001": "avk",
+ "avl-Arab-ZZ": "avl",
+ "avm-Latn-AU": "avm",
+ "avn-Latn-ZZ": "avn",
+ "avo-Latn-BR": "avo",
+ "avs-Latn-PE": "avs",
+ "avt-Latn-ZZ": "avt",
+ "avu-Latn-ZZ": "avu",
+ "avv-Latn-BR": "avv",
+ "awa-Deva-IN": "awa",
+ "awb-Latn-ZZ": "awb",
+ "awc-Latn-NG": "awc",
+ "awe-Latn-BR": "awe",
+ "awg-Latn-AU": "awg",
+ "awh-Latn-ID": "awh",
+ "awi-Latn-PG": "awi",
+ "awk-Latn-AU": "awk",
+ "awm-Latn-PG": "awm",
+ "awn-Ethi-ET": "awn",
+ "awo-Latn-ZZ": "awo",
+ "awr-Latn-ID": "awr",
+ "aws-Latn-ID": "aws",
+ "awt-Latn-BR": "awt",
+ "awu-Latn-ID": "awu",
+ "awv-Latn-ID": "awv",
+ "aww-Latn-PG": "aww",
+ "awx-Latn-ZZ": "awx",
+ "awy-Latn-ID": "awy",
+ "axb-Latn-AR": "axb",
+ "axe-Latn-AU": "axe",
+ "axg-Latn-BR": "axg",
+ "axk-Latn-CF": "axk",
+ "axl-Latn-AU": "axl",
+ "axm-Armn-AM": "axm",
+ "axx-Latn-NC": "axx",
+ "ay-Latn-BO": "ay",
+ "aya-Latn-PG": "aya",
+ "ayb-Latn-ZZ": "ayb",
+ "ayc-Latn-PE": "ayc",
+ "ayd-Latn-AU": "ayd",
+ "aye-Latn-NG": "aye",
+ "ayg-Latn-TG": "ayg",
+ "ayh-Arab-YE": "ayh",
+ "ayi-Latn-NG": "ayi",
+ "ayk-Latn-NG": "ayk",
+ "ayl-Arab-LY": "ayl",
+ "ayn-Arab-YE": "ayn",
+ "ayo-Latn-PY": "ayo",
+ "ayp-Arab-IQ": "ayp",
+ "ayq-Latn-PG": "ayq",
+ "ays-Latn-PH": "ays",
+ "ayt-Latn-PH": "ayt",
+ "ayu-Latn-NG": "ayu",
+ "ayz-Latn-ID": "ayz",
+ "az-Arab-IQ": "az-IQ",
+ "az-Arab-IR": "az-IR",
+ "az-Cyrl-RU": "az-RU",
+ "az-Latn-AZ": "az",
+ "azb-Arab-IR": "azb",
+ "azb-Cyrl-AZ": "azb-Cyrl",
+ "azb-Latn-AZ": "azb-Latn",
+ "azd-Latn-MX": "azd",
+ "azg-Latn-MX": "azg",
+ "azm-Latn-MX": "azm",
+ "azn-Latn-MX": "azn",
+ "azo-Latn-CM": "azo",
+ "azt-Latn-PH": "azt",
+ "azz-Latn-MX": "azz",
+ "ba-Cyrl-RU": "ba",
+ "baa-Latn-SB": "baa",
+ "bab-Latn-GW": "bab",
+ "bac-Latn-ID": "bac",
+ "bae-Latn-VE": "bae",
+ "baf-Latn-CM": "baf",
+ "bag-Latn-CM": "bag",
+ "bah-Latn-BS": "bah",
+ "baj-Latn-ID": "baj",
+ "bal-Arab-PK": "bal",
+ "ban-Bali-ID": "ban-Bali",
+ "ban-Latn-ID": "ban",
+ "bao-Latn-CO": "bao",
+ "bap-Deva-NP": "bap",
+ "bar-Latn-AT": "bar",
+ "bas-Latn-CM": "bas",
+ "bau-Latn-NG": "bau",
+ "bav-Latn-ZZ": "bav",
+ "baw-Latn-CM": "baw",
+ "bax-Bamu-CM": "bax",
+ "bay-Latn-ID": "bay",
+ "bba-Latn-ZZ": "bba",
+ "bbb-Latn-ZZ": "bbb",
+ "bbc-Batk-ID": "bbc-Batk",
+ "bbc-Latn-ID": "bbc",
+ "bbd-Latn-ZZ": "bbd",
+ "bbe-Latn-CD": "bbe",
+ "bbf-Latn-PG": "bbf",
+ "bbg-Latn-GA": "bbg",
+ "bbi-Latn-CM": "bbi",
+ "bbj-Latn-CM": "bbj",
+ "bbk-Latn-CM": "bbk",
+ "bbl-Geor-GE": "bbl",
+ "bbm-Latn-CD": "bbm",
+ "bbn-Latn-PG": "bbn",
+ "bbo-Latn-BF": "bbo",
+ "bbp-Latn-ZZ": "bbp",
+ "bbq-Latn-CM": "bbq",
+ "bbr-Latn-ZZ": "bbr",
+ "bbs-Latn-NG": "bbs",
+ "bbt-Latn-NG": "bbt",
+ "bbu-Latn-NG": "bbu",
+ "bbv-Latn-PG": "bbv",
+ "bbw-Latn-CM": "bbw",
+ "bbx-Latn-CM": "bbx",
+ "bby-Latn-CM": "bby",
+ "bca-Hani-CN": "bca-Hani",
+ "bca-Latn-CN": "bca",
+ "bcb-Latn-SN": "bcb",
+ "bcd-Latn-ID": "bcd",
+ "bce-Latn-CM": "bce",
+ "bcf-Latn-ZZ": "bcf",
+ "bcg-Latn-GN": "bcg",
+ "bch-Latn-ZZ": "bch",
+ "bci-Latn-CI": "bci",
+ "bcj-Latn-AU": "bcj",
+ "bck-Latn-AU": "bck",
+ "bcm-Latn-ZZ": "bcm",
+ "bcn-Latn-ZZ": "bcn",
+ "bco-Latn-ZZ": "bco",
+ "bcp-Latn-CD": "bcp",
+ "bcq-Ethi-ZZ": "bcq",
+ "bcr-Latn-CA": "bcr",
+ "bcs-Latn-NG": "bcs",
+ "bct-Latn-CD": "bct",
+ "bcu-Latn-ZZ": "bcu",
+ "bcv-Latn-NG": "bcv",
+ "bcw-Latn-CM": "bcw",
+ "bcy-Latn-NG": "bcy",
+ "bcz-Latn-SN": "bcz",
+ "bda-Latn-SN": "bda",
+ "bdb-Latn-ID": "bdb",
+ "bdc-Latn-CO": "bdc",
+ "bdd-Latn-ZZ": "bdd",
+ "bde-Latn-NG": "bde",
+ "bdf-Latn-PG": "bdf",
+ "bdg-Latn-MY": "bdg",
+ "bdh-Latn-SS": "bdh",
+ "bdi-Latn-SD": "bdi",
+ "bdj-Latn-SS": "bdj",
+ "bdk-Latn-AZ": "bdk",
+ "bdl-Latn-ID": "bdl",
+ "bdm-Latn-TD": "bdm",
+ "bdn-Latn-CM": "bdn",
+ "bdo-Latn-TD": "bdo",
+ "bdp-Latn-TZ": "bdp",
+ "bdq-Latn-VN": "bdq",
+ "bdr-Latn-MY": "bdr",
+ "bds-Latn-TZ": "bds",
+ "bdt-Latn-CF": "bdt",
+ "bdu-Latn-CM": "bdu",
+ "bdv-Orya-IN": "bdv",
+ "bdw-Latn-ID": "bdw",
+ "bdx-Latn-ID": "bdx",
+ "bdy-Latn-AU": "bdy",
+ "bdz-Arab-PK": "bdz",
+ "be-Cyrl-BY": "be",
+ "bea-Cans-CA": "bea-Cans",
+ "bea-Latn-CA": "bea",
+ "beb-Latn-CM": "beb",
+ "bec-Latn-CM": "bec",
+ "bed-Latn-ID": "bed",
+ "bee-Deva-IN": "bee",
+ "bef-Latn-ZZ": "bef",
+ "beh-Latn-ZZ": "beh",
+ "bei-Latn-ID": "bei",
+ "bej-Arab-SD": "bej",
+ "bek-Latn-PG": "bek",
+ "bem-Latn-ZM": "bem",
+ "beo-Latn-PG": "beo",
+ "bep-Latn-ID": "bep",
+ "beq-Latn-CG": "beq",
+ "bes-Latn-TD": "bes",
+ "bet-Latn-ZZ": "bet",
+ "beu-Latn-ID": "beu",
+ "bev-Latn-CI": "bev",
+ "bew-Latn-ID": "bew",
+ "bex-Latn-ZZ": "bex",
+ "bey-Latn-PG": "bey",
+ "bez-Latn-TZ": "bez",
+ "bfa-Arab-SS": "bfa-Arab",
+ "bfa-Latn-SS": "bfa",
+ "bfb-Deva-IN": "bfb",
+ "bfc-Latn-CN": "bfc",
+ "bfd-Latn-CM": "bfd",
+ "bfe-Latn-ID": "bfe",
+ "bff-Latn-CF": "bff",
+ "bfg-Latn-ID": "bfg",
+ "bfh-Latn-PG": "bfh",
+ "bfj-Latn-CM": "bfj",
+ "bfl-Latn-CF": "bfl",
+ "bfm-Latn-CM": "bfm",
+ "bfn-Latn-TL": "bfn",
+ "bfo-Latn-BF": "bfo",
+ "bfp-Latn-CM": "bfp",
+ "bfq-Taml-IN": "bfq",
+ "bfs-Hani-CN": "bfs-Hani",
+ "bfs-Latn-CN": "bfs",
+ "bft-Arab-PK": "bft",
+ "bfu-Takr-IN": "bfu-Takr",
+ "bfu-Tibt-IN": "bfu",
+ "bfw-Orya-IN": "bfw",
+ "bfx-Latn-PH": "bfx",
+ "bfy-Deva-IN": "bfy",
+ "bfz-Deva-IN": "bfz",
+ "bg-Cyrl-BG": "bg",
+ "bg-Cyrl-RO": "bg-RO",
+ "bga-Latn-NG": "bga",
+ "bgb-Latn-ID": "bgb",
+ "bgc-Deva-IN": "bgc",
+ "bgd-Deva-IN": "bgd",
+ "bgf-Latn-CM": "bgf",
+ "bgg-Latn-IN": "bgg",
+ "bgi-Latn-PH": "bgi",
+ "bgj-Latn-CM": "bgj",
+ "bgn-Arab-PK": "bgn",
+ "bgo-Latn-GN": "bgo",
+ "bgp-Arab-PK": "bgp",
+ "bgq-Deva-IN": "bgq",
+ "bgr-Latn-IN": "bgr",
+ "bgs-Latn-PH": "bgs",
+ "bgt-Latn-SB": "bgt",
+ "bgu-Latn-NG": "bgu",
+ "bgv-Latn-ID": "bgv",
+ "bgw-Deva-IN": "bgw",
+ "bgx-Grek-TR": "bgx",
+ "bgy-Latn-ID": "bgy",
+ "bgz-Latn-ID": "bgz",
+ "bha-Deva-IN": "bha",
+ "bhb-Deva-IN": "bhb",
+ "bhc-Latn-ID": "bhc",
+ "bhd-Arab-IN": "bhd-Arab",
+ "bhd-Deva-IN": "bhd",
+ "bhd-Takr-IN": "bhd-Takr",
+ "bhe-Arab-PK": "bhe",
+ "bhf-Latn-PG": "bhf",
+ "bhg-Latn-ZZ": "bhg",
+ "bhh-Cyrl-IL": "bhh",
+ "bhh-Hebr-IL": "bhh-Hebr",
+ "bhh-Latn-IL": "bhh-Latn",
+ "bhi-Deva-IN": "bhi",
+ "bhj-Deva-NP": "bhj",
+ "bhl-Latn-ZZ": "bhl",
+ "bhm-Arab-OM": "bhm",
+ "bhn-Syrc-GE": "bhn",
+ "bho-Deva-IN": "bho",
+ "bho-Deva-MU": "bho-MU",
+ "bho-Kthi-IN": "bho-Kthi",
+ "bhp-Latn-ID": "bhp",
+ "bhq-Latn-ID": "bhq",
+ "bhr-Latn-MG": "bhr",
+ "bhs-Latn-CM": "bhs",
+ "bht-Deva-IN": "bht-Deva",
+ "bht-Latn-IN": "bht-Latn",
+ "bht-Takr-IN": "bht",
+ "bhu-Deva-IN": "bhu",
+ "bhv-Latn-ID": "bhv",
+ "bhw-Latn-ID": "bhw",
+ "bhy-Latn-ZZ": "bhy",
+ "bhz-Latn-ID": "bhz",
+ "bi-Latn-VU": "bi",
+ "bia-Latn-AU": "bia",
+ "bib-Latn-ZZ": "bib",
+ "bid-Latn-TD": "bid",
+ "bie-Latn-PG": "bie",
+ "bif-Latn-GW": "bif",
+ "big-Latn-ZZ": "big",
+ "bik-Latn-PH": "bik",
+ "bil-Latn-NG": "bil",
+ "bim-Latn-ZZ": "bim",
+ "bin-Latn-NG": "bin",
+ "bio-Latn-ZZ": "bio",
+ "bip-Latn-CD": "bip",
+ "biq-Latn-ZZ": "biq",
+ "bir-Latn-PG": "bir",
+ "bit-Latn-PG": "bit",
+ "biu-Latn-IN": "biu",
+ "biv-Latn-GH": "biv",
+ "biw-Latn-CM": "biw",
+ "biy-Deva-IN": "biy",
+ "biz-Latn-CD": "biz",
+ "bja-Latn-CD": "bja",
+ "bjb-Latn-AU": "bjb",
+ "bjc-Latn-PG": "bjc",
+ "bjf-Syrc-IL": "bjf",
+ "bjg-Latn-GW": "bjg",
+ "bjh-Latn-ZZ": "bjh",
+ "bji-Ethi-ZZ": "bji",
+ "bjj-Deva-IN": "bjj",
+ "bjk-Latn-PG": "bjk",
+ "bjl-Latn-PG": "bjl",
+ "bjm-Arab-IQ": "bjm",
+ "bjn-Latn-ID": "bjn",
+ "bjo-Latn-ZZ": "bjo",
+ "bjp-Latn-PG": "bjp",
+ "bjr-Latn-ZZ": "bjr",
+ "bjs-Latn-BB": "bjs",
+ "bjt-Latn-SN": "bjt",
+ "bju-Latn-CM": "bju",
+ "bjv-Latn-TD": "bjv",
+ "bjw-Latn-CI": "bjw",
+ "bjx-Latn-PH": "bjx",
+ "bjy-Latn-AU": "bjy",
+ "bjz-Latn-ZZ": "bjz",
+ "bka-Latn-NG": "bka",
+ "bkc-Latn-ZZ": "bkc",
+ "bkd-Latn-PH": "bkd",
+ "bkf-Latn-CD": "bkf",
+ "bkg-Latn-CF": "bkg",
+ "bkh-Latn-CM": "bkh",
+ "bki-Latn-VU": "bki",
+ "bkj-Latn-CF": "bkj",
+ "bkl-Latn-ID": "bkl",
+ "bkm-Latn-CM": "bkm",
+ "bkn-Latn-ID": "bkn",
+ "bko-Latn-CM": "bko",
+ "bkp-Latn-CD": "bkp",
+ "bkq-Latn-ZZ": "bkq",
+ "bkr-Latn-ID": "bkr",
+ "bks-Latn-PH": "bks",
+ "bkt-Latn-CD": "bkt",
+ "bku-Buhd-PH": "bku-Buhd",
+ "bku-Latn-PH": "bku",
+ "bkv-Latn-ZZ": "bkv",
+ "bkw-Latn-CG": "bkw",
+ "bkx-Latn-TL": "bkx",
+ "bky-Latn-NG": "bky",
+ "bkz-Latn-ID": "bkz",
+ "bla-Latn-CA": "bla",
+ "blb-Latn-SB": "blb",
+ "blc-Latn-CA": "blc",
+ "bld-Latn-ID": "bld",
+ "ble-Latn-GW": "ble",
+ "blf-Latn-ID": "blf",
+ "blh-Latn-LR": "blh",
+ "bli-Latn-CD": "bli",
+ "blj-Latn-ID": "blj",
+ "blk-Mymr-MM": "blk",
+ "blm-Latn-SS": "blm",
+ "bln-Latn-PH": "bln",
+ "blo-Latn-BJ": "blo",
+ "blp-Latn-SB": "blp",
+ "blq-Latn-PG": "blq",
+ "blr-Latn-CN": "blr",
+ "blr-Tale-CN": "blr-Tale",
+ "blr-Thai-TH": "blr-Thai",
+ "bls-Latn-ID": "bls",
+ "blt-Tavt-VN": "blt",
+ "blv-Latn-AO": "blv",
+ "blw-Latn-PH": "blw",
+ "blx-Latn-PH": "blx",
+ "bly-Latn-BJ": "bly",
+ "blz-Latn-ID": "blz",
+ "bm-Latn-ML": "bm",
+ "bma-Latn-NG": "bma",
+ "bmb-Latn-CD": "bmb",
+ "bmc-Latn-PG": "bmc",
+ "bmd-Latn-GN": "bmd",
+ "bme-Latn-CF": "bme",
+ "bmf-Latn-SL": "bmf",
+ "bmg-Latn-CD": "bmg",
+ "bmh-Latn-ZZ": "bmh",
+ "bmi-Latn-TD": "bmi",
+ "bmj-Deva-NP": "bmj",
+ "bmk-Latn-ZZ": "bmk",
+ "bml-Latn-CD": "bml",
+ "bmm-Latn-MG": "bmm",
+ "bmn-Latn-PG": "bmn",
+ "bmo-Latn-CM": "bmo",
+ "bmp-Latn-PG": "bmp",
+ "bmq-Latn-ML": "bmq",
+ "bmr-Latn-CO": "bmr",
+ "bms-Latn-NE": "bms",
+ "bmu-Latn-ZZ": "bmu",
+ "bmv-Latn-CM": "bmv",
+ "bmw-Latn-CG": "bmw",
+ "bmx-Latn-PG": "bmx",
+ "bmz-Latn-PG": "bmz",
+ "bn-Beng-BD": "bn",
+ "bna-Latn-ID": "bna",
+ "bnb-Latn-MY": "bnb",
+ "bnc-Latn-PH": "bnc",
+ "bnd-Latn-ID": "bnd",
+ "bne-Latn-ID": "bne",
+ "bnf-Latn-ID": "bnf",
+ "bng-Latn-ZZ": "bng",
+ "bni-Latn-CD": "bni",
+ "bnj-Latn-PH": "bnj",
+ "bnk-Latn-VU": "bnk",
+ "bnm-Latn-ZZ": "bnm",
+ "bnn-Latn-TW": "bnn",
+ "bno-Latn-PH": "bno",
+ "bnp-Latn-ZZ": "bnp",
+ "bnq-Latn-ID": "bnq",
+ "bnr-Latn-VU": "bnr",
+ "bns-Deva-IN": "bns",
+ "bnu-Latn-ID": "bnu",
+ "bnv-Latn-ID": "bnv",
+ "bnw-Latn-PG": "bnw",
+ "bnx-Latn-CD": "bnx",
+ "bny-Latn-MY": "bny",
+ "bnz-Latn-CM": "bnz",
+ "bo-Marc-CN": "bo-Marc",
+ "bo-Tibt-CN": "bo",
+ "boa-Latn-PE": "boa",
+ "bob-Latn-KE": "bob",
+ "boe-Latn-CM": "boe",
+ "bof-Latn-BF": "bof",
+ "boh-Latn-CD": "boh",
+ "boj-Latn-ZZ": "boj",
+ "bok-Latn-CG": "bok",
+ "bol-Latn-NG": "bol",
+ "bom-Latn-ZZ": "bom",
+ "bon-Latn-ZZ": "bon",
+ "boo-Latn-ML": "boo",
+ "bop-Latn-PG": "bop",
+ "boq-Latn-PG": "boq",
+ "bor-Latn-BR": "bor",
+ "bot-Latn-SS": "bot",
+ "bou-Latn-TZ": "bou",
+ "bov-Latn-GH": "bov",
+ "bow-Latn-PG": "bow",
+ "box-Latn-BF": "box",
+ "boy-Latn-CF": "boy",
+ "boz-Arab-ML": "boz-Arab",
+ "boz-Latn-ML": "boz",
+ "bpa-Latn-VU": "bpa",
+ "bpc-Latn-CM": "bpc",
+ "bpd-Latn-CF": "bpd",
+ "bpe-Latn-PG": "bpe",
+ "bpg-Latn-ID": "bpg",
+ "bph-Cyrl-RU": "bph",
+ "bpi-Latn-PG": "bpi",
+ "bpj-Latn-CD": "bpj",
+ "bpk-Latn-NC": "bpk",
+ "bpl-Latn-AU": "bpl",
+ "bpm-Latn-PG": "bpm",
+ "bpo-Latn-ID": "bpo",
+ "bpp-Latn-ID": "bpp",
+ "bpq-Latn-ID": "bpq",
+ "bpr-Latn-PH": "bpr",
+ "bps-Latn-PH": "bps",
+ "bpt-Latn-AU": "bpt",
+ "bpu-Latn-PG": "bpu",
+ "bpv-Latn-ID": "bpv",
+ "bpw-Latn-PG": "bpw",
+ "bpx-Deva-IN": "bpx",
+ "bpy-Beng-IN": "bpy",
+ "bpz-Latn-ID": "bpz",
+ "bqa-Latn-BJ": "bqa",
+ "bqb-Latn-ID": "bqb",
+ "bqc-Latn-ZZ": "bqc",
+ "bqd-Latn-CM": "bqd",
+ "bqf-Arab-GN": "bqf-Arab",
+ "bqf-Latn-GN": "bqf",
+ "bqg-Latn-TG": "bqg",
+ "bqi-Arab-IR": "bqi",
+ "bqj-Latn-SN": "bqj",
+ "bqk-Latn-CF": "bqk",
+ "bql-Latn-PG": "bql",
+ "bqm-Latn-CM": "bqm",
+ "bqo-Latn-CM": "bqo",
+ "bqp-Latn-ZZ": "bqp",
+ "bqq-Latn-ID": "bqq",
+ "bqr-Latn-ID": "bqr",
+ "bqs-Latn-PG": "bqs",
+ "bqt-Latn-CM": "bqt",
+ "bqu-Latn-CD": "bqu",
+ "bqv-Latn-CI": "bqv",
+ "bqw-Latn-NG": "bqw",
+ "bqx-Latn-NG": "bqx",
+ "bqz-Latn-CM": "bqz",
+ "br-Latn-FR": "br",
+ "bra-Deva-IN": "bra",
+ "brb-Khmr-KH": "brb",
+ "brb-Laoo-LA": "brb-Laoo",
+ "brb-Latn-VN": "brb-Latn",
+ "brc-Latn-GY": "brc",
+ "brd-Deva-NP": "brd",
+ "brf-Latn-CD": "brf",
+ "brg-Latn-BO": "brg",
+ "brh-Arab-PK": "brh",
+ "bri-Latn-CM": "bri",
+ "brj-Latn-VU": "brj",
+ "brk-Arab-SD": "brk",
+ "brl-Latn-BW": "brl",
+ "brm-Latn-CD": "brm",
+ "brn-Latn-CR": "brn",
+ "brp-Latn-ID": "brp",
+ "brq-Latn-PG": "brq",
+ "brr-Latn-SB": "brr",
+ "brs-Latn-ID": "brs",
+ "brt-Latn-NG": "brt",
+ "bru-Laoo-LA": "bru-Laoo",
+ "bru-Latn-VN": "bru",
+ "bru-Thai-LA": "bru-Thai",
+ "brv-Laoo-LA": "brv",
+ "brx-Deva-IN": "brx",
+ "bry-Latn-PG": "bry",
+ "brz-Latn-ZZ": "brz",
+ "bs-Latn-BA": "bs",
+ "bsa-Latn-ID": "bsa",
+ "bsb-Latn-BN": "bsb",
+ "bsc-Latn-SN": "bsc",
+ "bse-Latn-CM": "bse",
+ "bsf-Latn-NG": "bsf",
+ "bsh-Arab-AF": "bsh",
+ "bsi-Latn-CM": "bsi",
+ "bsj-Latn-ZZ": "bsj",
+ "bsk-Arab-PK": "bsk",
+ "bsk-Latn-PK": "bsk-Latn",
+ "bsl-Latn-NG": "bsl",
+ "bsm-Latn-ID": "bsm",
+ "bsn-Latn-CO": "bsn",
+ "bso-Latn-TD": "bso",
+ "bsp-Latn-GN": "bsp",
+ "bsq-Bass-LR": "bsq",
+ "bsr-Latn-NG": "bsr",
+ "bss-Latn-CM": "bss",
+ "bst-Ethi-ZZ": "bst",
+ "bsu-Latn-ID": "bsu",
+ "bsv-Arab-GN": "bsv-Arab",
+ "bsv-Latn-GN": "bsv",
+ "bsw-Ethi-ET": "bsw-Ethi",
+ "bsw-Latn-ET": "bsw",
+ "bsx-Latn-NG": "bsx",
+ "bsy-Latn-MY": "bsy",
+ "bta-Latn-NG": "bta",
+ "btc-Latn-CM": "btc",
+ "btd-Batk-ID": "btd",
+ "bte-Latn-NG": "bte",
+ "btf-Latn-TD": "btf",
+ "btg-Latn-CI": "btg",
+ "bth-Latn-MY": "bth",
+ "bti-Latn-ID": "bti",
+ "btj-Latn-ID": "btj",
+ "btm-Batk-ID": "btm",
+ "btn-Latn-PH": "btn",
+ "bto-Latn-PH": "bto",
+ "btp-Latn-PG": "btp",
+ "btq-Latn-MY": "btq",
+ "btr-Latn-VU": "btr",
+ "bts-Batk-ID": "bts-Batk",
+ "bts-Latn-ID": "bts",
+ "btt-Latn-ZZ": "btt",
+ "btu-Latn-NG": "btu",
+ "btv-Deva-PK": "btv",
+ "btw-Latn-PH": "btw",
+ "btx-Batk-ID": "btx-Batk",
+ "btx-Latn-ID": "btx",
+ "bty-Latn-ID": "bty",
+ "btz-Latn-ID": "btz",
+ "bua-Cyrl-RU": "bua",
+ "bub-Latn-TD": "bub",
+ "buc-Latn-YT": "buc",
+ "bud-Latn-ZZ": "bud",
+ "bue-Latn-CA": "bue",
+ "buf-Latn-CD": "buf",
+ "bug-Bugi-ID": "bug-Bugi",
+ "bug-Latn-ID": "bug",
+ "buh-Latn-CN": "buh",
+ "bui-Latn-CG": "bui",
+ "buj-Latn-NG": "buj",
+ "buk-Latn-ZZ": "buk",
+ "bum-Latn-CM": "bum",
+ "bun-Latn-SL": "bun",
+ "buo-Latn-ZZ": "buo",
+ "bup-Latn-ID": "bup",
+ "buq-Latn-PG": "buq",
+ "bus-Latn-ZZ": "bus",
+ "but-Latn-PG": "but",
+ "buu-Latn-ZZ": "buu",
+ "buv-Latn-PG": "buv",
+ "buw-Latn-GA": "buw",
+ "bux-Latn-NG": "bux",
+ "buy-Latn-SL": "buy",
+ "buz-Latn-NG": "buz",
+ "bva-Latn-TD": "bva",
+ "bvb-Latn-GQ": "bvb",
+ "bvc-Latn-SB": "bvc",
+ "bvd-Latn-SB": "bvd",
+ "bve-Latn-ID": "bve",
+ "bvf-Latn-TD": "bvf",
+ "bvg-Latn-CM": "bvg",
+ "bvh-Latn-NG": "bvh",
+ "bvi-Latn-SS": "bvi",
+ "bvj-Latn-NG": "bvj",
+ "bvk-Latn-ID": "bvk",
+ "bvm-Latn-CM": "bvm",
+ "bvn-Latn-PG": "bvn",
+ "bvo-Latn-TD": "bvo",
+ "bvq-Latn-CF": "bvq",
+ "bvr-Latn-AU": "bvr",
+ "bvt-Latn-ID": "bvt",
+ "bvu-Latn-ID": "bvu",
+ "bvv-Latn-VE": "bvv",
+ "bvw-Latn-NG": "bvw",
+ "bvx-Latn-CG": "bvx",
+ "bvy-Latn-PH": "bvy",
+ "bvz-Latn-ID": "bvz",
+ "bwa-Latn-NC": "bwa",
+ "bwb-Latn-FJ": "bwb",
+ "bwc-Latn-ZM": "bwc",
+ "bwd-Latn-ZZ": "bwd",
+ "bwe-Latn-MM": "bwe-Latn",
+ "bwe-Mymr-MM": "bwe",
+ "bwf-Latn-PG": "bwf",
+ "bwg-Latn-MZ": "bwg",
+ "bwh-Latn-CM": "bwh",
+ "bwi-Latn-VE": "bwi",
+ "bwj-Latn-BF": "bwj",
+ "bwk-Latn-PG": "bwk",
+ "bwl-Latn-CD": "bwl",
+ "bwm-Latn-PG": "bwm",
+ "bwo-Ethi-ET": "bwo-Ethi",
+ "bwo-Latn-ET": "bwo",
+ "bwp-Latn-ID": "bwp",
+ "bwq-Latn-BF": "bwq",
+ "bwr-Latn-ZZ": "bwr",
+ "bws-Latn-CD": "bws",
+ "bwt-Latn-CM": "bwt",
+ "bwu-Latn-GH": "bwu",
+ "bww-Latn-CD": "bww",
+ "bwx-Latn-CN": "bwx",
+ "bwy-Latn-BF": "bwy",
+ "bwz-Latn-CG": "bwz",
+ "bxa-Latn-SB": "bxa",
+ "bxb-Latn-SS": "bxb",
+ "bxc-Latn-GQ": "bxc",
+ "bxf-Latn-PG": "bxf",
+ "bxg-Latn-CD": "bxg",
+ "bxh-Latn-ZZ": "bxh",
+ "bxi-Latn-AU": "bxi",
+ "bxj-Latn-AU": "bxj",
+ "bxl-Latn-BF": "bxl",
+ "bxm-Cyrl-MN": "bxm",
+ "bxm-Latn-MN": "bxm-Latn",
+ "bxm-Mong-MN": "bxm-Mong",
+ "bxn-Latn-AU": "bxn",
+ "bxo-Latn-NG": "bxo",
+ "bxp-Latn-CM": "bxp",
+ "bxq-Latn-NG": "bxq",
+ "bxs-Latn-CM": "bxs",
+ "bxu-Cyrl-CN": "bxu-Cyrl",
+ "bxu-Latn-CN": "bxu-Latn",
+ "bxu-Mong-CN": "bxu",
+ "bxv-Latn-TD": "bxv",
+ "bxw-Latn-ML": "bxw",
+ "bxz-Latn-PG": "bxz",
+ "bya-Latn-PH": "bya",
+ "byb-Latn-CM": "byb",
+ "byc-Latn-NG": "byc",
+ "byd-Latn-ID": "byd",
+ "bye-Latn-ZZ": "bye",
+ "byf-Latn-NG": "byf",
+ "byh-Deva-NP": "byh",
+ "byi-Latn-CD": "byi",
+ "byj-Latn-NG": "byj",
+ "byk-Latn-CN": "byk",
+ "byl-Latn-ID": "byl",
+ "bym-Latn-AU": "bym",
+ "byn-Ethi-ER": "byn",
+ "byp-Latn-NG": "byp",
+ "byr-Latn-ZZ": "byr",
+ "bys-Latn-ZZ": "bys",
+ "byv-Latn-CM": "byv",
+ "byw-Deva-NP": "byw",
+ "byx-Latn-ZZ": "byx",
+ "byz-Latn-PG": "byz",
+ "bza-Latn-ZZ": "bza",
+ "bzb-Latn-ID": "bzb",
+ "bzc-Latn-MG": "bzc",
+ "bzd-Latn-CR": "bzd",
+ "bze-Latn-ML": "bze",
+ "bzf-Latn-ZZ": "bzf",
+ "bzh-Latn-ZZ": "bzh",
+ "bzi-Thai-TH": "bzi",
+ "bzj-Latn-BZ": "bzj",
+ "bzk-Latn-NI": "bzk",
+ "bzl-Latn-ID": "bzl",
+ "bzm-Latn-CD": "bzm",
+ "bzn-Latn-ID": "bzn",
+ "bzo-Latn-CD": "bzo",
+ "bzp-Latn-ID": "bzp",
+ "bzq-Latn-ID": "bzq",
+ "bzr-Latn-AU": "bzr",
+ "bzt-Latn-001": "bzt",
+ "bzu-Latn-ID": "bzu",
+ "bzv-Latn-CM": "bzv",
+ "bzw-Latn-ZZ": "bzw",
+ "bzx-Latn-ML": "bzx",
+ "bzy-Latn-NG": "bzy",
+ "bzz-Latn-NG": "bzz",
+ "ca-Latn-AD": "ca-AD",
+ "ca-Latn-ES": "ca",
+ "caa-Latn-GT": "caa",
+ "cab-Latn-HN": "cab",
+ "cac-Latn-GT": "cac",
+ "cad-Latn-US": "cad",
+ "cae-Latn-SN": "cae",
+ "caf-Cans-CA": "caf-Cans",
+ "caf-Latn-CA": "caf",
+ "cag-Latn-PY": "cag",
+ "cah-Latn-PE": "cah",
+ "caj-Latn-AR": "caj",
+ "cak-Latn-GT": "cak",
+ "cal-Latn-MP": "cal",
+ "cam-Latn-NC": "cam",
+ "can-Latn-ZZ": "can",
+ "cao-Latn-BO": "cao",
+ "cap-Latn-BO": "cap",
+ "caq-Latn-IN": "caq",
+ "car-Latn-VE": "car",
+ "cas-Latn-BO": "cas",
+ "cav-Latn-BO": "cav",
+ "caw-Latn-BO": "caw",
+ "cax-Latn-BO": "cax",
+ "cay-Latn-CA": "cay",
+ "caz-Latn-BO": "caz",
+ "cbb-Latn-CO": "cbb",
+ "cbc-Latn-CO": "cbc",
+ "cbd-Latn-CO": "cbd",
+ "cbg-Latn-CO": "cbg",
+ "cbi-Latn-EC": "cbi",
+ "cbj-Latn-ZZ": "cbj",
+ "cbk-Brai-PH": "cbk-Brai",
+ "cbk-Latn-PH": "cbk",
+ "cbl-Latn-MM": "cbl",
+ "cbn-Thai-TH": "cbn",
+ "cbo-Latn-NG": "cbo",
+ "cbq-Latn-NG": "cbq",
+ "cbr-Latn-PE": "cbr",
+ "cbs-Latn-PE": "cbs",
+ "cbt-Latn-PE": "cbt",
+ "cbu-Latn-PE": "cbu",
+ "cbv-Latn-CO": "cbv",
+ "cbw-Latn-PH": "cbw",
+ "cby-Latn-CO": "cby",
+ "ccc-Latn-PE": "ccc",
+ "ccd-Latn-BR": "ccd",
+ "cce-Latn-MZ": "cce",
+ "ccg-Latn-NG": "ccg",
+ "cch-Latn-NG": "cch",
+ "ccj-Latn-GW": "ccj",
+ "ccl-Latn-TZ": "ccl",
+ "ccm-Latn-MY": "ccm",
+ "cco-Latn-MX": "cco",
+ "ccp-Cakm-BD": "ccp",
+ "ccr-Latn-SV": "ccr",
+ "cde-Telu-IN": "cde",
+ "cdf-Beng-IN": "cdf-Beng",
+ "cdf-Latn-IN": "cdf",
+ "cdh-Deva-IN": "cdh",
+ "cdh-Takr-IN": "cdh-Takr",
+ "cdi-Gujr-IN": "cdi",
+ "cdj-Deva-IN": "cdj",
+ "cdm-Deva-NP": "cdm",
+ "cdm-Latn-NP": "cdm-Latn",
+ "cdo-Hans-CN": "cdo",
+ "cdo-Hant-CN": "cdo-Hant",
+ "cdo-Latn-CN": "cdo-Latn",
+ "cdr-Latn-NG": "cdr",
+ "cdz-Beng-IN": "cdz",
+ "ce-Cyrl-RU": "ce",
+ "cea-Latn-US": "cea",
+ "ceb-Latn-PH": "ceb",
+ "ceg-Latn-PY": "ceg",
+ "cek-Latn-MM": "cek",
+ "cen-Latn-NG": "cen",
+ "cet-Latn-NG": "cet",
+ "cey-Latn-MM": "cey",
+ "cfa-Latn-ZZ": "cfa",
+ "cfd-Latn-NG": "cfd",
+ "cfg-Latn-NG": "cfg",
+ "cfm-Beng-IN": "cfm-Beng",
+ "cfm-Latn-MM": "cfm",
+ "cga-Latn-PG": "cga",
+ "cgc-Latn-PH": "cgc",
+ "cgg-Latn-UG": "cgg",
+ "cgk-Tibt-BT": "cgk",
+ "ch-Latn-GU": "ch",
+ "chb-Latn-CO": "chb",
+ "chd-Latn-MX": "chd",
+ "chf-Latn-MX": "chf",
+ "chg-Arab-TM": "chg",
+ "chh-Latn-US": "chh",
+ "chj-Latn-MX": "chj",
+ "chk-Latn-FM": "chk",
+ "chl-Latn-US": "chl",
+ "chm-Cyrl-RU": "chm",
+ "chn-Dupl-US": "chn-Dupl",
+ "chn-Latn-US": "chn",
+ "cho-Latn-US": "cho",
+ "chp-Latn-CA": "chp",
+ "chq-Latn-MX": "chq",
+ "chr-Cher-US": "chr",
+ "cht-Latn-PE": "cht",
+ "chw-Latn-MZ": "chw",
+ "chx-Deva-NP": "chx",
+ "chy-Latn-US": "chy",
+ "chz-Latn-MX": "chz",
+ "cia-Arab-ID": "cia-Arab",
+ "cia-Hang-ID": "cia-Hang",
+ "cia-Latn-ID": "cia",
+ "cib-Latn-BJ": "cib",
+ "cic-Latn-US": "cic",
+ "cie-Latn-NG": "cie",
+ "cih-Deva-IN": "cih",
+ "cim-Latn-IT": "cim",
+ "cin-Latn-BR": "cin",
+ "cip-Latn-MX": "cip",
+ "cir-Latn-NC": "cir",
+ "ciw-Cans-US": "ciw-Cans",
+ "ciw-Latn-US": "ciw",
+ "ciy-Latn-VE": "ciy",
+ "cja-Arab-KH": "cja",
+ "cje-Latn-VN": "cje",
+ "cjh-Latn-US": "cjh",
+ "cji-Cyrl-RU": "cji",
+ "cjk-Latn-AO": "cjk",
+ "cjm-Cham-VN": "cjm",
+ "cjn-Latn-PG": "cjn",
+ "cjo-Latn-PE": "cjo",
+ "cjp-Latn-CR": "cjp",
+ "cjs-Cyrl-RU": "cjs-Cyrl",
+ "cjs-Latn-RU": "cjs",
+ "cjv-Latn-ZZ": "cjv",
+ "cjy-Hans-CN": "cjy",
+ "cjy-Hant-CN": "cjy-Hant",
+ "ckb-Arab-IQ": "ckb",
+ "ckl-Latn-ZZ": "ckl",
+ "ckm-Glag-HR": "ckm-Glag",
+ "ckm-Latn-HR": "ckm",
+ "ckn-Latn-MM": "ckn",
+ "cko-Latn-ZZ": "cko",
+ "ckq-Latn-TD": "ckq",
+ "ckr-Latn-PG": "ckr",
+ "cks-Latn-NC": "cks",
+ "ckt-Cyrl-RU": "ckt",
+ "cku-Latn-US": "cku",
+ "ckv-Latn-TW": "ckv",
+ "ckx-Latn-CM": "ckx",
+ "cky-Latn-ZZ": "cky",
+ "ckz-Latn-GT": "ckz",
+ "cla-Latn-ZZ": "cla",
+ "clc-Latn-CA": "clc",
+ "cle-Latn-MX": "cle",
+ "clh-Arab-PK": "clh",
+ "cli-Latn-GH": "cli",
+ "clj-Latn-MM": "clj",
+ "clk-Latn-IN": "clk",
+ "clk-Tibt-CN": "clk-Tibt",
+ "cll-Latn-GH": "cll",
+ "clm-Latn-US": "clm",
+ "clo-Latn-MX": "clo",
+ "clt-Latn-MM": "clt",
+ "clu-Latn-PH": "clu",
+ "clw-Cyrl-RU": "clw",
+ "cly-Latn-MX": "cly",
+ "cma-Latn-VN": "cma",
+ "cme-Latn-ZZ": "cme",
+ "cmg-Soyo-MN": "cmg",
+ "cmg-Zanb-MN": "cmg-Zanb",
+ "cmi-Latn-CO": "cmi",
+ "cml-Latn-ID": "cml",
+ "cmo-Khmr-KH": "cmo-Khmr",
+ "cmo-Latn-KH": "cmo-KH",
+ "cmo-Latn-VN": "cmo",
+ "cmr-Latn-MM": "cmr",
+ "cms-Latn-IT": "cms",
+ "cmt-Latn-ZA": "cmt",
+ "cna-Tibt-IN": "cna",
+ "cnb-Latn-MM": "cnb",
+ "cnc-Latn-VN": "cnc",
+ "cng-Latn-CN": "cng",
+ "cnh-Latn-MM": "cnh",
+ "cni-Latn-PE": "cni",
+ "cnk-Latn-MM": "cnk",
+ "cnl-Latn-MX": "cnl",
+ "cnp-Hans-CN": "cnp",
+ "cnp-Hant-CN": "cnp-Hant",
+ "cnq-Latn-CM": "cnq",
+ "cns-Latn-ID": "cns",
+ "cnt-Latn-MX": "cnt",
+ "cnw-Latn-MM": "cnw",
+ "cnx-Latn-GB": "cnx",
+ "co-Latn-FR": "co",
+ "coa-Latn-AU": "coa",
+ "cob-Latn-MX": "cob",
+ "coc-Latn-MX": "coc",
+ "cod-Latn-PE": "cod",
+ "coe-Latn-CO": "coe",
+ "cof-Latn-EC": "cof",
+ "cog-Thai-TH": "cog",
+ "coh-Latn-KE": "coh",
+ "coj-Latn-MX": "coj",
+ "cok-Latn-MX": "cok",
+ "col-Latn-US": "col",
+ "com-Latn-US": "com",
+ "coo-Latn-CA": "coo",
+ "cop-Copt-EG": "cop",
+ "coq-Latn-US": "coq",
+ "cot-Latn-PE": "cot",
+ "cou-Latn-SN": "cou",
+ "cox-Latn-PE": "cox",
+ "coz-Latn-MX": "coz",
+ "cpa-Latn-MX": "cpa",
+ "cpb-Latn-PE": "cpb",
+ "cpc-Latn-PE": "cpc",
+ "cpg-Grek-GR": "cpg",
+ "cpi-Latn-NR": "cpi",
+ "cpn-Latn-GH": "cpn",
+ "cpo-Latn-BF": "cpo",
+ "cps-Latn-PH": "cps",
+ "cpu-Latn-PE": "cpu",
+ "cpx-Latn-CN": "cpx",
+ "cpy-Latn-PE": "cpy",
+ "cqd-Latn-CN": "cqd",
+ "cr-Cans-CA": "cr",
+ "crb-Latn-VC": "crb",
+ "crc-Latn-VU": "crc",
+ "crd-Latn-US": "crd",
+ "crf-Latn-CO": "crf",
+ "crg-Latn-CA": "crg",
+ "crh-Cyrl-UA": "crh",
+ "cri-Latn-ST": "cri",
+ "crj-Cans-CA": "crj",
+ "crj-Latn-CA": "crj-Latn",
+ "crk-Cans-CA": "crk",
+ "crl-Cans-CA": "crl",
+ "crm-Cans-CA": "crm",
+ "crn-Latn-MX": "crn",
+ "cro-Latn-US": "cro",
+ "crq-Latn-AR": "crq",
+ "crs-Latn-SC": "crs",
+ "crt-Latn-AR": "crt",
+ "crv-Latn-IN": "crv",
+ "crw-Latn-VN": "crw",
+ "crx-Cans-CA": "crx-Cans",
+ "crx-Latn-CA": "crx",
+ "cry-Latn-NG": "cry",
+ "crz-Latn-US": "crz",
+ "cs-Latn-CZ": "cs",
+ "csa-Latn-MX": "csa",
+ "csb-Latn-PL": "csb",
+ "csh-Latn-MM": "csh-Latn",
+ "csh-Mymr-MM": "csh",
+ "csj-Latn-MM": "csj",
+ "csk-Latn-SN": "csk",
+ "csm-Latn-US": "csm",
+ "cso-Latn-MX": "cso",
+ "csp-Hans-CN": "csp",
+ "csp-Hant-CN": "csp-Hant",
+ "css-Latn-US": "css",
+ "cst-Latn-US": "cst",
+ "csv-Latn-MM": "csv",
+ "csw-Cans-CA": "csw",
+ "csy-Latn-MM": "csy",
+ "csz-Latn-US": "csz",
+ "cta-Latn-MX": "cta",
+ "ctc-Latn-US": "ctc",
+ "ctd-Pauc-MM": "ctd",
+ "cte-Latn-MX": "cte",
+ "ctg-Arab-BD": "ctg-Arab",
+ "ctg-Beng-BD": "ctg",
+ "ctg-Latn-BD": "ctg-Latn",
+ "cth-Latn-MM": "cth",
+ "ctl-Latn-MX": "ctl",
+ "ctm-Latn-US": "ctm",
+ "ctn-Deva-NP": "ctn",
+ "cto-Latn-CO": "cto",
+ "ctp-Latn-MX": "ctp",
+ "cts-Latn-PH": "cts",
+ "ctt-Taml-IN": "ctt",
+ "ctu-Latn-MX": "ctu",
+ "ctz-Latn-MX": "ctz",
+ "cu-Cyrl-RU": "cu",
+ "cu-Glag-BG": "cu-Glag",
+ "cua-Latn-VN": "cua",
+ "cub-Latn-CO": "cub",
+ "cuc-Latn-MX": "cuc",
+ "cuh-Latn-KE": "cuh",
+ "cui-Latn-CO": "cui",
+ "cuj-Latn-PE": "cuj",
+ "cuk-Latn-PA": "cuk",
+ "cul-Latn-BR": "cul",
+ "cuo-Latn-VE": "cuo",
+ "cup-Latn-US": "cup",
+ "cut-Latn-MX": "cut",
+ "cuu-Lana-CN": "cuu",
+ "cuv-Latn-CM": "cuv",
+ "cux-Latn-MX": "cux",
+ "cv-Cyrl-RU": "cv",
+ "cvg-Latn-IN": "cvg",
+ "cvg-Tibt-IN": "cvg-Tibt",
+ "cvn-Latn-MX": "cvn",
+ "cwa-Latn-TZ": "cwa",
+ "cwb-Latn-MZ": "cwb",
+ "cwe-Latn-TZ": "cwe",
+ "cwg-Latn-MY": "cwg",
+ "cwt-Latn-SN": "cwt",
+ "cy-Latn-GB": "cy",
+ "cya-Latn-MX": "cya",
+ "cyb-Latn-BO": "cyb",
+ "cyo-Latn-PH": "cyo",
+ "czh-Hans-CN": "czh",
+ "czh-Hant-CN": "czh-Hant",
+ "czk-Hebr-CZ": "czk",
+ "czn-Latn-MX": "czn",
+ "czt-Latn-MM": "czt",
+ "da-Latn-DK": "da",
+ "daa-Latn-TD": "daa",
+ "dac-Latn-PG": "dac",
+ "dad-Latn-ZZ": "dad",
+ "dae-Latn-CM": "dae",
+ "dag-Latn-ZZ": "dag",
+ "dah-Latn-ZZ": "dah",
+ "dai-Latn-TD": "dai",
+ "daj-Latn-SD": "daj",
+ "dak-Latn-US": "dak",
+ "dal-Latn-KE": "dal",
+ "dam-Latn-NG": "dam",
+ "dao-Latn-MM": "dao",
+ "daq-Deva-IN": "daq",
+ "dar-Cyrl-RU": "dar",
+ "das-Latn-CI": "das",
+ "dau-Latn-TD": "dau",
+ "dav-Latn-KE": "dav",
+ "daw-Latn-PH": "daw",
+ "dax-Latn-AU": "dax",
+ "daz-Latn-ID": "daz",
+ "dba-Latn-ML": "dba",
+ "dbb-Latn-NG": "dbb",
+ "dbd-Latn-ZZ": "dbd",
+ "dbe-Latn-ID": "dbe",
+ "dbf-Latn-ID": "dbf",
+ "dbg-Latn-ML": "dbg",
+ "dbi-Latn-NG": "dbi",
+ "dbj-Arab-MY": "dbj-Arab",
+ "dbj-Latn-MY": "dbj",
+ "dbl-Latn-AU": "dbl",
+ "dbm-Latn-NG": "dbm",
+ "dbn-Latn-ID": "dbn",
+ "dbo-Latn-NG": "dbo",
+ "dbp-Latn-NG": "dbp",
+ "dbq-Latn-ZZ": "dbq",
+ "dbt-Latn-ML": "dbt",
+ "dbu-Latn-ML": "dbu",
+ "dbv-Latn-NG": "dbv",
+ "dbw-Latn-ML": "dbw",
+ "dby-Latn-PG": "dby",
+ "dcc-Arab-IN": "dcc",
+ "dcr-Latn-VI": "dcr",
+ "dda-Latn-AU": "dda",
+ "ddd-Latn-SS": "ddd",
+ "dde-Latn-CG": "dde",
+ "ddg-Latn-TL": "ddg",
+ "ddi-Latn-PG": "ddi",
+ "ddj-Latn-AU": "ddj",
+ "ddn-Latn-ZZ": "ddn",
+ "ddo-Cyrl-RU": "ddo",
+ "ddr-Latn-AU": "ddr",
+ "dds-Latn-ML": "dds",
+ "ddw-Latn-ID": "ddw",
+ "de-Latn-AT": "de-AT",
+ "de-Latn-CH": "de-CH",
+ "de-Latn-DE": "de",
+ "de-Latn-EZ": "de-EZ",
+ "de-Latn-LI": "de-LI",
+ "dec-Latn-SD": "dec",
+ "ded-Latn-ZZ": "ded",
+ "dee-Latn-LR": "dee",
+ "def-Arab-IR": "def",
+ "deg-Latn-NG": "deg",
+ "deh-Arab-PK": "deh",
+ "dei-Latn-ID": "dei",
+ "dek-Latn-CM": "dek",
+ "del-Latn-US": "del",
+ "dem-Latn-ID": "dem",
+ "den-Latn-CA": "den",
+ "deq-Latn-CF": "deq",
+ "der-Beng-IN": "der",
+ "der-Latn-IN": "der-Latn",
+ "des-Latn-BR": "des",
+ "dev-Latn-PG": "dev",
+ "dez-Latn-CD": "dez",
+ "dga-Latn-ZZ": "dga",
+ "dgb-Latn-ML": "dgb",
+ "dgc-Latn-PH": "dgc",
+ "dgd-Latn-BF": "dgd",
+ "dge-Latn-PG": "dge",
+ "dgg-Latn-PG": "dgg",
+ "dgh-Latn-ZZ": "dgh",
+ "dgi-Latn-ZZ": "dgi",
+ "dgk-Latn-CF": "dgk",
+ "dgl-Arab-ZZ": "dgl",
+ "dgn-Latn-AU": "dgn",
+ "dgr-Latn-CA": "dgr",
+ "dgs-Latn-BF": "dgs",
+ "dgt-Latn-AU": "dgt",
+ "dgw-Latn-AU": "dgw",
+ "dgx-Latn-PG": "dgx",
+ "dgz-Latn-ZZ": "dgz",
+ "dhg-Latn-AU": "dhg",
+ "dhi-Deva-NP": "dhi",
+ "dhl-Latn-AU": "dhl",
+ "dhm-Latn-AO": "dhm",
+ "dhn-Gujr-IN": "dhn",
+ "dho-Deva-IN": "dho",
+ "dhr-Latn-AU": "dhr",
+ "dhs-Latn-TZ": "dhs",
+ "dhu-Latn-AU": "dhu",
+ "dhv-Latn-NC": "dhv",
+ "dhw-Deva-NP": "dhw",
+ "dhx-Latn-AU": "dhx",
+ "dia-Latn-ZZ": "dia",
+ "dib-Latn-SS": "dib",
+ "dic-Latn-CI": "dic",
+ "did-Latn-SS": "did",
+ "dif-Latn-AU": "dif",
+ "dig-Latn-KE": "dig",
+ "dih-Latn-MX": "dih",
+ "dii-Latn-CM": "dii",
+ "dij-Latn-ID": "dij",
+ "dil-Latn-SD": "dil",
+ "din-Arab-SS": "din-Arab",
+ "din-Latn-SS": "din",
+ "dio-Latn-NG": "dio",
+ "dip-Latn-SS": "dip",
+ "dir-Latn-NG": "dir",
+ "dis-Beng-IN": "dis-Beng",
+ "dis-Latn-IN": "dis",
+ "diu-Latn-NA": "diu",
+ "diw-Latn-SS": "diw",
+ "dix-Latn-VU": "dix",
+ "diy-Latn-ID": "diy",
+ "diz-Latn-CD": "diz",
+ "dja-Latn-AU": "dja",
+ "djb-Latn-AU": "djb",
+ "djc-Latn-TD": "djc",
+ "djd-Latn-AU": "djd",
+ "dje-Latn-NE": "dje",
+ "djf-Latn-AU": "djf",
+ "dji-Latn-AU": "dji",
+ "djj-Latn-AU": "djj",
+ "djk-Latn-SR": "djk",
+ "djm-Latn-ML": "djm",
+ "djn-Latn-AU": "djn",
+ "djo-Latn-ID": "djo",
+ "djr-Latn-AU": "djr",
+ "dju-Latn-PG": "dju",
+ "djw-Latn-AU": "djw",
+ "dka-Tibt-BT": "dka",
+ "dkg-Latn-NG": "dkg",
+ "dkk-Latn-ID": "dkk",
+ "dkr-Latn-MY": "dkr",
+ "dks-Latn-SS": "dks",
+ "dkx-Latn-CM": "dkx",
+ "dlg-Cyrl-RU": "dlg",
+ "dlm-Latn-HR": "dlm",
+ "dln-Latn-IN": "dln",
+ "dma-Latn-GA": "dma",
+ "dmb-Latn-ML": "dmb",
+ "dmc-Latn-PG": "dmc",
+ "dmd-Latn-AU": "dmd",
+ "dme-Latn-CM": "dme",
+ "dmf-Medf-NG": "dmf",
+ "dmg-Latn-MY": "dmg",
+ "dmk-Arab-PK": "dmk",
+ "dml-Arab-PK": "dml",
+ "dmm-Latn-CM": "dmm",
+ "dmo-Latn-CM": "dmo",
+ "dmr-Latn-ID": "dmr",
+ "dms-Latn-ID": "dms",
+ "dmu-Latn-ID": "dmu",
+ "dmv-Latn-MY": "dmv",
+ "dmw-Latn-AU": "dmw",
+ "dmx-Latn-MZ": "dmx",
+ "dmy-Latn-ID": "dmy",
+ "dna-Latn-ID": "dna",
+ "dnd-Latn-PG": "dnd",
+ "dne-Latn-TZ": "dne",
+ "dng-Arab-KG": "dng-Arab",
+ "dng-Cyrl-KG": "dng",
+ "dni-Latn-ID": "dni",
+ "dnj-Latn-CI": "dnj",
+ "dnk-Latn-ID": "dnk",
+ "dnn-Latn-BF": "dnn",
+ "dno-Latn-CD": "dno",
+ "dnr-Latn-PG": "dnr",
+ "dnt-Latn-ID": "dnt",
+ "dnu-Mymr-MM": "dnu",
+ "dnv-Mymr-MM": "dnv",
+ "dnw-Latn-ID": "dnw",
+ "dny-Latn-BR": "dny",
+ "doa-Latn-PG": "doa",
+ "dob-Latn-ZZ": "dob",
+ "doc-Latn-CN": "doc",
+ "doe-Latn-TZ": "doe",
+ "dof-Latn-PG": "dof",
+ "doh-Latn-NG": "doh",
+ "doi-Deva-IN": "doi",
+ "doi-Dogr-IN": "doi-Dogr",
+ "doi-Takr-IN": "doi-Takr",
+ "dok-Latn-ID": "dok",
+ "dol-Latn-PG": "dol",
+ "don-Latn-PG": "don",
+ "doo-Latn-CD": "doo",
+ "dop-Latn-ZZ": "dop",
+ "dor-Latn-SB": "dor",
+ "dos-Latn-BF": "dos",
+ "dot-Latn-NG": "dot",
+ "dov-Latn-ZW": "dov",
+ "dow-Latn-ZZ": "dow",
+ "dox-Ethi-ET": "dox",
+ "doy-Latn-GH": "doy",
+ "dpp-Latn-MY": "dpp",
+ "drc-Latn-PT": "drc",
+ "dre-Tibt-NP": "dre",
+ "drg-Latn-MY": "drg",
+ "dri-Latn-ZZ": "dri",
+ "drl-Latn-AU": "drl",
+ "drn-Latn-ID": "drn",
+ "dro-Latn-MY": "dro",
+ "drq-Deva-NP": "drq",
+ "drs-Ethi-ZZ": "drs",
+ "drt-Latn-NL": "drt",
+ "dru-Latn-TW": "dru",
+ "dry-Deva-NP": "dry",
+ "dsb-Latn-DE": "dsb",
+ "dsh-Latn-KE": "dsh",
+ "dsi-Latn-TD": "dsi",
+ "dsn-Latn-ID": "dsn",
+ "dso-Orya-IN": "dso",
+ "dsq-Arab-ML": "dsq-Arab",
+ "dsq-Latn-ML": "dsq",
+ "dta-Cyrl-CN": "dta-Cyrl",
+ "dta-Hans-CN": "dta-Hans",
+ "dta-Latn-CN": "dta",
+ "dtb-Latn-MY": "dtb",
+ "dtd-Latn-CA": "dtd",
+ "dth-Latn-AU": "dth",
+ "dti-Latn-ML": "dti",
+ "dtk-Latn-ML": "dtk",
+ "dtm-Latn-ML": "dtm",
+ "dto-Latn-ML": "dto",
+ "dtp-Latn-MY": "dtp",
+ "dtr-Latn-MY": "dtr",
+ "dts-Latn-ZZ": "dts",
+ "dtt-Latn-ML": "dtt",
+ "dtu-Latn-ML": "dtu",
+ "dty-Deva-NP": "dty",
+ "dua-Latn-CM": "dua",
+ "dub-Gujr-IN": "dub",
+ "duc-Latn-ZZ": "duc",
+ "due-Latn-PH": "due",
+ "duf-Latn-NC": "duf",
+ "dug-Latn-ZZ": "dug",
+ "duh-Deva-IN": "duh",
+ "duh-Gujr-IN": "duh-Gujr",
+ "dui-Latn-PG": "dui",
+ "duk-Latn-PG": "duk",
+ "dul-Latn-PH": "dul",
+ "dum-Latn-NL": "dum",
+ "dun-Latn-ID": "dun",
+ "duo-Latn-PH": "duo",
+ "dup-Latn-ID": "dup",
+ "duq-Latn-ID": "duq",
+ "dur-Latn-CM": "dur",
+ "dus-Deva-NP": "dus",
+ "duu-Latn-CN": "duu",
+ "duv-Latn-ID": "duv",
+ "duw-Latn-ID": "duw",
+ "dux-Latn-ML": "dux",
+ "duy-Latn-PH": "duy",
+ "duz-Latn-CM": "duz",
+ "dv-Diak-MV": "dv-Diak",
+ "dv-Thaa-MV": "dv",
+ "dva-Latn-ZZ": "dva",
+ "dwa-Latn-NG": "dwa",
+ "dwk-Orya-IN": "dwk",
+ "dwr-Ethi-ET": "dwr-Ethi",
+ "dwr-Latn-ET": "dwr",
+ "dws-Latn-001": "dws",
+ "dwu-Latn-AU": "dwu",
+ "dww-Latn-ZZ": "dww",
+ "dwy-Latn-AU": "dwy",
+ "dwz-Deva-NP": "dwz",
+ "dya-Latn-BF": "dya",
+ "dyb-Latn-AU": "dyb",
+ "dyd-Latn-AU": "dyd",
+ "dyg-Latn-PH": "dyg",
+ "dyi-Latn-CI": "dyi",
+ "dym-Latn-ML": "dym",
+ "dyn-Latn-AU": "dyn",
+ "dyo-Latn-SN": "dyo",
+ "dyu-Latn-BF": "dyu",
+ "dyy-Latn-AU": "dyy",
+ "dz-Tibt-BT": "dz",
+ "dza-Latn-NG": "dza",
+ "dze-Latn-AU": "dze",
+ "dzg-Latn-ZZ": "dzg",
+ "dzl-Tibt-BT": "dzl",
+ "dzn-Latn-CD": "dzn",
+ "eaa-Latn-AU": "eaa",
+ "ebc-Latn-ID": "ebc",
+ "ebg-Latn-NG": "ebg",
+ "ebk-Latn-PH": "ebk",
+ "ebo-Latn-CG": "ebo",
+ "ebr-Latn-CI": "ebr",
+ "ebu-Latn-KE": "ebu",
+ "ecr-Grek-GR": "ecr",
+ "ecy-Cprt-CY": "ecy",
+ "ee-Latn-GH": "ee",
+ "efa-Latn-NG": "efa",
+ "efe-Latn-CD": "efe",
+ "efi-Latn-NG": "efi",
+ "ega-Latn-CI": "ega",
+ "egl-Latn-IT": "egl",
+ "egm-Latn-TZ": "egm",
+ "ego-Latn-NG": "ego",
+ "egy-Egyp-EG": "egy",
+ "ehu-Latn-NG": "ehu",
+ "eip-Latn-ID": "eip",
+ "eit-Latn-PG": "eit",
+ "eiv-Latn-PG": "eiv",
+ "eja-Latn-GW": "eja",
+ "eka-Latn-ZZ": "eka",
+ "eke-Latn-NG": "eke",
+ "ekg-Latn-ID": "ekg",
+ "eki-Latn-NG": "eki",
+ "ekl-Latn-BD": "ekl",
+ "ekm-Latn-CM": "ekm",
+ "eko-Arab-MZ": "eko-Arab",
+ "eko-Latn-MZ": "eko",
+ "ekp-Latn-NG": "ekp",
+ "ekr-Latn-NG": "ekr",
+ "eky-Kali-MM": "eky",
+ "el-Grek-CY": "el-CY",
+ "el-Grek-GR": "el",
+ "ele-Latn-PG": "ele",
+ "elk-Latn-PG": "elk",
+ "elm-Latn-NG": "elm",
+ "elo-Latn-KE": "elo",
+ "elu-Latn-PG": "elu",
+ "ema-Latn-ZZ": "ema",
+ "emb-Latn-ID": "emb",
+ "eme-Latn-GF": "eme",
+ "emg-Deva-NP": "emg",
+ "emi-Latn-ZZ": "emi",
+ "emm-Latn-MX": "emm",
+ "emn-Latn-CM": "emn",
+ "emp-Latn-PA": "emp",
+ "ems-Cyrl-US": "ems-Cyrl",
+ "ems-Latn-US": "ems",
+ "emu-Deva-IN": "emu",
+ "emw-Latn-ID": "emw",
+ "emx-Latn-FR": "emx",
+ "emz-Latn-CM": "emz",
+ "en-Latn-AU": "en-AU",
+ "en-Latn-DG": "en-DG",
+ "en-Latn-ET": "en-ET",
+ "en-Latn-GB": "en-GB",
+ "en-Latn-GU": "en-GU",
+ "en-Latn-IE": "en-IE",
+ "en-Latn-NG": "en-NG",
+ "en-Latn-PG": "en-PG",
+ "en-Latn-US": "en",
+ "en-Latn-ZA": "en-ZA",
+ "en-Shaw-GB": "en-Shaw",
+ "ena-Latn-PG": "ena",
+ "enb-Latn-KE": "enb",
+ "enc-Latn-VN": "enc",
+ "end-Latn-ID": "end",
+ "enf-Cyrl-RU": "enf",
+ "enh-Cyrl-RU": "enh",
+ "enl-Latn-PY": "enl",
+ "enm-Latn-GB": "enm",
+ "enn-Latn-ZZ": "enn",
+ "eno-Latn-ID": "eno",
+ "enq-Latn-ZZ": "enq",
+ "enr-Latn-ID": "enr",
+ "env-Latn-NG": "env",
+ "enw-Latn-NG": "enw",
+ "enx-Latn-PY": "enx",
+ "eo-Latn-001": "eo",
+ "eot-Latn-CI": "eot",
+ "epi-Latn-NG": "epi",
+ "era-Taml-IN": "era",
+ "erg-Latn-VU": "erg",
+ "erh-Latn-NG": "erh",
+ "eri-Latn-ZZ": "eri",
+ "erk-Latn-VU": "erk",
+ "err-Latn-AU": "err",
+ "ert-Latn-ID": "ert",
+ "erw-Latn-ID": "erw",
+ "es-Latn-419": "es-419",
+ "es-Latn-AR": "es-AR",
+ "es-Latn-BO": "es-BO",
+ "es-Latn-CL": "es-CL",
+ "es-Latn-CO": "es-CO",
+ "es-Latn-CR": "es-CR",
+ "es-Latn-CU": "es-CU",
+ "es-Latn-DO": "es-DO",
+ "es-Latn-EA": "es-EA",
+ "es-Latn-EC": "es-EC",
+ "es-Latn-ES": "es",
+ "es-Latn-GQ": "es-GQ",
+ "es-Latn-GT": "es-GT",
+ "es-Latn-HN": "es-HN",
+ "es-Latn-IC": "es-IC",
+ "es-Latn-MX": "es-MX",
+ "es-Latn-NI": "es-NI",
+ "es-Latn-PA": "es-PA",
+ "es-Latn-PE": "es-PE",
+ "es-Latn-PR": "es-PR",
+ "es-Latn-SV": "es-SV",
+ "es-Latn-UY": "es-UY",
+ "es-Latn-VE": "es-VE",
+ "ese-Latn-BO": "ese",
+ "esg-Gonm-IN": "esg",
+ "esh-Arab-IR": "esh",
+ "esi-Latn-US": "esi",
+ "esm-Latn-CI": "esm",
+ "ess-Cyrl-US": "ess-Cyrl",
+ "ess-Latn-US": "ess",
+ "esu-Latn-US": "esu",
+ "esy-Latn-PH": "esy",
+ "et-Latn-EE": "et",
+ "etb-Latn-NG": "etb",
+ "etn-Latn-VU": "etn",
+ "eto-Latn-CM": "eto",
+ "etr-Latn-ZZ": "etr",
+ "ets-Latn-NG": "ets",
+ "ett-Ital-IT": "ett",
+ "etu-Latn-ZZ": "etu",
+ "etx-Latn-ZZ": "etx",
+ "etz-Latn-ID": "etz",
+ "eu-Latn-ES": "eu",
+ "eve-Cyrl-RU": "eve",
+ "evh-Latn-NG": "evh",
+ "evn-Cyrl-RU": "evn",
+ "evn-Latn-CN": "evn-Latn",
+ "evn-Mong-CN": "evn-Mong",
+ "ewo-Latn-CM": "ewo",
+ "ext-Latn-ES": "ext",
+ "eya-Latn-US": "eya",
+ "eyo-Latn-KE": "eyo",
+ "eza-Latn-ZZ": "eza",
+ "eze-Latn-NG": "eze",
+ "fa-Arab-AF": "fa-AF",
+ "fa-Arab-IR": "fa",
+ "fa-Arab-TJ": "fa-TJ",
+ "faa-Latn-ZZ": "faa",
+ "fab-Latn-ZZ": "fab",
+ "fad-Latn-PG": "fad",
+ "faf-Latn-SB": "faf",
+ "fag-Latn-ZZ": "fag",
+ "fah-Latn-NG": "fah",
+ "fai-Latn-ZZ": "fai",
+ "faj-Latn-PG": "faj",
+ "fak-Latn-CM": "fak",
+ "fal-Latn-CM": "fal",
+ "fam-Latn-NG": "fam",
+ "fan-Latn-GQ": "fan",
+ "fap-Latn-SN": "fap",
+ "far-Latn-SB": "far",
+ "fau-Latn-ID": "fau",
+ "fax-Latn-ES": "fax",
+ "fay-Arab-IR": "fay",
+ "faz-Arab-IR": "faz",
+ "fbl-Latn-PH": "fbl",
+ "fer-Latn-SS": "fer",
+ "ff-Adlm-GN": "ff-Adlm",
+ "ff-Latn-SN": "ff",
+ "ffi-Latn-ZZ": "ffi",
+ "ffm-Latn-ML": "ffm",
+ "fgr-Latn-TD": "fgr",
+ "fi-Latn-FI": "fi",
+ "fia-Arab-SD": "fia",
+ "fie-Latn-NG": "fie",
+ "fif-Latn-SA": "fif",
+ "fil-Latn-PH": "fil",
+ "fil-Tglg-PH": "fil-Tglg",
+ "fip-Latn-TZ": "fip",
+ "fir-Latn-NG": "fir",
+ "fit-Latn-SE": "fit",
+ "fiw-Latn-PG": "fiw",
+ "fj-Latn-FJ": "fj",
+ "fkk-Latn-NG": "fkk",
+ "fkv-Latn-NO": "fkv",
+ "fla-Latn-US": "fla",
+ "flh-Latn-ID": "flh",
+ "fli-Latn-NG": "fli",
+ "fll-Latn-CM": "fll",
+ "fln-Latn-AU": "fln",
+ "flr-Latn-ZZ": "flr",
+ "fly-Latn-ZA": "fly",
+ "fmp-Latn-ZZ": "fmp",
+ "fmu-Deva-IN": "fmu",
+ "fnb-Latn-VU": "fnb",
+ "fng-Latn-ZA": "fng",
+ "fni-Latn-TD": "fni",
+ "fo-Latn-FO": "fo",
+ "fod-Latn-ZZ": "fod",
+ "foi-Latn-PG": "foi",
+ "fom-Latn-CD": "fom",
+ "fon-Latn-BJ": "fon",
+ "for-Latn-ZZ": "for",
+ "fos-Latn-TW": "fos",
+ "fpe-Latn-ZZ": "fpe",
+ "fqs-Latn-ZZ": "fqs",
+ "fr-Brai-FR": "fr-Brai",
+ "fr-Dupl-FR": "fr-Dupl",
+ "fr-Latn-BF": "fr-BF",
+ "fr-Latn-BJ": "fr-BJ",
+ "fr-Latn-BL": "fr-BL",
+ "fr-Latn-CF": "fr-CF",
+ "fr-Latn-CG": "fr-CG",
+ "fr-Latn-CI": "fr-CI",
+ "fr-Latn-CM": "fr-CM",
+ "fr-Latn-DZ": "fr-DZ",
+ "fr-Latn-FR": "fr",
+ "fr-Latn-GA": "fr-GA",
+ "fr-Latn-GF": "fr-GF",
+ "fr-Latn-GN": "fr-GN",
+ "fr-Latn-GP": "fr-GP",
+ "fr-Latn-KM": "fr-KM",
+ "fr-Latn-LU": "fr-LU",
+ "fr-Latn-MA": "fr-MA",
+ "fr-Latn-MC": "fr-MC",
+ "fr-Latn-MF": "fr-MF",
+ "fr-Latn-MQ": "fr-MQ",
+ "fr-Latn-MR": "fr-MR",
+ "fr-Latn-NC": "fr-NC",
+ "fr-Latn-PF": "fr-PF",
+ "fr-Latn-PM": "fr-PM",
+ "fr-Latn-RE": "fr-RE",
+ "fr-Latn-SC": "fr-SC",
+ "fr-Latn-SN": "fr-SN",
+ "fr-Latn-SY": "fr-SY",
+ "fr-Latn-TD": "fr-TD",
+ "fr-Latn-TF": "fr-TF",
+ "fr-Latn-TG": "fr-TG",
+ "fr-Latn-TN": "fr-TN",
+ "fr-Latn-WF": "fr-WF",
+ "fr-Latn-YT": "fr-YT",
+ "frc-Latn-US": "frc",
+ "frd-Latn-ID": "frd",
+ "frk-Latn-DE": "frk",
+ "frm-Latn-FR": "frm",
+ "fro-Latn-FR": "fro",
+ "frp-Latn-FR": "frp",
+ "frq-Latn-PG": "frq",
+ "frr-Latn-DE": "frr",
+ "frs-Latn-DE": "frs",
+ "frt-Latn-VU": "frt",
+ "fub-Arab-CM": "fub",
+ "fud-Latn-WF": "fud",
+ "fue-Latn-ZZ": "fue",
+ "fuf-Latn-GN": "fuf",
+ "fuh-Latn-ZZ": "fuh",
+ "fui-Latn-TD": "fui",
+ "fum-Latn-NG": "fum",
+ "fun-Latn-BR": "fun",
+ "fuq-Latn-NE": "fuq",
+ "fur-Latn-IT": "fur",
+ "fut-Latn-VU": "fut",
+ "fuu-Latn-CD": "fuu",
+ "fuv-Latn-NG": "fuv",
+ "fuy-Latn-ZZ": "fuy",
+ "fvr-Latn-SD": "fvr",
+ "fwa-Latn-NC": "fwa",
+ "fwe-Latn-NA": "fwe",
+ "fy-Latn-NL": "fy",
+ "ga-Latn-IE": "ga",
+ "gaa-Latn-GH": "gaa",
+ "gab-Latn-TD": "gab",
+ "gac-Deva-IN": "gac-Deva",
+ "gac-Latn-IN": "gac",
+ "gad-Latn-PH": "gad",
+ "gae-Latn-VE": "gae",
+ "gaf-Latn-ZZ": "gaf",
+ "gag-Latn-MD": "gag",
+ "gah-Latn-ZZ": "gah",
+ "gai-Latn-PG": "gai",
+ "gaj-Latn-ZZ": "gaj",
+ "gak-Latn-ID": "gak",
+ "gal-Latn-TL": "gal",
+ "gam-Latn-ZZ": "gam",
+ "gan-Hans-CN": "gan",
+ "gao-Latn-PG": "gao",
+ "gap-Latn-PG": "gap",
+ "gaq-Orya-IN": "gaq",
+ "gar-Latn-PG": "gar",
+ "gas-Gujr-IN": "gas",
+ "gat-Latn-PG": "gat",
+ "gau-Telu-IN": "gau",
+ "gaw-Latn-ZZ": "gaw",
+ "gax-Ethi-ET": "gax-Ethi",
+ "gax-Latn-ET": "gax",
+ "gay-Latn-ID": "gay",
+ "gba-Latn-ZZ": "gba",
+ "gbb-Latn-AU": "gbb",
+ "gbd-Latn-AU": "gbd",
+ "gbe-Latn-PG": "gbe",
+ "gbf-Latn-ZZ": "gbf",
+ "gbg-Latn-CF": "gbg",
+ "gbh-Latn-BJ": "gbh",
+ "gbi-Latn-ID": "gbi",
+ "gbj-Orya-IN": "gbj",
+ "gbk-Deva-IN": "gbk",
+ "gbk-Takr-IN": "gbk-Takr",
+ "gbl-Deva-IN": "gbl-Deva",
+ "gbl-Gujr-IN": "gbl",
+ "gbm-Deva-IN": "gbm",
+ "gbn-Latn-SS": "gbn",
+ "gbp-Latn-CF": "gbp",
+ "gbq-Latn-CF": "gbq",
+ "gbr-Latn-NG": "gbr",
+ "gbs-Latn-BJ": "gbs",
+ "gbu-Latn-AU": "gbu",
+ "gbv-Latn-CF": "gbv",
+ "gbw-Latn-AU": "gbw",
+ "gbx-Latn-BJ": "gbx",
+ "gby-Latn-ZZ": "gby",
+ "gbz-Arab-IR": "gbz",
+ "gcc-Latn-PG": "gcc",
+ "gcd-Latn-AU": "gcd",
+ "gcf-Latn-GP": "gcf",
+ "gcl-Latn-GD": "gcl",
+ "gcn-Latn-PG": "gcn",
+ "gcr-Latn-GF": "gcr",
+ "gct-Latn-VE": "gct",
+ "gd-Latn-GB": "gd",
+ "gdb-Orya-IN": "gdb",
+ "gdb-Telu-IN": "gdb-Telu",
+ "gdc-Latn-AU": "gdc",
+ "gdd-Latn-PG": "gdd",
+ "gde-Latn-ZZ": "gde",
+ "gdf-Latn-NG": "gdf",
+ "gdg-Latn-PH": "gdg",
+ "gdh-Latn-AU": "gdh",
+ "gdi-Latn-CF": "gdi",
+ "gdj-Latn-AU": "gdj",
+ "gdk-Latn-TD": "gdk",
+ "gdl-Ethi-ET": "gdl-Ethi",
+ "gdl-Latn-ET": "gdl",
+ "gdm-Latn-TD": "gdm",
+ "gdn-Latn-ZZ": "gdn",
+ "gdo-Cyrl-RU": "gdo",
+ "gdq-Latn-YE": "gdq",
+ "gdr-Latn-ZZ": "gdr",
+ "gdt-Latn-AU": "gdt",
+ "gdu-Latn-NG": "gdu",
+ "gdx-Deva-IN": "gdx",
+ "gea-Latn-NG": "gea",
+ "geb-Latn-ZZ": "geb",
+ "gec-Latn-LR": "gec",
+ "ged-Latn-NG": "ged",
+ "gef-Latn-ID": "gef",
+ "geg-Latn-NG": "geg",
+ "geh-Latn-CA": "geh",
+ "gei-Latn-ID": "gei",
+ "gej-Latn-ZZ": "gej",
+ "gek-Latn-NG": "gek",
+ "gel-Latn-ZZ": "gel",
+ "geq-Latn-CF": "geq",
+ "ges-Latn-ID": "ges",
+ "gev-Latn-GA": "gev",
+ "gew-Latn-NG": "gew",
+ "gex-Latn-SO": "gex",
+ "gey-Latn-CD": "gey",
+ "gez-Ethi-ET": "gez",
+ "gfk-Latn-ZZ": "gfk",
+ "gga-Latn-SB": "gga",
+ "ggb-Latn-LR": "ggb",
+ "ggd-Latn-AU": "ggd",
+ "gge-Latn-AU": "gge",
+ "ggg-Arab-PK": "ggg",
+ "ggk-Latn-AU": "ggk",
+ "ggl-Latn-PG": "ggl",
+ "ggt-Latn-PG": "ggt",
+ "ggu-Latn-CI": "ggu",
+ "ggw-Latn-PG": "ggw",
+ "gha-Arab-LY": "gha",
+ "gha-Latn-LY": "gha-Latn",
+ "gha-Tfng-LY": "gha-Tfng",
+ "ghc-Latn-GB": "ghc",
+ "ghe-Deva-NP": "ghe",
+ "ghk-Latn-MM": "ghk",
+ "ghn-Latn-SB": "ghn",
+ "ghr-Arab-PK": "ghr",
+ "ghs-Latn-ZZ": "ghs",
+ "ght-Tibt-NP": "ght",
+ "gia-Latn-AU": "gia",
+ "gib-Latn-NG": "gib",
+ "gic-Latn-ZA": "gic",
+ "gid-Latn-CM": "gid",
+ "gie-Latn-CI": "gie",
+ "gig-Arab-PK": "gig",
+ "gih-Latn-AU": "gih",
+ "gil-Latn-KI": "gil",
+ "gim-Latn-ZZ": "gim",
+ "gin-Cyrl-RU": "gin",
+ "gip-Latn-PG": "gip",
+ "giq-Latn-VN": "giq",
+ "gir-Latn-VN": "gir",
+ "gis-Latn-CM": "gis",
+ "git-Latn-CA": "git",
+ "gix-Latn-CD": "gix",
+ "giy-Latn-AU": "giy",
+ "giz-Latn-CM": "giz",
+ "gjk-Arab-PK": "gjk",
+ "gjm-Latn-AU": "gjm",
+ "gjn-Latn-ZZ": "gjn",
+ "gjr-Latn-AU": "gjr",
+ "gju-Arab-PK": "gju",
+ "gka-Latn-PG": "gka",
+ "gkd-Latn-PG": "gkd",
+ "gke-Latn-CM": "gke",
+ "gkn-Latn-ZZ": "gkn",
+ "gko-Latn-AU": "gko",
+ "gkp-Latn-ZZ": "gkp",
+ "gku-Latn-ZA": "gku",
+ "gl-Latn-ES": "gl",
+ "glb-Latn-NG": "glb",
+ "glc-Latn-TD": "glc",
+ "gld-Cyrl-RU": "gld",
+ "glh-Arab-AF": "glh",
+ "glj-Latn-TD": "glj",
+ "glk-Arab-IR": "glk",
+ "gll-Latn-AU": "gll",
+ "glo-Latn-NG": "glo",
+ "glr-Latn-LR": "glr",
+ "glu-Latn-TD": "glu",
+ "glw-Latn-NG": "glw",
+ "gma-Latn-AU": "gma",
+ "gmb-Latn-SB": "gmb",
+ "gmd-Latn-NG": "gmd",
+ "gmg-Latn-PG": "gmg",
+ "gmh-Latn-DE": "gmh",
+ "gmm-Latn-ZZ": "gmm",
+ "gmn-Latn-CM": "gmn",
+ "gmr-Latn-AU": "gmr",
+ "gmu-Latn-PG": "gmu",
+ "gmv-Ethi-ZZ": "gmv",
+ "gmx-Latn-TZ": "gmx",
+ "gmy-Linb-GR": "gmy",
+ "gmz-Latn-NG": "gmz",
+ "gn-Latn-PY": "gn",
+ "gna-Latn-BF": "gna",
+ "gnb-Latn-IN": "gnb",
+ "gnc-Latn-ES": "gnc",
+ "gnd-Latn-ZZ": "gnd",
+ "gne-Latn-NG": "gne",
+ "gng-Latn-ZZ": "gng",
+ "gnh-Latn-NG": "gnh",
+ "gni-Latn-AU": "gni",
+ "gnj-Latn-CI": "gnj",
+ "gnk-Latn-BW": "gnk",
+ "gnl-Latn-AU": "gnl",
+ "gnm-Latn-PG": "gnm",
+ "gnn-Latn-AU": "gnn",
+ "gnq-Latn-MY": "gnq",
+ "gnr-Latn-AU": "gnr",
+ "gnt-Latn-PG": "gnt",
+ "gnu-Latn-PG": "gnu",
+ "gnw-Latn-BO": "gnw",
+ "gnz-Latn-CF": "gnz",
+ "goa-Latn-CI": "goa",
+ "gob-Latn-CO": "gob",
+ "goc-Latn-PG": "goc",
+ "god-Latn-ZZ": "god",
+ "goe-Tibt-BT": "goe",
+ "gof-Ethi-ZZ": "gof",
+ "gog-Latn-TZ": "gog",
+ "goh-Latn-DE": "goh",
+ "goi-Latn-ZZ": "goi",
+ "gok-Deva-IN": "gok",
+ "gol-Latn-LR": "gol",
+ "gom-Deva-IN": "gom",
+ "gon-Telu-IN": "gon",
+ "goo-Latn-FJ": "goo",
+ "gop-Latn-ID": "gop",
+ "goq-Latn-ID": "goq",
+ "gor-Latn-ID": "gor",
+ "gos-Latn-NL": "gos",
+ "got-Goth-UA": "got",
+ "gou-Latn-CM": "gou",
+ "gov-Latn-CI": "gov",
+ "gow-Latn-TZ": "gow",
+ "gox-Latn-CD": "gox",
+ "goy-Latn-TD": "goy",
+ "gpa-Latn-NG": "gpa",
+ "gpe-Latn-GH": "gpe",
+ "gpn-Latn-PG": "gpn",
+ "gqa-Latn-NG": "gqa",
+ "gqn-Latn-BR": "gqn",
+ "gqr-Latn-TD": "gqr",
+ "gra-Deva-IN": "gra",
+ "gra-Gujr-IN": "gra-Gujr",
+ "grb-Latn-ZZ": "grb",
+ "grc-Cprt-CY": "grc",
+ "grc-Linb-GR": "grc-Linb",
+ "grd-Latn-NG": "grd",
+ "grg-Latn-PG": "grg",
+ "grh-Latn-NG": "grh",
+ "gri-Latn-SB": "gri",
+ "grj-Latn-LR": "grj",
+ "grm-Latn-MY": "grm",
+ "grq-Latn-PG": "grq",
+ "grs-Latn-ID": "grs",
+ "grt-Beng-IN": "grt",
+ "gru-Ethi-ET": "gru",
+ "gru-Latn-ET": "gru-Latn",
+ "grv-Latn-LR": "grv",
+ "grw-Latn-ZZ": "grw",
+ "grx-Latn-PG": "grx",
+ "gry-Latn-LR": "gry",
+ "grz-Latn-PG": "grz",
+ "gsl-Latn-SN": "gsl",
+ "gsn-Latn-PG": "gsn",
+ "gso-Latn-CF": "gso",
+ "gsp-Latn-PG": "gsp",
+ "gsw-Latn-CH": "gsw",
+ "gta-Latn-BR": "gta",
+ "gtu-Latn-AU": "gtu",
+ "gu-Gujr-IN": "gu",
+ "gua-Latn-NG": "gua",
+ "gub-Latn-BR": "gub",
+ "guc-Latn-CO": "guc",
+ "gud-Latn-ZZ": "gud",
+ "gue-Latn-AU": "gue",
+ "guf-Latn-AU": "guf",
+ "guh-Latn-CO": "guh",
+ "gui-Latn-BO": "gui",
+ "guk-Ethi-ET": "guk-Ethi",
+ "guk-Latn-ET": "guk",
+ "gul-Latn-US": "gul",
+ "gum-Latn-CO": "gum",
+ "gun-Latn-BR": "gun",
+ "guo-Latn-CO": "guo",
+ "gup-Latn-AU": "gup",
+ "guq-Latn-PY": "guq",
+ "gur-Latn-GH": "gur",
+ "gut-Latn-CR": "gut",
+ "guu-Latn-VE": "guu",
+ "guw-Latn-ZZ": "guw",
+ "gux-Latn-ZZ": "gux",
+ "guz-Latn-KE": "guz",
+ "gv-Latn-IM": "gv",
+ "gva-Latn-PY": "gva",
+ "gvc-Latn-BR": "gvc",
+ "gve-Latn-PG": "gve",
+ "gvf-Latn-ZZ": "gvf",
+ "gvj-Latn-BR": "gvj",
+ "gvl-Latn-TD": "gvl",
+ "gvm-Latn-NG": "gvm",
+ "gvn-Latn-AU": "gvn",
+ "gvo-Latn-BR": "gvo",
+ "gvp-Latn-BR": "gvp",
+ "gvr-Deva-NP": "gvr",
+ "gvs-Latn-ZZ": "gvs",
+ "gvy-Latn-AU": "gvy",
+ "gwa-Latn-CI": "gwa",
+ "gwb-Latn-NG": "gwb",
+ "gwc-Arab-ZZ": "gwc",
+ "gwd-Latn-ET": "gwd",
+ "gwe-Latn-TZ": "gwe",
+ "gwf-Arab-PK": "gwf",
+ "gwg-Latn-NG": "gwg",
+ "gwi-Latn-CA": "gwi",
+ "gwj-Latn-BW": "gwj",
+ "gwm-Latn-AU": "gwm",
+ "gwn-Latn-NG": "gwn",
+ "gwr-Latn-UG": "gwr",
+ "gwt-Arab-ZZ": "gwt",
+ "gwu-Latn-AU": "gwu",
+ "gww-Latn-AU": "gww",
+ "gwx-Latn-GH": "gwx",
+ "gxx-Latn-CI": "gxx",
+ "gyb-Latn-PG": "gyb",
+ "gyd-Latn-AU": "gyd",
+ "gye-Latn-NG": "gye",
+ "gyf-Latn-AU": "gyf",
+ "gyg-Latn-CF": "gyg",
+ "gyi-Latn-ZZ": "gyi",
+ "gyl-Ethi-ET": "gyl-Ethi",
+ "gyl-Latn-ET": "gyl",
+ "gym-Latn-PA": "gym",
+ "gyn-Latn-GY": "gyn",
+ "gyo-Deva-NP": "gyo",
+ "gyr-Latn-BO": "gyr",
+ "gyy-Latn-AU": "gyy",
+ "gyz-Latn-NG": "gyz",
+ "gza-Latn-SD": "gza",
+ "gzi-Arab-IR": "gzi",
+ "gzn-Latn-ID": "gzn",
+ "ha-Arab-CM": "ha-CM",
+ "ha-Arab-NG": "ha-Arab",
+ "ha-Arab-SD": "ha-SD",
+ "ha-Latn-NE": "ha-NE",
+ "ha-Latn-NG": "ha",
+ "haa-Latn-US": "haa",
+ "hac-Arab-IR": "hac",
+ "had-Latn-ID": "had",
+ "hae-Latn-ET": "hae",
+ "hag-Latn-ZZ": "hag",
+ "hah-Latn-PG": "hah",
+ "hai-Latn-CA": "hai",
+ "haj-Beng-IN": "haj-Beng",
+ "haj-Latn-IN": "haj",
+ "hak-Hans-CN": "hak",
+ "hal-Latn-VN": "hal",
+ "ham-Latn-ZZ": "ham",
+ "han-Latn-TZ": "han",
+ "hao-Latn-PG": "hao",
+ "hap-Latn-ID": "hap",
+ "haq-Latn-TZ": "haq",
+ "har-Arab-ET": "har-Arab",
+ "har-Ethi-ET": "har",
+ "har-Latn-ET": "har-Latn",
+ "has-Latn-CA": "has",
+ "hav-Latn-CD": "hav",
+ "haw-Latn-US": "haw",
+ "hax-Latn-CA": "hax",
+ "hay-Latn-TZ": "hay",
+ "haz-Arab-AF": "haz",
+ "hba-Latn-CD": "hba",
+ "hbb-Latn-ZZ": "hbb",
+ "hbn-Latn-SD": "hbn",
+ "hbo-Hebr-IL": "hbo",
+ "hbu-Latn-TL": "hbu",
+ "hch-Latn-MX": "hch",
+ "hdy-Ethi-ZZ": "hdy",
+ "he-Hebr-IL": "he",
+ "hed-Latn-TD": "hed",
+ "heg-Latn-ID": "heg",
+ "heh-Latn-TZ": "heh",
+ "hei-Latn-CA": "hei",
+ "hem-Latn-CD": "hem",
+ "hgm-Latn-NA": "hgm",
+ "hgw-Latn-PG": "hgw",
+ "hhi-Latn-PG": "hhi",
+ "hhr-Latn-SN": "hhr",
+ "hhy-Latn-ZZ": "hhy",
+ "hi-Deva-IN": "hi",
+ "hi-Latn-IN": "hi-Latn",
+ "hi-Mahj-IN": "hi-Mahj",
+ "hia-Latn-ZZ": "hia",
+ "hib-Latn-PE": "hib",
+ "hid-Latn-US": "hid",
+ "hif-Deva-FJ": "hif-Deva",
+ "hif-Latn-FJ": "hif",
+ "hig-Latn-ZZ": "hig",
+ "hih-Latn-ZZ": "hih",
+ "hii-Deva-IN": "hii-Deva",
+ "hii-Takr-IN": "hii",
+ "hij-Latn-CM": "hij",
+ "hik-Latn-ID": "hik",
+ "hil-Latn-PH": "hil",
+ "hio-Latn-BW": "hio",
+ "hir-Latn-BR": "hir",
+ "hit-Xsux-TR": "hit",
+ "hiw-Latn-VU": "hiw",
+ "hix-Latn-BR": "hix",
+ "hji-Latn-ID": "hji",
+ "hka-Latn-TZ": "hka",
+ "hke-Latn-CD": "hke",
+ "hkh-Arab-IN": "hkh",
+ "hkh-Deva-IN": "hkh-Deva",
+ "hkh-Latn-IN": "hkh-Latn",
+ "hkk-Latn-PG": "hkk",
+ "hla-Latn-ZZ": "hla",
+ "hlb-Deva-IN": "hlb",
+ "hld-Latn-VN": "hld",
+ "hlt-Latn-MM": "hlt",
+ "hlu-Hluw-TR": "hlu",
+ "hma-Latn-CN": "hma",
+ "hmb-Latn-ML": "hmb",
+ "hmd-Plrd-CN": "hmd",
+ "hmf-Latn-VN": "hmf",
+ "hmj-Bopo-CN": "hmj",
+ "hmm-Latn-CN": "hmm",
+ "hmn-Bopo-CN": "hmn-Bopo",
+ "hmn-Hmng-CN": "hmn-Hmng",
+ "hmn-Latn-CN": "hmn",
+ "hmp-Latn-CN": "hmp",
+ "hmq-Bopo-CN": "hmq",
+ "hmr-Latn-IN": "hmr",
+ "hms-Latn-CN": "hms",
+ "hmt-Latn-ZZ": "hmt",
+ "hmu-Latn-ID": "hmu",
+ "hmv-Latn-VN": "hmv",
+ "hmw-Latn-CN": "hmw",
+ "hmy-Latn-CN": "hmy",
+ "hmz-Latn-CN": "hmz",
+ "hmz-Plrd-CN": "hmz-Plrd",
+ "hna-Latn-CM": "hna",
+ "hnd-Arab-PK": "hnd",
+ "hne-Deva-IN": "hne",
+ "hng-Latn-AO": "hng",
+ "hnh-Latn-BW": "hnh",
+ "hni-Latn-CN": "hni",
+ "hnj-Hmng-LA": "hnj-Hmng-LA",
+ "hnj-Hmnp-US": "hnj",
+ "hnj-Laoo-AU": "hnj-AU",
+ "hnj-Laoo-CN": "hnj-CN",
+ "hnj-Laoo-FR": "hnj-FR",
+ "hnj-Laoo-GF": "hnj-GF",
+ "hnj-Laoo-LA": "hnj-LA",
+ "hnj-Laoo-MM": "hnj-MM",
+ "hnj-Laoo-SR": "hnj-SR",
+ "hnj-Laoo-TH": "hnj-TH",
+ "hnj-Laoo-US": "hnj-Laoo-US",
+ "hnj-Laoo-VN": "hnj-VN",
+ "hnn-Hano-PH": "hnn-Hano",
+ "hnn-Latn-PH": "hnn",
+ "hno-Arab-PK": "hno",
+ "hns-Latn-SR": "hns",
+ "ho-Latn-PG": "ho",
+ "hoa-Latn-SB": "hoa",
+ "hob-Latn-PG": "hob",
+ "hoc-Deva-IN": "hoc",
+ "hoc-Wara-IN": "hoc-Wara",
+ "hod-Latn-NG": "hod",
+ "hoe-Latn-NG": "hoe",
+ "hoh-Arab-OM": "hoh",
+ "hoi-Latn-US": "hoi",
+ "hoj-Deva-IN": "hoj",
+ "hol-Latn-AO": "hol",
+ "hom-Latn-SS": "hom",
+ "hoo-Latn-CD": "hoo",
+ "hop-Latn-US": "hop",
+ "hor-Latn-TD": "hor",
+ "hot-Latn-ZZ": "hot",
+ "hov-Latn-ID": "hov",
+ "how-Hani-CN": "how",
+ "hoy-Deva-IN": "hoy",
+ "hpo-Mymr-MM": "hpo",
+ "hr-Latn-HR": "hr",
+ "hra-Latn-IN": "hra",
+ "hrc-Latn-PG": "hrc",
+ "hre-Latn-VN": "hre",
+ "hrk-Latn-ID": "hrk",
+ "hrm-Hmng-CN": "hrm-Hmng",
+ "hrm-Latn-CN": "hrm",
+ "hro-Latn-VN": "hro",
+ "hrp-Latn-AU": "hrp",
+ "hrt-Syrc-TR": "hrt",
+ "hru-Latn-IN": "hru",
+ "hrw-Latn-PG": "hrw",
+ "hrx-Latn-BR": "hrx",
+ "hrz-Arab-IR": "hrz",
+ "hsb-Latn-DE": "hsb",
+ "hsn-Hans-CN": "hsn",
+ "hss-Arab-OM": "hss",
+ "ht-Latn-HT": "ht",
+ "hti-Latn-ID": "hti",
+ "hto-Latn-CO": "hto",
+ "hts-Latn-TZ": "hts",
+ "htu-Latn-ID": "htu",
+ "htx-Xsux-TR": "htx",
+ "hu-Hung-HU": "hu-Hung",
+ "hu-Latn-HU": "hu",
+ "hub-Latn-PE": "hub",
+ "huc-Latn-BW": "huc",
+ "hud-Latn-ID": "hud",
+ "hue-Latn-MX": "hue",
+ "huf-Latn-PG": "huf",
+ "hug-Latn-PE": "hug",
+ "huh-Latn-CL": "huh",
+ "hui-Latn-ZZ": "hui",
+ "huk-Latn-ID": "huk",
+ "hul-Latn-PG": "hul",
+ "hum-Latn-CD": "hum",
+ "hup-Latn-US": "hup",
+ "hur-Latn-CA": "hur",
+ "hus-Latn-MX": "hus",
+ "hut-Deva-NP": "hut",
+ "hut-Tibt-NP": "hut-Tibt",
+ "huu-Latn-PE": "huu",
+ "huv-Latn-MX": "huv",
+ "huw-Latn-ID": "huw",
+ "hux-Latn-PE": "hux",
+ "huy-Hebr-IL": "huy",
+ "huz-Cyrl-RU": "huz",
+ "hvc-Latn-HT": "hvc",
+ "hve-Latn-MX": "hve",
+ "hvk-Latn-NC": "hvk",
+ "hvn-Latn-ID": "hvn",
+ "hvv-Latn-MX": "hvv",
+ "hwa-Latn-CI": "hwa",
+ "hwc-Latn-US": "hwc",
+ "hwo-Latn-NG": "hwo",
+ "hy-Armn-AM": "hy",
+ "hya-Latn-CM": "hya",
+ "hyw-Armn-AM": "hyw",
+ "hz-Latn-NA": "hz",
+ "ia-Latn-001": "ia",
+ "iai-Latn-NC": "iai",
+ "ian-Latn-ZZ": "ian",
+ "iar-Latn-ZZ": "iar",
+ "iba-Latn-MY": "iba",
+ "ibb-Latn-NG": "ibb",
+ "ibd-Latn-AU": "ibd",
+ "ibe-Latn-NG": "ibe",
+ "ibg-Latn-PH": "ibg",
+ "ibh-Latn-VN": "ibh",
+ "ibl-Latn-PH": "ibl",
+ "ibm-Latn-NG": "ibm",
+ "ibn-Latn-NG": "ibn",
+ "ibr-Latn-NG": "ibr",
+ "ibu-Latn-ID": "ibu",
+ "iby-Latn-ZZ": "iby",
+ "ica-Latn-ZZ": "ica",
+ "ich-Latn-ZZ": "ich",
+ "icr-Latn-CO": "icr",
+ "id-Latn-ID": "id",
+ "ida-Latn-KE": "ida",
+ "idb-Latn-IN": "idb",
+ "idc-Latn-NG": "idc",
+ "idd-Latn-ZZ": "idd",
+ "ide-Latn-NG": "ide",
+ "idi-Latn-ZZ": "idi",
+ "idr-Latn-SS": "idr",
+ "ids-Latn-NG": "ids",
+ "idt-Latn-TL": "idt",
+ "idu-Latn-ZZ": "idu",
+ "ie-Latn-001": "ie",
+ "ifa-Latn-PH": "ifa",
+ "ifb-Latn-PH": "ifb",
+ "ife-Latn-TG": "ife",
+ "iff-Latn-VU": "iff",
+ "ifk-Latn-PH": "ifk",
+ "ifm-Latn-CG": "ifm",
+ "ifu-Latn-PH": "ifu",
+ "ify-Latn-PH": "ify",
+ "ig-Latn-NG": "ig",
+ "igb-Latn-ZZ": "igb",
+ "ige-Latn-ZZ": "ige",
+ "igg-Latn-PG": "igg",
+ "igl-Latn-NG": "igl",
+ "igm-Latn-PG": "igm",
+ "ign-Latn-BO": "ign",
+ "igo-Latn-PG": "igo",
+ "igs-Grek-001": "igs-Grek",
+ "igs-Latn-001": "igs",
+ "igw-Latn-NG": "igw",
+ "ihb-Latn-ID": "ihb",
+ "ihi-Latn-NG": "ihi",
+ "ihp-Latn-ID": "ihp",
+ "ihw-Latn-AU": "ihw",
+ "ii-Yiii-CN": "ii",
+ "iin-Latn-AU": "iin",
+ "ijc-Latn-NG": "ijc",
+ "ije-Latn-NG": "ije",
+ "ijj-Latn-ZZ": "ijj",
+ "ijn-Latn-NG": "ijn",
+ "ijs-Latn-NG": "ijs",
+ "ik-Latn-US": "ik",
+ "iki-Latn-NG": "iki",
+ "ikk-Latn-ZZ": "ikk",
+ "ikl-Latn-NG": "ikl",
+ "iko-Latn-NG": "iko",
+ "ikp-Latn-NG": "ikp",
+ "ikr-Latn-AU": "ikr",
+ "ikt-Cans-CA": "ikt-Cans",
+ "ikt-Latn-CA": "ikt",
+ "ikv-Latn-NG": "ikv",
+ "ikw-Latn-ZZ": "ikw",
+ "ikx-Latn-ZZ": "ikx",
+ "ikz-Latn-TZ": "ikz",
+ "ila-Latn-ID": "ila",
+ "ilb-Latn-ZM": "ilb",
+ "ilg-Latn-AU": "ilg",
+ "ili-Arab-CN": "ili-Arab",
+ "ili-Cyrl-KZ": "ili-Cyrl",
+ "ili-Latn-CN": "ili",
+ "ilk-Latn-PH": "ilk",
+ "ilm-Latn-MY": "ilm",
+ "ilo-Latn-PH": "ilo",
+ "ilp-Latn-PH": "ilp",
+ "ilu-Latn-ID": "ilu",
+ "ilv-Latn-NG": "ilv",
+ "imi-Latn-PG": "imi",
+ "iml-Latn-US": "iml",
+ "imn-Latn-PG": "imn",
+ "imo-Latn-ZZ": "imo",
+ "imr-Latn-ID": "imr",
+ "ims-Latn-IT": "ims",
+ "imt-Latn-SS": "imt",
+ "imy-Lyci-TR": "imy",
+ "inb-Latn-CO": "inb",
+ "ing-Latn-US": "ing",
+ "inh-Cyrl-RU": "inh",
+ "inj-Latn-CO": "inj",
+ "inn-Latn-PH": "inn",
+ "ino-Latn-PG": "ino",
+ "inp-Latn-PE": "inp",
+ "int-Mymr-MM": "int",
+ "io-Latn-001": "io",
+ "ior-Ethi-ET": "ior",
+ "iou-Latn-ZZ": "iou",
+ "iow-Latn-US": "iow",
+ "ipi-Latn-PG": "ipi",
+ "ipo-Latn-PG": "ipo",
+ "iqu-Latn-PE": "iqu",
+ "iqw-Latn-NG": "iqw",
+ "ire-Latn-ID": "ire",
+ "irh-Latn-ID": "irh",
+ "iri-Latn-ZZ": "iri",
+ "irk-Latn-TZ": "irk",
+ "irn-Latn-BR": "irn",
+ "iru-Mlym-IN": "iru-Mlym",
+ "iru-Taml-IN": "iru",
+ "irx-Latn-ID": "irx",
+ "iry-Latn-PH": "iry",
+ "is-Latn-IS": "is",
+ "isa-Latn-PG": "isa",
+ "isc-Latn-PE": "isc",
+ "isd-Latn-PH": "isd",
+ "ish-Latn-NG": "ish",
+ "isi-Latn-NG": "isi",
+ "isk-Arab-AF": "isk",
+ "isk-Cyrl-TJ": "isk-Cyrl",
+ "ism-Latn-ID": "ism",
+ "isn-Latn-TZ": "isn",
+ "iso-Latn-NG": "iso",
+ "ist-Latn-HR": "ist",
+ "isu-Latn-CM": "isu",
+ "it-Latn-IT": "it",
+ "it-Latn-SM": "it-SM",
+ "it-Latn-VA": "it-VA",
+ "itb-Latn-PH": "itb",
+ "itd-Latn-ID": "itd",
+ "ite-Latn-BO": "ite",
+ "iti-Latn-PH": "iti",
+ "itk-Hebr-IT": "itk",
+ "itl-Cyrl-RU": "itl",
+ "itm-Latn-NG": "itm",
+ "ito-Latn-BO": "ito",
+ "itr-Latn-PG": "itr",
+ "its-Latn-NG": "its",
+ "itt-Latn-PH": "itt",
+ "itv-Latn-PH": "itv",
+ "itw-Latn-NG": "itw",
+ "itx-Latn-ID": "itx",
+ "ity-Latn-PH": "ity",
+ "itz-Latn-GT": "itz",
+ "iu-Cans-CA": "iu",
+ "ium-Hani-CN": "ium-Hani",
+ "ium-Laoo-LA": "ium-Laoo",
+ "ium-Latn-CN": "ium",
+ "ium-Thai-TH": "ium-Thai",
+ "ivb-Latn-PH": "ivb",
+ "ivv-Latn-PH": "ivv",
+ "iwk-Latn-PH": "iwk",
+ "iwm-Latn-ZZ": "iwm",
+ "iwo-Latn-ID": "iwo",
+ "iws-Latn-ZZ": "iws",
+ "ixc-Latn-MX": "ixc",
+ "ixl-Latn-GT": "ixl",
+ "iya-Latn-NG": "iya",
+ "iyo-Latn-CM": "iyo",
+ "iyx-Latn-CG": "iyx",
+ "izh-Latn-RU": "izh",
+ "izr-Latn-NG": "izr",
+ "izz-Latn-NG": "izz",
+ "ja-Hira-JP": "ja-Hira",
+ "ja-Jpan-JP": "ja",
+ "ja-Kana-JP": "ja-Kana",
+ "jaa-Latn-BR": "jaa",
+ "jab-Latn-ZZ": "jab",
+ "jac-Latn-GT": "jac",
+ "jad-Arab-GN": "jad",
+ "jae-Latn-PG": "jae",
+ "jaf-Latn-NG": "jaf",
+ "jah-Latn-MY": "jah",
+ "jaj-Latn-SB": "jaj",
+ "jak-Latn-MY": "jak",
+ "jal-Latn-ID": "jal",
+ "jam-Latn-JM": "jam",
+ "jan-Latn-AU": "jan",
+ "jao-Latn-AU": "jao",
+ "jaq-Latn-ID": "jaq",
+ "jas-Latn-NC": "jas",
+ "jat-Arab-AF": "jat",
+ "jau-Latn-ID": "jau",
+ "jax-Latn-ID": "jax",
+ "jay-Latn-AU": "jay",
+ "jaz-Latn-NC": "jaz",
+ "jbe-Hebr-IL": "jbe",
+ "jbi-Latn-AU": "jbi",
+ "jbj-Latn-ID": "jbj",
+ "jbk-Latn-PG": "jbk",
+ "jbm-Latn-NG": "jbm",
+ "jbn-Arab-LY": "jbn",
+ "jbo-Latn-001": "jbo",
+ "jbr-Latn-ID": "jbr",
+ "jbt-Latn-BR": "jbt",
+ "jbu-Latn-ZZ": "jbu",
+ "jbw-Latn-AU": "jbw",
+ "jct-Cyrl-UA": "jct",
+ "jct-Latn-UA": "jct-Latn",
+ "jda-Tibt-IN": "jda",
+ "jdg-Arab-PK": "jdg",
+ "jdt-Cyrl-RU": "jdt",
+ "jdt-Hebr-RU": "jdt-Hebr",
+ "jdt-Latn-AZ": "jdt-Latn",
+ "jeb-Latn-PE": "jeb",
+ "jee-Deva-NP": "jee",
+ "jeh-Laoo-LA": "jeh-Laoo",
+ "jeh-Latn-VN": "jeh",
+ "jei-Latn-ID": "jei",
+ "jek-Latn-CI": "jek",
+ "jel-Latn-ID": "jel",
+ "jen-Latn-ZZ": "jen",
+ "jer-Latn-NG": "jer",
+ "jet-Latn-PG": "jet",
+ "jeu-Latn-TD": "jeu",
+ "jgb-Latn-CD": "jgb",
+ "jge-Geor-GE": "jge",
+ "jge-Hebr-IL": "jge-Hebr",
+ "jgk-Latn-ZZ": "jgk",
+ "jgo-Latn-CM": "jgo",
+ "jhi-Latn-MY": "jhi",
+ "jia-Latn-CM": "jia",
+ "jib-Latn-ZZ": "jib",
+ "jic-Latn-HN": "jic",
+ "jid-Latn-NG": "jid",
+ "jie-Latn-NG": "jie",
+ "jig-Latn-AU": "jig",
+ "jil-Latn-PG": "jil",
+ "jim-Latn-CM": "jim",
+ "jit-Latn-TZ": "jit",
+ "jiu-Latn-CN": "jiu",
+ "jiv-Latn-EC": "jiv",
+ "jiy-Latn-CN": "jiy",
+ "jje-Hang-KR": "jje",
+ "jjr-Latn-NG": "jjr",
+ "jka-Latn-ID": "jka",
+ "jkm-Brai-MM": "jkm-Brai",
+ "jkm-Latn-MM": "jkm-Latn",
+ "jkm-Mymr-MM": "jkm",
+ "jko-Latn-PG": "jko",
+ "jku-Latn-NG": "jku",
+ "jle-Latn-SD": "jle",
+ "jma-Latn-PG": "jma",
+ "jmb-Latn-NG": "jmb",
+ "jmc-Latn-TZ": "jmc",
+ "jmd-Latn-ID": "jmd",
+ "jmi-Latn-NG": "jmi",
+ "jml-Deva-NP": "jml",
+ "jmn-Latn-MM": "jmn",
+ "jmr-Latn-GH": "jmr",
+ "jms-Latn-NG": "jms",
+ "jmw-Latn-PG": "jmw",
+ "jmx-Latn-MX": "jmx",
+ "jna-Takr-IN": "jna",
+ "jnd-Arab-PK": "jnd",
+ "jng-Latn-AU": "jng",
+ "jni-Latn-NG": "jni",
+ "jnj-Ethi-ET": "jnj-Ethi",
+ "jnj-Latn-ET": "jnj",
+ "jnl-Deva-IN": "jnl",
+ "jns-Deva-IN": "jns",
+ "jns-Latn-IN": "jns-Latn",
+ "jns-Takr-IN": "jns-Takr",
+ "job-Latn-CD": "job",
+ "jod-Latn-CI": "jod",
+ "jog-Arab-PK": "jog",
+ "jor-Latn-BO": "jor",
+ "jow-Latn-ML": "jow",
+ "jpa-Hebr-PS": "jpa",
+ "jpr-Hebr-IL": "jpr",
+ "jqr-Latn-PE": "jqr",
+ "jra-Latn-ZZ": "jra",
+ "jrr-Latn-NG": "jrr",
+ "jrt-Latn-NG": "jrt",
+ "jru-Latn-VE": "jru",
+ "jua-Latn-BR": "jua",
+ "jub-Latn-NG": "jub",
+ "jud-Latn-CI": "jud",
+ "juh-Latn-NG": "juh",
+ "jui-Latn-AU": "jui",
+ "juk-Latn-NG": "juk",
+ "jul-Deva-NP": "jul",
+ "jum-Latn-SD": "jum",
+ "jun-Orya-IN": "jun",
+ "juo-Latn-NG": "juo",
+ "jup-Latn-BR": "jup",
+ "jur-Latn-BR": "jur",
+ "jut-Latn-DK": "jut",
+ "juu-Latn-NG": "juu",
+ "juw-Latn-NG": "juw",
+ "juy-Orya-IN": "juy",
+ "jv-Java-ID": "jv-Java",
+ "jv-Latn-ID": "jv",
+ "jvd-Latn-ID": "jvd",
+ "jvn-Latn-SR": "jvn",
+ "jwi-Latn-GH": "jwi",
+ "jya-Tibt-CN": "jya",
+ "jye-Hebr-IL": "jye",
+ "jyy-Latn-TD": "jyy",
+ "ka-Geor-GE": "ka",
+ "kaa-Cyrl-UZ": "kaa",
+ "kab-Latn-DZ": "kab",
+ "kac-Latn-MM": "kac",
+ "kad-Latn-ZZ": "kad",
+ "kag-Latn-MY": "kag",
+ "kah-Latn-CF": "kah",
+ "kai-Latn-ZZ": "kai",
+ "kaj-Latn-NG": "kaj",
+ "kak-Latn-PH": "kak",
+ "kam-Latn-KE": "kam",
+ "kao-Latn-ML": "kao",
+ "kap-Cyrl-RU": "kap",
+ "kaq-Latn-PE": "kaq",
+ "kav-Latn-BR": "kav",
+ "kaw-Kawi-ID": "kaw",
+ "kax-Latn-ID": "kax",
+ "kay-Latn-BR": "kay",
+ "kba-Latn-AU": "kba",
+ "kbb-Latn-BR": "kbb",
+ "kbc-Latn-BR": "kbc",
+ "kbd-Cyrl-RU": "kbd",
+ "kbd-Cyrl-TR": "kbd-TR",
+ "kbe-Latn-AU": "kbe",
+ "kbh-Latn-CO": "kbh",
+ "kbi-Latn-ID": "kbi",
+ "kbj-Latn-CD": "kbj",
+ "kbk-Latn-PG": "kbk",
+ "kbl-Latn-TD": "kbl",
+ "kbm-Latn-ZZ": "kbm",
+ "kbn-Latn-CF": "kbn",
+ "kbo-Latn-SS": "kbo",
+ "kbp-Latn-ZZ": "kbp",
+ "kbq-Latn-ZZ": "kbq",
+ "kbr-Ethi-ET": "kbr-Ethi",
+ "kbr-Latn-ET": "kbr",
+ "kbs-Latn-GA": "kbs",
+ "kbt-Latn-PG": "kbt",
+ "kbu-Arab-PK": "kbu",
+ "kbv-Latn-ID": "kbv",
+ "kbw-Latn-PG": "kbw",
+ "kbx-Latn-ZZ": "kbx",
+ "kby-Arab-NE": "kby",
+ "kbz-Latn-NG": "kbz",
+ "kca-Cyrl-RU": "kca",
+ "kcb-Latn-PG": "kcb",
+ "kcc-Latn-NG": "kcc",
+ "kcd-Latn-ID": "kcd",
+ "kce-Latn-NG": "kce",
+ "kcf-Latn-NG": "kcf",
+ "kcg-Latn-NG": "kcg",
+ "kch-Latn-NG": "kch",
+ "kci-Latn-NG": "kci",
+ "kcj-Latn-GW": "kcj",
+ "kck-Latn-ZW": "kck",
+ "kcl-Latn-ZZ": "kcl",
+ "kcm-Latn-CF": "kcm",
+ "kcn-Latn-UG": "kcn",
+ "kco-Latn-PG": "kco",
+ "kcp-Latn-SD": "kcp",
+ "kcq-Latn-NG": "kcq",
+ "kcs-Latn-NG": "kcs",
+ "kct-Latn-ZZ": "kct",
+ "kcu-Latn-TZ": "kcu",
+ "kcv-Latn-CD": "kcv",
+ "kcw-Latn-CD": "kcw",
+ "kcz-Latn-TZ": "kcz",
+ "kda-Latn-AU": "kda",
+ "kdc-Latn-TZ": "kdc",
+ "kdd-Latn-AU": "kdd",
+ "kde-Latn-TZ": "kde",
+ "kdf-Latn-PG": "kdf",
+ "kdg-Latn-CD": "kdg",
+ "kdh-Latn-TG": "kdh",
+ "kdi-Latn-UG": "kdi",
+ "kdj-Latn-UG": "kdj",
+ "kdk-Latn-NC": "kdk",
+ "kdl-Latn-ZZ": "kdl",
+ "kdm-Latn-NG": "kdm",
+ "kdn-Latn-ZW": "kdn",
+ "kdp-Latn-NG": "kdp",
+ "kdq-Beng-IN": "kdq",
+ "kdr-Cyrl-UA": "kdr-Cyrl",
+ "kdr-Latn-LT": "kdr",
+ "kdt-Thai-KH": "kdt-KH",
+ "kdt-Thai-LA": "kdt-LA",
+ "kdt-Thai-TH": "kdt",
+ "kdw-Latn-ID": "kdw",
+ "kdx-Latn-NG": "kdx",
+ "kdy-Latn-ID": "kdy",
+ "kdz-Latn-CM": "kdz",
+ "kea-Latn-CV": "kea",
+ "keb-Latn-GA": "keb",
+ "kec-Latn-SD": "kec",
+ "ked-Latn-TZ": "ked",
+ "kee-Latn-US": "kee",
+ "kef-Latn-TG": "kef",
+ "keg-Latn-SD": "keg",
+ "keh-Latn-PG": "keh",
+ "kei-Latn-ID": "kei",
+ "kek-Latn-GT": "kek",
+ "kel-Latn-CD": "kel",
+ "kem-Latn-TL": "kem",
+ "ken-Latn-CM": "ken",
+ "keo-Latn-UG": "keo",
+ "ker-Latn-TD": "ker",
+ "kes-Latn-NG": "kes",
+ "ket-Cyrl-RU": "ket",
+ "keu-Latn-TG": "keu",
+ "kew-Latn-PG": "kew",
+ "kex-Deva-IN": "kex",
+ "kex-Gujr-IN": "kex-Gujr",
+ "key-Telu-IN": "key",
+ "kez-Latn-ZZ": "kez",
+ "kfa-Knda-IN": "kfa",
+ "kfb-Deva-IN": "kfb",
+ "kfc-Telu-IN": "kfc",
+ "kfd-Knda-IN": "kfd",
+ "kfe-Taml-IN": "kfe",
+ "kff-Deva-IN": "kff-Deva",
+ "kff-Latn-IN": "kff",
+ "kff-Orya-IN": "kff-Orya",
+ "kff-Telu-IN": "kff-Telu",
+ "kfh-Mlym-IN": "kfh",
+ "kfi-Knda-IN": "kfi-Knda",
+ "kfi-Taml-IN": "kfi",
+ "kfk-Deva-IN": "kfk",
+ "kfk-Takr-IN": "kfk-Takr",
+ "kfl-Latn-CM": "kfl",
+ "kfm-Arab-IR": "kfm",
+ "kfn-Latn-CM": "kfn",
+ "kfo-Latn-CI": "kfo",
+ "kfp-Deva-IN": "kfp",
+ "kfq-Deva-IN": "kfq",
+ "kfr-Deva-IN": "kfr",
+ "kfs-Deva-IN": "kfs",
+ "kfv-Latn-IN": "kfv",
+ "kfw-Latn-IN": "kfw",
+ "kfx-Deva-IN": "kfx",
+ "kfx-Takr-IN": "kfx-Takr",
+ "kfy-Deva-IN": "kfy",
+ "kfz-Latn-BF": "kfz",
+ "kg-Latn-CD": "kg",
+ "kga-Latn-CI": "kga",
+ "kgb-Latn-ID": "kgb",
+ "kge-Latn-ID": "kge",
+ "kgf-Latn-ZZ": "kgf",
+ "kgj-Deva-NP": "kgj",
+ "kgk-Latn-BR": "kgk",
+ "kgl-Latn-AU": "kgl",
+ "kgm-Latn-BR": "kgm",
+ "kgo-Latn-SD": "kgo",
+ "kgp-Latn-BR": "kgp",
+ "kgq-Latn-ID": "kgq",
+ "kgr-Latn-ID": "kgr",
+ "kgs-Latn-AU": "kgs",
+ "kgt-Latn-NG": "kgt",
+ "kgu-Latn-PG": "kgu",
+ "kgv-Latn-ID": "kgv",
+ "kgw-Latn-ID": "kgw",
+ "kgx-Latn-ID": "kgx",
+ "kgy-Deva-NP": "kgy",
+ "kha-Latn-IN": "kha",
+ "khb-Talu-CN": "khb",
+ "khc-Latn-ID": "khc",
+ "khd-Latn-ID": "khd",
+ "khe-Latn-ID": "khe",
+ "khf-Thai-LA": "khf",
+ "khg-Tibt-CN": "khg",
+ "khh-Latn-ID": "khh",
+ "khj-Latn-NG": "khj",
+ "khl-Latn-PG": "khl",
+ "khn-Deva-IN": "khn",
+ "khp-Latn-ID": "khp",
+ "khq-Latn-ML": "khq",
+ "khr-Deva-IN": "khr-Deva",
+ "khr-Latn-IN": "khr",
+ "khs-Latn-ZZ": "khs",
+ "kht-Mymr-IN": "kht",
+ "khu-Latn-AO": "khu",
+ "khv-Cyrl-RU": "khv",
+ "khw-Arab-PK": "khw",
+ "khx-Latn-CD": "khx",
+ "khy-Latn-CD": "khy",
+ "khz-Latn-ZZ": "khz",
+ "ki-Latn-KE": "ki",
+ "kia-Latn-TD": "kia",
+ "kib-Latn-SD": "kib",
+ "kic-Latn-US": "kic",
+ "kid-Latn-CM": "kid",
+ "kie-Latn-TD": "kie",
+ "kif-Deva-NP": "kif",
+ "kig-Latn-ID": "kig",
+ "kih-Latn-PG": "kih",
+ "kij-Latn-ZZ": "kij",
+ "kil-Latn-NG": "kil",
+ "kim-Cyrl-RU": "kim",
+ "kio-Latn-US": "kio",
+ "kip-Deva-NP": "kip",
+ "kiq-Latn-ID": "kiq",
+ "kis-Latn-PG": "kis",
+ "kit-Latn-PG": "kit",
+ "kiu-Latn-TR": "kiu",
+ "kiv-Latn-TZ": "kiv",
+ "kiw-Latn-ZZ": "kiw",
+ "kix-Latn-IN": "kix",
+ "kiy-Latn-ID": "kiy",
+ "kiz-Latn-TZ": "kiz",
+ "kj-Latn-NA": "kj",
+ "kja-Latn-ID": "kja",
+ "kjb-Latn-GT": "kjb",
+ "kjc-Latn-ID": "kjc",
+ "kjd-Latn-ZZ": "kjd",
+ "kje-Latn-ID": "kje",
+ "kjg-Laoo-LA": "kjg",
+ "kjh-Cyrl-RU": "kjh",
+ "kji-Latn-SB": "kji",
+ "kjj-Latn-AZ": "kjj",
+ "kjk-Latn-ID": "kjk",
+ "kjl-Deva-NP": "kjl",
+ "kjm-Latn-VN": "kjm",
+ "kjn-Latn-AU": "kjn",
+ "kjo-Deva-IN": "kjo",
+ "kjp-Mymr-MM": "kjp",
+ "kjp-Thai-TH": "kjp-Thai",
+ "kjq-Latn-US": "kjq",
+ "kjr-Latn-ID": "kjr",
+ "kjs-Latn-ZZ": "kjs",
+ "kjt-Thai-TH": "kjt",
+ "kju-Latn-US": "kju",
+ "kjx-Latn-PG": "kjx",
+ "kjy-Latn-ZZ": "kjy",
+ "kk-Arab-AF": "kk-AF",
+ "kk-Arab-CN": "kk-CN",
+ "kk-Arab-IR": "kk-IR",
+ "kk-Arab-MN": "kk-MN",
+ "kk-Cyrl-KZ": "kk",
+ "kka-Latn-NG": "kka",
+ "kkb-Latn-ID": "kkb",
+ "kkc-Latn-ZZ": "kkc",
+ "kkd-Latn-NG": "kkd",
+ "kke-Arab-GN": "kke-Arab",
+ "kke-Latn-GN": "kke",
+ "kkf-Tibt-IN": "kkf",
+ "kkg-Latn-PH": "kkg",
+ "kkh-Lana-MM": "kkh",
+ "kki-Latn-TZ": "kki",
+ "kkj-Latn-CM": "kkj",
+ "kkk-Latn-SB": "kkk",
+ "kkl-Latn-ID": "kkl",
+ "kkm-Latn-NG": "kkm",
+ "kko-Latn-SD": "kko",
+ "kkp-Latn-AU": "kkp",
+ "kkq-Latn-CD": "kkq",
+ "kkr-Latn-NG": "kkr",
+ "kks-Latn-NG": "kks",
+ "kkt-Deva-NP": "kkt",
+ "kku-Latn-NG": "kku",
+ "kkv-Latn-ID": "kkv",
+ "kkw-Latn-CG": "kkw",
+ "kkx-Latn-ID": "kkx",
+ "kky-Latn-AU": "kky",
+ "kkz-Latn-CA": "kkz",
+ "kl-Latn-GL": "kl",
+ "kla-Latn-US": "kla",
+ "klb-Latn-MX": "klb",
+ "klc-Latn-CM": "klc",
+ "kld-Latn-AU": "kld",
+ "kle-Deva-NP": "kle",
+ "klf-Latn-TD": "klf",
+ "klg-Latn-PH": "klg",
+ "klh-Latn-PG": "klh",
+ "kli-Latn-ID": "kli",
+ "klj-Arab-IR": "klj",
+ "klk-Latn-NG": "klk",
+ "kll-Latn-PH": "kll",
+ "klm-Latn-PG": "klm",
+ "kln-Latn-KE": "kln",
+ "klo-Latn-NG": "klo",
+ "klp-Latn-PG": "klp",
+ "klq-Latn-ZZ": "klq",
+ "klr-Deva-NP": "klr",
+ "kls-Arab-PK": "kls-Arab",
+ "kls-Latn-PK": "kls",
+ "klt-Latn-ZZ": "klt",
+ "klu-Latn-LR": "klu",
+ "klv-Latn-VU": "klv",
+ "klw-Latn-ID": "klw",
+ "klx-Latn-ZZ": "klx",
+ "kly-Latn-ID": "kly",
+ "klz-Latn-ID": "klz",
+ "km-Khmr-KH": "km",
+ "kma-Latn-GH": "kma",
+ "kmb-Latn-AO": "kmb",
+ "kmc-Hani-CN": "kmc-Hani",
+ "kmc-Latn-CN": "kmc",
+ "kmd-Latn-PH": "kmd",
+ "kme-Latn-CM": "kme",
+ "kmf-Latn-PG": "kmf",
+ "kmg-Latn-PG": "kmg",
+ "kmh-Latn-ZZ": "kmh",
+ "kmi-Latn-NG": "kmi",
+ "kmj-Deva-IN": "kmj",
+ "kmk-Latn-PH": "kmk",
+ "kml-Latn-PH": "kml",
+ "kmm-Latn-IN": "kmm",
+ "kmn-Latn-PG": "kmn",
+ "kmo-Latn-ZZ": "kmo",
+ "kmp-Latn-CM": "kmp",
+ "kmq-Latn-ET": "kmq",
+ "kms-Latn-ZZ": "kms",
+ "kmt-Latn-ID": "kmt",
+ "kmu-Latn-ZZ": "kmu",
+ "kmv-Latn-BR": "kmv",
+ "kmw-Latn-ZZ": "kmw",
+ "kmx-Latn-PG": "kmx",
+ "kmy-Latn-NG": "kmy",
+ "kmz-Arab-IR": "kmz",
+ "kn-Knda-IN": "kn",
+ "kna-Latn-NG": "kna",
+ "knb-Latn-PH": "knb",
+ "knd-Latn-ID": "knd",
+ "kne-Latn-PH": "kne",
+ "knf-Latn-GW": "knf",
+ "kni-Latn-NG": "kni",
+ "knj-Latn-GT": "knj",
+ "knk-Arab-SL": "knk-Arab",
+ "knk-Latn-SL": "knk",
+ "knl-Latn-ID": "knl",
+ "knm-Latn-BR": "knm",
+ "kno-Latn-SL": "kno",
+ "knp-Latn-ZZ": "knp",
+ "knq-Latn-MY": "knq",
+ "knr-Latn-PG": "knr",
+ "kns-Latn-MY": "kns",
+ "kns-Thai-TH": "kns-Thai",
+ "knt-Latn-BR": "knt",
+ "knu-Latn-GN": "knu",
+ "knv-Latn-PG": "knv",
+ "knw-Latn-NA": "knw",
+ "knx-Latn-ID": "knx",
+ "kny-Latn-CD": "kny",
+ "knz-Latn-BF": "knz",
+ "ko-Hang-KR": "ko-Hang",
+ "ko-Jamo-KR": "ko-Jamo",
+ "ko-Kore-KP": "ko-KP",
+ "ko-Kore-KR": "ko",
+ "koa-Latn-PG": "koa",
+ "koc-Latn-NG": "koc",
+ "kod-Latn-ID": "kod",
+ "koe-Latn-SS": "koe",
+ "kof-Latn-NG": "kof",
+ "kog-Latn-CO": "kog",
+ "koh-Latn-CG": "koh",
+ "koi-Cyrl-RU": "koi",
+ "kok-Deva-IN": "kok",
+ "kol-Latn-ZZ": "kol",
+ "koo-Latn-UG": "koo",
+ "kop-Latn-PG": "kop",
+ "koq-Latn-GA": "koq",
+ "kos-Latn-FM": "kos",
+ "kot-Latn-CM": "kot",
+ "kou-Latn-TD": "kou",
+ "kov-Latn-NG": "kov",
+ "kow-Latn-NG": "kow",
+ "koy-Latn-US": "koy",
+ "koz-Latn-ZZ": "koz",
+ "kpa-Latn-NG": "kpa",
+ "kpc-Latn-CO": "kpc",
+ "kpd-Latn-ID": "kpd",
+ "kpe-Latn-LR": "kpe",
+ "kpf-Latn-ZZ": "kpf",
+ "kpg-Latn-FM": "kpg",
+ "kph-Latn-GH": "kph",
+ "kpi-Latn-ID": "kpi",
+ "kpj-Latn-BR": "kpj",
+ "kpk-Latn-NG": "kpk",
+ "kpl-Latn-CD": "kpl",
+ "kpm-Latn-VN": "kpm",
+ "kpn-Latn-BR": "kpn",
+ "kpo-Latn-ZZ": "kpo",
+ "kpq-Latn-ID": "kpq",
+ "kpr-Latn-ZZ": "kpr",
+ "kps-Latn-ID": "kps",
+ "kpt-Cyrl-RU": "kpt",
+ "kpu-Latn-ID": "kpu",
+ "kpw-Latn-PG": "kpw",
+ "kpx-Latn-ZZ": "kpx",
+ "kpy-Cyrl-RU": "kpy",
+ "kpz-Latn-UG": "kpz",
+ "kqa-Latn-PG": "kqa",
+ "kqb-Latn-ZZ": "kqb",
+ "kqc-Latn-PG": "kqc",
+ "kqd-Syrc-IQ": "kqd",
+ "kqe-Latn-PH": "kqe",
+ "kqf-Latn-ZZ": "kqf",
+ "kqg-Latn-BF": "kqg",
+ "kqh-Latn-TZ": "kqh",
+ "kqi-Latn-PG": "kqi",
+ "kqj-Latn-PG": "kqj",
+ "kqk-Latn-BJ": "kqk",
+ "kql-Latn-PG": "kql",
+ "kqm-Latn-CI": "kqm",
+ "kqn-Latn-ZM": "kqn",
+ "kqo-Latn-LR": "kqo",
+ "kqp-Latn-TD": "kqp",
+ "kqq-Latn-BR": "kqq",
+ "kqr-Latn-MY": "kqr",
+ "kqs-Latn-ZZ": "kqs",
+ "kqt-Latn-MY": "kqt",
+ "kqu-Latn-ZA": "kqu",
+ "kqv-Latn-ID": "kqv",
+ "kqw-Latn-PG": "kqw",
+ "kqx-Latn-CM": "kqx",
+ "kqy-Ethi-ZZ": "kqy",
+ "kqz-Latn-ZA": "kqz",
+ "kr-Latn-ZZ": "kr",
+ "kra-Deva-NP": "kra",
+ "krb-Latn-US": "krb",
+ "krc-Cyrl-RU": "krc",
+ "krd-Latn-TL": "krd",
+ "kre-Latn-BR": "kre",
+ "krf-Latn-VU": "krf",
+ "krh-Latn-NG": "krh",
+ "kri-Latn-SL": "kri",
+ "krj-Latn-PH": "krj",
+ "krk-Cyrl-RU": "krk",
+ "krl-Latn-RU": "krl",
+ "krn-Latn-LR": "krn",
+ "krp-Latn-NG": "krp",
+ "krr-Khmr-KH": "krr",
+ "krs-Latn-ZZ": "krs",
+ "krt-Latn-NE": "krt",
+ "kru-Deva-IN": "kru",
+ "krv-Khmr-KH": "krv",
+ "krw-Latn-LR": "krw",
+ "krx-Latn-SN": "krx",
+ "kry-Latn-AZ": "kry",
+ "krz-Latn-ID": "krz",
+ "ks-Arab-IN": "ks",
+ "ksa-Latn-NG": "ksa",
+ "ksb-Latn-TZ": "ksb",
+ "ksc-Latn-PH": "ksc",
+ "ksd-Latn-ZZ": "ksd",
+ "kse-Latn-PG": "kse",
+ "ksf-Latn-CM": "ksf",
+ "ksg-Latn-SB": "ksg",
+ "ksh-Latn-DE": "ksh",
+ "ksi-Latn-PG": "ksi",
+ "ksj-Latn-ZZ": "ksj",
+ "ksk-Latn-US": "ksk",
+ "ksl-Latn-PG": "ksl",
+ "ksm-Latn-NG": "ksm",
+ "ksn-Latn-PH": "ksn",
+ "kso-Latn-NG": "kso",
+ "ksp-Latn-CF": "ksp",
+ "ksq-Latn-NG": "ksq",
+ "ksr-Latn-ZZ": "ksr",
+ "kss-Latn-LR": "kss",
+ "kst-Latn-BF": "kst",
+ "ksu-Mymr-IN": "ksu",
+ "ksv-Latn-CD": "ksv",
+ "ksw-Latn-MM": "ksw-Latn",
+ "ksw-Mymr-MM": "ksw",
+ "ksx-Latn-ID": "ksx",
+ "ksz-Deva-IN": "ksz",
+ "kta-Latn-VN": "kta",
+ "ktb-Ethi-ZZ": "ktb",
+ "ktc-Latn-NG": "ktc",
+ "ktd-Latn-AU": "ktd",
+ "ktf-Latn-CD": "ktf",
+ "ktg-Latn-AU": "ktg",
+ "kth-Latn-TD": "kth",
+ "kti-Latn-ID": "kti",
+ "ktj-Latn-CI": "ktj",
+ "ktk-Latn-PG": "ktk",
+ "ktl-Arab-IR": "ktl",
+ "ktm-Latn-ZZ": "ktm",
+ "ktn-Latn-BR": "ktn",
+ "kto-Latn-ZZ": "kto",
+ "ktp-Plrd-CN": "ktp",
+ "ktq-Latn-PH": "ktq",
+ "kts-Latn-ID": "kts",
+ "ktt-Latn-ID": "ktt",
+ "ktu-Latn-CD": "ktu",
+ "ktv-Latn-VN": "ktv",
+ "ktw-Latn-US": "ktw",
+ "ktx-Latn-BR": "ktx",
+ "kty-Latn-CD": "kty",
+ "ktz-Latn-NA": "ktz",
+ "ku-Arab-IQ": "ku-Arab",
+ "ku-Arab-LB": "ku-LB",
+ "ku-Latn-AM": "ku-AM",
+ "ku-Latn-GE": "ku-GE",
+ "ku-Latn-TR": "ku",
+ "ku-Yezi-GE": "ku-Yezi",
+ "kub-Latn-ZZ": "kub",
+ "kuc-Latn-ID": "kuc",
+ "kud-Latn-ZZ": "kud",
+ "kue-Latn-ZZ": "kue",
+ "kuf-Laoo-LA": "kuf",
+ "kug-Latn-NG": "kug",
+ "kuh-Latn-NG": "kuh",
+ "kui-Latn-BR": "kui",
+ "kuj-Latn-ZZ": "kuj",
+ "kuk-Latn-ID": "kuk",
+ "kul-Latn-NG": "kul",
+ "kum-Cyrl-RU": "kum",
+ "kun-Latn-ZZ": "kun",
+ "kuo-Latn-PG": "kuo",
+ "kup-Latn-ZZ": "kup",
+ "kuq-Latn-BR": "kuq",
+ "kus-Latn-ZZ": "kus",
+ "kut-Latn-CA": "kut",
+ "kuu-Latn-US": "kuu",
+ "kuv-Latn-ID": "kuv",
+ "kuw-Latn-CF": "kuw",
+ "kux-Latn-AU": "kux",
+ "kuy-Latn-AU": "kuy",
+ "kuz-Latn-CL": "kuz",
+ "kv-Cyrl-RU": "kv",
+ "kv-Perm-RU": "kv-Perm",
+ "kva-Cyrl-RU": "kva",
+ "kvb-Latn-ID": "kvb",
+ "kvc-Latn-PG": "kvc",
+ "kvd-Latn-ID": "kvd",
+ "kve-Latn-MY": "kve",
+ "kvf-Latn-TD": "kvf",
+ "kvg-Latn-ZZ": "kvg",
+ "kvh-Latn-ID": "kvh",
+ "kvi-Latn-TD": "kvi",
+ "kvj-Latn-CM": "kvj",
+ "kvl-Latn-MM": "kvl",
+ "kvm-Latn-CM": "kvm",
+ "kvn-Latn-CO": "kvn",
+ "kvo-Latn-ID": "kvo",
+ "kvp-Latn-ID": "kvp",
+ "kvq-Latn-MM": "kvq-Latn",
+ "kvq-Mymr-MM": "kvq",
+ "kvr-Latn-ID": "kvr",
+ "kvt-Mymr-MM": "kvt",
+ "kvv-Latn-ID": "kvv",
+ "kvw-Latn-ID": "kvw",
+ "kvx-Arab-PK": "kvx",
+ "kvy-Kali-MM": "kvy",
+ "kvz-Latn-ID": "kvz",
+ "kw-Latn-GB": "kw",
+ "kwa-Latn-BR": "kwa",
+ "kwb-Latn-NG": "kwb",
+ "kwc-Latn-CG": "kwc",
+ "kwd-Latn-SB": "kwd",
+ "kwe-Latn-ID": "kwe",
+ "kwf-Latn-SB": "kwf",
+ "kwg-Latn-TD": "kwg",
+ "kwh-Latn-ID": "kwh",
+ "kwi-Latn-CO": "kwi",
+ "kwj-Latn-ZZ": "kwj",
+ "kwk-Latn-CA": "kwk",
+ "kwl-Latn-NG": "kwl",
+ "kwm-Latn-NA": "kwm",
+ "kwn-Latn-NA": "kwn",
+ "kwo-Latn-ZZ": "kwo",
+ "kwp-Latn-CI": "kwp",
+ "kwr-Latn-ID": "kwr",
+ "kws-Latn-CD": "kws",
+ "kwt-Latn-ID": "kwt",
+ "kwu-Latn-CM": "kwu",
+ "kwv-Latn-TD": "kwv",
+ "kww-Latn-SR": "kww",
+ "kwy-Latn-CD": "kwy",
+ "kwz-Latn-AO": "kwz",
+ "kxa-Latn-ZZ": "kxa",
+ "kxb-Latn-CI": "kxb",
+ "kxc-Ethi-ZZ": "kxc",
+ "kxd-Arab-BN": "kxd-Arab",
+ "kxd-Latn-BN": "kxd",
+ "kxf-Latn-MM": "kxf-Latn",
+ "kxf-Mymr-MM": "kxf",
+ "kxi-Latn-MY": "kxi",
+ "kxj-Latn-TD": "kxj",
+ "kxk-Mymr-MM": "kxk",
+ "kxm-Thai-TH": "kxm",
+ "kxn-Latn-MY": "kxn",
+ "kxo-Latn-BR": "kxo",
+ "kxp-Arab-PK": "kxp",
+ "kxq-Latn-ID": "kxq",
+ "kxr-Latn-PG": "kxr",
+ "kxt-Latn-PG": "kxt",
+ "kxv-Latn-IN": "kxv-Latn",
+ "kxv-Orya-IN": "kxv",
+ "kxv-Telu-IN": "kxv-Telu",
+ "kxw-Latn-ZZ": "kxw",
+ "kxx-Latn-CG": "kxx",
+ "kxy-Latn-VN": "kxy",
+ "kxz-Latn-ZZ": "kxz",
+ "ky-Arab-CN": "ky-CN",
+ "ky-Cyrl-KG": "ky",
+ "ky-Latn-TR": "ky-TR",
+ "kya-Latn-TZ": "kya",
+ "kyb-Latn-PH": "kyb",
+ "kyc-Latn-PG": "kyc",
+ "kyd-Latn-ID": "kyd",
+ "kye-Latn-ZZ": "kye",
+ "kyf-Latn-CI": "kyf",
+ "kyg-Latn-PG": "kyg",
+ "kyh-Latn-US": "kyh",
+ "kyi-Latn-MY": "kyi",
+ "kyj-Latn-PH": "kyj",
+ "kyk-Latn-PH": "kyk",
+ "kyl-Latn-US": "kyl",
+ "kym-Latn-CF": "kym",
+ "kyn-Latn-PH": "kyn",
+ "kyo-Latn-ID": "kyo",
+ "kyq-Latn-TD": "kyq",
+ "kyr-Latn-BR": "kyr",
+ "kys-Latn-MY": "kys",
+ "kyt-Latn-ID": "kyt",
+ "kyu-Kali-MM": "kyu",
+ "kyu-Latn-MM": "kyu-Latn",
+ "kyu-Mymr-MM": "kyu-Mymr",
+ "kyv-Deva-NP": "kyv",
+ "kyw-Beng-IN": "kyw-Beng",
+ "kyw-Deva-IN": "kyw",
+ "kyw-Orya-IN": "kyw-Orya",
+ "kyx-Latn-ZZ": "kyx",
+ "kyy-Latn-PG": "kyy",
+ "kyz-Latn-BR": "kyz",
+ "kza-Latn-BF": "kza",
+ "kzb-Latn-ID": "kzb",
+ "kzc-Latn-CI": "kzc",
+ "kzd-Latn-ID": "kzd",
+ "kze-Latn-PG": "kze",
+ "kzf-Latn-ID": "kzf",
+ "kzi-Latn-MY": "kzi",
+ "kzk-Latn-SB": "kzk",
+ "kzl-Latn-ID": "kzl",
+ "kzm-Latn-ID": "kzm",
+ "kzn-Latn-MW": "kzn",
+ "kzo-Latn-GA": "kzo",
+ "kzp-Latn-ID": "kzp",
+ "kzr-Latn-ZZ": "kzr",
+ "kzs-Latn-MY": "kzs",
+ "kzu-Latn-ID": "kzu",
+ "kzv-Latn-ID": "kzv",
+ "kzw-Latn-BR": "kzw",
+ "kzx-Latn-ID": "kzx",
+ "kzy-Latn-CD": "kzy",
+ "kzz-Latn-ID": "kzz",
+ "la-Latn-VA": "la",
+ "laa-Latn-PH": "laa",
+ "lab-Lina-GR": "lab",
+ "lac-Latn-MX": "lac",
+ "lad-Hebr-IL": "lad",
+ "lae-Deva-IN": "lae",
+ "lae-Tibt-IN": "lae-Tibt",
+ "lag-Latn-TZ": "lag",
+ "lah-Arab-PK": "lah",
+ "lai-Latn-MW": "lai",
+ "laj-Latn-UG": "laj",
+ "lal-Latn-CD": "lal",
+ "lam-Latn-ZM": "lam",
+ "lan-Latn-NG": "lan",
+ "lap-Latn-TD": "lap",
+ "laq-Latn-VN": "laq",
+ "lar-Latn-GH": "lar",
+ "las-Latn-ZZ": "las",
+ "lau-Latn-ID": "lau",
+ "law-Latn-ID": "law",
+ "lax-Beng-IN": "lax-Beng",
+ "lax-Latn-IN": "lax",
+ "laz-Latn-PG": "laz",
+ "lb-Latn-LU": "lb",
+ "lbb-Latn-PG": "lbb",
+ "lbc-Lisu-CN": "lbc",
+ "lbe-Cyrl-RU": "lbe",
+ "lbf-Deva-IN": "lbf",
+ "lbf-Tibt-CN": "lbf-Tibt",
+ "lbi-Latn-CM": "lbi",
+ "lbj-Arab-IN": "lbj-Arab",
+ "lbj-Tibt-IN": "lbj",
+ "lbl-Latn-PH": "lbl",
+ "lbm-Deva-IN": "lbm",
+ "lbn-Laoo-LA": "lbn-Laoo",
+ "lbn-Latn-LA": "lbn",
+ "lbo-Laoo-LA": "lbo",
+ "lbo-Latn-US": "lbo-Latn",
+ "lbq-Latn-PG": "lbq",
+ "lbr-Deva-NP": "lbr",
+ "lbt-Latn-VN": "lbt",
+ "lbu-Latn-ZZ": "lbu",
+ "lbv-Latn-PG": "lbv",
+ "lbw-Latn-ID": "lbw",
+ "lbx-Latn-ID": "lbx",
+ "lby-Latn-AU": "lby",
+ "lbz-Latn-AU": "lbz",
+ "lcc-Latn-ID": "lcc",
+ "lcd-Latn-ID": "lcd",
+ "lce-Latn-ID": "lce",
+ "lcf-Latn-ID": "lcf",
+ "lch-Latn-AO": "lch",
+ "lcl-Latn-ID": "lcl",
+ "lcm-Latn-ZZ": "lcm",
+ "lcp-Thai-CN": "lcp",
+ "lcq-Latn-ID": "lcq",
+ "lcs-Latn-ID": "lcs",
+ "lda-Latn-CI": "lda",
+ "ldb-Latn-ZZ": "ldb",
+ "ldd-Latn-NG": "ldd",
+ "ldg-Latn-NG": "ldg",
+ "ldh-Latn-NG": "ldh",
+ "ldi-Latn-CG": "ldi",
+ "ldj-Latn-NG": "ldj",
+ "ldk-Latn-NG": "ldk",
+ "ldl-Latn-NG": "ldl",
+ "ldm-Latn-GN": "ldm",
+ "ldn-Latn-001": "ldn",
+ "ldo-Latn-NG": "ldo",
+ "ldp-Latn-NG": "ldp",
+ "ldq-Latn-NG": "ldq",
+ "lea-Latn-CD": "lea",
+ "leb-Latn-ZM": "leb",
+ "lec-Latn-BO": "lec",
+ "led-Latn-ZZ": "led",
+ "lee-Latn-ZZ": "lee",
+ "lef-Latn-GH": "lef",
+ "leh-Latn-ZM": "leh",
+ "lei-Latn-PG": "lei",
+ "lej-Latn-CD": "lej",
+ "lek-Latn-PG": "lek",
+ "lel-Latn-CD": "lel",
+ "lem-Latn-ZZ": "lem",
+ "len-Latn-HN": "len",
+ "leo-Latn-CM": "leo",
+ "lep-Lepc-IN": "lep",
+ "leq-Latn-ZZ": "leq",
+ "ler-Latn-PG": "ler",
+ "les-Latn-CD": "les",
+ "let-Latn-PG": "let",
+ "leu-Latn-ZZ": "leu",
+ "lev-Latn-ID": "lev",
+ "lew-Latn-ID": "lew",
+ "lex-Latn-ID": "lex",
+ "ley-Latn-ID": "ley",
+ "lez-Cyrl-RU": "lez",
+ "lfa-Latn-CM": "lfa",
+ "lfn-Cyrl-001": "lfn-Cyrl",
+ "lfn-Latn-001": "lfn",
+ "lg-Latn-UG": "lg",
+ "lga-Latn-SB": "lga",
+ "lgb-Latn-SB": "lgb",
+ "lgg-Latn-ZZ": "lgg",
+ "lgh-Latn-VN": "lgh",
+ "lgi-Latn-ID": "lgi",
+ "lgk-Latn-VU": "lgk",
+ "lgl-Latn-SB": "lgl",
+ "lgm-Latn-CD": "lgm",
+ "lgn-Latn-ET": "lgn",
+ "lgo-Latn-SS": "lgo",
+ "lgq-Latn-GH": "lgq",
+ "lgr-Latn-SB": "lgr",
+ "lgt-Latn-PG": "lgt",
+ "lgu-Latn-SB": "lgu",
+ "lgz-Latn-CD": "lgz",
+ "lha-Latn-VN": "lha",
+ "lhh-Latn-ID": "lhh",
+ "lhi-Latn-CN": "lhi",
+ "lhm-Deva-NP": "lhm",
+ "lhn-Latn-MY": "lhn",
+ "lhs-Syrc-SY": "lhs",
+ "lht-Latn-VU": "lht",
+ "lhu-Latn-CN": "lhu",
+ "li-Latn-NL": "li",
+ "lia-Latn-ZZ": "lia",
+ "lib-Latn-PG": "lib",
+ "lic-Latn-CN": "lic",
+ "lid-Latn-ZZ": "lid",
+ "lie-Latn-CD": "lie",
+ "lif-Deva-NP": "lif",
+ "lif-Limb-IN": "lif-Limb",
+ "lig-Latn-ZZ": "lig",
+ "lih-Latn-ZZ": "lih",
+ "lij-Latn-IT": "lij",
+ "lik-Latn-CD": "lik",
+ "lil-Latn-CA": "lil",
+ "lio-Latn-ID": "lio",
+ "lip-Latn-GH": "lip",
+ "liq-Latn-ET": "liq",
+ "lir-Latn-LR": "lir",
+ "lis-Lisu-CN": "lis",
+ "liu-Latn-SD": "liu",
+ "liv-Latn-LV": "liv",
+ "liw-Latn-ID": "liw",
+ "lix-Latn-ID": "lix",
+ "liy-Latn-CF": "liy",
+ "liz-Latn-CD": "liz",
+ "lja-Latn-AU": "lja",
+ "lje-Latn-ID": "lje",
+ "lji-Latn-ID": "lji",
+ "ljl-Latn-ID": "ljl",
+ "ljp-Latn-ID": "ljp",
+ "ljw-Latn-AU": "ljw",
+ "ljx-Latn-AU": "ljx",
+ "lka-Latn-TL": "lka",
+ "lkb-Latn-KE": "lkb",
+ "lkc-Latn-VN": "lkc",
+ "lkd-Latn-BR": "lkd",
+ "lke-Latn-UG": "lke",
+ "lkh-Tibt-BT": "lkh",
+ "lki-Arab-IR": "lki",
+ "lkj-Latn-MY": "lkj",
+ "lkl-Latn-PG": "lkl",
+ "lkm-Latn-AU": "lkm",
+ "lkn-Latn-VU": "lkn",
+ "lko-Latn-KE": "lko",
+ "lkr-Latn-SS": "lkr",
+ "lks-Latn-KE": "lks",
+ "lkt-Latn-US": "lkt",
+ "lku-Latn-AU": "lku",
+ "lky-Latn-SS": "lky",
+ "lla-Latn-NG": "lla",
+ "llb-Latn-MZ": "llb",
+ "llc-Latn-GN": "llc",
+ "lld-Latn-IT": "lld",
+ "lle-Latn-ZZ": "lle",
+ "llf-Latn-PG": "llf",
+ "llg-Latn-ID": "llg",
+ "lli-Latn-CG": "lli",
+ "llj-Latn-AU": "llj",
+ "llk-Latn-MY": "llk",
+ "lll-Latn-PG": "lll",
+ "llm-Latn-ID": "llm",
+ "lln-Latn-ZZ": "lln",
+ "llp-Latn-VU": "llp",
+ "llq-Latn-ID": "llq",
+ "llu-Latn-SB": "llu",
+ "llx-Latn-FJ": "llx",
+ "lma-Latn-GN": "lma",
+ "lmb-Latn-VU": "lmb",
+ "lmc-Latn-AU": "lmc",
+ "lmd-Latn-SD": "lmd",
+ "lme-Latn-TD": "lme",
+ "lmf-Latn-ID": "lmf",
+ "lmg-Latn-PG": "lmg",
+ "lmh-Deva-NP": "lmh",
+ "lmi-Latn-CD": "lmi",
+ "lmj-Latn-ID": "lmj",
+ "lmk-Latn-IN": "lmk",
+ "lmk-Mymr-IN": "lmk-Mymr",
+ "lml-Latn-VU": "lml",
+ "lmn-Telu-IN": "lmn",
+ "lmo-Latn-IT": "lmo",
+ "lmp-Latn-ZZ": "lmp",
+ "lmq-Latn-ID": "lmq",
+ "lmr-Latn-ID": "lmr",
+ "lmu-Latn-VU": "lmu",
+ "lmv-Latn-FJ": "lmv",
+ "lmw-Latn-US": "lmw",
+ "lmx-Latn-CM": "lmx",
+ "lmy-Latn-ID": "lmy",
+ "ln-Latn-CD": "ln",
+ "lna-Latn-CF": "lna",
+ "lnb-Latn-NA": "lnb",
+ "lnd-Latn-ID": "lnd",
+ "lnh-Latn-MY": "lnh",
+ "lni-Latn-PG": "lni",
+ "lnj-Latn-AU": "lnj",
+ "lnl-Latn-CF": "lnl",
+ "lnm-Latn-PG": "lnm",
+ "lnn-Latn-VU": "lnn",
+ "lns-Latn-ZZ": "lns",
+ "lnu-Latn-ZZ": "lnu",
+ "lnw-Latn-AU": "lnw",
+ "lnz-Latn-CD": "lnz",
+ "lo-Laoo-LA": "lo",
+ "loa-Latn-ID": "loa",
+ "lob-Latn-BF": "lob",
+ "loc-Latn-PH": "loc",
+ "loe-Latn-ID": "loe",
+ "log-Latn-CD": "log",
+ "loh-Latn-SS": "loh",
+ "loi-Latn-CI": "loi",
+ "loj-Latn-ZZ": "loj",
+ "lok-Latn-ZZ": "lok",
+ "lol-Latn-CD": "lol",
+ "lom-Latn-LR": "lom",
+ "lon-Latn-MW": "lon",
+ "loo-Latn-CD": "loo",
+ "lop-Latn-NG": "lop",
+ "loq-Latn-CD": "loq",
+ "lor-Latn-ZZ": "lor",
+ "los-Latn-ZZ": "los",
+ "lot-Arab-SS": "lot-Arab",
+ "lot-Latn-SS": "lot",
+ "lou-Latn-US": "lou",
+ "low-Latn-MY": "low",
+ "lox-Latn-ID": "lox",
+ "loy-Deva-NP": "loy",
+ "loy-Tibt-NP": "loy-Tibt",
+ "loz-Latn-ZM": "loz",
+ "lpa-Latn-VU": "lpa",
+ "lpe-Latn-ID": "lpe",
+ "lpn-Latn-MM": "lpn",
+ "lpo-Lisu-CN": "lpo-Lisu",
+ "lpo-Plrd-CN": "lpo",
+ "lpx-Latn-SS": "lpx",
+ "lqr-Latn-SS": "lqr",
+ "lra-Latn-MY": "lra",
+ "lrc-Arab-IR": "lrc",
+ "lrg-Latn-AU": "lrg",
+ "lri-Latn-KE": "lri",
+ "lrk-Arab-PK": "lrk",
+ "lrl-Arab-IR": "lrl",
+ "lrm-Latn-KE": "lrm",
+ "lrn-Latn-ID": "lrn",
+ "lro-Latn-SD": "lro",
+ "lrt-Latn-ID": "lrt",
+ "lrv-Latn-VU": "lrv",
+ "lrz-Latn-VU": "lrz",
+ "lsa-Arab-IR": "lsa",
+ "lsd-Hebr-IL": "lsd",
+ "lse-Latn-CD": "lse",
+ "lsi-Latn-MM": "lsi",
+ "lsm-Latn-UG": "lsm",
+ "lsr-Latn-PG": "lsr",
+ "lss-Arab-PK": "lss",
+ "lt-Latn-LT": "lt",
+ "ltg-Latn-LV": "ltg",
+ "lth-Latn-UG": "lth",
+ "lti-Latn-ID": "lti",
+ "ltn-Latn-BR": "ltn",
+ "lto-Latn-KE": "lto",
+ "lts-Latn-KE": "lts",
+ "ltu-Latn-ID": "ltu",
+ "lu-Latn-CD": "lu",
+ "lua-Latn-CD": "lua",
+ "luc-Latn-UG": "luc",
+ "lud-Latn-RU": "lud",
+ "lue-Latn-ZM": "lue",
+ "luf-Latn-PG": "luf",
+ "lui-Latn-US": "lui",
+ "luj-Latn-CD": "luj",
+ "luk-Tibt-BT": "luk",
+ "lul-Latn-SS": "lul",
+ "lum-Latn-AO": "lum",
+ "lun-Latn-ZM": "lun",
+ "luo-Latn-KE": "luo",
+ "lup-Latn-GA": "lup",
+ "luq-Latn-CU": "luq",
+ "lur-Latn-ID": "lur",
+ "lus-Beng-BD": "lus-Beng",
+ "lus-Brai-IN": "lus-Brai",
+ "lus-Latn-IN": "lus",
+ "lut-Latn-US": "lut",
+ "luu-Deva-NP": "luu",
+ "luv-Arab-OM": "luv",
+ "luw-Latn-CM": "luw",
+ "luy-Latn-KE": "luy",
+ "luz-Arab-IR": "luz",
+ "lv-Latn-LV": "lv",
+ "lva-Latn-TL": "lva",
+ "lvi-Latn-LA": "lvi",
+ "lvk-Latn-SB": "lvk",
+ "lvu-Latn-ID": "lvu",
+ "lwa-Latn-CD": "lwa",
+ "lwe-Latn-ID": "lwe",
+ "lwg-Latn-KE": "lwg",
+ "lwh-Latn-VN": "lwh",
+ "lwl-Thai-TH": "lwl",
+ "lwm-Thai-CN": "lwm",
+ "lwo-Latn-SS": "lwo",
+ "lwo-Latn-ZA": "lwo-ZA",
+ "lwt-Latn-ID": "lwt",
+ "lww-Latn-VU": "lww",
+ "lxm-Latn-PG": "lxm",
+ "lya-Tibt-BT": "lya",
+ "lyn-Latn-ZM": "lyn",
+ "lzh-Hans-CN": "lzh",
+ "lzh-Phag-CN": "lzh-Phag",
+ "lzl-Latn-VU": "lzl",
+ "lzn-Latn-MM": "lzn",
+ "lzz-Latn-TR": "lzz",
+ "maa-Latn-MX": "maa",
+ "mab-Latn-MX": "mab",
+ "mad-Latn-ID": "mad",
+ "mae-Latn-NG": "mae",
+ "maf-Latn-CM": "maf",
+ "mag-Deva-IN": "mag",
+ "mai-Deva-IN": "mai",
+ "mai-Tirh-IN": "mai-Tirh",
+ "maj-Latn-MX": "maj",
+ "mak-Latn-ID": "mak",
+ "mak-Maka-ID": "mak-Maka",
+ "mam-Latn-GT": "mam",
+ "man-Latn-GM": "man",
+ "man-Nkoo-GN": "man-GN",
+ "maq-Latn-MX": "maq",
+ "mas-Latn-KE": "mas",
+ "mat-Latn-MX": "mat",
+ "mau-Latn-MX": "mau",
+ "mav-Latn-BR": "mav",
+ "maw-Latn-ZZ": "maw",
+ "max-Latn-ID": "max",
+ "maz-Latn-MX": "maz",
+ "mba-Latn-PH": "mba",
+ "mbb-Latn-PH": "mbb",
+ "mbc-Latn-BR": "mbc",
+ "mbd-Latn-PH": "mbd",
+ "mbf-Latn-SG": "mbf",
+ "mbh-Latn-ZZ": "mbh",
+ "mbi-Latn-PH": "mbi",
+ "mbj-Latn-BR": "mbj",
+ "mbk-Latn-PG": "mbk",
+ "mbl-Latn-BR": "mbl",
+ "mbm-Latn-CG": "mbm",
+ "mbn-Latn-CO": "mbn",
+ "mbo-Latn-ZZ": "mbo",
+ "mbp-Latn-CO": "mbp",
+ "mbq-Latn-ZZ": "mbq",
+ "mbr-Latn-CO": "mbr",
+ "mbs-Latn-PH": "mbs",
+ "mbt-Latn-PH": "mbt",
+ "mbu-Latn-ZZ": "mbu",
+ "mbv-Latn-GN": "mbv",
+ "mbw-Latn-ZZ": "mbw",
+ "mbx-Latn-PG": "mbx",
+ "mby-Arab-PK": "mby",
+ "mbz-Latn-MX": "mbz",
+ "mca-Latn-PY": "mca",
+ "mcb-Latn-PE": "mcb",
+ "mcc-Latn-PG": "mcc",
+ "mcd-Latn-PE": "mcd",
+ "mce-Latn-MX": "mce",
+ "mcf-Latn-PE": "mcf",
+ "mcg-Latn-VE": "mcg",
+ "mch-Latn-VE": "mch",
+ "mci-Latn-ZZ": "mci",
+ "mcj-Latn-NG": "mcj",
+ "mck-Latn-AO": "mck",
+ "mcl-Latn-CO": "mcl",
+ "mcm-Latn-MY": "mcm",
+ "mcn-Latn-TD": "mcn",
+ "mco-Latn-MX": "mco",
+ "mcp-Latn-ZZ": "mcp",
+ "mcq-Latn-ZZ": "mcq",
+ "mcr-Latn-ZZ": "mcr",
+ "mcs-Latn-CM": "mcs",
+ "mct-Latn-CM": "mct",
+ "mcu-Latn-ZZ": "mcu",
+ "mcv-Latn-PG": "mcv",
+ "mcw-Latn-TD": "mcw",
+ "mcx-Latn-CF": "mcx",
+ "mcy-Latn-PG": "mcy",
+ "mcz-Latn-PG": "mcz",
+ "mda-Latn-ZZ": "mda",
+ "mdb-Latn-PG": "mdb",
+ "mdc-Latn-PG": "mdc",
+ "mdd-Latn-CM": "mdd",
+ "mde-Arab-ZZ": "mde",
+ "mdf-Cyrl-RU": "mdf",
+ "mdg-Latn-TD": "mdg",
+ "mdh-Latn-PH": "mdh",
+ "mdi-Latn-CD": "mdi",
+ "mdj-Latn-ZZ": "mdj",
+ "mdk-Latn-CD": "mdk",
+ "mdm-Latn-CD": "mdm",
+ "mdn-Latn-CF": "mdn",
+ "mdp-Latn-CD": "mdp",
+ "mdq-Latn-CD": "mdq",
+ "mdr-Latn-ID": "mdr",
+ "mds-Latn-PG": "mds",
+ "mdt-Latn-CG": "mdt",
+ "mdu-Latn-CG": "mdu",
+ "mdv-Latn-MX": "mdv",
+ "mdw-Latn-CG": "mdw",
+ "mdx-Ethi-ZZ": "mdx",
+ "mdy-Ethi-ET": "mdy",
+ "mdy-Latn-ET": "mdy-Latn",
+ "mdz-Latn-BR": "mdz",
+ "mea-Latn-CM": "mea",
+ "meb-Latn-PG": "meb",
+ "mec-Latn-AU": "mec",
+ "med-Latn-ZZ": "med",
+ "mee-Latn-ZZ": "mee",
+ "meh-Latn-MX": "meh",
+ "mej-Latn-ID": "mej",
+ "mek-Latn-ZZ": "mek",
+ "mel-Latn-MY": "mel",
+ "mem-Latn-AU": "mem",
+ "men-Latn-SL": "men",
+ "men-Mend-SL": "men-Mend",
+ "meo-Arab-MY": "meo-Arab",
+ "meo-Latn-MY": "meo",
+ "mep-Latn-AU": "mep",
+ "meq-Latn-CM": "meq",
+ "mer-Latn-KE": "mer",
+ "mes-Latn-TD": "mes",
+ "met-Latn-ZZ": "met",
+ "meu-Latn-ZZ": "meu",
+ "mev-Latn-LR": "mev",
+ "mew-Latn-NG": "mew",
+ "mey-Arab-MR": "mey-Arab",
+ "mey-Latn-MR": "mey",
+ "mez-Latn-US": "mez",
+ "mfa-Arab-TH": "mfa",
+ "mfb-Latn-ID": "mfb",
+ "mfc-Latn-CD": "mfc",
+ "mfd-Latn-CM": "mfd",
+ "mfe-Latn-MU": "mfe",
+ "mff-Latn-CM": "mff",
+ "mfg-Arab-GN": "mfg-Arab",
+ "mfg-Latn-GN": "mfg",
+ "mfh-Latn-CM": "mfh",
+ "mfi-Arab-CM": "mfi",
+ "mfi-Latn-CM": "mfi-Latn",
+ "mfj-Latn-CM": "mfj",
+ "mfk-Latn-CM": "mfk",
+ "mfl-Latn-NG": "mfl",
+ "mfm-Latn-NG": "mfm",
+ "mfn-Latn-ZZ": "mfn",
+ "mfo-Latn-ZZ": "mfo",
+ "mfp-Latn-ID": "mfp",
+ "mfq-Latn-ZZ": "mfq",
+ "mfr-Latn-AU": "mfr",
+ "mft-Latn-PG": "mft",
+ "mfu-Latn-AO": "mfu",
+ "mfv-Latn-GW": "mfv",
+ "mfw-Latn-PG": "mfw",
+ "mfx-Ethi-ET": "mfx-Ethi",
+ "mfx-Latn-ET": "mfx",
+ "mfy-Latn-MX": "mfy",
+ "mfz-Latn-SS": "mfz",
+ "mg-Latn-MG": "mg",
+ "mgb-Latn-TD": "mgb",
+ "mgc-Latn-SS": "mgc",
+ "mgd-Arab-SS": "mgd-Arab",
+ "mgd-Latn-SS": "mgd",
+ "mge-Latn-TD": "mge",
+ "mgf-Latn-ID": "mgf",
+ "mgg-Latn-CM": "mgg",
+ "mgh-Latn-MZ": "mgh",
+ "mgi-Latn-NG": "mgi",
+ "mgj-Latn-NG": "mgj",
+ "mgk-Latn-ID": "mgk",
+ "mgl-Latn-ZZ": "mgl",
+ "mgm-Latn-TL": "mgm",
+ "mgn-Latn-CF": "mgn",
+ "mgo-Latn-CM": "mgo",
+ "mgp-Deva-NP": "mgp",
+ "mgq-Latn-TZ": "mgq",
+ "mgr-Latn-ZM": "mgr",
+ "mgs-Latn-TZ": "mgs",
+ "mgt-Latn-PG": "mgt",
+ "mgu-Latn-PG": "mgu",
+ "mgv-Latn-TZ": "mgv",
+ "mgw-Latn-TZ": "mgw",
+ "mgy-Latn-TZ": "mgy",
+ "mgz-Latn-TZ": "mgz",
+ "mh-Latn-MH": "mh",
+ "mhb-Latn-GA": "mhb",
+ "mhc-Latn-MX": "mhc",
+ "mhd-Latn-TZ": "mhd",
+ "mhe-Latn-MY": "mhe",
+ "mhf-Latn-PG": "mhf",
+ "mhg-Latn-AU": "mhg",
+ "mhi-Latn-ZZ": "mhi",
+ "mhj-Arab-AF": "mhj",
+ "mhk-Latn-CM": "mhk",
+ "mhl-Latn-ZZ": "mhl",
+ "mhm-Latn-MZ": "mhm",
+ "mhn-Latn-IT": "mhn",
+ "mho-Latn-ZM": "mho",
+ "mhp-Latn-ID": "mhp",
+ "mhq-Latn-US": "mhq",
+ "mhs-Latn-ID": "mhs",
+ "mht-Latn-VE": "mht",
+ "mhu-Latn-IN": "mhu",
+ "mhw-Latn-BW": "mhw",
+ "mhx-Latn-MM": "mhx",
+ "mhy-Latn-ID": "mhy",
+ "mhz-Latn-ID": "mhz",
+ "mi-Latn-NZ": "mi",
+ "mia-Latn-US": "mia",
+ "mib-Latn-MX": "mib",
+ "mic-Latn-CA": "mic",
+ "mid-Mand-IQ": "mid",
+ "mie-Latn-MX": "mie",
+ "mif-Latn-ZZ": "mif",
+ "mig-Latn-MX": "mig",
+ "mih-Latn-MX": "mih",
+ "mii-Latn-MX": "mii",
+ "mij-Latn-CM": "mij",
+ "mik-Latn-US": "mik",
+ "mil-Latn-MX": "mil",
+ "mim-Latn-MX": "mim",
+ "min-Latn-ID": "min",
+ "mio-Latn-MX": "mio",
+ "mip-Latn-MX": "mip",
+ "miq-Latn-NI": "miq",
+ "mir-Latn-MX": "mir",
+ "mit-Latn-MX": "mit",
+ "miu-Latn-MX": "miu",
+ "miw-Latn-ZZ": "miw",
+ "mix-Latn-MX": "mix",
+ "miy-Latn-MX": "miy",
+ "miz-Latn-MX": "miz",
+ "mjb-Latn-TL": "mjb",
+ "mjc-Latn-MX": "mjc",
+ "mjd-Latn-US": "mjd",
+ "mje-Latn-TD": "mje",
+ "mjg-Latn-CN": "mjg",
+ "mjh-Latn-TZ": "mjh",
+ "mji-Latn-CN": "mji",
+ "mjj-Latn-PG": "mjj",
+ "mjk-Latn-PG": "mjk",
+ "mjl-Deva-IN": "mjl",
+ "mjl-Takr-IN": "mjl-Takr",
+ "mjm-Latn-PG": "mjm",
+ "mjn-Latn-PG": "mjn",
+ "mjq-Mlym-IN": "mjq",
+ "mjr-Mlym-IN": "mjr",
+ "mjs-Latn-NG": "mjs",
+ "mjt-Beng-BD": "mjt-Beng",
+ "mjt-Deva-IN": "mjt",
+ "mju-Telu-IN": "mju",
+ "mjv-Mlym-IN": "mjv",
+ "mjw-Latn-IN": "mjw",
+ "mjx-Beng-BD": "mjx-Beng",
+ "mjx-Latn-BD": "mjx",
+ "mjy-Latn-US": "mjy",
+ "mjz-Deva-NP": "mjz",
+ "mk-Cyrl-AL": "mk-AL",
+ "mk-Cyrl-GR": "mk-GR",
+ "mk-Cyrl-MK": "mk",
+ "mka-Latn-CI": "mka",
+ "mkb-Deva-IN": "mkb",
+ "mkc-Latn-PG": "mkc",
+ "mke-Deva-IN": "mke",
+ "mkf-Latn-NG": "mkf",
+ "mki-Arab-ZZ": "mki",
+ "mkj-Latn-FM": "mkj",
+ "mkk-Latn-CM": "mkk",
+ "mkl-Latn-ZZ": "mkl",
+ "mkm-Thai-TH": "mkm",
+ "mkn-Latn-ID": "mkn",
+ "mko-Latn-NG": "mko",
+ "mkp-Latn-ZZ": "mkp",
+ "mkr-Latn-PG": "mkr",
+ "mks-Latn-MX": "mks",
+ "mkt-Latn-NC": "mkt",
+ "mku-Latn-GN": "mku",
+ "mkv-Latn-VU": "mkv",
+ "mkw-Latn-ZZ": "mkw",
+ "mkx-Latn-PH": "mkx",
+ "mky-Latn-ID": "mky",
+ "mkz-Latn-TL": "mkz",
+ "ml-Mlym-IN": "ml",
+ "mla-Latn-VU": "mla",
+ "mlb-Latn-CM": "mlb",
+ "mlc-Latn-VN": "mlc",
+ "mle-Latn-ZZ": "mle",
+ "mlf-Latn-LA": "mlf-Latn",
+ "mlf-Thai-LA": "mlf",
+ "mlh-Latn-PG": "mlh",
+ "mli-Latn-ID": "mli",
+ "mlj-Latn-TD": "mlj",
+ "mlk-Latn-KE": "mlk",
+ "mll-Latn-VU": "mll",
+ "mln-Latn-SB": "mln",
+ "mlo-Latn-SN": "mlo",
+ "mlp-Latn-ZZ": "mlp",
+ "mlq-Arab-SN": "mlq-Arab",
+ "mlq-Latn-SN": "mlq",
+ "mlr-Latn-CM": "mlr",
+ "mls-Latn-SD": "mls",
+ "mlu-Latn-SB": "mlu",
+ "mlv-Latn-VU": "mlv",
+ "mlw-Latn-CM": "mlw",
+ "mlx-Latn-VU": "mlx",
+ "mlz-Latn-PH": "mlz",
+ "mma-Latn-NG": "mma",
+ "mmb-Latn-ID": "mmb",
+ "mmc-Latn-MX": "mmc",
+ "mmd-Hans-CN": "mmd-Hans",
+ "mmd-Hant-CN": "mmd-Hant",
+ "mmd-Latn-CN": "mmd",
+ "mme-Latn-VU": "mme",
+ "mmf-Latn-NG": "mmf",
+ "mmg-Latn-VU": "mmg",
+ "mmh-Latn-BR": "mmh",
+ "mmi-Latn-PG": "mmi",
+ "mmm-Latn-VU": "mmm",
+ "mmn-Latn-PH": "mmn",
+ "mmo-Latn-ZZ": "mmo",
+ "mmp-Latn-PG": "mmp",
+ "mmq-Latn-PG": "mmq",
+ "mmr-Latn-CN": "mmr",
+ "mmt-Latn-PG": "mmt",
+ "mmu-Latn-ZZ": "mmu",
+ "mmv-Latn-BR": "mmv",
+ "mmw-Latn-VU": "mmw",
+ "mmx-Latn-ZZ": "mmx",
+ "mmy-Latn-TD": "mmy",
+ "mmz-Latn-CD": "mmz",
+ "mn-Cyrl-MN": "mn",
+ "mn-Mong-CN": "mn-CN",
+ "mna-Latn-ZZ": "mna",
+ "mnb-Latn-ID": "mnb",
+ "mnd-Latn-BR": "mnd",
+ "mne-Latn-TD": "mne",
+ "mnf-Latn-ZZ": "mnf",
+ "mng-Latn-VN": "mng",
+ "mnh-Latn-CD": "mnh",
+ "mni-Beng-IN": "mni",
+ "mni-Mtei-IN": "mni-Mtei",
+ "mnj-Arab-AF": "mnj",
+ "mnl-Latn-VU": "mnl",
+ "mnm-Latn-PG": "mnm",
+ "mnn-Latn-VN": "mnn",
+ "mnp-Latn-CN": "mnp",
+ "mnq-Latn-MY": "mnq",
+ "mnr-Latn-US": "mnr",
+ "mns-Cyrl-RU": "mns",
+ "mnu-Latn-ID": "mnu",
+ "mnv-Latn-SB": "mnv",
+ "mnw-Mymr-MM": "mnw",
+ "mnw-Mymr-TH": "mnw-TH",
+ "mnx-Latn-ID": "mnx",
+ "mny-Latn-MZ": "mny",
+ "mnz-Latn-ID": "mnz",
+ "moa-Latn-ZZ": "moa",
+ "moc-Latn-AR": "moc",
+ "mod-Latn-US": "mod",
+ "moe-Latn-CA": "moe",
+ "mog-Latn-ID": "mog",
+ "moh-Latn-CA": "moh",
+ "moi-Latn-NG": "moi",
+ "moj-Latn-CG": "moj",
+ "mok-Latn-ID": "mok",
+ "mom-Latn-NI": "mom",
+ "moo-Latn-VN": "moo",
+ "mop-Latn-BZ": "mop",
+ "moq-Latn-ID": "moq",
+ "mor-Latn-SD": "mor",
+ "mos-Latn-BF": "mos",
+ "mot-Latn-CO": "mot",
+ "mou-Latn-TD": "mou",
+ "mov-Latn-US": "mov",
+ "mow-Latn-CG": "mow",
+ "mox-Latn-ZZ": "mox",
+ "moy-Ethi-ET": "moy-Ethi",
+ "moy-Latn-ET": "moy",
+ "moz-Latn-TD": "moz",
+ "mpa-Latn-TZ": "mpa",
+ "mpb-Latn-AU": "mpb",
+ "mpc-Latn-AU": "mpc",
+ "mpd-Latn-BR": "mpd",
+ "mpe-Ethi-ET": "mpe-Ethi",
+ "mpe-Latn-ET": "mpe",
+ "mpg-Latn-TD": "mpg",
+ "mph-Latn-AU": "mph",
+ "mpi-Latn-CM": "mpi",
+ "mpj-Latn-AU": "mpj",
+ "mpk-Latn-TD": "mpk",
+ "mpl-Latn-PG": "mpl",
+ "mpm-Latn-MX": "mpm",
+ "mpn-Latn-PG": "mpn",
+ "mpo-Latn-PG": "mpo",
+ "mpp-Latn-ZZ": "mpp",
+ "mpq-Latn-BR": "mpq",
+ "mpr-Latn-SB": "mpr",
+ "mps-Latn-ZZ": "mps",
+ "mpt-Latn-ZZ": "mpt",
+ "mpu-Latn-BR": "mpu",
+ "mpv-Latn-PG": "mpv",
+ "mpw-Latn-BR": "mpw",
+ "mpx-Latn-ZZ": "mpx",
+ "mpy-Latn-ID": "mpy",
+ "mpz-Thai-TH": "mpz",
+ "mqa-Latn-ID": "mqa",
+ "mqb-Latn-CM": "mqb",
+ "mqc-Latn-ID": "mqc",
+ "mqe-Latn-PG": "mqe",
+ "mqf-Latn-ID": "mqf",
+ "mqg-Latn-ID": "mqg",
+ "mqh-Latn-MX": "mqh",
+ "mqi-Latn-ID": "mqi",
+ "mqj-Latn-ID": "mqj",
+ "mqk-Latn-PH": "mqk",
+ "mql-Latn-ZZ": "mql",
+ "mqm-Latn-PF": "mqm",
+ "mqn-Latn-ID": "mqn",
+ "mqo-Latn-ID": "mqo",
+ "mqp-Latn-ID": "mqp",
+ "mqq-Latn-MY": "mqq",
+ "mqr-Latn-ID": "mqr",
+ "mqs-Latn-ID": "mqs",
+ "mqu-Latn-SS": "mqu",
+ "mqv-Latn-PG": "mqv",
+ "mqw-Latn-PG": "mqw",
+ "mqx-Bugi-ID": "mqx-Bugi",
+ "mqx-Latn-ID": "mqx",
+ "mqy-Latn-ID": "mqy",
+ "mqz-Latn-PG": "mqz",
+ "mr-Deva-IN": "mr",
+ "mr-Modi-IN": "mr-Modi",
+ "mra-Thai-TH": "mra",
+ "mrb-Latn-VU": "mrb",
+ "mrc-Latn-US": "mrc",
+ "mrd-Deva-NP": "mrd",
+ "mrf-Latn-ID": "mrf",
+ "mrg-Beng-IN": "mrg-Beng",
+ "mrg-Deva-IN": "mrg-Deva",
+ "mrg-Latn-IN": "mrg",
+ "mrh-Latn-IN": "mrh",
+ "mrj-Cyrl-RU": "mrj",
+ "mrk-Latn-NC": "mrk",
+ "mrl-Latn-FM": "mrl",
+ "mrm-Latn-VU": "mrm",
+ "mrn-Latn-SB": "mrn",
+ "mro-Mroo-BD": "mro",
+ "mrp-Latn-VU": "mrp",
+ "mrq-Latn-PF": "mrq",
+ "mrr-Deva-IN": "mrr",
+ "mrs-Latn-VU": "mrs",
+ "mrt-Latn-NG": "mrt",
+ "mru-Latn-CM": "mru",
+ "mrv-Latn-PF": "mrv",
+ "mrw-Arab-PH": "mrw-Arab",
+ "mrw-Latn-PH": "mrw",
+ "mrx-Latn-ID": "mrx",
+ "mry-Latn-PH": "mry",
+ "mrz-Latn-ID": "mrz",
+ "ms-Arab-CC": "ms-CC",
+ "ms-Arab-ID": "ms-Arab-ID",
+ "ms-Latn-BN": "ms-BN",
+ "ms-Latn-MY": "ms",
+ "msb-Latn-PH": "msb",
+ "msc-Latn-GN": "msc",
+ "mse-Latn-TD": "mse",
+ "msf-Latn-ID": "msf",
+ "msg-Latn-ID": "msg",
+ "msh-Latn-MG": "msh",
+ "msi-Latn-MY": "msi",
+ "msj-Latn-CD": "msj",
+ "msk-Latn-PH": "msk",
+ "msl-Latn-ID": "msl",
+ "msm-Latn-PH": "msm",
+ "msn-Latn-VU": "msn",
+ "mso-Latn-ID": "mso",
+ "msp-Latn-BR": "msp",
+ "msq-Latn-NC": "msq",
+ "mss-Latn-ID": "mss",
+ "msu-Latn-PG": "msu",
+ "msv-Latn-CM": "msv",
+ "msw-Latn-GW": "msw",
+ "msx-Latn-PG": "msx",
+ "msy-Latn-PG": "msy",
+ "msz-Latn-PG": "msz",
+ "mt-Latn-MT": "mt",
+ "mta-Latn-PH": "mta",
+ "mtb-Latn-CI": "mtb",
+ "mtc-Latn-ZZ": "mtc",
+ "mtd-Latn-ID": "mtd",
+ "mte-Latn-SB": "mte",
+ "mtf-Latn-ZZ": "mtf",
+ "mtg-Latn-ID": "mtg",
+ "mth-Latn-ID": "mth",
+ "mti-Latn-ZZ": "mti",
+ "mtj-Latn-ID": "mtj",
+ "mtk-Latn-CM": "mtk",
+ "mtl-Latn-NG": "mtl",
+ "mtm-Cyrl-RU": "mtm",
+ "mtn-Latn-NI": "mtn",
+ "mto-Latn-MX": "mto",
+ "mtp-Latn-BO": "mtp",
+ "mtq-Latn-VN": "mtq",
+ "mtr-Deva-IN": "mtr",
+ "mts-Latn-PE": "mts",
+ "mtt-Latn-VU": "mtt",
+ "mtu-Latn-MX": "mtu",
+ "mtv-Latn-PG": "mtv",
+ "mtw-Latn-PH": "mtw",
+ "mtx-Latn-MX": "mtx",
+ "mty-Latn-PG": "mty",
+ "mua-Latn-CM": "mua",
+ "mub-Latn-TD": "mub",
+ "muc-Latn-CM": "muc",
+ "mud-Cyrl-RU": "mud",
+ "mue-Latn-EC": "mue",
+ "mug-Latn-CM": "mug",
+ "muh-Latn-SS": "muh",
+ "mui-Latn-ID": "mui",
+ "muj-Latn-TD": "muj",
+ "muk-Tibt-NP": "muk",
+ "mum-Latn-PG": "mum",
+ "muo-Latn-CM": "muo",
+ "muq-Latn-CN": "muq",
+ "mur-Latn-ZZ": "mur",
+ "mus-Latn-US": "mus",
+ "mut-Deva-IN": "mut",
+ "muu-Latn-KE": "muu",
+ "muv-Taml-IN": "muv",
+ "mux-Latn-PG": "mux",
+ "muy-Latn-CM": "muy",
+ "muz-Ethi-ET": "muz",
+ "muz-Latn-ET": "muz-Latn",
+ "mva-Latn-ZZ": "mva",
+ "mvd-Latn-ID": "mvd",
+ "mvf-Mong-CN": "mvf",
+ "mvf-Phag-CN": "mvf-Phag",
+ "mvg-Latn-MX": "mvg",
+ "mvh-Latn-TD": "mvh",
+ "mvk-Latn-PG": "mvk",
+ "mvl-Latn-AU": "mvl",
+ "mvn-Latn-ZZ": "mvn",
+ "mvo-Latn-SB": "mvo",
+ "mvp-Latn-ID": "mvp",
+ "mvq-Latn-PG": "mvq",
+ "mvr-Latn-ID": "mvr",
+ "mvs-Latn-ID": "mvs",
+ "mvt-Latn-VU": "mvt",
+ "mvu-Latn-TD": "mvu",
+ "mvv-Latn-MY": "mvv",
+ "mvw-Latn-TZ": "mvw",
+ "mvx-Latn-ID": "mvx",
+ "mvy-Arab-PK": "mvy",
+ "mvz-Arab-ET": "mvz-Arab",
+ "mvz-Ethi-ET": "mvz",
+ "mwa-Latn-PG": "mwa",
+ "mwb-Latn-PG": "mwb",
+ "mwc-Latn-PG": "mwc",
+ "mwe-Latn-TZ": "mwe",
+ "mwf-Latn-AU": "mwf",
+ "mwg-Latn-PG": "mwg",
+ "mwh-Latn-PG": "mwh",
+ "mwi-Latn-VU": "mwi",
+ "mwk-Latn-ML": "mwk",
+ "mwl-Latn-PT": "mwl",
+ "mwm-Latn-TD": "mwm",
+ "mwn-Latn-ZM": "mwn",
+ "mwo-Latn-VU": "mwo",
+ "mwp-Latn-AU": "mwp",
+ "mwq-Latn-MM": "mwq",
+ "mwr-Deva-IN": "mwr",
+ "mws-Latn-KE": "mws",
+ "mwt-Mymr-MM": "mwt",
+ "mwt-Thai-TH": "mwt-Thai",
+ "mwu-Latn-SS": "mwu",
+ "mwv-Latn-ID": "mwv",
+ "mww-Hmnp-US": "mww",
+ "mwz-Latn-CD": "mwz",
+ "mxa-Latn-MX": "mxa",
+ "mxb-Latn-MX": "mxb",
+ "mxc-Latn-ZW": "mxc",
+ "mxd-Latn-ID": "mxd",
+ "mxe-Latn-VU": "mxe",
+ "mxf-Latn-CM": "mxf",
+ "mxg-Latn-AO": "mxg",
+ "mxh-Latn-CD": "mxh",
+ "mxi-Latn-ES": "mxi",
+ "mxj-Latn-IN": "mxj",
+ "mxk-Latn-PG": "mxk",
+ "mxl-Latn-BJ": "mxl",
+ "mxm-Latn-ZZ": "mxm",
+ "mxn-Latn-ID": "mxn",
+ "mxo-Latn-ZM": "mxo",
+ "mxp-Latn-MX": "mxp",
+ "mxq-Latn-MX": "mxq",
+ "mxr-Latn-MY": "mxr",
+ "mxs-Latn-MX": "mxs",
+ "mxt-Latn-MX": "mxt",
+ "mxu-Latn-CM": "mxu",
+ "mxv-Latn-MX": "mxv",
+ "mxw-Latn-PG": "mxw",
+ "mxx-Latn-CI": "mxx",
+ "mxy-Latn-MX": "mxy",
+ "mxz-Latn-ID": "mxz",
+ "my-Mymr-MM": "my",
+ "myb-Latn-TD": "myb",
+ "myc-Latn-CD": "myc",
+ "mye-Latn-GA": "mye",
+ "myf-Latn-ET": "myf",
+ "myg-Latn-CM": "myg",
+ "myh-Latn-US": "myh",
+ "myj-Latn-SS": "myj",
+ "myk-Latn-ZZ": "myk",
+ "myl-Latn-ID": "myl",
+ "mym-Ethi-ZZ": "mym",
+ "myp-Latn-BR": "myp",
+ "myr-Latn-PE": "myr",
+ "myu-Latn-BR": "myu",
+ "myv-Cyrl-RU": "myv",
+ "myw-Latn-ZZ": "myw",
+ "myx-Latn-UG": "myx",
+ "myy-Latn-CO": "myy",
+ "myz-Mand-IR": "myz",
+ "mza-Latn-MX": "mza",
+ "mzd-Latn-CM": "mzd",
+ "mze-Latn-PG": "mze",
+ "mzh-Latn-AR": "mzh",
+ "mzi-Latn-MX": "mzi",
+ "mzj-Latn-LR": "mzj",
+ "mzk-Latn-ZZ": "mzk",
+ "mzl-Latn-MX": "mzl",
+ "mzm-Latn-ZZ": "mzm",
+ "mzn-Arab-IR": "mzn",
+ "mzo-Latn-BR": "mzo",
+ "mzp-Latn-ZZ": "mzp",
+ "mzq-Latn-ID": "mzq",
+ "mzr-Latn-BR": "mzr",
+ "mzt-Latn-MY": "mzt",
+ "mzu-Latn-PG": "mzu",
+ "mzv-Latn-CF": "mzv",
+ "mzw-Latn-ZZ": "mzw",
+ "mzx-Latn-GY": "mzx",
+ "mzz-Latn-ZZ": "mzz",
+ "na-Latn-NR": "na",
+ "naa-Latn-ID": "naa",
+ "nab-Latn-BR": "nab",
+ "nac-Latn-ZZ": "nac",
+ "nae-Latn-ID": "nae",
+ "naf-Latn-ZZ": "naf",
+ "nag-Latn-IN": "nag",
+ "naj-Latn-GN": "naj",
+ "nak-Latn-ZZ": "nak",
+ "nal-Latn-PG": "nal",
+ "nam-Latn-AU": "nam",
+ "nan-Hans-CN": "nan",
+ "nao-Deva-NP": "nao",
+ "nap-Latn-IT": "nap",
+ "naq-Latn-NA": "naq",
+ "nar-Latn-NG": "nar",
+ "nas-Latn-ZZ": "nas",
+ "nat-Latn-NG": "nat",
+ "naw-Latn-GH": "naw",
+ "nax-Latn-PG": "nax",
+ "nay-Latn-AU": "nay",
+ "naz-Latn-MX": "naz",
+ "nb-Latn-NO": "nb",
+ "nb-Latn-SJ": "nb-SJ",
+ "nba-Latn-AO": "nba",
+ "nbb-Latn-NG": "nbb",
+ "nbc-Latn-IN": "nbc",
+ "nbd-Latn-CD": "nbd",
+ "nbe-Latn-IN": "nbe",
+ "nbh-Latn-NG": "nbh",
+ "nbi-Latn-IN": "nbi",
+ "nbj-Latn-AU": "nbj",
+ "nbk-Latn-PG": "nbk",
+ "nbm-Latn-CF": "nbm",
+ "nbn-Latn-ID": "nbn",
+ "nbo-Latn-NG": "nbo",
+ "nbp-Latn-NG": "nbp",
+ "nbq-Latn-ID": "nbq",
+ "nbr-Latn-NG": "nbr",
+ "nbt-Deva-IN": "nbt-Deva",
+ "nbt-Latn-IN": "nbt",
+ "nbu-Latn-IN": "nbu",
+ "nbv-Latn-CM": "nbv",
+ "nbw-Latn-CD": "nbw",
+ "nby-Latn-PG": "nby",
+ "nca-Latn-ZZ": "nca",
+ "ncb-Deva-IN": "ncb-Deva",
+ "ncb-Latn-IN": "ncb",
+ "ncc-Latn-PG": "ncc",
+ "ncd-Deva-NP": "ncd",
+ "nce-Latn-ZZ": "nce",
+ "ncf-Latn-ZZ": "ncf",
+ "ncg-Latn-CA": "ncg",
+ "nch-Latn-MX": "nch",
+ "nci-Latn-MX": "nci",
+ "ncj-Latn-MX": "ncj",
+ "nck-Latn-AU": "nck",
+ "ncl-Latn-MX": "ncl",
+ "ncm-Latn-PG": "ncm",
+ "ncn-Latn-PG": "ncn",
+ "nco-Latn-ZZ": "nco",
+ "ncq-Laoo-LA": "ncq",
+ "ncq-Thai-LA": "ncq-Thai",
+ "ncr-Latn-CM": "ncr",
+ "nct-Beng-IN": "nct-Beng",
+ "nct-Latn-IN": "nct",
+ "ncu-Latn-ZZ": "ncu",
+ "ncx-Latn-MX": "ncx",
+ "ncz-Latn-US": "ncz",
+ "nd-Latn-ZW": "nd",
+ "nda-Latn-CG": "nda",
+ "ndb-Latn-CM": "ndb",
+ "ndc-Latn-MZ": "ndc",
+ "ndd-Latn-NG": "ndd",
+ "ndf-Cyrl-RU": "ndf",
+ "ndg-Latn-TZ": "ndg",
+ "ndh-Latn-TZ": "ndh",
+ "ndi-Latn-NG": "ndi",
+ "ndj-Latn-TZ": "ndj",
+ "ndk-Latn-CD": "ndk",
+ "ndl-Latn-CD": "ndl",
+ "ndm-Latn-TD": "ndm",
+ "ndn-Latn-CG": "ndn",
+ "ndp-Latn-UG": "ndp",
+ "ndq-Latn-AO": "ndq",
+ "ndr-Latn-NG": "ndr",
+ "nds-Latn-DE": "nds",
+ "ndt-Latn-CD": "ndt",
+ "ndu-Latn-CM": "ndu",
+ "ndv-Latn-SN": "ndv",
+ "ndw-Latn-CD": "ndw",
+ "ndx-Latn-ID": "ndx",
+ "ndy-Latn-CF": "ndy",
+ "ndy-Latn-TD": "ndy-TD",
+ "ndz-Latn-SS": "ndz",
+ "ne-Deva-BT": "ne-BT",
+ "ne-Deva-NP": "ne",
+ "nea-Latn-ID": "nea",
+ "neb-Latn-ZZ": "neb",
+ "nec-Latn-ID": "nec",
+ "ned-Latn-NG": "ned",
+ "nee-Latn-NC": "nee",
+ "neg-Cyrl-RU": "neg",
+ "neh-Tibt-BT": "neh",
+ "nei-Xsux-TR": "nei",
+ "nej-Latn-PG": "nej",
+ "nek-Latn-NC": "nek",
+ "nem-Latn-NC": "nem",
+ "nen-Latn-NC": "nen",
+ "neo-Latn-VN": "neo",
+ "neq-Latn-MX": "neq",
+ "ner-Latn-ID": "ner",
+ "net-Latn-PG": "net",
+ "neu-Latn-001": "neu",
+ "new-Deva-NP": "new",
+ "new-Newa-NP": "new-Newa",
+ "nex-Latn-ZZ": "nex",
+ "ney-Latn-CI": "ney",
+ "nez-Latn-US": "nez",
+ "nfa-Latn-ID": "nfa",
+ "nfd-Latn-NG": "nfd",
+ "nfl-Latn-SB": "nfl",
+ "nfr-Latn-ZZ": "nfr",
+ "nfu-Latn-CM": "nfu",
+ "ng-Latn-NA": "ng",
+ "nga-Latn-ZZ": "nga",
+ "ngb-Latn-ZZ": "ngb",
+ "ngc-Latn-CD": "ngc",
+ "ngd-Latn-CF": "ngd",
+ "nge-Latn-CM": "nge",
+ "ngg-Latn-CF": "ngg",
+ "ngh-Latn-ZA": "ngh",
+ "ngi-Latn-NG": "ngi",
+ "ngj-Latn-CM": "ngj",
+ "ngk-Latn-AU": "ngk",
+ "ngl-Latn-MZ": "ngl",
+ "ngm-Latn-FM": "ngm",
+ "ngn-Latn-CM": "ngn",
+ "ngp-Latn-TZ": "ngp",
+ "ngq-Latn-TZ": "ngq",
+ "ngr-Latn-SB": "ngr",
+ "ngs-Latn-NG": "ngs",
+ "ngt-Laoo-LA": "ngt",
+ "ngu-Latn-MX": "ngu",
+ "ngv-Latn-CM": "ngv",
+ "ngw-Latn-NG": "ngw",
+ "ngx-Latn-NG": "ngx",
+ "ngy-Latn-CM": "ngy",
+ "ngz-Latn-CG": "ngz",
+ "nha-Latn-AU": "nha",
+ "nhb-Latn-ZZ": "nhb",
+ "nhc-Latn-MX": "nhc",
+ "nhd-Latn-PY": "nhd",
+ "nhe-Latn-MX": "nhe",
+ "nhf-Latn-AU": "nhf",
+ "nhg-Latn-MX": "nhg",
+ "nhi-Latn-MX": "nhi",
+ "nhk-Latn-MX": "nhk",
+ "nhm-Latn-MX": "nhm",
+ "nhn-Latn-MX": "nhn",
+ "nho-Latn-PG": "nho",
+ "nhp-Latn-MX": "nhp",
+ "nhq-Latn-MX": "nhq",
+ "nhr-Latn-BW": "nhr",
+ "nht-Latn-MX": "nht",
+ "nhu-Latn-CM": "nhu",
+ "nhv-Latn-MX": "nhv",
+ "nhw-Latn-MX": "nhw",
+ "nhx-Latn-MX": "nhx",
+ "nhy-Latn-MX": "nhy",
+ "nhz-Latn-MX": "nhz",
+ "nia-Latn-ID": "nia",
+ "nib-Latn-PG": "nib",
+ "nid-Latn-AU": "nid",
+ "nie-Latn-TD": "nie",
+ "nif-Latn-ZZ": "nif",
+ "nig-Latn-AU": "nig",
+ "nih-Latn-TZ": "nih",
+ "nii-Latn-ZZ": "nii",
+ "nij-Latn-ID": "nij",
+ "nil-Latn-ID": "nil",
+ "nim-Latn-TZ": "nim",
+ "nin-Latn-ZZ": "nin",
+ "nio-Cyrl-RU": "nio",
+ "niq-Latn-KE": "niq",
+ "nir-Latn-ID": "nir",
+ "nis-Latn-PG": "nis",
+ "nit-Telu-IN": "nit",
+ "niu-Latn-NU": "niu",
+ "niv-Cyrl-RU": "niv",
+ "niv-Latn-RU": "niv-Latn",
+ "niw-Latn-PG": "niw",
+ "nix-Latn-CD": "nix",
+ "niy-Latn-ZZ": "niy",
+ "niz-Latn-ZZ": "niz",
+ "nja-Latn-NG": "nja",
+ "njb-Latn-IN": "njb",
+ "njd-Latn-TZ": "njd",
+ "njh-Latn-IN": "njh",
+ "nji-Latn-AU": "nji",
+ "njj-Latn-CM": "njj",
+ "njl-Latn-SS": "njl",
+ "njm-Latn-IN": "njm",
+ "njn-Latn-IN": "njn",
+ "njo-Latn-IN": "njo",
+ "njr-Latn-NG": "njr",
+ "njs-Latn-ID": "njs",
+ "njt-Latn-SR": "njt",
+ "nju-Latn-AU": "nju",
+ "njx-Latn-CG": "njx",
+ "njy-Latn-CM": "njy",
+ "njz-Beng-IN": "njz-Beng",
+ "njz-Latn-IN": "njz",
+ "nka-Latn-ZM": "nka",
+ "nkb-Latn-IN": "nkb",
+ "nkc-Latn-CM": "nkc",
+ "nkd-Latn-IN": "nkd",
+ "nke-Latn-SB": "nke",
+ "nkf-Latn-IN": "nkf",
+ "nkg-Latn-ZZ": "nkg",
+ "nkh-Latn-IN": "nkh",
+ "nki-Beng-IN": "nki-Beng",
+ "nki-Latn-IN": "nki",
+ "nkj-Latn-ID": "nkj",
+ "nkk-Latn-VU": "nkk",
+ "nkm-Latn-PG": "nkm",
+ "nkn-Latn-AO": "nkn",
+ "nko-Latn-ZZ": "nko",
+ "nkq-Latn-GH": "nkq",
+ "nkr-Latn-FM": "nkr",
+ "nks-Latn-ID": "nks",
+ "nkt-Latn-TZ": "nkt",
+ "nku-Latn-CI": "nku",
+ "nkv-Latn-MW": "nkv",
+ "nkw-Latn-CD": "nkw",
+ "nkx-Latn-NG": "nkx",
+ "nkz-Latn-NG": "nkz",
+ "nl-Latn-AW": "nl-AW",
+ "nl-Latn-BE": "nl-BE",
+ "nl-Latn-NL": "nl",
+ "nl-Latn-SR": "nl-SR",
+ "nla-Latn-CM": "nla",
+ "nlc-Latn-ID": "nlc",
+ "nle-Latn-KE": "nle",
+ "nlg-Latn-SB": "nlg",
+ "nli-Arab-AF": "nli",
+ "nlj-Latn-CD": "nlj",
+ "nlk-Latn-ID": "nlk",
+ "nlm-Arab-PK": "nlm",
+ "nlo-Latn-CD": "nlo",
+ "nlq-Latn-MM": "nlq",
+ "nlu-Latn-GH": "nlu",
+ "nlv-Latn-MX": "nlv",
+ "nlw-Latn-AU": "nlw",
+ "nlx-Deva-IN": "nlx",
+ "nly-Latn-AU": "nly",
+ "nlz-Latn-SB": "nlz",
+ "nma-Latn-IN": "nma",
+ "nmb-Latn-VU": "nmb",
+ "nmc-Latn-TD": "nmc",
+ "nmd-Latn-GA": "nmd",
+ "nme-Latn-IN": "nme",
+ "nmf-Latn-IN": "nmf",
+ "nmg-Latn-CM": "nmg",
+ "nmh-Latn-IN": "nmh",
+ "nmi-Latn-NG": "nmi",
+ "nmj-Latn-CF": "nmj",
+ "nmk-Latn-VU": "nmk",
+ "nml-Latn-CM": "nml",
+ "nmm-Deva-NP": "nmm",
+ "nmm-Tibt-NP": "nmm-Tibt",
+ "nmn-Latn-BW": "nmn",
+ "nmo-Beng-IN": "nmo-Beng",
+ "nmo-Latn-IN": "nmo",
+ "nmp-Latn-AU": "nmp",
+ "nmq-Latn-ZW": "nmq",
+ "nmr-Latn-CM": "nmr",
+ "nms-Latn-VU": "nms",
+ "nmt-Latn-FM": "nmt",
+ "nmu-Latn-US": "nmu",
+ "nmv-Latn-AU": "nmv",
+ "nmw-Latn-PG": "nmw",
+ "nmx-Latn-PG": "nmx",
+ "nmz-Latn-ZZ": "nmz",
+ "nn-Latn-NO": "nn",
+ "nna-Latn-AU": "nna",
+ "nnb-Latn-CD": "nnb",
+ "nnc-Latn-TD": "nnc",
+ "nnd-Latn-VU": "nnd",
+ "nne-Latn-AO": "nne",
+ "nnf-Latn-ZZ": "nnf",
+ "nng-Beng-IN": "nng-Beng",
+ "nng-Latn-IN": "nng",
+ "nnh-Latn-CM": "nnh",
+ "nni-Latn-ID": "nni",
+ "nnj-Latn-ET": "nnj",
+ "nnk-Latn-ZZ": "nnk",
+ "nnl-Latn-IN": "nnl",
+ "nnm-Latn-ZZ": "nnm",
+ "nnn-Latn-TD": "nnn",
+ "nnp-Wcho-IN": "nnp",
+ "nnq-Latn-TZ": "nnq",
+ "nnr-Latn-AU": "nnr",
+ "nnt-Latn-US": "nnt",
+ "nnu-Latn-GH": "nnu",
+ "nnv-Latn-AU": "nnv",
+ "nnw-Latn-BF": "nnw",
+ "nny-Latn-AU": "nny",
+ "nnz-Latn-CM": "nnz",
+ "no-Latn-NO": "no",
+ "noa-Latn-CO": "noa",
+ "noc-Latn-PG": "noc",
+ "nod-Lana-TH": "nod",
+ "noe-Deva-IN": "noe",
+ "nof-Latn-PG": "nof",
+ "nog-Cyrl-RU": "nog",
+ "noh-Latn-PG": "noh",
+ "noi-Deva-IN": "noi",
+ "noj-Latn-CO": "noj",
+ "nok-Latn-US": "nok",
+ "nom-Latn-PE": "nom",
+ "non-Runr-SE": "non",
+ "nop-Latn-ZZ": "nop",
+ "noq-Latn-CD": "noq",
+ "nos-Yiii-CN": "nos",
+ "not-Latn-PE": "not",
+ "nou-Latn-ZZ": "nou",
+ "nov-Latn-001": "nov",
+ "now-Latn-TZ": "now",
+ "noy-Latn-TD": "noy",
+ "npb-Tibt-BT": "npb",
+ "npg-Latn-MM": "npg",
+ "nph-Latn-IN": "nph",
+ "npl-Latn-MX": "npl",
+ "npn-Latn-PG": "npn",
+ "npo-Latn-IN": "npo",
+ "nps-Latn-ID": "nps",
+ "npu-Latn-IN": "npu",
+ "npx-Latn-SB": "npx",
+ "npy-Latn-ID": "npy",
+ "nqg-Latn-BJ": "nqg",
+ "nqk-Latn-BJ": "nqk",
+ "nql-Latn-AO": "nql",
+ "nqm-Latn-ID": "nqm",
+ "nqn-Latn-PG": "nqn",
+ "nqo-Nkoo-GN": "nqo",
+ "nqq-Latn-MM": "nqq",
+ "nqt-Latn-NG": "nqt",
+ "nqy-Latn-MM": "nqy",
+ "nr-Latn-ZA": "nr",
+ "nra-Latn-GA": "nra",
+ "nrb-Latn-ZZ": "nrb",
+ "nre-Latn-IN": "nre",
+ "nrf-Latn-JE": "nrf",
+ "nrg-Latn-VU": "nrg",
+ "nri-Latn-IN": "nri",
+ "nrk-Latn-AU": "nrk",
+ "nrl-Latn-AU": "nrl",
+ "nrm-Latn-MY": "nrm",
+ "nrp-Latn-IT": "nrp",
+ "nru-Hans-CN": "nru-Hans",
+ "nru-Hant-CN": "nru-Hant",
+ "nru-Latn-CN": "nru",
+ "nrx-Latn-AU": "nrx",
+ "nrz-Latn-PG": "nrz",
+ "nsa-Latn-IN": "nsa",
+ "nsb-Latn-ZA": "nsb",
+ "nsc-Latn-NG": "nsc",
+ "nsd-Yiii-CN": "nsd",
+ "nse-Latn-ZM": "nse",
+ "nsf-Yiii-CN": "nsf",
+ "nsg-Latn-TZ": "nsg",
+ "nsh-Latn-CM": "nsh",
+ "nsk-Cans-CA": "nsk",
+ "nsm-Latn-IN": "nsm",
+ "nsn-Latn-ZZ": "nsn",
+ "nso-Latn-ZA": "nso",
+ "nsq-Latn-US": "nsq",
+ "nss-Latn-ZZ": "nss",
+ "nst-Tnsa-IN": "nst",
+ "nsu-Latn-MX": "nsu",
+ "nsv-Yiii-CN": "nsv",
+ "nsw-Latn-VU": "nsw",
+ "nsx-Latn-AO": "nsx",
+ "nsy-Latn-ID": "nsy",
+ "nsz-Latn-US": "nsz",
+ "ntd-Latn-MY": "ntd",
+ "nte-Latn-MZ": "nte",
+ "ntg-Latn-AU": "ntg",
+ "nti-Latn-BF": "nti",
+ "ntj-Latn-AU": "ntj",
+ "ntk-Latn-TZ": "ntk",
+ "ntm-Latn-ZZ": "ntm",
+ "nto-Latn-CD": "nto",
+ "ntp-Latn-MX": "ntp",
+ "ntr-Latn-ZZ": "ntr",
+ "ntu-Latn-SB": "ntu",
+ "ntx-Latn-MM": "ntx",
+ "nty-Yiii-VN": "nty",
+ "ntz-Arab-IR": "ntz",
+ "nua-Latn-NC": "nua",
+ "nuc-Latn-BR": "nuc",
+ "nud-Latn-PG": "nud",
+ "nue-Latn-CD": "nue",
+ "nuf-Latn-CN": "nuf",
+ "nug-Latn-AU": "nug",
+ "nuh-Latn-NG": "nuh",
+ "nui-Latn-ZZ": "nui",
+ "nuj-Latn-UG": "nuj",
+ "nuk-Latn-CA": "nuk",
+ "num-Latn-TO": "num",
+ "nun-Latn-MM": "nun",
+ "nuo-Latn-VN": "nuo",
+ "nup-Latn-ZZ": "nup",
+ "nuq-Latn-PG": "nuq",
+ "nur-Latn-PG": "nur",
+ "nus-Latn-SS": "nus",
+ "nut-Latn-VN": "nut",
+ "nuu-Latn-CD": "nuu",
+ "nuv-Latn-ZZ": "nuv",
+ "nuw-Latn-FM": "nuw",
+ "nux-Latn-ZZ": "nux",
+ "nuy-Latn-AU": "nuy",
+ "nuz-Latn-MX": "nuz",
+ "nv-Latn-US": "nv",
+ "nvh-Latn-VU": "nvh",
+ "nvm-Latn-PG": "nvm",
+ "nvo-Latn-CM": "nvo",
+ "nwb-Latn-ZZ": "nwb",
+ "nwc-Brah-NP": "nwc-Brah",
+ "nwc-Deva-NP": "nwc-Deva",
+ "nwc-Newa-NP": "nwc",
+ "nwc-Sidd-NP": "nwc-Sidd",
+ "nwe-Latn-CM": "nwe",
+ "nwg-Latn-AU": "nwg",
+ "nwi-Latn-VU": "nwi",
+ "nwm-Latn-SS": "nwm",
+ "nwo-Latn-AU": "nwo",
+ "nwr-Latn-PG": "nwr",
+ "nww-Latn-TZ": "nww",
+ "nwx-Deva-NP": "nwx",
+ "nxa-Latn-TL": "nxa",
+ "nxd-Latn-CD": "nxd",
+ "nxe-Latn-ID": "nxe",
+ "nxg-Latn-ID": "nxg",
+ "nxi-Latn-TZ": "nxi",
+ "nxl-Latn-ID": "nxl",
+ "nxn-Latn-AU": "nxn",
+ "nxo-Latn-GA": "nxo",
+ "nxq-Latn-CN": "nxq",
+ "nxr-Latn-ZZ": "nxr",
+ "nxx-Latn-ID": "nxx",
+ "ny-Latn-MW": "ny",
+ "nyb-Latn-GH": "nyb",
+ "nyc-Latn-CD": "nyc",
+ "nyd-Latn-KE": "nyd",
+ "nye-Latn-AO": "nye",
+ "nyf-Latn-KE": "nyf",
+ "nyg-Latn-CD": "nyg",
+ "nyh-Latn-AU": "nyh",
+ "nyi-Latn-SD": "nyi",
+ "nyj-Latn-CD": "nyj",
+ "nyk-Latn-AO": "nyk",
+ "nyl-Thai-TH": "nyl",
+ "nym-Latn-TZ": "nym",
+ "nyn-Latn-UG": "nyn",
+ "nyo-Latn-UG": "nyo",
+ "nyp-Latn-UG": "nyp",
+ "nyq-Arab-IR": "nyq",
+ "nyr-Latn-MW": "nyr",
+ "nys-Latn-AU": "nys",
+ "nyt-Latn-AU": "nyt",
+ "nyu-Latn-MZ": "nyu",
+ "nyv-Latn-AU": "nyv",
+ "nyx-Latn-AU": "nyx",
+ "nyy-Latn-TZ": "nyy",
+ "nza-Latn-CM": "nza",
+ "nzb-Latn-GA": "nzb",
+ "nzd-Latn-CD": "nzd",
+ "nzi-Latn-GH": "nzi",
+ "nzk-Latn-CF": "nzk",
+ "nzm-Latn-IN": "nzm",
+ "nzu-Latn-CG": "nzu",
+ "nzy-Latn-TD": "nzy",
+ "nzz-Latn-ML": "nzz",
+ "oaa-Cyrl-RU": "oaa",
+ "oac-Cyrl-RU": "oac",
+ "oar-Syrc-SY": "oar",
+ "oav-Geor-GE": "oav",
+ "obi-Latn-US": "obi",
+ "obk-Latn-PH": "obk",
+ "obl-Latn-CM": "obl",
+ "obm-Phnx-JO": "obm",
+ "obo-Latn-PH": "obo",
+ "obr-Mymr-MM": "obr",
+ "obt-Latn-FR": "obt",
+ "obu-Latn-NG": "obu",
+ "oc-Latn-FR": "oc",
+ "oca-Latn-PE": "oca",
+ "oco-Latn-GB": "oco",
+ "ocu-Latn-MX": "ocu",
+ "oda-Latn-NG": "oda",
+ "odk-Arab-PK": "odk",
+ "odt-Latn-NL": "odt",
+ "odu-Latn-NG": "odu",
+ "ofu-Latn-NG": "ofu",
+ "ogb-Latn-NG": "ogb",
+ "ogc-Latn-ZZ": "ogc",
+ "ogg-Latn-NG": "ogg",
+ "ogo-Latn-NG": "ogo",
+ "ogu-Latn-NG": "ogu",
+ "oht-Xsux-TR": "oht",
+ "oia-Latn-ID": "oia",
+ "oie-Latn-SS": "oie",
+ "oin-Latn-PG": "oin",
+ "oj-Cans-CA": "oj",
+ "ojb-Cans-CA": "ojb-Cans",
+ "ojb-Latn-CA": "ojb",
+ "ojc-Latn-CA": "ojc",
+ "ojs-Cans-CA": "ojs",
+ "ojv-Latn-SB": "ojv",
+ "ojw-Cans-CA": "ojw-Cans",
+ "ojw-Latn-CA": "ojw",
+ "oka-Latn-CA": "oka",
+ "okb-Latn-NG": "okb",
+ "okc-Latn-CD": "okc",
+ "okd-Latn-NG": "okd",
+ "oke-Latn-NG": "oke",
+ "okg-Latn-AU": "okg",
+ "oki-Latn-KE": "oki",
+ "okk-Latn-PG": "okk",
+ "okm-Hang-KR": "okm",
+ "oko-Hani-KR": "oko",
+ "okr-Latn-ZZ": "okr",
+ "oks-Latn-NG": "oks",
+ "oku-Latn-CM": "oku",
+ "okv-Latn-ZZ": "okv",
+ "okx-Latn-NG": "okx",
+ "okz-Khmr-KH": "okz",
+ "ola-Deva-NP": "ola",
+ "ola-Tibt-CN": "ola-Tibt",
+ "old-Latn-TZ": "old",
+ "ole-Tibt-BT": "ole",
+ "olk-Latn-AU": "olk",
+ "olm-Latn-NG": "olm",
+ "olo-Latn-RU": "olo",
+ "olr-Latn-VU": "olr",
+ "olt-Latn-LT": "olt",
+ "olu-Latn-AO": "olu",
+ "om-Latn-ET": "om",
+ "oma-Latn-US": "oma",
+ "omb-Latn-VU": "omb",
+ "omc-Latn-PE": "omc",
+ "omg-Latn-PE": "omg",
+ "omi-Latn-CD": "omi",
+ "omk-Cyrl-RU": "omk",
+ "oml-Latn-CD": "oml",
+ "omo-Latn-PG": "omo",
+ "omp-Mtei-IN": "omp",
+ "omr-Modi-IN": "omr",
+ "omt-Latn-KE": "omt",
+ "omu-Latn-PE": "omu",
+ "omw-Latn-PG": "omw",
+ "ona-Latn-AR": "ona",
+ "one-Latn-CA": "one",
+ "ong-Latn-ZZ": "ong",
+ "oni-Latn-ID": "oni",
+ "onj-Latn-PG": "onj",
+ "onk-Latn-PG": "onk",
+ "onn-Latn-ZZ": "onn",
+ "ono-Latn-CA": "ono",
+ "onp-Deva-IN": "onp-Deva",
+ "onp-Latn-IN": "onp",
+ "onr-Latn-PG": "onr",
+ "ons-Latn-ZZ": "ons",
+ "ont-Latn-PG": "ont",
+ "onu-Latn-VU": "onu",
+ "onx-Latn-ID": "onx",
+ "ood-Latn-US": "ood",
+ "oon-Deva-IN": "oon",
+ "oor-Latn-ZA": "oor",
+ "opa-Latn-NG": "opa",
+ "opk-Latn-ID": "opk",
+ "opm-Latn-ZZ": "opm",
+ "opo-Latn-PG": "opo",
+ "opt-Latn-MX": "opt",
+ "opy-Latn-BR": "opy",
+ "or-Orya-IN": "or",
+ "ora-Latn-SB": "ora",
+ "orc-Latn-KE": "orc",
+ "ore-Latn-PE": "ore",
+ "org-Latn-NG": "org",
+ "orn-Latn-MY": "orn",
+ "oro-Latn-ZZ": "oro",
+ "orr-Latn-NG": "orr",
+ "ors-Latn-MY": "ors",
+ "ort-Telu-IN": "ort",
+ "oru-Arab-ZZ": "oru",
+ "orv-Cyrl-RU": "orv",
+ "orw-Latn-BR": "orw",
+ "orx-Latn-NG": "orx",
+ "orz-Latn-ID": "orz",
+ "os-Cyrl-GE": "os",
+ "osa-Osge-US": "osa",
+ "osc-Ital-IT": "osc",
+ "osc-Latn-IT": "osc-Latn",
+ "osi-Java-ID": "osi",
+ "oso-Latn-NG": "oso",
+ "osp-Latn-ES": "osp",
+ "ost-Latn-CM": "ost",
+ "osu-Latn-PG": "osu",
+ "osx-Latn-DE": "osx",
+ "ota-Arab-ZZ": "ota",
+ "otb-Tibt-CN": "otb",
+ "otd-Latn-ID": "otd",
+ "ote-Latn-MX": "ote",
+ "oti-Latn-BR": "oti",
+ "otk-Orkh-MN": "otk",
+ "otl-Latn-MX": "otl",
+ "otm-Latn-MX": "otm",
+ "otn-Latn-MX": "otn",
+ "otq-Latn-MX": "otq",
+ "otr-Latn-SD": "otr",
+ "ots-Latn-MX": "ots",
+ "ott-Latn-MX": "ott",
+ "otu-Latn-BR": "otu",
+ "otw-Latn-CA": "otw",
+ "otx-Latn-MX": "otx",
+ "oty-Gran-IN": "oty",
+ "otz-Latn-MX": "otz",
+ "oub-Latn-LR": "oub",
+ "oue-Latn-PG": "oue",
+ "oui-Ougr-143": "oui",
+ "oum-Latn-PG": "oum",
+ "ovd-Latn-SE": "ovd",
+ "owi-Latn-PG": "owi",
+ "owl-Latn-GB": "owl",
+ "oyd-Latn-ET": "oyd",
+ "oym-Latn-BR": "oym",
+ "oyy-Latn-PG": "oyy",
+ "ozm-Latn-ZZ": "ozm",
+ "pa-Arab-PK": "pa-PK",
+ "pa-Guru-IN": "pa",
+ "pab-Latn-BR": "pab",
+ "pac-Latn-VN": "pac",
+ "pad-Latn-BR": "pad",
+ "pae-Latn-CD": "pae",
+ "paf-Latn-BR": "paf",
+ "pag-Latn-PH": "pag",
+ "pah-Latn-BR": "pah",
+ "pai-Latn-NG": "pai",
+ "pak-Latn-BR": "pak",
+ "pal-Phli-IR": "pal",
+ "pal-Phlp-CN": "pal-Phlp",
+ "pam-Latn-PH": "pam",
+ "pao-Latn-US": "pao",
+ "pap-Latn-BQ": "pap-BQ",
+ "pap-Latn-CW": "pap",
+ "paq-Cyrl-TJ": "paq",
+ "par-Latn-US": "par",
+ "pas-Latn-ID": "pas",
+ "pau-Latn-PW": "pau",
+ "pav-Latn-BR": "pav",
+ "paw-Latn-US": "paw",
+ "pax-Latn-BR": "pax",
+ "pay-Latn-HN": "pay",
+ "paz-Latn-BR": "paz",
+ "pbb-Latn-CO": "pbb",
+ "pbc-Latn-GY": "pbc",
+ "pbe-Latn-MX": "pbe",
+ "pbf-Latn-MX": "pbf",
+ "pbg-Latn-VE": "pbg",
+ "pbh-Latn-VE": "pbh",
+ "pbi-Latn-ZZ": "pbi",
+ "pbl-Latn-NG": "pbl",
+ "pbm-Latn-MX": "pbm",
+ "pbn-Latn-NG": "pbn",
+ "pbo-Latn-GW": "pbo",
+ "pbp-Latn-GN": "pbp",
+ "pbr-Latn-TZ": "pbr",
+ "pbs-Latn-MX": "pbs",
+ "pbt-Arab-AF": "pbt",
+ "pbv-Latn-IN": "pbv",
+ "pby-Latn-PG": "pby",
+ "pca-Latn-MX": "pca",
+ "pcb-Khmr-KH": "pcb",
+ "pcc-Hani-CN": "pcc-Hani",
+ "pcc-Latn-CN": "pcc",
+ "pcd-Latn-FR": "pcd",
+ "pce-Mymr-MM": "pce",
+ "pce-Thai-TH": "pce-Thai",
+ "pcf-Mlym-IN": "pcf",
+ "pcg-Knda-IN": "pcg-Knda",
+ "pcg-Mlym-IN": "pcg",
+ "pcg-Taml-IN": "pcg-Taml",
+ "pch-Deva-IN": "pch",
+ "pci-Deva-IN": "pci",
+ "pci-Orya-IN": "pci-Orya",
+ "pcj-Telu-IN": "pcj",
+ "pck-Latn-IN": "pck",
+ "pcm-Latn-NG": "pcm",
+ "pcn-Latn-NG": "pcn",
+ "pcp-Latn-BO": "pcp",
+ "pcw-Latn-NG": "pcw",
+ "pda-Latn-PG": "pda",
+ "pdc-Latn-US": "pdc",
+ "pdn-Latn-ID": "pdn",
+ "pdo-Latn-ID": "pdo",
+ "pdt-Latn-CA": "pdt",
+ "pdu-Latn-MM": "pdu",
+ "pdu-Mymr-MM": "pdu-Mymr",
+ "pea-Latn-ID": "pea",
+ "peb-Latn-US": "peb",
+ "ped-Latn-ZZ": "ped",
+ "pee-Latn-ID": "pee",
+ "peg-Orya-IN": "peg",
+ "pei-Latn-MX": "pei",
+ "pek-Latn-PG": "pek",
+ "pel-Latn-ID": "pel",
+ "pem-Latn-CD": "pem",
+ "peo-Xpeo-IR": "peo",
+ "pep-Latn-PG": "pep",
+ "peq-Latn-US": "peq",
+ "pev-Latn-VE": "pev",
+ "pex-Latn-ZZ": "pex",
+ "pey-Latn-ID": "pey",
+ "pez-Latn-MY": "pez",
+ "pfa-Latn-FM": "pfa",
+ "pfe-Latn-CM": "pfe",
+ "pfl-Latn-DE": "pfl",
+ "pga-Latn-SS": "pga",
+ "pgd-Khar-PK": "pgd",
+ "pgg-Deva-IN": "pgg",
+ "pgi-Latn-PG": "pgi",
+ "pgk-Latn-VU": "pgk",
+ "pgl-Ogam-IE": "pgl",
+ "pgn-Ital-IT": "pgn",
+ "pgs-Latn-NG": "pgs",
+ "pgu-Latn-ID": "pgu",
+ "phd-Deva-IN": "phd",
+ "phg-Latn-VN": "phg",
+ "phh-Latn-VN": "phh",
+ "phk-Mymr-IN": "phk",
+ "phl-Arab-ZZ": "phl",
+ "phm-Latn-MZ": "phm",
+ "phn-Phnx-LB": "phn",
+ "pho-Laoo-LA": "pho",
+ "phr-Arab-PK": "phr",
+ "pht-Thai-TH": "pht",
+ "phv-Arab-AF": "phv",
+ "phw-Deva-NP": "phw",
+ "pi-Brah-IN": "pi-Brah",
+ "pi-Deva-IN": "pi-Deva",
+ "pi-Khar-IN": "pi-Khar",
+ "pi-Khmr-IN": "pi-Khmr",
+ "pi-Mymr-IN": "pi-Mymr",
+ "pi-Sinh-IN": "pi",
+ "pi-Thai-IN": "pi-Thai",
+ "pia-Latn-MX": "pia",
+ "pib-Latn-PE": "pib",
+ "pic-Latn-GA": "pic",
+ "pid-Latn-VE": "pid",
+ "pif-Latn-FM": "pif",
+ "pig-Latn-PE": "pig",
+ "pih-Latn-NF": "pih",
+ "pij-Latn-CO": "pij",
+ "pil-Latn-ZZ": "pil",
+ "pim-Latn-US": "pim",
+ "pin-Latn-PG": "pin",
+ "pio-Latn-CO": "pio",
+ "pip-Latn-ZZ": "pip",
+ "pir-Latn-BR": "pir",
+ "pis-Latn-SB": "pis",
+ "pit-Latn-AU": "pit",
+ "piu-Latn-AU": "piu",
+ "piv-Latn-SB": "piv",
+ "piw-Latn-TZ": "piw",
+ "pix-Latn-PG": "pix",
+ "piy-Latn-NG": "piy",
+ "piz-Latn-NC": "piz",
+ "pjt-Latn-AU": "pjt",
+ "pka-Brah-IN": "pka",
+ "pkb-Latn-KE": "pkb",
+ "pkg-Latn-PG": "pkg",
+ "pkh-Deva-BD": "pkh-Deva",
+ "pkh-Latn-BD": "pkh",
+ "pkn-Latn-AU": "pkn",
+ "pko-Latn-KE": "pko",
+ "pkp-Latn-CK": "pkp",
+ "pkr-Mlym-IN": "pkr",
+ "pku-Latn-ID": "pku",
+ "pl-Latn-PL": "pl",
+ "pl-Latn-UA": "pl-UA",
+ "pla-Latn-ZZ": "pla",
+ "plb-Latn-VU": "plb",
+ "plc-Latn-PH": "plc",
+ "pld-Latn-GB": "pld",
+ "ple-Latn-ID": "ple",
+ "plg-Latn-AR": "plg",
+ "plh-Latn-ID": "plh",
+ "plj-Latn-NG": "plj",
+ "plk-Arab-PK": "plk",
+ "pll-Mymr-MM": "pll",
+ "pln-Latn-CO": "pln",
+ "plo-Latn-MX": "plo",
+ "plr-Latn-CI": "plr",
+ "pls-Latn-MX": "pls",
+ "plu-Latn-BR": "plu",
+ "plv-Latn-PH": "plv",
+ "plw-Latn-PH": "plw",
+ "plz-Latn-MY": "plz",
+ "pma-Latn-VU": "pma",
+ "pmb-Latn-CD": "pmb",
+ "pmd-Latn-AU": "pmd",
+ "pme-Latn-NC": "pme",
+ "pmf-Latn-ID": "pmf",
+ "pmh-Brah-IN": "pmh",
+ "pmi-Latn-CN": "pmi",
+ "pmj-Latn-CN": "pmj",
+ "pml-Latn-TN": "pml",
+ "pmm-Latn-CM": "pmm",
+ "pmn-Latn-CM": "pmn",
+ "pmo-Latn-ID": "pmo",
+ "pmq-Latn-MX": "pmq",
+ "pmr-Latn-PG": "pmr",
+ "pms-Latn-IT": "pms",
+ "pmt-Latn-PF": "pmt",
+ "pmw-Latn-US": "pmw",
+ "pmx-Latn-IN": "pmx",
+ "pmy-Latn-ID": "pmy",
+ "pmz-Latn-MX": "pmz",
+ "pna-Latn-MY": "pna",
+ "pnc-Latn-ID": "pnc",
+ "pnd-Latn-AO": "pnd",
+ "pne-Latn-MY": "pne",
+ "png-Latn-ZZ": "png",
+ "pnh-Latn-CK": "pnh",
+ "pni-Latn-ID": "pni",
+ "pnj-Latn-AU": "pnj",
+ "pnk-Latn-BO": "pnk",
+ "pnl-Latn-BF": "pnl",
+ "pnm-Latn-MY": "pnm",
+ "pnn-Latn-ZZ": "pnn",
+ "pno-Latn-PE": "pno",
+ "pnp-Latn-ID": "pnp",
+ "pnq-Latn-BF": "pnq",
+ "pnr-Latn-PG": "pnr",
+ "pns-Latn-ID": "pns",
+ "pnt-Grek-GR": "pnt",
+ "pnv-Latn-AU": "pnv",
+ "pnw-Latn-AU": "pnw",
+ "pny-Latn-CM": "pny",
+ "pnz-Latn-CF": "pnz",
+ "poc-Latn-GT": "poc",
+ "poe-Latn-MX": "poe",
+ "pof-Latn-CD": "pof",
+ "pog-Latn-BR": "pog",
+ "poh-Latn-GT": "poh",
+ "poi-Latn-MX": "poi",
+ "pok-Latn-BR": "pok",
+ "pom-Latn-US": "pom",
+ "pon-Latn-FM": "pon",
+ "poo-Latn-US": "poo",
+ "pop-Latn-NC": "pop",
+ "poq-Latn-MX": "poq",
+ "pos-Latn-MX": "pos",
+ "pot-Latn-US": "pot",
+ "pov-Latn-GW": "pov",
+ "pow-Latn-MX": "pow",
+ "poy-Latn-TZ": "poy",
+ "ppe-Latn-PG": "ppe",
+ "ppi-Latn-MX": "ppi",
+ "ppk-Latn-ID": "ppk",
+ "ppl-Latn-SV": "ppl",
+ "ppm-Latn-ID": "ppm",
+ "ppn-Latn-PG": "ppn",
+ "ppo-Latn-ZZ": "ppo",
+ "ppp-Latn-CD": "ppp",
+ "ppq-Latn-PG": "ppq",
+ "pps-Latn-MX": "pps",
+ "ppt-Latn-PG": "ppt",
+ "pqa-Latn-NG": "pqa",
+ "pqm-Latn-CA": "pqm",
+ "pra-Khar-PK": "pra",
+ "prc-Arab-AF": "prc",
+ "prd-Arab-IR": "prd",
+ "pre-Latn-ST": "pre",
+ "prf-Latn-PH": "prf",
+ "prg-Latn-001": "prg",
+ "prh-Latn-PH": "prh",
+ "pri-Latn-NC": "pri",
+ "prk-Latn-MM": "prk",
+ "prm-Latn-PG": "prm",
+ "pro-Latn-FR": "pro",
+ "prp-Gujr-IN": "prp",
+ "prq-Latn-PE": "prq",
+ "prr-Latn-BR": "prr",
+ "prt-Thai-TH": "prt",
+ "pru-Latn-ID": "pru",
+ "prw-Latn-PG": "prw",
+ "prx-Arab-IN": "prx",
+ "prx-Tibt-IN": "prx-Tibt",
+ "ps-Arab-AF": "ps",
+ "psa-Latn-ID": "psa",
+ "pse-Latn-ID": "pse",
+ "psh-Arab-AF": "psh",
+ "psi-Arab-AF": "psi",
+ "psm-Latn-BO": "psm",
+ "psn-Latn-ID": "psn",
+ "psq-Latn-PG": "psq",
+ "pss-Latn-ZZ": "pss",
+ "pst-Arab-PK": "pst",
+ "psw-Latn-VU": "psw",
+ "pt-Latn-AO": "pt-AO",
+ "pt-Latn-BR": "pt",
+ "pt-Latn-CV": "pt-CV",
+ "pt-Latn-GW": "pt-GW",
+ "pt-Latn-MO": "pt-MO",
+ "pt-Latn-MZ": "pt-MZ",
+ "pt-Latn-PT": "pt-PT",
+ "pt-Latn-ST": "pt-ST",
+ "pt-Latn-TL": "pt-TL",
+ "pta-Latn-PY": "pta",
+ "pth-Latn-BR": "pth",
+ "pti-Latn-AU": "pti",
+ "ptn-Latn-ID": "ptn",
+ "pto-Latn-BR": "pto",
+ "ptp-Latn-ZZ": "ptp",
+ "ptr-Latn-VU": "ptr",
+ "ptt-Latn-ID": "ptt",
+ "ptu-Latn-ID": "ptu",
+ "ptv-Latn-VU": "ptv",
+ "pua-Latn-MX": "pua",
+ "pub-Latn-IN": "pub",
+ "puc-Latn-ID": "puc",
+ "pud-Latn-ID": "pud",
+ "pue-Latn-AR": "pue",
+ "puf-Latn-ID": "puf",
+ "pug-Latn-BF": "pug",
+ "pui-Latn-CO": "pui",
+ "puj-Latn-ID": "puj",
+ "pum-Deva-NP": "pum",
+ "puo-Latn-VN": "puo",
+ "pup-Latn-PG": "pup",
+ "puq-Latn-PE": "puq",
+ "pur-Latn-BR": "pur",
+ "put-Latn-ID": "put",
+ "puu-Latn-GA": "puu",
+ "puw-Latn-FM": "puw",
+ "pux-Latn-PG": "pux",
+ "puy-Latn-US": "puy",
+ "pwa-Latn-ZZ": "pwa",
+ "pwb-Latn-NG": "pwb",
+ "pwg-Latn-PG": "pwg",
+ "pwm-Latn-PH": "pwm",
+ "pwn-Latn-TW": "pwn",
+ "pwo-Mymr-MM": "pwo",
+ "pwr-Deva-IN": "pwr",
+ "pww-Thai-TH": "pww",
+ "pxm-Latn-MX": "pxm",
+ "pye-Latn-CI": "pye",
+ "pym-Latn-NG": "pym",
+ "pyn-Latn-BR": "pyn",
+ "pyu-Hani-TW": "pyu-Hani",
+ "pyu-Latn-TW": "pyu",
+ "pyx-Mymr-MM": "pyx",
+ "pyy-Latn-MM": "pyy",
+ "pzh-Latn-TW": "pzh",
+ "pzn-Latn-MM": "pzn",
+ "qu-Latn-PE": "qu",
+ "qua-Latn-US": "qua",
+ "qub-Latn-PE": "qub",
+ "quc-Latn-GT": "quc",
+ "qud-Latn-EC": "qud",
+ "quf-Latn-PE": "quf",
+ "qug-Latn-EC": "qug",
+ "qui-Latn-US": "qui",
+ "quk-Latn-PE": "quk",
+ "qul-Latn-BO": "qul",
+ "qum-Latn-GT": "qum",
+ "qun-Latn-US": "qun",
+ "qup-Latn-PE": "qup",
+ "quq-Latn-ES": "quq",
+ "qur-Latn-PE": "qur",
+ "qus-Latn-AR": "qus",
+ "quv-Latn-GT": "quv",
+ "quw-Latn-EC": "quw",
+ "qux-Latn-PE": "qux",
+ "quy-Latn-PE": "quy",
+ "qva-Latn-PE": "qva",
+ "qvc-Latn-PE": "qvc",
+ "qve-Latn-PE": "qve",
+ "qvh-Latn-PE": "qvh",
+ "qvi-Latn-EC": "qvi",
+ "qvj-Latn-EC": "qvj",
+ "qvl-Latn-PE": "qvl",
+ "qvm-Latn-PE": "qvm",
+ "qvn-Latn-PE": "qvn",
+ "qvo-Latn-PE": "qvo",
+ "qvp-Latn-PE": "qvp",
+ "qvs-Latn-PE": "qvs",
+ "qvw-Latn-PE": "qvw",
+ "qvz-Latn-EC": "qvz",
+ "qwa-Latn-PE": "qwa",
+ "qwc-Latn-PE": "qwc",
+ "qwh-Latn-PE": "qwh",
+ "qwm-Cyrl-RU": "qwm-Cyrl",
+ "qwm-Latn-RU": "qwm",
+ "qwm-Runr-RU": "qwm-Runr",
+ "qws-Latn-PE": "qws",
+ "qwt-Latn-US": "qwt",
+ "qxa-Latn-PE": "qxa",
+ "qxc-Latn-PE": "qxc",
+ "qxh-Latn-PE": "qxh",
+ "qxl-Latn-EC": "qxl",
+ "qxn-Latn-PE": "qxn",
+ "qxo-Latn-PE": "qxo",
+ "qxp-Latn-PE": "qxp",
+ "qxq-Arab-IR": "qxq",
+ "qxr-Latn-EC": "qxr",
+ "qxt-Latn-PE": "qxt",
+ "qxu-Latn-PE": "qxu",
+ "qxw-Latn-PE": "qxw",
+ "qya-Latn-001": "qya",
+ "qyp-Latn-US": "qyp",
+ "raa-Deva-NP": "raa",
+ "rab-Deva-NP": "rab",
+ "rac-Latn-ID": "rac",
+ "rad-Latn-VN": "rad",
+ "raf-Deva-NP": "raf",
+ "rag-Latn-KE": "rag",
+ "rah-Beng-IN": "rah",
+ "rah-Latn-IN": "rah-Latn",
+ "rai-Latn-ZZ": "rai",
+ "raj-Deva-IN": "raj",
+ "rak-Latn-PG": "rak",
+ "ram-Latn-BR": "ram",
+ "ran-Latn-ID": "ran",
+ "rao-Latn-ZZ": "rao",
+ "rap-Latn-CL": "rap",
+ "rar-Latn-CK": "rar",
+ "rav-Deva-NP": "rav",
+ "raw-Latn-MM": "raw",
+ "rax-Latn-NG": "rax",
+ "ray-Latn-PF": "ray",
+ "raz-Latn-ID": "raz",
+ "rbb-Mymr-MM": "rbb",
+ "rbk-Latn-PH": "rbk",
+ "rbl-Latn-PH": "rbl",
+ "rbp-Latn-AU": "rbp",
+ "rcf-Latn-RE": "rcf",
+ "rdb-Arab-IR": "rdb",
+ "rea-Latn-PG": "rea",
+ "reb-Latn-ID": "reb",
+ "ree-Latn-MY": "ree",
+ "reg-Latn-TZ": "reg",
+ "rei-Orya-IN": "rei",
+ "rei-Telu-IN": "rei-Telu",
+ "rej-Latn-ID": "rej",
+ "rej-Rjng-ID": "rej-Rjng",
+ "rel-Latn-ZZ": "rel",
+ "rem-Latn-PE": "rem",
+ "ren-Latn-VN": "ren",
+ "res-Latn-ZZ": "res",
+ "ret-Latn-ID": "ret",
+ "rey-Latn-BO": "rey",
+ "rga-Latn-VU": "rga",
+ "rgn-Latn-IT": "rgn",
+ "rgr-Latn-PE": "rgr",
+ "rgs-Latn-VN": "rgs",
+ "rgu-Latn-ID": "rgu",
+ "rhg-Arab-MM": "rhg-Arab",
+ "rhg-Rohg-MM": "rhg",
+ "rhp-Latn-PG": "rhp",
+ "ria-Latn-IN": "ria",
+ "rif-Latn-MA": "rif",
+ "ril-Latn-MM": "ril",
+ "rim-Latn-TZ": "rim",
+ "rin-Latn-NG": "rin",
+ "rir-Latn-ID": "rir",
+ "rit-Latn-AU": "rit",
+ "riu-Latn-ID": "riu",
+ "rjg-Latn-ID": "rjg",
+ "rji-Deva-NP": "rji",
+ "rjs-Deva-NP": "rjs",
+ "rka-Khmr-KH": "rka",
+ "rkb-Latn-BR": "rkb",
+ "rkh-Latn-CK": "rkh",
+ "rki-Mymr-MM": "rki",
+ "rkm-Latn-BF": "rkm",
+ "rkt-Beng-BD": "rkt",
+ "rkw-Latn-AU": "rkw",
+ "rm-Latn-CH": "rm",
+ "rma-Latn-NI": "rma",
+ "rmb-Latn-AU": "rmb",
+ "rmc-Latn-SK": "rmc",
+ "rmd-Latn-DK": "rmd",
+ "rme-Latn-GB": "rme",
+ "rmf-Latn-FI": "rmf",
+ "rmg-Latn-NO": "rmg",
+ "rmh-Latn-ID": "rmh",
+ "rmi-Armn-AM": "rmi",
+ "rmk-Latn-PG": "rmk",
+ "rml-Cyrl-BY": "rml-Cyrl",
+ "rml-Latn-PL": "rml",
+ "rmm-Latn-ID": "rmm",
+ "rmn-Cyrl-BG": "rmn-Cyrl",
+ "rmn-Grek-GR": "rmn-Grek",
+ "rmn-Latn-RS": "rmn",
+ "rmo-Latn-CH": "rmo",
+ "rmp-Latn-PG": "rmp",
+ "rmq-Latn-ES": "rmq",
+ "rmt-Arab-IR": "rmt",
+ "rmu-Latn-SE": "rmu",
+ "rmw-Latn-GB": "rmw",
+ "rmx-Latn-VN": "rmx",
+ "rmz-Mymr-IN": "rmz",
+ "rn-Latn-BI": "rn",
+ "rna-Latn-ZZ": "rna",
+ "rnd-Latn-CD": "rnd",
+ "rng-Latn-MZ": "rng",
+ "rnl-Latn-IN": "rnl",
+ "rnn-Latn-ID": "rnn",
+ "rnr-Latn-AU": "rnr",
+ "rnw-Latn-TZ": "rnw",
+ "ro-Latn-MD": "ro-MD",
+ "ro-Latn-RO": "ro",
+ "rob-Latn-ID": "rob",
+ "roc-Latn-VN": "roc",
+ "rod-Latn-NG": "rod",
+ "roe-Latn-PG": "roe",
+ "rof-Latn-TZ": "rof",
+ "rog-Latn-VN": "rog",
+ "rol-Latn-PH": "rol",
+ "rom-Cyrl-RO": "rom-Cyrl",
+ "rom-Latn-RO": "rom",
+ "roo-Latn-ZZ": "roo",
+ "rop-Latn-AU": "rop",
+ "ror-Latn-ID": "ror",
+ "rou-Latn-TD": "rou",
+ "row-Latn-ID": "row",
+ "rpn-Latn-VU": "rpn",
+ "rpt-Latn-PG": "rpt",
+ "rri-Latn-SB": "rri",
+ "rro-Latn-ZZ": "rro",
+ "rrt-Latn-AU": "rrt",
+ "rsk-Cyrl-RS": "rsk",
+ "rtc-Latn-MM": "rtc",
+ "rth-Latn-ID": "rth",
+ "rtm-Latn-FJ": "rtm",
+ "rtw-Deva-IN": "rtw",
+ "ru-Cyrl-KZ": "ru-KZ",
+ "ru-Cyrl-RU": "ru",
+ "rub-Latn-UG": "rub",
+ "ruc-Latn-UG": "ruc",
+ "rue-Cyrl-UA": "rue",
+ "ruf-Latn-TZ": "ruf",
+ "rug-Latn-SB": "rug",
+ "rui-Latn-TZ": "rui",
+ "ruk-Latn-NG": "ruk",
+ "ruo-Latn-HR": "ruo",
+ "rup-Grek-GR": "rup-Grek",
+ "rup-Latn-RO": "rup",
+ "ruq-Latn-GR": "ruq",
+ "rut-Cyrl-RU": "rut",
+ "rut-Latn-AZ": "rut-Latn",
+ "ruu-Latn-MY": "ruu",
+ "ruy-Latn-NG": "ruy",
+ "ruz-Latn-NG": "ruz",
+ "rw-Latn-RW": "rw",
+ "rwa-Latn-PG": "rwa",
+ "rwk-Latn-TZ": "rwk",
+ "rwl-Latn-TZ": "rwl",
+ "rwm-Latn-UG": "rwm",
+ "rwo-Latn-ZZ": "rwo",
+ "rwr-Deva-IN": "rwr",
+ "rxd-Latn-AU": "rxd",
+ "rxw-Latn-AU": "rxw",
+ "ryu-Kana-JP": "ryu",
+ "sa-Bhks-IN": "sa-Bhks",
+ "sa-Deva-IN": "sa",
+ "sa-Gran-IN": "sa-Gran",
+ "sa-Nand-IN": "sa-Nand",
+ "sa-Shrd-IN": "sa-Shrd",
+ "sa-Sidd-IN": "sa-Sidd",
+ "saa-Latn-TD": "saa",
+ "sab-Latn-PA": "sab",
+ "sac-Latn-US": "sac",
+ "sad-Latn-TZ": "sad",
+ "sae-Latn-BR": "sae",
+ "saf-Latn-GH": "saf",
+ "sah-Cyrl-RU": "sah",
+ "saj-Latn-ID": "saj",
+ "sak-Latn-GA": "sak",
+ "sam-Hebr-PS": "sam-Hebr",
+ "sam-Samr-PS": "sam",
+ "sam-Syrc-PS": "sam-Syrc",
+ "sao-Latn-ID": "sao",
+ "saq-Latn-KE": "saq",
+ "sar-Latn-BO": "sar",
+ "sas-Latn-ID": "sas",
+ "sat-Olck-IN": "sat",
+ "sau-Latn-ID": "sau",
+ "sav-Latn-SN": "sav",
+ "saw-Latn-ID": "saw",
+ "sax-Latn-VU": "sax",
+ "say-Latn-NG": "say",
+ "saz-Saur-IN": "saz",
+ "sba-Latn-ZZ": "sba",
+ "sbb-Latn-SB": "sbb",
+ "sbc-Latn-PG": "sbc",
+ "sbd-Latn-BF": "sbd",
+ "sbe-Latn-ZZ": "sbe",
+ "sbg-Latn-ID": "sbg",
+ "sbh-Latn-PG": "sbh",
+ "sbi-Latn-PG": "sbi",
+ "sbj-Latn-TD": "sbj",
+ "sbk-Latn-TZ": "sbk",
+ "sbl-Latn-PH": "sbl",
+ "sbm-Latn-TZ": "sbm",
+ "sbn-Arab-PK": "sbn",
+ "sbo-Latn-MY": "sbo",
+ "sbp-Latn-TZ": "sbp",
+ "sbq-Latn-PG": "sbq",
+ "sbr-Latn-ID": "sbr",
+ "sbs-Latn-NA": "sbs",
+ "sbt-Latn-ID": "sbt",
+ "sbu-Deva-IN": "sbu-Deva",
+ "sbu-Tibt-IN": "sbu",
+ "sbv-Latn-IT": "sbv",
+ "sbw-Latn-GA": "sbw",
+ "sbx-Latn-ID": "sbx",
+ "sby-Latn-ZM": "sby",
+ "sbz-Latn-CF": "sbz",
+ "sc-Latn-IT": "sc",
+ "scb-Latn-VN": "scb",
+ "sce-Arab-CN": "sce-Arab",
+ "sce-Latn-CN": "sce",
+ "scf-Latn-PA": "scf",
+ "scg-Latn-ID": "scg",
+ "sch-Latn-IN": "sch",
+ "sci-Latn-LK": "sci",
+ "sck-Deva-IN": "sck",
+ "scl-Arab-ZZ": "scl",
+ "scn-Latn-IT": "scn",
+ "sco-Latn-GB": "sco",
+ "scp-Deva-NP": "scp",
+ "scs-Cans-CA": "scs-Cans",
+ "scs-Latn-CA": "scs",
+ "sct-Laoo-LA": "sct",
+ "scu-Takr-IN": "scu",
+ "scv-Latn-NG": "scv",
+ "scw-Latn-NG": "scw",
+ "scx-Grek-IT": "scx",
+ "sd-Arab-PK": "sd",
+ "sd-Deva-IN": "sd-IN",
+ "sd-Khoj-IN": "sd-Khoj",
+ "sd-Sind-IN": "sd-Sind",
+ "sda-Latn-ID": "sda",
+ "sdb-Arab-IQ": "sdb",
+ "sdc-Latn-IT": "sdc",
+ "sde-Latn-NG": "sde",
+ "sdf-Arab-IQ": "sdf",
+ "sdg-Arab-AF": "sdg",
+ "sdh-Arab-IR": "sdh",
+ "sdj-Latn-CG": "sdj",
+ "sdk-Latn-PG": "sdk",
+ "sdn-Latn-IT": "sdn",
+ "sdo-Latn-MY": "sdo",
+ "sdq-Latn-ID": "sdq",
+ "sds-Arab-TN": "sds",
+ "sdu-Latn-ID": "sdu",
+ "sdx-Latn-MY": "sdx",
+ "se-Latn-NO": "se",
+ "sea-Latn-MY": "sea",
+ "seb-Latn-CI": "seb",
+ "sec-Latn-CA": "sec",
+ "sed-Latn-VN": "sed",
+ "see-Latn-US": "see",
+ "sef-Latn-CI": "sef",
+ "seg-Latn-TZ": "seg",
+ "seh-Latn-MZ": "seh",
+ "sei-Latn-MX": "sei",
+ "sej-Latn-PG": "sej",
+ "sek-Cans-CA": "sek-Cans",
+ "sek-Latn-CA": "sek",
+ "sel-Cyrl-RU": "sel",
+ "sen-Latn-BF": "sen",
+ "seo-Latn-PG": "seo",
+ "sep-Latn-BF": "sep",
+ "seq-Latn-BF": "seq",
+ "ser-Latn-US": "ser",
+ "ses-Latn-ML": "ses",
+ "set-Latn-ID": "set",
+ "seu-Latn-ID": "seu",
+ "sev-Latn-CI": "sev",
+ "sew-Latn-PG": "sew",
+ "sey-Latn-EC": "sey",
+ "sez-Latn-MM": "sez",
+ "sfe-Latn-PH": "sfe",
+ "sfm-Plrd-CN": "sfm",
+ "sfw-Latn-GH": "sfw",
+ "sg-Latn-CF": "sg",
+ "sga-Ogam-IE": "sga",
+ "sgb-Latn-PH": "sgb",
+ "sgc-Latn-KE": "sgc",
+ "sgd-Latn-PH": "sgd",
+ "sge-Latn-ID": "sge",
+ "sgh-Arab-AF": "sgh-Arab",
+ "sgh-Cyrl-TJ": "sgh",
+ "sgh-Latn-TJ": "sgh-Latn",
+ "sgi-Latn-CM": "sgi",
+ "sgj-Deva-IN": "sgj",
+ "sgm-Latn-KE": "sgm",
+ "sgp-Latn-IN": "sgp",
+ "sgr-Arab-IR": "sgr",
+ "sgs-Latn-LT": "sgs",
+ "sgt-Tibt-BT": "sgt",
+ "sgu-Latn-ID": "sgu",
+ "sgw-Ethi-ZZ": "sgw",
+ "sgy-Arab-AF": "sgy",
+ "sgz-Latn-ZZ": "sgz",
+ "sha-Latn-NG": "sha",
+ "shb-Latn-BR": "shb",
+ "shc-Latn-CD": "shc",
+ "shd-Arab-PK": "shd",
+ "she-Latn-ET": "she",
+ "shg-Latn-BW": "shg",
+ "shh-Latn-US": "shh",
+ "shi-Tfng-MA": "shi",
+ "shj-Latn-SD": "shj",
+ "shk-Latn-ZZ": "shk",
+ "shm-Arab-IR": "shm",
+ "shn-Mymr-MM": "shn",
+ "sho-Latn-NG": "sho",
+ "shp-Latn-PE": "shp",
+ "shq-Latn-ZM": "shq",
+ "shr-Latn-CD": "shr",
+ "shs-Latn-CA": "shs",
+ "sht-Latn-US": "sht",
+ "shu-Arab-ZZ": "shu",
+ "shv-Arab-OM": "shv",
+ "shw-Latn-SD": "shw",
+ "shy-Arab-DZ": "shy-Arab",
+ "shy-Latn-DZ": "shy",
+ "shy-Tfng-DZ": "shy-Tfng",
+ "shz-Latn-ML": "shz",
+ "si-Sinh-LK": "si",
+ "sia-Cyrl-RU": "sia",
+ "sib-Latn-MY": "sib",
+ "sid-Latn-ET": "sid",
+ "sie-Latn-ZM": "sie",
+ "sif-Latn-BF": "sif",
+ "sig-Latn-ZZ": "sig",
+ "sih-Latn-NC": "sih",
+ "sii-Latn-IN": "sii",
+ "sij-Latn-PG": "sij",
+ "sik-Latn-BR": "sik",
+ "sil-Latn-ZZ": "sil",
+ "sim-Latn-ZZ": "sim",
+ "sip-Tibt-IN": "sip",
+ "siq-Latn-PG": "siq",
+ "sir-Latn-NG": "sir",
+ "sis-Latn-US": "sis",
+ "siu-Latn-PG": "siu",
+ "siv-Latn-PG": "siv",
+ "siw-Latn-PG": "siw",
+ "six-Latn-PG": "six",
+ "siy-Arab-IR": "siy",
+ "siz-Arab-EG": "siz",
+ "sja-Latn-CO": "sja",
+ "sjb-Latn-ID": "sjb",
+ "sjd-Cyrl-RU": "sjd",
+ "sje-Latn-SE": "sje",
+ "sjg-Latn-TD": "sjg",
+ "sjl-Latn-IN": "sjl",
+ "sjm-Latn-PH": "sjm",
+ "sjp-Beng-IN": "sjp-Beng",
+ "sjp-Deva-IN": "sjp",
+ "sjr-Latn-ZZ": "sjr",
+ "sjt-Cyrl-RU": "sjt",
+ "sju-Latn-SE": "sju",
+ "sjw-Latn-US": "sjw",
+ "sk-Latn-SK": "sk",
+ "ska-Latn-US": "ska",
+ "skb-Thai-TH": "skb",
+ "skc-Latn-ZZ": "skc",
+ "skd-Latn-US": "skd",
+ "ske-Latn-VU": "ske",
+ "skf-Latn-BR": "skf",
+ "skg-Latn-MG": "skg",
+ "skh-Latn-ID": "skh",
+ "ski-Latn-ID": "ski",
+ "skj-Deva-NP": "skj",
+ "skm-Latn-PG": "skm",
+ "skn-Latn-PH": "skn",
+ "sko-Latn-ID": "sko",
+ "skp-Latn-MY": "skp",
+ "skq-Latn-BF": "skq",
+ "skr-Arab-PK": "skr",
+ "skr-Mult-PK": "skr-Mult",
+ "sks-Latn-ZZ": "sks",
+ "skt-Latn-CD": "skt",
+ "sku-Latn-VU": "sku",
+ "skv-Latn-ID": "skv",
+ "skw-Latn-GY": "skw",
+ "skx-Latn-ID": "skx",
+ "sky-Latn-SB": "sky",
+ "skz-Latn-ID": "skz",
+ "sl-Latn-SI": "sl",
+ "slc-Latn-CO": "slc",
+ "sld-Latn-ZZ": "sld",
+ "slg-Latn-ID": "slg",
+ "slh-Latn-US": "slh",
+ "sli-Latn-PL": "sli",
+ "slj-Latn-BR": "slj",
+ "sll-Latn-ZZ": "sll",
+ "slm-Latn-PH": "slm",
+ "sln-Latn-US": "sln",
+ "slp-Latn-ID": "slp",
+ "slq-Arab-IR": "slq",
+ "slr-Latn-CN": "slr",
+ "slu-Latn-ID": "slu",
+ "slw-Latn-PG": "slw",
+ "slx-Latn-CD": "slx",
+ "sly-Latn-ID": "sly",
+ "slz-Latn-ID": "slz",
+ "sm-Latn-AS": "sm-AS",
+ "sm-Latn-WS": "sm",
+ "sma-Latn-SE": "sma",
+ "smb-Latn-PG": "smb",
+ "smc-Latn-PG": "smc",
+ "smf-Latn-PG": "smf",
+ "smg-Latn-PG": "smg",
+ "smh-Yiii-CN": "smh",
+ "smj-Latn-SE": "smj",
+ "smk-Latn-PH": "smk",
+ "sml-Latn-PH": "sml",
+ "smn-Latn-FI": "smn",
+ "smp-Samr-IL": "smp",
+ "smq-Latn-ZZ": "smq",
+ "smr-Latn-ID": "smr",
+ "sms-Latn-FI": "sms",
+ "smt-Latn-IN": "smt",
+ "smu-Khmr-KH": "smu",
+ "smw-Latn-ID": "smw",
+ "smx-Latn-CD": "smx",
+ "smy-Arab-IR": "smy",
+ "smz-Latn-PG": "smz",
+ "sn-Latn-ZW": "sn",
+ "snc-Latn-ZZ": "snc",
+ "sne-Latn-MY": "sne",
+ "snf-Latn-SN": "snf",
+ "sng-Brai-CD": "sng-Brai",
+ "sng-Latn-CD": "sng",
+ "sni-Latn-PE": "sni",
+ "snj-Latn-CF": "snj",
+ "snk-Latn-ML": "snk",
+ "snl-Latn-PH": "snl",
+ "snm-Latn-UG": "snm",
+ "snn-Latn-CO": "snn",
+ "sno-Latn-US": "sno",
+ "snp-Latn-ZZ": "snp",
+ "snq-Latn-GA": "snq",
+ "snr-Latn-PG": "snr",
+ "sns-Latn-VU": "sns",
+ "snu-Latn-ID": "snu",
+ "snv-Latn-MY": "snv",
+ "snw-Latn-GH": "snw",
+ "snx-Latn-ZZ": "snx",
+ "sny-Latn-ZZ": "sny",
+ "snz-Latn-PG": "snz",
+ "so-Latn-SO": "so",
+ "so-Osma-SO": "so-Osma",
+ "soa-Tavt-TH": "soa",
+ "soa-Thai-TH": "soa-Thai",
+ "sob-Latn-ID": "sob",
+ "soc-Latn-CD": "soc",
+ "sod-Latn-CD": "sod",
+ "soe-Latn-CD": "soe",
+ "sog-Sogd-UZ": "sog",
+ "sog-Sogo-UZ": "sog-Sogo",
+ "soi-Deva-NP": "soi",
+ "sok-Latn-ZZ": "sok",
+ "sol-Latn-PG": "sol",
+ "soo-Latn-CD": "soo",
+ "sop-Latn-CD": "sop",
+ "soq-Latn-ZZ": "soq",
+ "sor-Latn-TD": "sor",
+ "sos-Latn-BF": "sos",
+ "sou-Thai-TH": "sou",
+ "sov-Latn-PW": "sov",
+ "sow-Latn-PG": "sow",
+ "sox-Latn-CM": "sox",
+ "soy-Latn-ZZ": "soy",
+ "soz-Latn-TZ": "soz",
+ "spb-Latn-ID": "spb",
+ "spc-Latn-VE": "spc",
+ "spd-Latn-ZZ": "spd",
+ "spe-Latn-PG": "spe",
+ "spg-Latn-MY": "spg",
+ "spi-Latn-ID": "spi",
+ "spk-Latn-PG": "spk",
+ "spl-Latn-ZZ": "spl",
+ "spm-Latn-PG": "spm",
+ "spn-Latn-PY": "spn",
+ "spo-Latn-US": "spo",
+ "spp-Latn-ML": "spp",
+ "spq-Latn-PE": "spq",
+ "spr-Latn-ID": "spr",
+ "sps-Latn-ZZ": "sps",
+ "spt-Tibt-IN": "spt",
+ "spv-Orya-IN": "spv",
+ "sq-Elba-AL": "sq-Elba",
+ "sq-Latn-AL": "sq",
+ "sq-Latn-MK": "sq-MK",
+ "sq-Latn-XK": "sq-XK",
+ "sq-Vith-AL": "sq-Vith",
+ "sqa-Latn-NG": "sqa",
+ "sqh-Latn-NG": "sqh",
+ "sqm-Latn-CF": "sqm",
+ "sqo-Arab-IR": "sqo",
+ "sqq-Laoo-LA": "sqq",
+ "sqt-Arab-YE": "sqt",
+ "sqt-Latn-YE": "sqt-Latn",
+ "squ-Latn-CA": "squ",
+ "sr-Cyrl-BA": "sr-BA",
+ "sr-Cyrl-RS": "sr",
+ "sr-Cyrl-XK": "sr-XK",
+ "sr-Latn-ME": "sr-ME",
+ "sr-Latn-RO": "sr-RO",
+ "sr-Latn-RU": "sr-RU",
+ "sr-Latn-TR": "sr-TR",
+ "sra-Latn-PG": "sra",
+ "srb-Sora-IN": "srb",
+ "sre-Latn-ID": "sre",
+ "srf-Latn-PG": "srf",
+ "srg-Latn-PH": "srg",
+ "srh-Arab-CN": "srh",
+ "sri-Latn-CO": "sri",
+ "srk-Latn-MY": "srk",
+ "srl-Latn-ID": "srl",
+ "srm-Latn-SR": "srm",
+ "srn-Latn-SR": "srn",
+ "sro-Latn-IT": "sro",
+ "srq-Latn-BO": "srq",
+ "srr-Latn-SN": "srr",
+ "srs-Latn-CA": "srs",
+ "srt-Latn-ID": "srt",
+ "sru-Latn-BR": "sru",
+ "srv-Latn-PH": "srv",
+ "srw-Latn-ID": "srw",
+ "srx-Deva-IN": "srx",
+ "sry-Latn-PG": "sry",
+ "srz-Arab-IR": "srz",
+ "ss-Latn-ZA": "ss",
+ "ssb-Latn-PH": "ssb",
+ "ssc-Latn-TZ": "ssc",
+ "ssd-Latn-ZZ": "ssd",
+ "sse-Arab-PH": "sse-Arab",
+ "sse-Latn-PH": "sse",
+ "ssf-Latn-TW": "ssf",
+ "ssg-Latn-ZZ": "ssg",
+ "ssh-Arab-AE": "ssh",
+ "ssj-Latn-PG": "ssj",
+ "ssl-Latn-GH": "ssl",
+ "ssm-Latn-MY": "ssm",
+ "ssn-Latn-KE": "ssn",
+ "sso-Latn-PG": "sso",
+ "ssq-Latn-ID": "ssq",
+ "sss-Laoo-LA": "sss",
+ "sss-Thai-TH": "sss-Thai",
+ "sst-Latn-PG": "sst",
+ "ssu-Latn-PG": "ssu",
+ "ssv-Latn-VU": "ssv",
+ "ssx-Latn-PG": "ssx",
+ "ssy-Latn-ER": "ssy",
+ "ssz-Latn-PG": "ssz",
+ "st-Latn-LS": "st-LS",
+ "st-Latn-ZA": "st",
+ "sta-Latn-ZM": "sta",
+ "stb-Latn-PH": "stb",
+ "ste-Latn-ID": "ste",
+ "stf-Latn-PG": "stf",
+ "stg-Latn-VN": "stg",
+ "sth-Latn-IE": "sth",
+ "sti-Latn-KH": "sti-KH",
+ "sti-Latn-VN": "sti",
+ "stj-Latn-BF": "stj",
+ "stk-Latn-ZZ": "stk",
+ "stl-Latn-NL": "stl",
+ "stm-Latn-PG": "stm",
+ "stn-Latn-SB": "stn",
+ "sto-Latn-CA": "sto",
+ "stp-Latn-MX": "stp",
+ "stq-Latn-DE": "stq",
+ "str-Latn-CA": "str",
+ "sts-Arab-AF": "sts",
+ "stt-Latn-VN": "stt",
+ "stv-Arab-ET": "stv-Arab",
+ "stv-Ethi-ET": "stv",
+ "stw-Latn-FM": "stw",
+ "sty-Cyrl-RU": "sty",
+ "su-Latn-ID": "su",
+ "su-Sund-ID": "su-Sund",
+ "sua-Latn-ZZ": "sua",
+ "sub-Latn-CD": "sub",
+ "suc-Latn-PH": "suc",
+ "sue-Latn-ZZ": "sue",
+ "sug-Latn-PG": "sug",
+ "sui-Latn-PG": "sui",
+ "suj-Latn-TZ": "suj",
+ "suk-Latn-TZ": "suk",
+ "suo-Latn-PG": "suo",
+ "suq-Ethi-ET": "suq-Ethi",
+ "suq-Latn-ET": "suq",
+ "sur-Latn-ZZ": "sur",
+ "sus-Latn-GN": "sus",
+ "sut-Latn-NI": "sut",
+ "suv-Beng-IN": "suv-Beng",
+ "suv-Deva-IN": "suv-Deva",
+ "suv-Latn-IN": "suv",
+ "suw-Latn-TZ": "suw",
+ "suy-Latn-BR": "suy",
+ "suz-Deva-NP": "suz",
+ "sv-Latn-AX": "sv-AX",
+ "sv-Latn-SE": "sv",
+ "sva-Cyrl-GE": "sva-Cyrl",
+ "sva-Geor-GE": "sva",
+ "sva-Latn-GE": "sva-Latn",
+ "svb-Latn-PG": "svb",
+ "svc-Latn-VC": "svc",
+ "sve-Latn-ID": "sve",
+ "svm-Latn-IT": "svm",
+ "svs-Latn-SB": "svs",
+ "sw-Latn-CD": "sw-CD",
+ "sw-Latn-KE": "sw-KE",
+ "sw-Latn-TZ": "sw",
+ "sw-Latn-UG": "sw-UG",
+ "swb-Arab-YT": "swb",
+ "swf-Latn-CD": "swf",
+ "swg-Latn-DE": "swg",
+ "swi-Hani-CN": "swi",
+ "swj-Latn-GA": "swj",
+ "swk-Latn-MW": "swk",
+ "swm-Latn-PG": "swm",
+ "swo-Latn-BR": "swo",
+ "swp-Latn-ZZ": "swp",
+ "swq-Latn-CM": "swq",
+ "swr-Latn-ID": "swr",
+ "sws-Latn-ID": "sws",
+ "swt-Latn-ID": "swt",
+ "swu-Latn-ID": "swu",
+ "swv-Deva-IN": "swv",
+ "sww-Latn-VU": "sww",
+ "swx-Latn-BR": "swx",
+ "swy-Latn-TD": "swy",
+ "sxb-Latn-KE": "sxb",
+ "sxe-Latn-GA": "sxe",
+ "sxn-Latn-ID": "sxn",
+ "sxr-Latn-TW": "sxr",
+ "sxs-Latn-NG": "sxs",
+ "sxu-Latn-DE": "sxu",
+ "sxu-Runr-DE": "sxu-Runr",
+ "sxw-Latn-ZZ": "sxw",
+ "sya-Latn-ID": "sya",
+ "syb-Latn-PH": "syb",
+ "syc-Syrc-TR": "syc",
+ "syi-Latn-GA": "syi",
+ "syk-Latn-NG": "syk",
+ "syl-Beng-BD": "syl",
+ "syl-Sylo-BD": "syl-Sylo",
+ "sym-Latn-BF": "sym",
+ "syn-Syrc-IR": "syn",
+ "syo-Latn-KH": "syo",
+ "syr-Syrc-IQ": "syr",
+ "sys-Latn-TD": "sys",
+ "syw-Deva-NP": "syw",
+ "syx-Latn-GA": "syx",
+ "sza-Latn-MY": "sza",
+ "szb-Latn-ID": "szb",
+ "szc-Latn-MY": "szc",
+ "szd-Latn-MY": "szd",
+ "szg-Latn-CD": "szg",
+ "szl-Latn-PL": "szl",
+ "szn-Latn-ID": "szn",
+ "szp-Latn-ID": "szp",
+ "szv-Latn-CM": "szv",
+ "szw-Latn-ID": "szw",
+ "szy-Latn-TW": "szy",
+ "ta-Taml-IN": "ta",
+ "taa-Latn-US": "taa",
+ "tab-Cyrl-RU": "tab",
+ "tac-Latn-MX": "tac",
+ "tad-Latn-ID": "tad",
+ "tae-Latn-BR": "tae",
+ "taf-Latn-BR": "taf",
+ "tag-Latn-SD": "tag",
+ "taj-Deva-NP": "taj",
+ "tak-Latn-NG": "tak",
+ "tal-Latn-ZZ": "tal",
+ "tan-Latn-ZZ": "tan",
+ "tao-Latn-TW": "tao",
+ "tap-Latn-CD": "tap",
+ "taq-Latn-ZZ": "taq",
+ "tar-Latn-MX": "tar",
+ "tas-Latn-VN": "tas",
+ "tau-Latn-US": "tau",
+ "tav-Latn-CO": "tav",
+ "taw-Latn-PG": "taw",
+ "tax-Latn-TD": "tax",
+ "tay-Hans-TW": "tay-Hans",
+ "tay-Hant-TW": "tay-Hant",
+ "tay-Latn-TW": "tay",
+ "taz-Latn-SD": "taz",
+ "tba-Latn-BR": "tba",
+ "tbc-Latn-ZZ": "tbc",
+ "tbd-Latn-ZZ": "tbd",
+ "tbe-Latn-SB": "tbe",
+ "tbf-Latn-ZZ": "tbf",
+ "tbg-Latn-ZZ": "tbg",
+ "tbh-Latn-AU": "tbh",
+ "tbi-Latn-SD": "tbi",
+ "tbj-Latn-PG": "tbj",
+ "tbk-Hano-PH": "tbk-Hano",
+ "tbk-Latn-PH": "tbk-Latn",
+ "tbk-Tagb-PH": "tbk",
+ "tbl-Latn-PH": "tbl",
+ "tbm-Latn-CD": "tbm",
+ "tbn-Latn-CO": "tbn",
+ "tbo-Latn-ZZ": "tbo",
+ "tbp-Latn-ID": "tbp",
+ "tbs-Latn-PG": "tbs",
+ "tbt-Latn-CD": "tbt",
+ "tbu-Latn-MX": "tbu",
+ "tbv-Latn-PG": "tbv",
+ "tbw-Latn-PH": "tbw",
+ "tbw-Tagb-PH": "tbw-Tagb",
+ "tbx-Latn-PG": "tbx",
+ "tby-Latn-ID": "tby",
+ "tbz-Latn-ZZ": "tbz",
+ "tca-Latn-BR": "tca",
+ "tcb-Latn-US": "tcb",
+ "tcc-Latn-TZ": "tcc",
+ "tcd-Latn-GH": "tcd",
+ "tce-Latn-CA": "tce",
+ "tcf-Latn-MX": "tcf",
+ "tcg-Latn-ID": "tcg",
+ "tch-Latn-TC": "tch",
+ "tci-Latn-ZZ": "tci",
+ "tck-Latn-GA": "tck",
+ "tcm-Latn-ID": "tcm",
+ "tcn-Tibt-NP": "tcn",
+ "tco-Mymr-MM": "tco",
+ "tcp-Latn-MM": "tcp",
+ "tcq-Latn-ID": "tcq",
+ "tcs-Latn-AU": "tcs",
+ "tcu-Latn-MX": "tcu",
+ "tcw-Latn-MX": "tcw",
+ "tcx-Taml-IN": "tcx",
+ "tcy-Knda-IN": "tcy",
+ "tcz-Latn-IN": "tcz",
+ "tda-Arab-NE": "tda-Arab",
+ "tda-Latn-NE": "tda-Latn",
+ "tda-Tfng-NE": "tda",
+ "tdb-Beng-IN": "tdb-Beng",
+ "tdb-Deva-IN": "tdb",
+ "tdb-Kthi-IN": "tdb-Kthi",
+ "tdc-Latn-CO": "tdc",
+ "tdd-Tale-CN": "tdd",
+ "tde-Latn-ML": "tde",
+ "tdg-Deva-NP": "tdg",
+ "tdh-Deva-NP": "tdh",
+ "tdi-Latn-ID": "tdi",
+ "tdj-Latn-ID": "tdj",
+ "tdk-Latn-NG": "tdk",
+ "tdl-Latn-NG": "tdl",
+ "tdm-Latn-GY": "tdm",
+ "tdn-Latn-ID": "tdn",
+ "tdo-Latn-NG": "tdo",
+ "tdq-Latn-NG": "tdq",
+ "tdr-Latn-VN": "tdr",
+ "tds-Latn-ID": "tds",
+ "tdt-Latn-TL": "tdt",
+ "tdv-Latn-NG": "tdv",
+ "tdx-Latn-MG": "tdx",
+ "tdy-Latn-PH": "tdy",
+ "te-Telu-IN": "te",
+ "tea-Latn-MY": "tea",
+ "teb-Latn-EC": "teb",
+ "tec-Latn-KE": "tec",
+ "ted-Latn-ZZ": "ted",
+ "tee-Latn-MX": "tee",
+ "teg-Latn-GA": "teg",
+ "teh-Latn-AR": "teh",
+ "tei-Latn-PG": "tei",
+ "tek-Latn-CD": "tek",
+ "tem-Latn-SL": "tem",
+ "ten-Latn-CO": "ten",
+ "teo-Latn-UG": "teo",
+ "tep-Latn-MX": "tep",
+ "teq-Latn-SD": "teq",
+ "ter-Latn-BR": "ter",
+ "tes-Java-ID": "tes",
+ "tet-Latn-TL": "tet",
+ "teu-Latn-UG": "teu",
+ "tev-Latn-ID": "tev",
+ "tew-Latn-US": "tew",
+ "tex-Latn-SS": "tex",
+ "tey-Latn-SD": "tey",
+ "tfi-Latn-ZZ": "tfi",
+ "tfn-Latn-US": "tfn",
+ "tfo-Latn-ID": "tfo",
+ "tfr-Latn-PA": "tfr",
+ "tft-Latn-ID": "tft",
+ "tg-Arab-PK": "tg-PK",
+ "tg-Cyrl-TJ": "tg",
+ "tga-Latn-KE": "tga",
+ "tgb-Latn-MY": "tgb",
+ "tgc-Latn-ZZ": "tgc",
+ "tgd-Latn-NG": "tgd",
+ "tge-Deva-NP": "tge",
+ "tgf-Tibt-BT": "tgf",
+ "tgh-Latn-TT": "tgh",
+ "tgi-Latn-PG": "tgi",
+ "tgj-Latn-IN": "tgj",
+ "tgn-Latn-PH": "tgn",
+ "tgo-Latn-ZZ": "tgo",
+ "tgp-Latn-VU": "tgp",
+ "tgq-Latn-MY": "tgq",
+ "tgs-Latn-VU": "tgs",
+ "tgt-Hano-PH": "tgt-Hano",
+ "tgt-Latn-PH": "tgt",
+ "tgt-Tagb-PH": "tgt-Tagb",
+ "tgu-Latn-ZZ": "tgu",
+ "tgv-Latn-BR": "tgv",
+ "tgw-Latn-CI": "tgw",
+ "tgx-Latn-CA": "tgx",
+ "tgy-Latn-SS": "tgy",
+ "tgz-Latn-AU": "tgz",
+ "th-Thai-TH": "th",
+ "thd-Latn-AU": "thd",
+ "the-Deva-NP": "the",
+ "thf-Deva-NP": "thf",
+ "thh-Latn-MX": "thh",
+ "thi-Tale-LA": "thi",
+ "thk-Latn-KE": "thk",
+ "thl-Deva-NP": "thl",
+ "thm-Thai-TH": "thm",
+ "thp-Dupl-CA": "thp-Dupl",
+ "thp-Latn-CA": "thp",
+ "thq-Deva-NP": "thq",
+ "thr-Deva-NP": "thr",
+ "ths-Deva-NP": "ths",
+ "tht-Latn-CA": "tht",
+ "thu-Latn-SS": "thu",
+ "thv-Arab-DZ": "thv-Arab",
+ "thv-Latn-DZ": "thv",
+ "thv-Tfng-DZ": "thv-Tfng",
+ "thy-Latn-NG": "thy",
+ "thz-Latn-NE": "thz",
+ "thz-Tfng-NE": "thz-Tfng",
+ "ti-Ethi-ER": "ti-ER",
+ "ti-Ethi-ET": "ti",
+ "tic-Latn-SD": "tic",
+ "tif-Latn-ZZ": "tif",
+ "tig-Ethi-ER": "tig",
+ "tih-Latn-MY": "tih",
+ "tii-Latn-CD": "tii",
+ "tij-Deva-NP": "tij",
+ "tik-Latn-ZZ": "tik",
+ "til-Latn-US": "til",
+ "tim-Latn-ZZ": "tim",
+ "tin-Cyrl-RU": "tin",
+ "tio-Latn-ZZ": "tio",
+ "tip-Latn-ID": "tip",
+ "tiq-Latn-BF": "tiq",
+ "tis-Latn-PH": "tis",
+ "tit-Latn-CO": "tit",
+ "tiu-Latn-PH": "tiu",
+ "tiv-Latn-NG": "tiv",
+ "tiw-Latn-AU": "tiw",
+ "tix-Latn-US": "tix",
+ "tiy-Latn-PH": "tiy",
+ "tja-Latn-LR": "tja",
+ "tjg-Latn-ID": "tjg",
+ "tji-Latn-CN": "tji",
+ "tjj-Latn-AU": "tjj",
+ "tjl-Mymr-MM": "tjl",
+ "tjn-Latn-CI": "tjn",
+ "tjo-Arab-DZ": "tjo",
+ "tjp-Latn-AU": "tjp",
+ "tjs-Latn-CN": "tjs",
+ "tju-Latn-AU": "tju",
+ "tjw-Latn-AU": "tjw",
+ "tk-Latn-AF": "tk-AF",
+ "tk-Latn-IR": "tk-IR",
+ "tk-Latn-TM": "tk",
+ "tka-Latn-BR": "tka",
+ "tkb-Deva-IN": "tkb",
+ "tkd-Latn-TL": "tkd",
+ "tke-Latn-MZ": "tke",
+ "tkf-Latn-BR": "tkf",
+ "tkg-Latn-MG": "tkg",
+ "tkl-Latn-TK": "tkl",
+ "tkp-Latn-SB": "tkp",
+ "tkq-Latn-NG": "tkq",
+ "tkr-Latn-AZ": "tkr",
+ "tks-Arab-IR": "tks",
+ "tkt-Deva-NP": "tkt",
+ "tku-Latn-MX": "tku",
+ "tkv-Latn-PG": "tkv",
+ "tkw-Latn-SB": "tkw",
+ "tkx-Latn-ID": "tkx",
+ "tkz-Latn-VN": "tkz",
+ "tla-Latn-MX": "tla",
+ "tlb-Latn-ID": "tlb",
+ "tlc-Latn-MX": "tlc",
+ "tld-Latn-ID": "tld",
+ "tlf-Latn-ZZ": "tlf",
+ "tlg-Latn-ID": "tlg",
+ "tli-Cyrl-US": "tli-Cyrl",
+ "tli-Latn-US": "tli",
+ "tlj-Latn-UG": "tlj",
+ "tlk-Latn-ID": "tlk",
+ "tll-Latn-CD": "tll",
+ "tlm-Latn-VU": "tlm",
+ "tln-Latn-ID": "tln",
+ "tlp-Latn-MX": "tlp",
+ "tlq-Latn-MM": "tlq",
+ "tlr-Latn-SB": "tlr",
+ "tls-Latn-VU": "tls",
+ "tlt-Latn-ID": "tlt",
+ "tlu-Latn-ID": "tlu",
+ "tlv-Latn-ID": "tlv",
+ "tlx-Latn-ZZ": "tlx",
+ "tly-Latn-AZ": "tly",
+ "tma-Latn-TD": "tma",
+ "tmb-Latn-VU": "tmb",
+ "tmc-Latn-TD": "tmc",
+ "tmd-Latn-PG": "tmd",
+ "tme-Latn-BR": "tme",
+ "tmf-Latn-PY": "tmf",
+ "tmg-Latn-ID": "tmg",
+ "tmh-Latn-NE": "tmh",
+ "tmi-Latn-VU": "tmi",
+ "tmj-Latn-ID": "tmj",
+ "tmk-Deva-NP": "tmk",
+ "tml-Latn-ID": "tml",
+ "tmm-Latn-VN": "tmm",
+ "tmn-Latn-ID": "tmn",
+ "tmo-Latn-MY": "tmo",
+ "tmq-Latn-PG": "tmq",
+ "tmr-Syrc-IL": "tmr",
+ "tmt-Latn-VU": "tmt",
+ "tmu-Latn-ID": "tmu",
+ "tmv-Latn-CD": "tmv",
+ "tmw-Latn-MY": "tmw",
+ "tmy-Latn-ZZ": "tmy",
+ "tmz-Latn-VE": "tmz",
+ "tn-Latn-ZA": "tn",
+ "tna-Latn-BO": "tna",
+ "tnb-Latn-CO": "tnb",
+ "tnc-Latn-CO": "tnc",
+ "tnd-Latn-CO": "tnd",
+ "tng-Latn-TD": "tng",
+ "tnh-Latn-ZZ": "tnh",
+ "tni-Latn-ID": "tni",
+ "tnk-Latn-VU": "tnk",
+ "tnl-Latn-VU": "tnl",
+ "tnm-Latn-ID": "tnm",
+ "tnn-Latn-VU": "tnn",
+ "tno-Latn-BO": "tno",
+ "tnp-Latn-VU": "tnp",
+ "tnq-Latn-PR": "tnq",
+ "tnr-Latn-SN": "tnr",
+ "tns-Latn-PG": "tns",
+ "tnt-Latn-ID": "tnt",
+ "tnv-Cakm-BD": "tnv",
+ "tnw-Latn-ID": "tnw",
+ "tnx-Latn-SB": "tnx",
+ "tny-Latn-TZ": "tny",
+ "to-Latn-TO": "to",
+ "tob-Latn-AR": "tob",
+ "toc-Latn-MX": "toc",
+ "tod-Latn-GN": "tod",
+ "tof-Latn-ZZ": "tof",
+ "tog-Latn-MW": "tog",
+ "toh-Latn-MZ": "toh",
+ "toi-Latn-ZM": "toi",
+ "toj-Latn-MX": "toj",
+ "tok-Latn-001": "tok",
+ "tol-Latn-US": "tol",
+ "tom-Latn-ID": "tom",
+ "too-Latn-MX": "too",
+ "top-Latn-MX": "top",
+ "toq-Latn-ZZ": "toq",
+ "tor-Latn-CD": "tor",
+ "tos-Latn-MX": "tos",
+ "tou-Latn-VN": "tou",
+ "tov-Arab-IR": "tov",
+ "tow-Latn-US": "tow",
+ "tox-Latn-PW": "tox",
+ "toy-Latn-ID": "toy",
+ "toz-Latn-CM": "toz",
+ "tpa-Latn-PG": "tpa",
+ "tpc-Latn-MX": "tpc",
+ "tpe-Beng-BD": "tpe-Beng",
+ "tpe-Latn-BD": "tpe",
+ "tpf-Latn-ID": "tpf",
+ "tpg-Latn-ID": "tpg",
+ "tpi-Latn-PG": "tpi",
+ "tpj-Latn-PY": "tpj",
+ "tpk-Latn-BR": "tpk",
+ "tpl-Latn-MX": "tpl",
+ "tpm-Latn-ZZ": "tpm",
+ "tpn-Latn-BR": "tpn",
+ "tpp-Latn-MX": "tpp",
+ "tpr-Latn-BR": "tpr",
+ "tpt-Latn-MX": "tpt",
+ "tpu-Khmr-KH": "tpu",
+ "tpv-Latn-MP": "tpv",
+ "tpx-Latn-MX": "tpx",
+ "tpy-Latn-BR": "tpy",
+ "tpz-Latn-ZZ": "tpz",
+ "tqb-Latn-BR": "tqb",
+ "tql-Latn-VU": "tql",
+ "tqm-Latn-PG": "tqm",
+ "tqn-Latn-US": "tqn",
+ "tqo-Latn-ZZ": "tqo",
+ "tqp-Latn-PG": "tqp",
+ "tqt-Latn-MX": "tqt",
+ "tqu-Latn-SB": "tqu",
+ "tqw-Latn-US": "tqw",
+ "tr-Latn-CY": "tr-CY",
+ "tr-Latn-TR": "tr",
+ "tra-Arab-AF": "tra",
+ "trb-Latn-PG": "trb",
+ "trc-Latn-MX": "trc",
+ "tre-Latn-ID": "tre",
+ "trf-Latn-TT": "trf",
+ "trg-Hebr-IL": "trg",
+ "trh-Latn-PG": "trh",
+ "tri-Latn-SR": "tri",
+ "trj-Latn-TD": "trj",
+ "trl-Latn-GB": "trl",
+ "trm-Arab-AF": "trm",
+ "trn-Latn-BO": "trn",
+ "tro-Latn-IN": "tro",
+ "trp-Beng-IN": "trp-Beng",
+ "trp-Latn-IN": "trp",
+ "trq-Latn-MX": "trq",
+ "trr-Latn-PE": "trr",
+ "trs-Latn-MX": "trs",
+ "trt-Latn-ID": "trt",
+ "tru-Latn-TR": "tru",
+ "trv-Latn-TW": "trv",
+ "trw-Arab-PK": "trw",
+ "trx-Latn-MY": "trx",
+ "try-Latn-IN": "try",
+ "trz-Latn-BR": "trz",
+ "ts-Latn-ZA": "ts",
+ "tsa-Latn-CG": "tsa",
+ "tsb-Latn-ET": "tsb",
+ "tsc-Latn-MZ": "tsc",
+ "tsd-Grek-GR": "tsd",
+ "tsg-Latn-PH": "tsg",
+ "tsh-Latn-CM": "tsh",
+ "tsi-Latn-CA": "tsi",
+ "tsj-Tibt-BT": "tsj",
+ "tsl-Latn-VN": "tsl",
+ "tsp-Latn-BF": "tsp",
+ "tsr-Latn-VU": "tsr",
+ "tst-Latn-ML": "tst",
+ "tsu-Latn-TW": "tsu",
+ "tsv-Latn-GA": "tsv",
+ "tsw-Latn-ZZ": "tsw",
+ "tsx-Latn-PG": "tsx",
+ "tsz-Latn-MX": "tsz",
+ "tt-Cyrl-RU": "tt",
+ "ttb-Latn-NG": "ttb",
+ "ttc-Latn-GT": "ttc",
+ "ttd-Latn-ZZ": "ttd",
+ "tte-Latn-ZZ": "tte",
+ "ttf-Latn-CM": "ttf",
+ "tth-Laoo-LA": "tth",
+ "tti-Latn-ID": "tti",
+ "ttj-Latn-UG": "ttj",
+ "ttk-Latn-CO": "ttk",
+ "ttl-Latn-ZM": "ttl",
+ "ttm-Latn-CA": "ttm",
+ "ttn-Latn-ID": "ttn",
+ "tto-Laoo-LA": "tto",
+ "ttp-Latn-ID": "ttp",
+ "ttr-Latn-ZZ": "ttr",
+ "tts-Thai-TH": "tts",
+ "ttt-Latn-AZ": "ttt",
+ "ttu-Latn-PG": "ttu",
+ "ttv-Latn-PG": "ttv",
+ "ttw-Latn-MY": "ttw",
+ "tty-Latn-ID": "tty",
+ "tua-Latn-PG": "tua",
+ "tub-Latn-US": "tub",
+ "tuc-Latn-PG": "tuc",
+ "tud-Latn-BR": "tud",
+ "tue-Latn-CO": "tue",
+ "tuf-Latn-CO": "tuf",
+ "tug-Latn-TD": "tug",
+ "tuh-Latn-ZZ": "tuh",
+ "tui-Latn-CM": "tui",
+ "tuj-Latn-ID": "tuj",
+ "tul-Latn-ZZ": "tul",
+ "tum-Latn-MW": "tum",
+ "tun-Latn-US": "tun",
+ "tuo-Latn-BR": "tuo",
+ "tuq-Latn-ZZ": "tuq",
+ "tus-Latn-CA": "tus",
+ "tuu-Latn-US": "tuu",
+ "tuv-Latn-KE": "tuv",
+ "tux-Latn-BR": "tux",
+ "tuy-Latn-KE": "tuy",
+ "tuz-Latn-BF": "tuz",
+ "tva-Latn-SB": "tva",
+ "tvd-Latn-ZZ": "tvd",
+ "tve-Latn-ID": "tve",
+ "tvk-Latn-VU": "tvk",
+ "tvl-Latn-TV": "tvl",
+ "tvm-Latn-ID": "tvm",
+ "tvn-Mymr-MM": "tvn",
+ "tvo-Latn-ID": "tvo",
+ "tvs-Latn-KE": "tvs",
+ "tvt-Latn-IN": "tvt",
+ "tvu-Latn-ZZ": "tvu",
+ "tvw-Latn-ID": "tvw",
+ "tvx-Latn-TW": "tvx",
+ "twa-Latn-US": "twa",
+ "twb-Latn-PH": "twb",
+ "twd-Latn-NL": "twd",
+ "twe-Latn-ID": "twe",
+ "twf-Latn-US": "twf",
+ "twg-Latn-ID": "twg",
+ "twh-Latn-ZZ": "twh",
+ "twl-Latn-MZ": "twl",
+ "twm-Deva-IN": "twm",
+ "twn-Latn-CM": "twn",
+ "two-Latn-BW": "two",
+ "twp-Latn-PG": "twp",
+ "twq-Latn-NE": "twq",
+ "twr-Latn-MX": "twr",
+ "twt-Latn-BR": "twt",
+ "twu-Latn-ID": "twu",
+ "tww-Latn-PG": "tww",
+ "twx-Latn-MZ": "twx",
+ "twy-Latn-ID": "twy",
+ "txa-Latn-MY": "txa",
+ "txe-Latn-ID": "txe",
+ "txg-Tang-CN": "txg",
+ "txi-Latn-BR": "txi",
+ "txj-Latn-NG": "txj",
+ "txm-Latn-ID": "txm",
+ "txn-Latn-ID": "txn",
+ "txo-Toto-IN": "txo",
+ "txq-Latn-ID": "txq",
+ "txs-Latn-ID": "txs",
+ "txt-Latn-ID": "txt",
+ "txu-Latn-BR": "txu",
+ "txx-Latn-MY": "txx",
+ "txy-Latn-MG": "txy",
+ "ty-Latn-PF": "ty",
+ "tya-Latn-ZZ": "tya",
+ "tye-Latn-NG": "tye",
+ "tyh-Latn-VN": "tyh",
+ "tyi-Latn-CG": "tyi",
+ "tyj-Latn-VN": "tyj",
+ "tyl-Latn-VN": "tyl",
+ "tyn-Latn-ID": "tyn",
+ "typ-Latn-AU": "typ",
+ "tyr-Tavt-VN": "tyr",
+ "tys-Latn-VN": "tys",
+ "tyt-Latn-VN": "tyt",
+ "tyt-Tavt-VN": "tyt-Tavt",
+ "tyu-Latn-BW": "tyu",
+ "tyv-Cyrl-RU": "tyv",
+ "tyx-Latn-CG": "tyx",
+ "tyy-Latn-NG": "tyy",
+ "tyz-Latn-VN": "tyz",
+ "tzh-Latn-MX": "tzh",
+ "tzj-Latn-GT": "tzj",
+ "tzl-Latn-001": "tzl",
+ "tzm-Latn-MA": "tzm",
+ "tzn-Latn-ID": "tzn",
+ "tzo-Latn-MX": "tzo",
+ "tzx-Latn-PG": "tzx",
+ "uam-Latn-BR": "uam",
+ "uar-Latn-PG": "uar",
+ "uba-Latn-NG": "uba",
+ "ubi-Latn-TD": "ubi",
+ "ubl-Latn-PH": "ubl",
+ "ubr-Latn-PG": "ubr",
+ "ubu-Latn-ZZ": "ubu",
+ "uda-Latn-NG": "uda",
+ "ude-Cyrl-RU": "ude",
+ "udg-Mlym-IN": "udg",
+ "udi-Aghb-RU": "udi",
+ "udj-Latn-ID": "udj",
+ "udl-Latn-CM": "udl",
+ "udm-Cyrl-RU": "udm",
+ "udu-Latn-SD": "udu",
+ "ues-Latn-ID": "ues",
+ "ufi-Latn-PG": "ufi",
+ "ug-Arab-CN": "ug",
+ "ug-Cyrl-KZ": "ug-KZ",
+ "ug-Cyrl-MN": "ug-MN",
+ "uga-Ugar-SY": "uga",
+ "ugb-Latn-AU": "ugb",
+ "uge-Latn-SB": "uge",
+ "ugh-Cyrl-RU": "ugh",
+ "ugo-Thai-TH": "ugo",
+ "uha-Latn-NG": "uha",
+ "uhn-Latn-ID": "uhn",
+ "uis-Latn-PG": "uis",
+ "uiv-Latn-CM": "uiv",
+ "uji-Latn-NG": "uji",
+ "uk-Cyrl-MD": "uk-MD",
+ "uk-Cyrl-SK": "uk-SK",
+ "uk-Cyrl-UA": "uk",
+ "uka-Latn-ID": "uka",
+ "ukg-Latn-PG": "ukg",
+ "ukh-Latn-CF": "ukh",
+ "uki-Orya-IN": "uki",
+ "ukk-Latn-MM": "ukk",
+ "ukp-Latn-NG": "ukp",
+ "ukq-Latn-NG": "ukq",
+ "uku-Latn-NG": "uku",
+ "ukv-Latn-SS": "ukv",
+ "ukw-Latn-NG": "ukw",
+ "uky-Latn-AU": "uky",
+ "ula-Latn-NG": "ula",
+ "ulb-Latn-NG": "ulb",
+ "ulc-Cyrl-RU": "ulc",
+ "ule-Latn-AR": "ule",
+ "ulf-Latn-ID": "ulf",
+ "uli-Latn-FM": "uli",
+ "ulk-Latn-AU": "ulk",
+ "ulm-Latn-ID": "ulm",
+ "uln-Latn-PG": "uln",
+ "ulu-Latn-ID": "ulu",
+ "ulw-Latn-NI": "ulw",
+ "uma-Latn-US": "uma",
+ "umb-Latn-AO": "umb",
+ "umd-Latn-AU": "umd",
+ "umg-Latn-AU": "umg",
+ "umi-Latn-MY": "umi",
+ "umm-Latn-NG": "umm",
+ "umn-Latn-MM": "umn",
+ "umo-Latn-BR": "umo",
+ "ump-Latn-AU": "ump",
+ "umr-Latn-AU": "umr",
+ "ums-Latn-ID": "ums",
+ "una-Latn-PG": "una",
+ "und-Cpmn-CY": "und-Cpmn",
+ "und-Latn-AQ": "und-AQ",
+ "und-Latn-BV": "und-BV",
+ "und-Latn-CP": "und-CP",
+ "und-Latn-GS": "und-GS",
+ "und-Latn-HM": "und-HM",
+ "une-Latn-NG": "une",
+ "ung-Latn-AU": "ung",
+ "uni-Latn-PG": "uni",
+ "unk-Latn-BR": "unk",
+ "unm-Latn-US": "unm",
+ "unn-Latn-AU": "unn",
+ "unr-Beng-IN": "unr",
+ "unr-Deva-NP": "unr-NP",
+ "unr-Nagm-IN": "unr-Nagm",
+ "unu-Latn-PG": "unu",
+ "unx-Beng-IN": "unx",
+ "unz-Latn-ID": "unz",
+ "uon-Latn-TW": "uon",
+ "upi-Latn-PG": "upi",
+ "upv-Latn-VU": "upv",
+ "ur-Arab-GB": "ur-GB",
+ "ur-Arab-IN": "ur-IN",
+ "ur-Arab-MU": "ur-MU",
+ "ur-Arab-PK": "ur",
+ "ura-Latn-PE": "ura",
+ "urb-Latn-BR": "urb",
+ "urc-Latn-AU": "urc",
+ "ure-Latn-BO": "ure",
+ "urf-Latn-AU": "urf",
+ "urg-Latn-PG": "urg",
+ "urh-Latn-NG": "urh",
+ "uri-Latn-ZZ": "uri",
+ "urk-Thai-TH": "urk",
+ "urm-Latn-PG": "urm",
+ "urn-Latn-ID": "urn",
+ "uro-Latn-PG": "uro",
+ "urp-Latn-BR": "urp",
+ "urr-Latn-VU": "urr",
+ "urt-Latn-ZZ": "urt",
+ "uru-Latn-BR": "uru",
+ "urv-Latn-PG": "urv",
+ "urw-Latn-ZZ": "urw",
+ "urx-Latn-PG": "urx",
+ "ury-Latn-ID": "ury",
+ "urz-Latn-BR": "urz",
+ "usa-Latn-ZZ": "usa",
+ "ush-Arab-PK": "ush",
+ "usi-Beng-BD": "usi-Beng",
+ "usi-Latn-BD": "usi",
+ "usk-Latn-CM": "usk",
+ "usp-Latn-GT": "usp",
+ "uss-Latn-NG": "uss",
+ "usu-Latn-PG": "usu",
+ "uta-Latn-NG": "uta",
+ "ute-Latn-US": "ute",
+ "uth-Latn-ZZ": "uth",
+ "utp-Latn-SB": "utp",
+ "utr-Latn-ZZ": "utr",
+ "utu-Latn-PG": "utu",
+ "uum-Cyrl-GE": "uum-Cyrl",
+ "uum-Grek-GE": "uum",
+ "uur-Latn-VU": "uur",
+ "uve-Latn-NC": "uve",
+ "uvh-Latn-ZZ": "uvh",
+ "uvl-Latn-ZZ": "uvl",
+ "uwa-Latn-AU": "uwa",
+ "uya-Latn-NG": "uya",
+ "uz-Arab-AF": "uz-AF",
+ "uz-Cyrl-CN": "uz-CN",
+ "uz-Latn-UZ": "uz",
+ "uzs-Arab-AF": "uzs",
+ "vaa-Taml-IN": "vaa",
+ "vae-Latn-CF": "vae",
+ "vaf-Arab-IR": "vaf",
+ "vag-Latn-ZZ": "vag",
+ "vah-Deva-IN": "vah",
+ "vai-Vaii-LR": "vai",
+ "vaj-Latn-NA": "vaj",
+ "val-Latn-PG": "val",
+ "vam-Latn-PG": "vam",
+ "van-Latn-ZZ": "van",
+ "vao-Latn-VU": "vao",
+ "vap-Latn-IN": "vap",
+ "var-Latn-MX": "var",
+ "vas-Deva-IN": "vas",
+ "vas-Gujr-IN": "vas-Gujr",
+ "vau-Latn-CD": "vau",
+ "vav-Deva-IN": "vav",
+ "vav-Gujr-IN": "vav-Gujr",
+ "vay-Deva-NP": "vay",
+ "vbb-Latn-ID": "vbb",
+ "vbk-Latn-PH": "vbk",
+ "ve-Latn-ZA": "ve",
+ "vec-Latn-IT": "vec",
+ "vem-Latn-NG": "vem",
+ "veo-Latn-US": "veo",
+ "vep-Latn-RU": "vep",
+ "ver-Latn-NG": "ver",
+ "vgr-Arab-PK": "vgr",
+ "vi-Latn-VN": "vi",
+ "vic-Latn-SX": "vic",
+ "vid-Latn-TZ": "vid",
+ "vif-Latn-CG": "vif",
+ "vig-Latn-BF": "vig",
+ "vil-Latn-AR": "vil",
+ "vin-Latn-TZ": "vin",
+ "vit-Latn-NG": "vit",
+ "viv-Latn-ZZ": "viv",
+ "vka-Latn-AU": "vka",
+ "vkj-Latn-TD": "vkj",
+ "vkk-Latn-ID": "vkk",
+ "vkl-Latn-ID": "vkl",
+ "vkm-Latn-BR": "vkm",
+ "vkn-Latn-NG": "vkn",
+ "vko-Latn-ID": "vko",
+ "vkp-Deva-IN": "vkp-Deva",
+ "vkp-Latn-IN": "vkp",
+ "vkt-Latn-ID": "vkt",
+ "vku-Latn-AU": "vku",
+ "vkz-Latn-NG": "vkz",
+ "vlp-Latn-VU": "vlp",
+ "vls-Latn-BE": "vls",
+ "vma-Latn-AU": "vma",
+ "vmb-Latn-AU": "vmb",
+ "vmc-Latn-MX": "vmc",
+ "vmd-Knda-IN": "vmd",
+ "vme-Latn-ID": "vme",
+ "vmf-Latn-DE": "vmf",
+ "vmg-Latn-PG": "vmg",
+ "vmh-Arab-IR": "vmh",
+ "vmi-Latn-AU": "vmi",
+ "vmj-Latn-MX": "vmj",
+ "vmk-Latn-MZ": "vmk",
+ "vml-Latn-AU": "vml",
+ "vmm-Latn-MX": "vmm",
+ "vmp-Latn-MX": "vmp",
+ "vmq-Latn-MX": "vmq",
+ "vmr-Latn-MZ": "vmr",
+ "vms-Latn-ID": "vms",
+ "vmu-Latn-AU": "vmu",
+ "vmw-Latn-MZ": "vmw",
+ "vmx-Latn-MX": "vmx",
+ "vmy-Latn-MX": "vmy",
+ "vmz-Latn-MX": "vmz",
+ "vnk-Latn-SB": "vnk",
+ "vnm-Latn-VU": "vnm",
+ "vnp-Latn-VU": "vnp",
+ "vo-Latn-001": "vo",
+ "vor-Latn-NG": "vor",
+ "vot-Latn-RU": "vot",
+ "vra-Latn-VU": "vra",
+ "vro-Latn-EE": "vro",
+ "vrs-Latn-SB": "vrs",
+ "vrt-Latn-VU": "vrt",
+ "vto-Latn-ID": "vto",
+ "vum-Latn-GA": "vum",
+ "vun-Latn-TZ": "vun",
+ "vut-Latn-ZZ": "vut",
+ "vwa-Latn-CN": "vwa",
+ "vwa-Mymr-CN": "vwa-Mymr",
+ "wa-Latn-BE": "wa",
+ "waa-Latn-US": "waa",
+ "wab-Latn-PG": "wab",
+ "wac-Latn-US": "wac",
+ "wad-Latn-ID": "wad",
+ "wae-Latn-CH": "wae",
+ "waf-Latn-BR": "waf",
+ "wag-Latn-PG": "wag",
+ "wah-Latn-ID": "wah",
+ "wai-Latn-ID": "wai",
+ "waj-Latn-ZZ": "waj",
+ "wal-Ethi-ET": "wal",
+ "wam-Latn-US": "wam",
+ "wan-Latn-ZZ": "wan",
+ "wap-Latn-GY": "wap",
+ "waq-Latn-AU": "waq",
+ "war-Latn-PH": "war",
+ "was-Latn-US": "was",
+ "wat-Latn-PG": "wat",
+ "wau-Latn-BR": "wau",
+ "wav-Latn-NG": "wav",
+ "waw-Latn-BR": "waw",
+ "wax-Latn-PG": "wax",
+ "way-Latn-SR": "way",
+ "waz-Latn-PG": "waz",
+ "wba-Latn-VE": "wba",
+ "wbb-Latn-ID": "wbb",
+ "wbe-Latn-ID": "wbe",
+ "wbf-Latn-BF": "wbf",
+ "wbh-Latn-TZ": "wbh",
+ "wbi-Latn-TZ": "wbi",
+ "wbj-Latn-TZ": "wbj",
+ "wbk-Arab-AF": "wbk",
+ "wbl-Arab-AF": "wbl-Arab",
+ "wbl-Cyrl-TJ": "wbl-Cyrl",
+ "wbl-Latn-PK": "wbl",
+ "wbm-Latn-CN": "wbm",
+ "wbp-Latn-AU": "wbp",
+ "wbq-Telu-IN": "wbq",
+ "wbr-Deva-IN": "wbr",
+ "wbt-Latn-AU": "wbt",
+ "wbv-Latn-AU": "wbv",
+ "wbw-Latn-ID": "wbw",
+ "wca-Latn-BR": "wca",
+ "wci-Latn-ZZ": "wci",
+ "wdd-Latn-GA": "wdd",
+ "wdg-Latn-PG": "wdg",
+ "wdj-Latn-AU": "wdj",
+ "wdk-Latn-AU": "wdk",
+ "wdt-Latn-CA": "wdt",
+ "wdu-Latn-AU": "wdu",
+ "wdy-Latn-AU": "wdy",
+ "wec-Latn-CI": "wec",
+ "wed-Latn-PG": "wed",
+ "weg-Latn-AU": "weg",
+ "weh-Latn-CM": "weh",
+ "wei-Latn-PG": "wei",
+ "wem-Latn-BJ": "wem",
+ "weo-Latn-ID": "weo",
+ "wep-Latn-DE": "wep",
+ "wer-Latn-ZZ": "wer",
+ "wes-Latn-CM": "wes",
+ "wet-Latn-ID": "wet",
+ "weu-Latn-MM": "weu",
+ "wew-Latn-ID": "wew",
+ "wfg-Latn-ID": "wfg",
+ "wga-Latn-AU": "wga",
+ "wgb-Latn-PG": "wgb",
+ "wgg-Latn-AU": "wgg",
+ "wgi-Latn-ZZ": "wgi",
+ "wgo-Latn-ID": "wgo",
+ "wgu-Latn-AU": "wgu",
+ "wgy-Latn-AU": "wgy",
+ "wha-Latn-ID": "wha",
+ "whg-Latn-ZZ": "whg",
+ "whk-Latn-ID": "whk",
+ "whu-Latn-ID": "whu",
+ "wib-Latn-ZZ": "wib",
+ "wic-Latn-US": "wic",
+ "wie-Latn-AU": "wie",
+ "wif-Latn-AU": "wif",
+ "wig-Latn-AU": "wig",
+ "wih-Latn-AU": "wih",
+ "wii-Latn-PG": "wii",
+ "wij-Latn-AU": "wij",
+ "wik-Latn-AU": "wik",
+ "wil-Latn-AU": "wil",
+ "wim-Latn-AU": "wim",
+ "win-Latn-US": "win",
+ "wir-Latn-BR": "wir",
+ "wiu-Latn-ZZ": "wiu",
+ "wiv-Latn-ZZ": "wiv",
+ "wiy-Latn-US": "wiy",
+ "wja-Latn-ZZ": "wja",
+ "wji-Latn-ZZ": "wji",
+ "wka-Latn-TZ": "wka",
+ "wkd-Latn-ID": "wkd",
+ "wkr-Latn-AU": "wkr",
+ "wkw-Latn-AU": "wkw",
+ "wky-Latn-AU": "wky",
+ "wla-Latn-PG": "wla",
+ "wlg-Latn-AU": "wlg",
+ "wlh-Latn-TL": "wlh",
+ "wli-Latn-ID": "wli",
+ "wlm-Latn-GB": "wlm",
+ "wlo-Arab-ID": "wlo",
+ "wlr-Latn-VU": "wlr",
+ "wls-Latn-WF": "wls",
+ "wlu-Latn-AU": "wlu",
+ "wlv-Latn-AR": "wlv",
+ "wlw-Latn-ID": "wlw",
+ "wlx-Latn-GH": "wlx",
+ "wma-Latn-NG": "wma",
+ "wmb-Latn-AU": "wmb",
+ "wmc-Latn-PG": "wmc",
+ "wmd-Latn-BR": "wmd",
+ "wme-Deva-NP": "wme",
+ "wmh-Latn-TL": "wmh",
+ "wmi-Latn-AU": "wmi",
+ "wmm-Latn-ID": "wmm",
+ "wmn-Latn-NC": "wmn",
+ "wmo-Latn-ZZ": "wmo",
+ "wms-Latn-ID": "wms",
+ "wmt-Latn-AU": "wmt",
+ "wmw-Arab-MZ": "wmw-Arab",
+ "wmw-Latn-MZ": "wmw",
+ "wmx-Latn-PG": "wmx",
+ "wnb-Latn-PG": "wnb",
+ "wnc-Latn-ZZ": "wnc",
+ "wnd-Latn-AU": "wnd",
+ "wne-Arab-PK": "wne",
+ "wng-Latn-ID": "wng",
+ "wni-Arab-KM": "wni",
+ "wnk-Latn-ID": "wnk",
+ "wnm-Latn-AU": "wnm",
+ "wnn-Latn-AU": "wnn",
+ "wno-Latn-ID": "wno",
+ "wnp-Latn-PG": "wnp",
+ "wnu-Latn-ZZ": "wnu",
+ "wnw-Latn-US": "wnw",
+ "wny-Latn-AU": "wny",
+ "wo-Latn-SN": "wo",
+ "woa-Latn-AU": "woa",
+ "wob-Latn-ZZ": "wob",
+ "woc-Latn-PG": "woc",
+ "wod-Latn-ID": "wod",
+ "woe-Latn-FM": "woe",
+ "wof-Arab-GM": "wof-Arab",
+ "wof-Latn-GM": "wof",
+ "wog-Latn-PG": "wog",
+ "woi-Latn-ID": "woi",
+ "wok-Latn-CM": "wok",
+ "wom-Latn-NG": "wom",
+ "won-Latn-CD": "won",
+ "woo-Latn-ID": "woo",
+ "wor-Latn-ID": "wor",
+ "wos-Latn-ZZ": "wos",
+ "wow-Latn-ID": "wow",
+ "wpc-Latn-VE": "wpc",
+ "wrb-Latn-AU": "wrb",
+ "wrg-Latn-AU": "wrg",
+ "wrh-Latn-AU": "wrh",
+ "wri-Latn-AU": "wri",
+ "wrk-Latn-AU": "wrk",
+ "wrl-Latn-AU": "wrl",
+ "wrm-Latn-AU": "wrm",
+ "wro-Latn-AU": "wro",
+ "wrp-Latn-ID": "wrp",
+ "wrr-Latn-AU": "wrr",
+ "wrs-Latn-ZZ": "wrs",
+ "wru-Latn-ID": "wru",
+ "wrv-Latn-PG": "wrv",
+ "wrw-Latn-AU": "wrw",
+ "wrx-Latn-ID": "wrx",
+ "wrz-Latn-AU": "wrz",
+ "wsa-Latn-ID": "wsa",
+ "wsg-Gong-IN": "wsg",
+ "wsi-Latn-VU": "wsi",
+ "wsk-Latn-ZZ": "wsk",
+ "wsr-Latn-PG": "wsr",
+ "wss-Latn-GH": "wss",
+ "wsu-Latn-BR": "wsu",
+ "wsv-Arab-AF": "wsv",
+ "wtf-Latn-PG": "wtf",
+ "wth-Latn-AU": "wth",
+ "wti-Latn-ET": "wti",
+ "wtk-Latn-PG": "wtk",
+ "wtm-Deva-IN": "wtm",
+ "wtw-Bugi-ID": "wtw-Bugi",
+ "wtw-Latn-ID": "wtw",
+ "wua-Latn-AU": "wua",
+ "wub-Latn-AU": "wub",
+ "wud-Latn-TG": "wud",
+ "wul-Latn-ID": "wul",
+ "wum-Latn-GA": "wum",
+ "wun-Latn-TZ": "wun",
+ "wur-Latn-AU": "wur",
+ "wut-Latn-PG": "wut",
+ "wuu-Hans-CN": "wuu",
+ "wuv-Latn-ZZ": "wuv",
+ "wux-Latn-AU": "wux",
+ "wuy-Latn-ID": "wuy",
+ "wwa-Latn-ZZ": "wwa",
+ "wwb-Latn-AU": "wwb",
+ "wwo-Latn-VU": "wwo",
+ "wwr-Latn-AU": "wwr",
+ "www-Latn-CM": "www",
+ "wxw-Latn-AU": "wxw",
+ "wyb-Latn-AU": "wyb",
+ "wyi-Latn-AU": "wyi",
+ "wym-Latn-PL": "wym",
+ "wyn-Latn-US": "wyn",
+ "wyr-Latn-BR": "wyr",
+ "wyy-Latn-FJ": "wyy",
+ "xaa-Latn-ES": "xaa",
+ "xab-Latn-NG": "xab",
+ "xai-Latn-BR": "xai",
+ "xaj-Latn-BR": "xaj",
+ "xak-Latn-VE": "xak",
+ "xal-Cyrl-RU": "xal",
+ "xam-Latn-ZA": "xam",
+ "xan-Ethi-ET": "xan",
+ "xao-Latn-VN": "xao",
+ "xar-Latn-PG": "xar",
+ "xas-Cyrl-RU": "xas",
+ "xat-Latn-BR": "xat",
+ "xau-Latn-ID": "xau",
+ "xav-Latn-BR": "xav",
+ "xaw-Latn-US": "xaw",
+ "xay-Latn-ID": "xay",
+ "xbb-Latn-AU": "xbb",
+ "xbd-Latn-AU": "xbd",
+ "xbe-Latn-AU": "xbe",
+ "xbg-Latn-AU": "xbg",
+ "xbi-Latn-ZZ": "xbi",
+ "xbj-Latn-AU": "xbj",
+ "xbm-Latn-FR": "xbm",
+ "xbn-Latn-MY": "xbn",
+ "xbp-Latn-AU": "xbp",
+ "xbr-Latn-ID": "xbr",
+ "xbw-Latn-BR": "xbw",
+ "xby-Latn-AU": "xby",
+ "xch-Latn-US": "xch",
+ "xco-Chrs-UZ": "xco",
+ "xcr-Cari-TR": "xcr",
+ "xda-Latn-AU": "xda",
+ "xdk-Latn-AU": "xdk",
+ "xdo-Latn-AO": "xdo",
+ "xdq-Cyrl-RU": "xdq",
+ "xdy-Latn-ID": "xdy",
+ "xed-Latn-CM": "xed",
+ "xeg-Latn-ZA": "xeg",
+ "xem-Latn-ID": "xem",
+ "xer-Latn-BR": "xer",
+ "xes-Latn-ZZ": "xes",
+ "xet-Latn-BR": "xet",
+ "xeu-Latn-PG": "xeu",
+ "xgb-Latn-CI": "xgb",
+ "xgd-Latn-AU": "xgd",
+ "xgg-Latn-AU": "xgg",
+ "xgi-Latn-AU": "xgi",
+ "xgm-Latn-AU": "xgm",
+ "xgu-Latn-AU": "xgu",
+ "xgw-Latn-AU": "xgw",
+ "xh-Latn-ZA": "xh",
+ "xhe-Arab-PK": "xhe",
+ "xhm-Khmr-KH": "xhm",
+ "xhv-Latn-VN": "xhv",
+ "xii-Latn-ZA": "xii",
+ "xin-Latn-GT": "xin",
+ "xir-Latn-BR": "xir",
+ "xis-Orya-IN": "xis",
+ "xiy-Latn-BR": "xiy",
+ "xjb-Latn-AU": "xjb",
+ "xjt-Latn-AU": "xjt",
+ "xka-Arab-PK": "xka",
+ "xkb-Latn-BJ": "xkb",
+ "xkc-Arab-IR": "xkc",
+ "xkd-Latn-ID": "xkd",
+ "xke-Latn-ID": "xke",
+ "xkg-Latn-ML": "xkg",
+ "xkj-Arab-IR": "xkj",
+ "xkl-Latn-ID": "xkl",
+ "xkn-Latn-ID": "xkn",
+ "xkp-Arab-IR": "xkp",
+ "xkq-Latn-ID": "xkq",
+ "xkr-Latn-BR": "xkr",
+ "xks-Latn-ID": "xks",
+ "xkt-Latn-GH": "xkt",
+ "xku-Latn-CG": "xku",
+ "xkv-Latn-BW": "xkv",
+ "xkw-Latn-ID": "xkw",
+ "xkx-Latn-PG": "xkx",
+ "xky-Latn-MY": "xky",
+ "xkz-Latn-BT": "xkz",
+ "xla-Latn-ZZ": "xla",
+ "xlc-Lyci-TR": "xlc",
+ "xld-Lydi-TR": "xld",
+ "xly-Elym-IR": "xly",
+ "xma-Latn-SO": "xma",
+ "xmb-Latn-CM": "xmb",
+ "xmc-Latn-MZ": "xmc",
+ "xmd-Latn-CM": "xmd",
+ "xmf-Geor-GE": "xmf",
+ "xmg-Latn-CM": "xmg",
+ "xmh-Latn-AU": "xmh",
+ "xmj-Latn-CM": "xmj",
+ "xmm-Latn-ID": "xmm",
+ "xmn-Mani-CN": "xmn",
+ "xmo-Latn-BR": "xmo",
+ "xmp-Latn-AU": "xmp",
+ "xmq-Latn-AU": "xmq",
+ "xmr-Merc-SD": "xmr",
+ "xmr-Mero-SD": "xmr-Mero",
+ "xmt-Latn-ID": "xmt",
+ "xmu-Latn-AU": "xmu",
+ "xmv-Latn-MG": "xmv",
+ "xmw-Latn-MG": "xmw",
+ "xmx-Latn-ID": "xmx",
+ "xmy-Latn-AU": "xmy",
+ "xmz-Latn-ID": "xmz",
+ "xna-Narb-SA": "xna",
+ "xnb-Latn-TW": "xnb",
+ "xni-Latn-AU": "xni",
+ "xnj-Latn-TZ": "xnj",
+ "xnk-Latn-AU": "xnk",
+ "xnm-Latn-AU": "xnm",
+ "xnn-Latn-PH": "xnn",
+ "xnq-Latn-MZ": "xnq",
+ "xnr-Deva-IN": "xnr",
+ "xnt-Latn-US": "xnt",
+ "xnu-Latn-AU": "xnu",
+ "xny-Latn-AU": "xny",
+ "xnz-Arab-EG": "xnz-Arab",
+ "xnz-Latn-EG": "xnz",
+ "xoc-Latn-NG": "xoc",
+ "xod-Latn-ID": "xod",
+ "xog-Latn-UG": "xog",
+ "xoi-Latn-PG": "xoi",
+ "xok-Latn-BR": "xok",
+ "xom-Ethi-ET": "xom-Ethi",
+ "xom-Latn-SD": "xom",
+ "xon-Latn-ZZ": "xon",
+ "xoo-Latn-BR": "xoo",
+ "xop-Latn-PG": "xop",
+ "xor-Latn-BR": "xor",
+ "xow-Latn-PG": "xow",
+ "xpa-Latn-AU": "xpa",
+ "xpb-Latn-AU": "xpb",
+ "xpd-Latn-AU": "xpd",
+ "xpf-Latn-AU": "xpf",
+ "xpg-Grek-TR": "xpg",
+ "xph-Latn-AU": "xph",
+ "xpi-Ogam-GB": "xpi",
+ "xpj-Latn-AU": "xpj",
+ "xpk-Latn-BR": "xpk",
+ "xpl-Latn-AU": "xpl",
+ "xpm-Cyrl-RU": "xpm",
+ "xpn-Latn-BR": "xpn",
+ "xpo-Latn-MX": "xpo",
+ "xpq-Latn-US": "xpq",
+ "xpr-Prti-IR": "xpr",
+ "xpt-Latn-AU": "xpt",
+ "xpv-Latn-AU": "xpv",
+ "xpw-Latn-AU": "xpw",
+ "xpx-Latn-AU": "xpx",
+ "xpz-Latn-AU": "xpz",
+ "xra-Latn-BR": "xra",
+ "xrb-Latn-ZZ": "xrb",
+ "xrd-Latn-AU": "xrd",
+ "xre-Latn-BR": "xre",
+ "xrg-Latn-AU": "xrg",
+ "xri-Latn-BR": "xri",
+ "xrm-Cyrl-RU": "xrm",
+ "xrn-Cyrl-RU": "xrn",
+ "xrr-Latn-IT": "xrr",
+ "xru-Latn-AU": "xru",
+ "xrw-Latn-PG": "xrw",
+ "xsa-Sarb-YE": "xsa",
+ "xsb-Latn-PH": "xsb",
+ "xse-Latn-ID": "xse",
+ "xsh-Latn-NG": "xsh",
+ "xsi-Latn-ZZ": "xsi",
+ "xsm-Latn-ZZ": "xsm",
+ "xsn-Latn-NG": "xsn",
+ "xsp-Latn-PG": "xsp",
+ "xsq-Latn-MZ": "xsq",
+ "xsr-Deva-NP": "xsr",
+ "xss-Cyrl-RU": "xss",
+ "xsu-Latn-VE": "xsu",
+ "xsy-Latn-TW": "xsy",
+ "xta-Latn-MX": "xta",
+ "xtb-Latn-MX": "xtb",
+ "xtc-Latn-SD": "xtc",
+ "xtd-Latn-MX": "xtd",
+ "xte-Latn-ID": "xte",
+ "xth-Latn-AU": "xth",
+ "xti-Latn-MX": "xti",
+ "xtj-Latn-MX": "xtj",
+ "xtl-Latn-MX": "xtl",
+ "xtm-Latn-MX": "xtm",
+ "xtn-Latn-MX": "xtn",
+ "xtp-Latn-MX": "xtp",
+ "xts-Latn-MX": "xts",
+ "xtt-Latn-MX": "xtt",
+ "xtu-Latn-MX": "xtu",
+ "xtv-Latn-AU": "xtv",
+ "xtw-Latn-BR": "xtw",
+ "xty-Latn-MX": "xty",
+ "xub-Knda-IN": "xub-Knda",
+ "xub-Mlym-IN": "xub-Mlym",
+ "xub-Taml-IN": "xub",
+ "xud-Latn-AU": "xud",
+ "xuj-Taml-IN": "xuj",
+ "xul-Latn-AU": "xul",
+ "xum-Ital-IT": "xum-Ital",
+ "xum-Latn-IT": "xum",
+ "xun-Latn-AU": "xun",
+ "xuo-Latn-TD": "xuo",
+ "xut-Latn-AU": "xut",
+ "xuu-Latn-NA": "xuu",
+ "xve-Ital-IT": "xve",
+ "xvi-Arab-AF": "xvi",
+ "xvn-Latn-ES": "xvn",
+ "xvo-Latn-IT": "xvo",
+ "xvs-Latn-IT": "xvs",
+ "xwa-Latn-BR": "xwa",
+ "xwd-Latn-AU": "xwd",
+ "xwe-Latn-ZZ": "xwe",
+ "xwj-Latn-AU": "xwj",
+ "xwk-Latn-AU": "xwk",
+ "xwl-Latn-BJ": "xwl",
+ "xwo-Cyrl-RU": "xwo",
+ "xwr-Latn-ID": "xwr",
+ "xwt-Latn-AU": "xwt",
+ "xww-Latn-AU": "xww",
+ "xxb-Latn-GH": "xxb",
+ "xxk-Latn-ID": "xxk",
+ "xxm-Latn-AU": "xxm",
+ "xxr-Latn-BR": "xxr",
+ "xxt-Latn-ID": "xxt",
+ "xya-Latn-AU": "xya",
+ "xyb-Latn-AU": "xyb",
+ "xyj-Latn-AU": "xyj",
+ "xyk-Latn-AU": "xyk",
+ "xyl-Latn-BR": "xyl",
+ "xyt-Latn-AU": "xyt",
+ "xyy-Latn-AU": "xyy",
+ "xzh-Marc-CN": "xzh",
+ "xzp-Latn-MX": "xzp",
+ "yaa-Latn-PE": "yaa",
+ "yab-Latn-BR": "yab",
+ "yac-Latn-ID": "yac",
+ "yad-Latn-PE": "yad",
+ "yae-Latn-VE": "yae",
+ "yaf-Latn-CD": "yaf",
+ "yag-Latn-CL": "yag",
+ "yai-Cyrl-TJ": "yai",
+ "yaj-Latn-CF": "yaj",
+ "yak-Latn-US": "yak",
+ "yal-Arab-GN": "yal-Arab",
+ "yal-Latn-GN": "yal",
+ "yam-Latn-ZZ": "yam",
+ "yan-Latn-NI": "yan",
+ "yao-Latn-MZ": "yao",
+ "yap-Latn-FM": "yap",
+ "yaq-Latn-MX": "yaq",
+ "yar-Latn-VE": "yar",
+ "yas-Latn-ZZ": "yas",
+ "yat-Latn-ZZ": "yat",
+ "yau-Latn-VE": "yau",
+ "yav-Latn-CM": "yav",
+ "yaw-Latn-BR": "yaw",
+ "yax-Latn-AO": "yax",
+ "yay-Latn-ZZ": "yay",
+ "yaz-Latn-ZZ": "yaz",
+ "yba-Latn-ZZ": "yba",
+ "ybb-Latn-CM": "ybb",
+ "ybe-Latn-CN": "ybe",
+ "ybe-Ougr-CN": "ybe-Ougr",
+ "ybh-Deva-NP": "ybh",
+ "ybi-Deva-NP": "ybi",
+ "ybj-Latn-NG": "ybj",
+ "ybl-Latn-NG": "ybl",
+ "ybm-Latn-PG": "ybm",
+ "ybn-Latn-BR": "ybn",
+ "ybo-Latn-PG": "ybo",
+ "ybx-Latn-PG": "ybx",
+ "yby-Latn-ZZ": "yby",
+ "ycl-Latn-CN": "ycl",
+ "ycn-Latn-CO": "ycn",
+ "yda-Latn-AU": "yda",
+ "yde-Latn-PG": "yde",
+ "ydg-Arab-PK": "ydg",
+ "ydk-Latn-PG": "ydk",
+ "yea-Knda-IN": "yea-Knda",
+ "yea-Mlym-IN": "yea",
+ "yec-Latn-DE": "yec",
+ "yee-Latn-PG": "yee",
+ "yei-Latn-CM": "yei",
+ "yej-Grek-IL": "yej",
+ "yel-Latn-CD": "yel",
+ "yer-Latn-ZZ": "yer",
+ "yes-Latn-NG": "yes",
+ "yet-Latn-ID": "yet",
+ "yeu-Telu-IN": "yeu",
+ "yev-Latn-PG": "yev",
+ "yey-Latn-BW": "yey",
+ "yga-Latn-AU": "yga",
+ "ygi-Latn-AU": "ygi",
+ "ygl-Latn-PG": "ygl",
+ "ygm-Latn-PG": "ygm",
+ "ygp-Plrd-CN": "ygp",
+ "ygr-Latn-ZZ": "ygr",
+ "ygu-Latn-AU": "ygu",
+ "ygw-Latn-ZZ": "ygw",
+ "yhd-Hebr-IL": "yhd",
+ "yi-Hebr-001": "yi",
+ "yi-Hebr-SE": "yi-SE",
+ "yi-Hebr-UA": "yi-UA",
+ "yi-Hebr-US": "yi-US",
+ "yia-Latn-AU": "yia",
+ "yig-Yiii-CN": "yig",
+ "yih-Hebr-DE": "yih",
+ "yii-Latn-AU": "yii",
+ "yij-Latn-AU": "yij",
+ "yil-Latn-AU": "yil",
+ "yim-Latn-IN": "yim",
+ "yir-Latn-ID": "yir",
+ "yis-Latn-PG": "yis",
+ "yiv-Yiii-CN": "yiv",
+ "yka-Arab-PH": "yka-Arab",
+ "yka-Latn-PH": "yka",
+ "ykg-Cyrl-RU": "ykg",
+ "yki-Latn-ID": "yki",
+ "ykk-Latn-PG": "ykk",
+ "ykm-Latn-PG": "ykm",
+ "yko-Latn-ZZ": "yko",
+ "ykr-Latn-PG": "ykr",
+ "yky-Latn-CF": "yky",
+ "yla-Latn-PG": "yla",
+ "ylb-Latn-PG": "ylb",
+ "yle-Latn-ZZ": "yle",
+ "ylg-Latn-ZZ": "ylg",
+ "yli-Latn-ID": "yli",
+ "yll-Latn-ZZ": "yll",
+ "ylr-Latn-AU": "ylr",
+ "ylu-Latn-PG": "ylu",
+ "yly-Latn-NC": "yly",
+ "ymb-Latn-PG": "ymb",
+ "yme-Latn-PE": "yme",
+ "ymg-Latn-CD": "ymg",
+ "ymk-Arab-MZ": "ymk-Arab",
+ "ymk-Latn-MZ": "ymk",
+ "yml-Latn-ZZ": "yml",
+ "ymm-Latn-SO": "ymm",
+ "ymn-Latn-ID": "ymn",
+ "ymo-Latn-PG": "ymo",
+ "ymp-Latn-PG": "ymp",
+ "yna-Plrd-CN": "yna",
+ "ynd-Latn-AU": "ynd",
+ "yng-Latn-CD": "yng",
+ "ynk-Cyrl-RU": "ynk",
+ "ynl-Latn-PG": "ynl",
+ "ynq-Latn-NG": "ynq",
+ "yns-Latn-CD": "yns",
+ "ynu-Latn-CO": "ynu",
+ "yo-Latn-NG": "yo",
+ "yob-Latn-PG": "yob",
+ "yog-Latn-PH": "yog",
+ "yoi-Jpan-JP": "yoi",
+ "yok-Latn-US": "yok",
+ "yol-Latn-GB": "yol",
+ "yom-Latn-CD": "yom",
+ "yon-Latn-ZZ": "yon",
+ "yot-Latn-NG": "yot",
+ "yoy-Thai-TH": "yoy",
+ "yra-Latn-PG": "yra",
+ "yrb-Latn-ZZ": "yrb",
+ "yre-Latn-ZZ": "yre",
+ "yrk-Cyrl-RU": "yrk",
+ "yrl-Latn-BR": "yrl",
+ "yrm-Latn-AU": "yrm",
+ "yro-Latn-BR": "yro",
+ "yrs-Latn-ID": "yrs",
+ "yrw-Latn-PG": "yrw",
+ "yry-Latn-AU": "yry",
+ "ysd-Yiii-CN": "ysd",
+ "ysn-Yiii-CN": "ysn",
+ "ysp-Yiii-CN": "ysp",
+ "ysr-Cyrl-RU": "ysr",
+ "yss-Latn-ZZ": "yss",
+ "ysy-Plrd-CN": "ysy",
+ "ytw-Latn-PG": "ytw",
+ "yty-Latn-AU": "yty",
+ "yua-Latn-MX": "yua",
+ "yub-Latn-AU": "yub",
+ "yuc-Latn-US": "yuc",
+ "yud-Hebr-IL": "yud",
+ "yue-Hans-CN": "yue-CN",
+ "yue-Hant-CA": "yue-CA",
+ "yue-Hant-HK": "yue",
+ "yuf-Latn-US": "yuf",
+ "yug-Cyrl-RU": "yug",
+ "yui-Latn-CO": "yui",
+ "yuj-Latn-ZZ": "yuj",
+ "yul-Latn-CF": "yul",
+ "yum-Latn-US": "yum",
+ "yun-Latn-NG": "yun",
+ "yup-Latn-CO": "yup",
+ "yuq-Latn-BO": "yuq",
+ "yur-Latn-US": "yur",
+ "yut-Latn-ZZ": "yut",
+ "yuw-Latn-ZZ": "yuw",
+ "yux-Cyrl-RU": "yux",
+ "yuz-Latn-BO": "yuz",
+ "yva-Latn-ID": "yva",
+ "yvt-Latn-VE": "yvt",
+ "ywa-Latn-PG": "ywa",
+ "ywg-Latn-AU": "ywg",
+ "ywn-Latn-BR": "ywn",
+ "ywq-Plrd-CN": "ywq",
+ "ywq-Yiii-CN": "ywq-Yiii",
+ "ywr-Latn-AU": "ywr",
+ "ywu-Plrd-CN": "ywu",
+ "ywu-Yiii-CN": "ywu-Yiii",
+ "yww-Latn-AU": "yww",
+ "yxa-Latn-AU": "yxa",
+ "yxg-Latn-AU": "yxg",
+ "yxl-Latn-AU": "yxl",
+ "yxm-Latn-AU": "yxm",
+ "yxu-Latn-AU": "yxu",
+ "yxy-Latn-AU": "yxy",
+ "yyr-Latn-AU": "yyr",
+ "yyu-Latn-PG": "yyu",
+ "za-Latn-CN": "za",
+ "zaa-Latn-MX": "zaa",
+ "zab-Latn-MX": "zab",
+ "zac-Latn-MX": "zac",
+ "zad-Latn-MX": "zad",
+ "zae-Latn-MX": "zae",
+ "zaf-Latn-MX": "zaf",
+ "zag-Latn-SD": "zag",
+ "zah-Latn-NG": "zah",
+ "zaj-Latn-TZ": "zaj",
+ "zak-Latn-TZ": "zak",
+ "zam-Latn-MX": "zam",
+ "zao-Latn-MX": "zao",
+ "zap-Latn-MX": "zap",
+ "zaq-Latn-MX": "zaq",
+ "zar-Latn-MX": "zar",
+ "zas-Latn-MX": "zas",
+ "zat-Latn-MX": "zat",
+ "zau-Arab-IN": "zau-Arab",
+ "zau-Tibt-IN": "zau",
+ "zav-Latn-MX": "zav",
+ "zaw-Latn-MX": "zaw",
+ "zax-Latn-MX": "zax",
+ "zay-Ethi-ET": "zay-Ethi",
+ "zay-Latn-ET": "zay",
+ "zaz-Latn-NG": "zaz",
+ "zba-Arab-001": "zba",
+ "zbc-Latn-MY": "zbc",
+ "zbe-Latn-MY": "zbe",
+ "zbt-Latn-ID": "zbt",
+ "zbu-Latn-NG": "zbu",
+ "zbw-Latn-MY": "zbw",
+ "zca-Latn-MX": "zca",
+ "zch-Hani-CN": "zch",
+ "zdj-Arab-KM": "zdj",
+ "zea-Latn-NL": "zea",
+ "zeg-Latn-PG": "zeg",
+ "zeh-Hani-CN": "zeh",
+ "zen-Arab-MR": "zen-Arab",
+ "zen-Tfng-MR": "zen",
+ "zga-Latn-TZ": "zga",
+ "zgb-Hani-CN": "zgb",
+ "zgh-Tfng-MA": "zgh",
+ "zgm-Hani-CN": "zgm",
+ "zgn-Hani-CN": "zgn",
+ "zgr-Latn-PG": "zgr",
+ "zh-Bopo-TW": "zh-Bopo",
+ "zh-Hanb-TW": "zh-Hanb",
+ "zh-Hani-CN": "zh-Hani",
+ "zh-Hans-CN": "zh",
+ "zh-Hant-AU": "zh-AU",
+ "zh-Hant-BN": "zh-BN",
+ "zh-Hant-GB": "zh-GB",
+ "zh-Hant-GF": "zh-GF",
+ "zh-Hant-HK": "zh-HK",
+ "zh-Hant-ID": "zh-ID",
+ "zh-Hant-MO": "zh-MO",
+ "zh-Hant-PA": "zh-PA",
+ "zh-Hant-PF": "zh-PF",
+ "zh-Hant-PH": "zh-PH",
+ "zh-Hant-SR": "zh-SR",
+ "zh-Hant-TH": "zh-TH",
+ "zh-Hant-TW": "zh-TW",
+ "zh-Hant-US": "zh-US",
+ "zh-Hant-VN": "zh-VN",
+ "zhd-Hani-CN": "zhd",
+ "zhd-Latn-VN": "zhd-Latn",
+ "zhi-Latn-NG": "zhi",
+ "zhn-Hani-CN": "zhn-Hani",
+ "zhn-Latn-CN": "zhn",
+ "zhw-Latn-CM": "zhw",
+ "zhx-Nshu-CN": "zhx",
+ "zia-Latn-ZZ": "zia",
+ "zik-Latn-PG": "zik",
+ "zil-Latn-GN": "zil",
+ "zim-Latn-TD": "zim",
+ "zin-Latn-TZ": "zin",
+ "ziw-Latn-TZ": "ziw",
+ "ziz-Latn-NG": "ziz",
+ "zka-Latn-ID": "zka",
+ "zkb-Cyrl-RU": "zkb",
+ "zkd-Latn-MM": "zkd",
+ "zko-Cyrl-RU": "zko",
+ "zkp-Latn-BR": "zkp",
+ "zkt-Kits-CN": "zkt",
+ "zku-Latn-AU": "zku",
+ "zkz-Cyrl-RU": "zkz",
+ "zla-Latn-CD": "zla",
+ "zlj-Hani-CN": "zlj",
+ "zlj-Latn-CN": "zlj-Latn",
+ "zlm-Latn-TG": "zlm",
+ "zln-Hani-CN": "zln",
+ "zlq-Hani-CN": "zlq",
+ "zma-Latn-AU": "zma",
+ "zmb-Latn-CD": "zmb",
+ "zmc-Latn-AU": "zmc",
+ "zmd-Latn-AU": "zmd",
+ "zme-Latn-AU": "zme",
+ "zmf-Latn-CD": "zmf",
+ "zmg-Latn-AU": "zmg",
+ "zmh-Latn-PG": "zmh",
+ "zmi-Latn-MY": "zmi",
+ "zmj-Latn-AU": "zmj",
+ "zmk-Latn-AU": "zmk",
+ "zml-Latn-AU": "zml",
+ "zmm-Latn-AU": "zmm",
+ "zmn-Latn-GA": "zmn",
+ "zmo-Latn-SD": "zmo",
+ "zmp-Latn-CD": "zmp",
+ "zmq-Latn-CD": "zmq",
+ "zmr-Latn-AU": "zmr",
+ "zms-Latn-CD": "zms",
+ "zmt-Latn-AU": "zmt",
+ "zmu-Latn-AU": "zmu",
+ "zmv-Latn-AU": "zmv",
+ "zmw-Latn-CD": "zmw",
+ "zmx-Latn-CG": "zmx",
+ "zmy-Latn-AU": "zmy",
+ "zmz-Latn-CD": "zmz",
+ "zna-Latn-TD": "zna",
+ "zne-Latn-ZZ": "zne",
+ "zng-Latn-VN": "zng",
+ "znk-Latn-AU": "znk",
+ "zns-Latn-NG": "zns",
+ "zoc-Latn-MX": "zoc",
+ "zoh-Latn-MX": "zoh",
+ "zom-Latn-IN": "zom",
+ "zoo-Latn-MX": "zoo",
+ "zoq-Latn-MX": "zoq",
+ "zor-Latn-MX": "zor",
+ "zos-Latn-MX": "zos",
+ "zpa-Latn-MX": "zpa",
+ "zpb-Latn-MX": "zpb",
+ "zpc-Latn-MX": "zpc",
+ "zpd-Latn-MX": "zpd",
+ "zpe-Latn-MX": "zpe",
+ "zpf-Latn-MX": "zpf",
+ "zpg-Latn-MX": "zpg",
+ "zph-Latn-MX": "zph",
+ "zpi-Latn-MX": "zpi",
+ "zpj-Latn-MX": "zpj",
+ "zpk-Latn-MX": "zpk",
+ "zpl-Latn-MX": "zpl",
+ "zpm-Latn-MX": "zpm",
+ "zpn-Latn-MX": "zpn",
+ "zpo-Latn-MX": "zpo",
+ "zpp-Latn-MX": "zpp",
+ "zpq-Latn-MX": "zpq",
+ "zpr-Latn-MX": "zpr",
+ "zps-Latn-MX": "zps",
+ "zpt-Latn-MX": "zpt",
+ "zpu-Latn-MX": "zpu",
+ "zpv-Latn-MX": "zpv",
+ "zpw-Latn-MX": "zpw",
+ "zpx-Latn-MX": "zpx",
+ "zpy-Latn-MX": "zpy",
+ "zpz-Latn-MX": "zpz",
+ "zqe-Hani-CN": "zqe",
+ "zqe-Latn-CN": "zqe-Latn",
+ "zrn-Latn-TD": "zrn",
+ "zro-Latn-EC": "zro",
+ "zrp-Hebr-FR": "zrp",
+ "zrs-Latn-ID": "zrs",
+ "zsa-Latn-PG": "zsa",
+ "zsr-Latn-MX": "zsr",
+ "zsu-Latn-PG": "zsu",
+ "zte-Latn-MX": "zte",
+ "ztg-Latn-MX": "ztg",
+ "ztl-Latn-MX": "ztl",
+ "ztm-Latn-MX": "ztm",
+ "ztn-Latn-MX": "ztn",
+ "ztp-Latn-MX": "ztp",
+ "ztq-Latn-MX": "ztq",
+ "zts-Latn-MX": "zts",
+ "ztt-Latn-MX": "ztt",
+ "ztu-Latn-MX": "ztu",
+ "ztx-Latn-MX": "ztx",
+ "zty-Latn-MX": "zty",
+ "zu-Latn-ZA": "zu",
+ "zua-Latn-NG": "zua",
+ "zuh-Latn-PG": "zuh",
+ "zum-Arab-OM": "zum",
+ "zun-Latn-US": "zun",
+ "zuy-Latn-CM": "zuy",
+ "zyg-Hani-CN": "zyg",
+ "zyj-Hani-CN": "zyj-Hani",
+ "zyj-Latn-CN": "zyj",
+ "zyn-Hani-CN": "zyn",
+ "zyp-Latn-MM": "zyp",
+ "zza-Latn-TR": "zza",
+ "zzj-Hani-CN": "zzj",
+};
+
+for (let [tag, maximal] of Object.entries(maxLikelySubtags)) {
+ assertEq(new Intl.Locale(tag).maximize().toString(), maximal);
+}
+
+for (let [tag, minimal] of Object.entries(minLikelySubtags)) {
+ assertEq(new Intl.Locale(tag).minimize().toString(), minimal);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/Locale/likely-subtags.js b/js/src/tests/non262/Intl/Locale/likely-subtags.js
new file mode 100644
index 0000000000..3b3e4bd905
--- /dev/null
+++ b/js/src/tests/non262/Intl/Locale/likely-subtags.js
@@ -0,0 +1,61 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+var testDataMaximal = {
+ // Keeps "und" primary language.
+ "und-AQ": "und-Latn-AQ",
+
+ // Modifies primary language.
+ "und-Cyrl-RO": "bg-Cyrl-RO",
+}
+
+var testDataMinimal = {
+ // Undefined primary language.
+ "und": "en",
+ "und-Thai": "th",
+ "und-419": "es-419",
+ "und-150": "ru",
+ "und-AT": "de-AT",
+
+ // https://ssl.icu-project.org/trac/ticket/13786
+ "aae-Latn-IT": "aae",
+ "aae-Thai-CO": "aae-Thai-CO",
+
+ // https://ssl.icu-project.org/trac/ticket/10220
+ // https://ssl.icu-project.org/trac/ticket/12345
+ "und-CW": "pap",
+ "und-US": "en",
+ "zh-Hant": "zh-TW",
+ "zh-Hani": "zh-Hani",
+};
+
+// Add variants, extensions, and privateuse subtags and ensure they don't
+// modify the result of the likely subtags algorithms.
+var extras = [
+ "fonipa",
+ "a-not-assigned",
+ "u-attr",
+ "u-co",
+ "u-co-phonebk",
+ "x-private",
+];
+
+for (var [tag, maximal] of Object.entries(testDataMaximal)) {
+ assertEq(new Intl.Locale(tag).maximize().toString(), maximal);
+ assertEq(new Intl.Locale(maximal).maximize().toString(), maximal);
+
+ for (var extra of extras) {
+ assertEq(new Intl.Locale(tag + "-" + extra).maximize().toString(), maximal + "-" + extra);
+ }
+}
+
+for (var [tag, minimal] of Object.entries(testDataMinimal)) {
+ assertEq(new Intl.Locale(tag).minimize().toString(), minimal);
+ assertEq(new Intl.Locale(minimal).minimize().toString(), minimal);
+
+ for (var extra of extras) {
+ assertEq(new Intl.Locale(tag + "-" + extra).minimize().toString(), minimal + "-" + extra);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/Locale/same-compartment.js b/js/src/tests/non262/Intl/Locale/same-compartment.js
new file mode 100644
index 0000000000..fb71c85f6c
--- /dev/null
+++ b/js/src/tests/non262/Intl/Locale/same-compartment.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.wrapWithProto)
+
+var tag = "de-Latn-AT-u-ca-gregory-nu-latn-co-phonebk-kf-false-kn-hc-h23";
+var locale = new Intl.Locale(tag);
+var scwLocale = wrapWithProto(locale, Intl.Locale.prototype);
+
+for (var [key, {get, value = get}] of Object.entries(Object.getOwnPropertyDescriptors(Intl.Locale.prototype))) {
+ if (typeof value === "function") {
+ if (key !== "constructor") {
+ var expectedValue = value.call(locale);
+
+ if (typeof expectedValue === "string" || typeof expectedValue === "boolean") {
+ assertEq(value.call(scwLocale), expectedValue, key);
+ } else if (expectedValue instanceof Intl.Locale) {
+ assertEq(value.call(scwLocale).toString(), expectedValue.toString(), key);
+ } else {
+ throw new Error("unexpected result value");
+ }
+ } else {
+ assertEq(new value(scwLocale).toString(), new value(locale).toString(), key);
+ }
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/Locale/shell.js b/js/src/tests/non262/Intl/Locale/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Intl/Locale/shell.js
diff --git a/js/src/tests/non262/Intl/Locale/surface.js b/js/src/tests/non262/Intl/Locale/surface.js
new file mode 100644
index 0000000000..ba90182436
--- /dev/null
+++ b/js/src/tests/non262/Intl/Locale/surface.js
@@ -0,0 +1,98 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+function assertProperty(object, name, desc) {
+ assertEq(desc === undefined || (typeof desc === "object" && desc !== null), true,
+ "desc is a property descriptor");
+
+ var actual = Object.getOwnPropertyDescriptor(object, name);
+ if (desc === undefined) {
+ assertEq(actual, desc, `property ${String(name)} is absent`);
+ return;
+ }
+ assertEq(actual !== undefined, true, `property ${String(name)} is present`);
+
+ var fields = ["value", "writable", "enumerable", "configurable", "get", "set"];
+ for (var field of fields) {
+ if (Object.prototype.hasOwnProperty.call(desc, field)) {
+ assertEq(actual[field], desc[field], `unexpected value for ${field}`);
+ }
+ }
+}
+
+function assertBuiltinFunction(fn, length, name) {
+ assertProperty(fn, "length", {
+ value: length, writable: false, enumerable: false, configurable: true,
+ });
+}
+
+function assertBuiltinMethod(object, propName, length, name) {
+ var desc = Object.getOwnPropertyDescriptor(object, propName);
+ assertProperty(object, propName, {
+ value: desc.value, writable: true, enumerable: false, configurable: true
+ });
+ assertBuiltinFunction(desc.value, length, name);
+}
+
+function assertBuiltinGetter(object, propName, length, name) {
+ var desc = Object.getOwnPropertyDescriptor(object, propName);
+
+ assertBuiltinFunction(desc.get, length, name);
+}
+
+// Intl.Locale( tag[, options] )
+assertBuiltinFunction(Intl.Locale, 1, "Locale");
+
+// Properties of the Intl.Locale Constructor
+
+// Intl.Locale.prototype
+assertProperty(Intl.Locale, "prototype", {
+ value: Intl.Locale.prototype, writable: false, enumerable: false, configurable: false,
+});
+
+// Properties of the Intl.Locale Prototype Object
+
+// Intl.Locale.prototype.constructor
+assertProperty(Intl.Locale.prototype, "constructor", {
+ value: Intl.Locale, writable: true, enumerable: false, configurable: true,
+});
+
+// Intl.Locale.prototype[ @@toStringTag ]
+assertProperty(Intl.Locale.prototype, Symbol.toStringTag, {
+ value: "Intl.Locale", writable: false, enumerable: false, configurable: true,
+});
+
+// Intl.Locale.prototype.toString ()
+assertBuiltinMethod(Intl.Locale.prototype, "toString", 0, "toString");
+
+// get Intl.Locale.prototype.baseName
+assertBuiltinGetter(Intl.Locale.prototype, "baseName", 0, "get baseName");
+
+// get Intl.Locale.prototype.calendar
+assertBuiltinGetter(Intl.Locale.prototype, "calendar", 0, "get calendar");
+
+// get Intl.Locale.prototype.collation
+assertBuiltinGetter(Intl.Locale.prototype, "collation", 0, "get collation");
+
+// get Intl.Locale.prototype.hourCycle
+assertBuiltinGetter(Intl.Locale.prototype, "hourCycle", 0, "get hourCycle");
+
+// get Intl.Locale.prototype.caseFirst
+assertBuiltinGetter(Intl.Locale.prototype, "caseFirst", 0, "get caseFirst");
+
+// get Intl.Locale.prototype.numeric
+assertBuiltinGetter(Intl.Locale.prototype, "numeric", 0, "get numeric");
+
+// get Intl.Locale.prototype.numberingSystem
+assertBuiltinGetter(Intl.Locale.prototype, "numberingSystem", 0, "get numberingSystem");
+
+// get Intl.Locale.prototype.language
+assertBuiltinGetter(Intl.Locale.prototype, "language", 0, "get language");
+
+// get Intl.Locale.prototype.script
+assertBuiltinGetter(Intl.Locale.prototype, "script", 0, "get script");
+
+// get Intl.Locale.prototype.region
+assertBuiltinGetter(Intl.Locale.prototype, "region", 0, "get region");
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/NumberFormat/StringBuffer.js b/js/src/tests/non262/Intl/NumberFormat/StringBuffer.js
new file mode 100644
index 0000000000..70aaa7bd75
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/StringBuffer.js
@@ -0,0 +1,37 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// The implementation of the format function uses the C++ StringBuffer class,
+// which changes its storage model at 32 characters, and uses it in a way which
+// also means that there's no room for null-termination at this limit.
+// This test makes sure that none of this affects the output.
+
+var format = new Intl.NumberFormat("it-IT", {minimumFractionDigits: 1});
+
+assertEq(format.format(1123123123123123123123.1), "1.123.123.123.123.123.100.000,0");
+assertEq(format.format(12123123123123123123123.1), "12.123.123.123.123.122.000.000,0");
+assertEq(format.format(123123123123123123123123.1), "123.123.123.123.123.120.000.000,0");
+
+// Ensure the ICU output matches Number.prototype.toFixed.
+function formatToFixed(x) {
+ var mfd = format.resolvedOptions().maximumFractionDigits;
+ var s = x.toFixed(mfd);
+
+ // To keep it simple we assume |s| is always in exponential form.
+ var m = s.match(/^(\d)\.(\d+)e\+(\d+)$/);
+ assertEq(m !== null, true);
+ s = m[1] + m[2].padEnd(m[3], "0");
+
+ // Group digits and append fractional part.
+ m = s.match(/\d{1,3}(?=(?:\d{3})*$)/g);
+ assertEq(m !== null, true);
+ return m.join(".") + ",0";
+}
+
+assertEq(formatToFixed(1123123123123123123123.1), "1.123.123.123.123.123.100.000,0");
+assertEq(formatToFixed(12123123123123123123123.1), "12.123.123.123.123.122.000.000,0");
+assertEq(formatToFixed(123123123123123123123123.1), "123.123.123.123.123.120.000.000,0");
+
+reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/NumberFormat/bigint-int64.js b/js/src/tests/non262/Intl/NumberFormat/bigint-int64.js
new file mode 100644
index 0000000000..7b670d0873
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/bigint-int64.js
@@ -0,0 +1,40 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Ensure the int64_t optimization when formatting a BigInt value works correctly by testing with
+// various integers around the (u)int[32,64] limits.
+
+const limits = {
+ int32: {
+ min: -0x80000000n,
+ max: 0x7FFFFFFFn,
+ },
+ uint32: {
+ min: 0n,
+ max: 0xFFFFFFFFn
+ },
+ int64: {
+ min: -0x8000000000000000n,
+ max: 0x7FFFFFFFFFFFFFFFn,
+ },
+ uint64: {
+ min: 0n,
+ max: 0xFFFFFFFFFFFFFFFFn
+ },
+};
+
+const nf = new Intl.NumberFormat("en", {useGrouping: false});
+
+const diff = 10n;
+
+for (const int of Object.values(limits)) {
+ for (let i = -diff; i <= diff; ++i) {
+ let n = int.min + i;
+ assertEq(nf.format(n), n.toString());
+
+ let m = int.max + i;
+ assertEq(nf.format(m), m.toString());
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/browser.js b/js/src/tests/non262/Intl/NumberFormat/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/browser.js
diff --git a/js/src/tests/non262/Intl/NumberFormat/call.js b/js/src/tests/non262/Intl/NumberFormat/call.js
new file mode 100644
index 0000000000..14ecf99eb5
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/call.js
@@ -0,0 +1,184 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+function IsIntlService(c) {
+ return typeof c === "function" &&
+ c.hasOwnProperty("prototype") &&
+ c.prototype.hasOwnProperty("resolvedOptions");
+}
+
+function IsObject(o) {
+ return Object(o) === o;
+}
+
+function IsPrimitive(o) {
+ return Object(o) !== o;
+}
+
+function thisValues() {
+ const intlConstructors = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService);
+
+ return [
+ // Primitive values.
+ ...[undefined, null, true, "abc", Symbol(), 123],
+
+ // Object values.
+ ...[{}, [], /(?:)/, function(){}, new Proxy({}, {})],
+
+ // Intl objects.
+ ...[].concat(...intlConstructors.map(ctor => {
+ let args = [];
+ if (ctor === Intl.DisplayNames) {
+ // Intl.DisplayNames can't be constructed without any arguments.
+ args = [undefined, {type: "language"}];
+ }
+
+ return [
+ // Instance of an Intl constructor.
+ new ctor(...args),
+
+ // Instance of a subclassed Intl constructor.
+ new class extends ctor {}(...args),
+
+ // Object inheriting from an Intl constructor prototype.
+ Object.create(ctor.prototype),
+
+ // Intl object not inheriting from its default prototype.
+ Object.setPrototypeOf(new ctor(...args), Object.prototype),
+ ];
+ })),
+ ];
+}
+
+const intlFallbackSymbol = Object.getOwnPropertySymbols(Intl.NumberFormat.call(Object.create(Intl.NumberFormat.prototype)))[0];
+
+// Invoking [[Call]] for Intl.NumberFormat returns a new instance unless called
+// with an instance inheriting from Intl.NumberFormat.prototype.
+for (let thisValue of thisValues()) {
+ let obj = Intl.NumberFormat.call(thisValue);
+
+ if (!Intl.NumberFormat.prototype.isPrototypeOf(thisValue)) {
+ assertEq(Object.is(obj, thisValue), false);
+ assertEq(obj instanceof Intl.NumberFormat, true);
+ if (IsObject(thisValue))
+ assertEqArray(Object.getOwnPropertySymbols(thisValue), []);
+ } else {
+ assertEq(Object.is(obj, thisValue), true);
+ assertEq(obj instanceof Intl.NumberFormat, true);
+ assertEqArray(Object.getOwnPropertySymbols(thisValue), [intlFallbackSymbol]);
+ }
+}
+
+// Intl.NumberFormat uses the legacy Intl constructor compromise semantics.
+// - Test when InstanceofOperator(thisValue, %NumberFormat%) returns true.
+for (let thisValue of thisValues().filter(IsObject)) {
+ let isPrototypeOf = Intl.NumberFormat.prototype.isPrototypeOf(thisValue);
+ let hasInstanceCalled = false;
+ Object.defineProperty(Intl.NumberFormat, Symbol.hasInstance, {
+ value() {
+ assertEq(hasInstanceCalled, false);
+ hasInstanceCalled = true;
+ return true;
+ }, configurable: true
+ });
+ let obj = Intl.NumberFormat.call(thisValue);
+ delete Intl.NumberFormat[Symbol.hasInstance];
+
+ assertEq(Object.is(obj, thisValue), isPrototypeOf);
+ assertEq(hasInstanceCalled, false);
+ assertEqArray(Object.getOwnPropertySymbols(thisValue), isPrototypeOf ? [intlFallbackSymbol] : []);
+}
+// - Test when InstanceofOperator(thisValue, %NumberFormat%) returns false.
+for (let thisValue of thisValues().filter(IsObject)) {
+ let isPrototypeOf = Intl.NumberFormat.prototype.isPrototypeOf(thisValue);
+ let hasInstanceCalled = false;
+ Object.defineProperty(Intl.NumberFormat, Symbol.hasInstance, {
+ value() {
+ assertEq(hasInstanceCalled, false);
+ hasInstanceCalled = true;
+ return false;
+ }, configurable: true
+ });
+ let obj = Intl.NumberFormat.call(thisValue);
+ delete Intl.NumberFormat[Symbol.hasInstance];
+
+ assertEq(Object.is(obj, thisValue), isPrototypeOf);
+ assertEq(obj instanceof Intl.NumberFormat, true);
+ assertEq(hasInstanceCalled, false);
+ assertEqArray(Object.getOwnPropertySymbols(thisValue), isPrototypeOf ? [intlFallbackSymbol] : []);
+}
+// - Test with primitive values.
+for (let thisValue of thisValues().filter(IsPrimitive)) {
+ // Ensure @@hasInstance is not called.
+ Object.defineProperty(Intl.NumberFormat, Symbol.hasInstance, {
+ value() { assertEq(true, false); }, configurable: true
+ });
+ let obj = Intl.NumberFormat.call(thisValue);
+ delete Intl.NumberFormat[Symbol.hasInstance];
+
+ assertEq(Object.is(obj, thisValue), false);
+ assertEq(obj instanceof Intl.NumberFormat, true);
+}
+
+// Throws an error when attempting to install [[FallbackSymbol]] twice.
+{
+ let thisValue = Object.create(Intl.NumberFormat.prototype);
+ assertEqArray(Object.getOwnPropertySymbols(thisValue), []);
+
+ assertEq(Intl.NumberFormat.call(thisValue), thisValue);
+ assertEqArray(Object.getOwnPropertySymbols(thisValue), [intlFallbackSymbol]);
+
+ assertThrowsInstanceOf(() => Intl.NumberFormat.call(thisValue), TypeError);
+ assertEqArray(Object.getOwnPropertySymbols(thisValue), [intlFallbackSymbol]);
+}
+
+// Throws an error when the thisValue is non-extensible.
+{
+ let thisValue = Object.create(Intl.NumberFormat.prototype);
+ Object.preventExtensions(thisValue);
+
+ assertThrowsInstanceOf(() => Intl.NumberFormat.call(thisValue), TypeError);
+ assertEqArray(Object.getOwnPropertySymbols(thisValue), []);
+}
+
+// [[FallbackSymbol]] is installed as a frozen property holding an Intl.NumberFormat instance.
+{
+ let thisValue = Object.create(Intl.NumberFormat.prototype);
+ Intl.NumberFormat.call(thisValue);
+
+ let desc = Object.getOwnPropertyDescriptor(thisValue, intlFallbackSymbol);
+ assertEq(desc !== undefined, true);
+ assertEq(desc.writable, false);
+ assertEq(desc.enumerable, false);
+ assertEq(desc.configurable, false);
+ assertEq(desc.value instanceof Intl.NumberFormat, true);
+}
+
+// Ensure [[FallbackSymbol]] is installed last by changing the [[Prototype]]
+// during initialization.
+{
+ let thisValue = {};
+ let options = {
+ get useGrouping() {
+ Object.setPrototypeOf(thisValue, Intl.NumberFormat.prototype);
+ return false;
+ }
+ };
+ let obj = Intl.NumberFormat.call(thisValue, undefined, options);
+ assertEq(Object.is(obj, thisValue), true);
+ assertEqArray(Object.getOwnPropertySymbols(thisValue), [intlFallbackSymbol]);
+}
+{
+ let thisValue = Object.create(Intl.NumberFormat.prototype);
+ let options = {
+ get useGrouping() {
+ Object.setPrototypeOf(thisValue, Object.prototype);
+ return false;
+ }
+ };
+ let obj = Intl.NumberFormat.call(thisValue, undefined, options);
+ assertEq(Object.is(obj, thisValue), false);
+ assertEqArray(Object.getOwnPropertySymbols(thisValue), []);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/construct-newtarget.js b/js/src/tests/non262/Intl/NumberFormat/construct-newtarget.js
new file mode 100644
index 0000000000..0053b2737e
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/construct-newtarget.js
@@ -0,0 +1,81 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+
+// Test subclassing %Intl.NumberFormat% works correctly.
+class MyNumberFormat extends Intl.NumberFormat {}
+
+var obj = new MyNumberFormat();
+assertEq(obj instanceof MyNumberFormat, true);
+assertEq(obj instanceof Intl.NumberFormat, true);
+assertEq(Object.getPrototypeOf(obj), MyNumberFormat.prototype);
+
+obj = Reflect.construct(MyNumberFormat, []);
+assertEq(obj instanceof MyNumberFormat, true);
+assertEq(obj instanceof Intl.NumberFormat, true);
+assertEq(Object.getPrototypeOf(obj), MyNumberFormat.prototype);
+
+obj = Reflect.construct(MyNumberFormat, [], MyNumberFormat);
+assertEq(obj instanceof MyNumberFormat, true);
+assertEq(obj instanceof Intl.NumberFormat, true);
+assertEq(Object.getPrototypeOf(obj), MyNumberFormat.prototype);
+
+obj = Reflect.construct(MyNumberFormat, [], Intl.NumberFormat);
+assertEq(obj instanceof MyNumberFormat, false);
+assertEq(obj instanceof Intl.NumberFormat, true);
+assertEq(Object.getPrototypeOf(obj), Intl.NumberFormat.prototype);
+
+
+// Set a different constructor as NewTarget.
+obj = Reflect.construct(MyNumberFormat, [], Array);
+assertEq(obj instanceof MyNumberFormat, false);
+assertEq(obj instanceof Intl.NumberFormat, false);
+assertEq(obj instanceof Array, true);
+assertEq(Object.getPrototypeOf(obj), Array.prototype);
+
+obj = Reflect.construct(Intl.NumberFormat, [], Array);
+assertEq(obj instanceof Intl.NumberFormat, false);
+assertEq(obj instanceof Array, true);
+assertEq(Object.getPrototypeOf(obj), Array.prototype);
+
+
+// The prototype defaults to %NumberFormatPrototype% if null.
+function NewTargetNullPrototype() {}
+NewTargetNullPrototype.prototype = null;
+
+obj = Reflect.construct(Intl.NumberFormat, [], NewTargetNullPrototype);
+assertEq(obj instanceof Intl.NumberFormat, true);
+assertEq(Object.getPrototypeOf(obj), Intl.NumberFormat.prototype);
+
+obj = Reflect.construct(MyNumberFormat, [], NewTargetNullPrototype);
+assertEq(obj instanceof MyNumberFormat, false);
+assertEq(obj instanceof Intl.NumberFormat, true);
+assertEq(Object.getPrototypeOf(obj), Intl.NumberFormat.prototype);
+
+
+// "prototype" property is retrieved exactly once.
+var trapLog = [], getLog = [];
+var ProxiedConstructor = new Proxy(Intl.NumberFormat, new Proxy({
+ get(target, propertyKey, receiver) {
+ getLog.push(propertyKey);
+ return Reflect.get(target, propertyKey, receiver);
+ }
+}, {
+ get(target, propertyKey, receiver) {
+ trapLog.push(propertyKey);
+ return Reflect.get(target, propertyKey, receiver);
+ }
+}));
+
+obj = Reflect.construct(Intl.NumberFormat, [], ProxiedConstructor);
+assertEqArray(trapLog, ["get"]);
+assertEqArray(getLog, ["prototype"]);
+assertEq(obj instanceof Intl.NumberFormat, true);
+assertEq(Object.getPrototypeOf(obj), Intl.NumberFormat.prototype);
+
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/NumberFormat/cross-compartment.js b/js/src/tests/non262/Intl/NumberFormat/cross-compartment.js
new file mode 100644
index 0000000000..806f889d6f
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/cross-compartment.js
@@ -0,0 +1,70 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+var otherGlobal = newGlobal();
+
+var numberFormat = new Intl.NumberFormat();
+var ccwNumberFormat = new otherGlobal.Intl.NumberFormat();
+
+// Test Intl.NumberFormat.prototype.format with a CCW object.
+var Intl_NumberFormat_format_get = Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, "format").get;
+
+assertEq(Intl_NumberFormat_format_get.call(ccwNumberFormat)(0),
+ Intl_NumberFormat_format_get.call(numberFormat)(0));
+
+// Test Intl.NumberFormat.prototype.formatToParts with a CCW object.
+var Intl_NumberFormat_formatToParts = Intl.NumberFormat.prototype.formatToParts;
+
+assertEq(deepEqual(Intl_NumberFormat_formatToParts.call(ccwNumberFormat, 0),
+ Intl_NumberFormat_formatToParts.call(numberFormat, 0)),
+ true);
+
+// Test Intl.NumberFormat.prototype.resolvedOptions with a CCW object.
+var Intl_NumberFormat_resolvedOptions = Intl.NumberFormat.prototype.resolvedOptions;
+
+assertEq(deepEqual(Intl_NumberFormat_resolvedOptions.call(ccwNumberFormat),
+ Intl_NumberFormat_resolvedOptions.call(numberFormat)),
+ true);
+
+// Special case for Intl.NumberFormat: The Intl fallback symbol.
+
+function fallbackSymbol(global) {
+ var NF = global.Intl.NumberFormat;
+ return Object.getOwnPropertySymbols(NF.call(Object.create(NF.prototype)))[0];
+}
+
+const intlFallbackSymbol = fallbackSymbol(this);
+const otherIntlFallbackSymbol = fallbackSymbol(otherGlobal);
+assertEq(intlFallbackSymbol === otherIntlFallbackSymbol, false);
+
+// Test when the fallback symbol points to a CCW NumberFormat object.
+var objWithFallbackCCWNumberFormat = {
+ __proto__: Intl.NumberFormat.prototype,
+ [intlFallbackSymbol]: ccwNumberFormat,
+};
+
+assertEq(Intl_NumberFormat_format_get.call(objWithFallbackCCWNumberFormat)(0),
+ Intl_NumberFormat_format_get.call(numberFormat)(0));
+
+assertEq(deepEqual(Intl_NumberFormat_resolvedOptions.call(objWithFallbackCCWNumberFormat),
+ Intl_NumberFormat_resolvedOptions.call(numberFormat)),
+ true);
+
+// Ensure the fallback symbol(s) are not accessed for CCW NumberFormat objects.
+var ccwNumberFormatWithPoisonedFallback = new otherGlobal.Intl.NumberFormat();
+Object.setPrototypeOf(ccwNumberFormatWithPoisonedFallback, Intl.NumberFormat.prototype);
+Object.defineProperty(ccwNumberFormatWithPoisonedFallback, intlFallbackSymbol, {
+ get() { throw new Error(); }
+});
+Object.defineProperty(ccwNumberFormatWithPoisonedFallback, otherIntlFallbackSymbol, {
+ get() { throw new Error(); }
+});
+
+assertEq(Intl_NumberFormat_format_get.call(ccwNumberFormatWithPoisonedFallback)(0),
+ Intl_NumberFormat_format_get.call(numberFormat)(0));
+
+assertEq(deepEqual(Intl_NumberFormat_resolvedOptions.call(ccwNumberFormatWithPoisonedFallback),
+ Intl_NumberFormat_resolvedOptions.call(numberFormat)),
+ true);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/currency-narrow-symbol.js b/js/src/tests/non262/Intl/NumberFormat/currency-narrow-symbol.js
new file mode 100644
index 0000000000..bf2b9adcd8
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/currency-narrow-symbol.js
@@ -0,0 +1,40 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const {
+ Integer, Decimal, Fraction, Currency, Literal,
+} = NumberFormatParts;
+
+const testcases = [
+ {
+ locale: "en-CA",
+ options: {
+ style: "currency",
+ currency: "USD",
+ currencyDisplay: "narrowSymbol",
+ },
+ values: [
+ {value: 123, string: "US$123.00",
+ parts: [Currency("US$"), Integer("123"), Decimal("."), Fraction("00")]},
+ ],
+ },
+
+ // And for comparison "symbol" currency-display.
+
+ {
+ locale: "en-CA",
+ options: {
+ style: "currency",
+ currency: "USD",
+ currencyDisplay: "symbol",
+ },
+ values: [
+ {value: 123, string: "US$123.00",
+ parts: [Currency("US$"), Integer("123"), Decimal("."), Fraction("00")]},
+ ],
+ },
+];
+
+runNumberFormattingTestcases(testcases);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/currency-sign-accounting.js b/js/src/tests/non262/Intl/NumberFormat/currency-sign-accounting.js
new file mode 100644
index 0000000000..6f91d6edd4
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/currency-sign-accounting.js
@@ -0,0 +1,192 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const {
+ Nan, Inf, Integer, MinusSign, PlusSign, Decimal, Fraction,
+ Currency, Literal,
+} = NumberFormatParts;
+
+const testcases = [
+ // "auto": Show the sign on negative numbers only.
+ {
+ locale: "en",
+ options: {
+ style: "currency",
+ currency: "USD",
+ currencySign: "accounting",
+ signDisplay: "auto",
+ },
+ values: [
+ {value: +0, string: "$0.00",
+ parts: [Currency("$"), Integer("0"), Decimal("."), Fraction("00")]},
+ {value: -0, string: "($0.00)",
+ parts: [Literal("("), Currency("$"), Integer("0"), Decimal("."), Fraction("00"), Literal(")")]},
+
+ {value: 1, string: "$1.00",
+ parts: [Currency("$"), Integer("1"), Decimal("."), Fraction("00")]},
+ {value: -1, string: "($1.00)",
+ parts: [Literal("("), Currency("$"), Integer("1"), Decimal("."), Fraction("00"), Literal(")")]},
+
+ {value: Infinity, string: "$∞", parts: [Currency("$"), Inf("∞")]},
+ {value: -Infinity, string: "($∞)", parts: [Literal("("), Currency("$"), Inf("∞"), Literal(")")]},
+
+ {value: NaN, string: "$NaN", parts: [Currency("$"), Nan("NaN")]},
+ {value: -NaN, string: "$NaN", parts: [Currency("$"), Nan("NaN")]},
+ ],
+ },
+
+ // "never": Show the sign on neither positive nor negative numbers.
+ {
+ locale: "en",
+ options: {
+ style: "currency",
+ currency: "USD",
+ currencySign: "accounting",
+ signDisplay: "never",
+ },
+ values: [
+ {value: +0, string: "$0.00", parts: [Currency("$"), Integer("0"), Decimal("."), Fraction("00")]},
+ {value: -0, string: "$0.00", parts: [Currency("$"), Integer("0"), Decimal("."), Fraction("00")]},
+
+ {value: 1, string: "$1.00", parts: [Currency("$"), Integer("1"), Decimal("."), Fraction("00")]},
+ {value: -1, string: "$1.00", parts: [Currency("$"), Integer("1"), Decimal("."), Fraction("00")]},
+
+ {value: Infinity, string: "$∞", parts: [Currency("$"), Inf("∞")]},
+ {value: -Infinity, string: "$∞", parts: [Currency("$"), Inf("∞")]},
+
+ {value: NaN, string: "$NaN", parts: [Currency("$"), Nan("NaN")]},
+ {value: -NaN, string: "$NaN", parts: [Currency("$"), Nan("NaN")]},
+ ],
+ },
+
+ // "always": Show the sign on positive and negative numbers including zero.
+ {
+ locale: "en",
+ options: {
+ style: "currency",
+ currency: "USD",
+ currencySign: "accounting",
+ signDisplay: "always",
+ },
+ values: [
+ {value: +0, string: "+$0.00",
+ parts: [PlusSign("+"), Currency("$"), Integer("0"), Decimal("."), Fraction("00")]},
+ {value: -0, string: "($0.00)",
+ parts: [Literal("("), Currency("$"), Integer("0"), Decimal("."), Fraction("00"), Literal(")")]},
+
+ {value: 1, string: "+$1.00",
+ parts: [PlusSign("+"), Currency("$"), Integer("1"), Decimal("."), Fraction("00")]},
+ {value: -1, string: "($1.00)",
+ parts: [Literal("("), Currency("$"), Integer("1"), Decimal("."), Fraction("00"), Literal(")")]},
+
+ {value: Infinity, string: "+$∞", parts: [PlusSign("+"), Currency("$"), Inf("∞")]},
+ {value: -Infinity, string: "($∞)", parts: [Literal("("), Currency("$"), Inf("∞"), Literal(")")]},
+
+ {value: NaN, string: "+$NaN", parts: [PlusSign("+"), Currency("$"), Nan("NaN")]},
+ {value: -NaN, string: "+$NaN", parts: [PlusSign("+"), Currency("$"), Nan("NaN")]},
+ ],
+ },
+
+ // "exceptZero": Show the sign on positive and negative numbers but not zero.
+ {
+ locale: "en",
+ options: {
+ style: "currency",
+ currency: "USD",
+ currencySign: "accounting",
+ signDisplay: "exceptZero",
+ },
+ values: [
+ {value: +0, string: "$0.00",
+ parts: [Currency("$"), Integer("0"), Decimal("."), Fraction("00")]},
+ {value: -0, string: "$0.00",
+ parts: [Currency("$"), Integer("0"), Decimal("."), Fraction("00")]},
+
+ {value: 1, string: "+$1.00",
+ parts: [PlusSign("+"), Currency("$"), Integer("1"), Decimal("."), Fraction("00")]},
+ {value: -1, string: "($1.00)",
+ parts: [Literal("("), Currency("$"), Integer("1"), Decimal("."), Fraction("00"), Literal(")")]},
+
+ {value: Infinity, string: "+$∞", parts: [PlusSign("+"), Currency("$"), Inf("∞")]},
+ {value: -Infinity, string: "($∞)", parts: [Literal("("), Currency("$"), Inf("∞"), Literal(")")]},
+
+ {value: NaN, string: "$NaN", parts: [Currency("$"), Nan("NaN")]},
+ {value: -NaN, string: "$NaN", parts: [Currency("$"), Nan("NaN")]},
+ ],
+ },
+
+ // Tests with suppressed fractional digits.
+
+ // "auto": Show the sign on negative numbers only.
+ {
+ locale: "en",
+ options: {
+ style: "currency",
+ currency: "USD",
+ currencySign: "accounting",
+ signDisplay: "auto",
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ },
+ values: [
+ {value: +0.1, string: "$0", parts: [Currency("$"), Integer("0")]},
+ {value: -0.1, string: "($0)", parts: [Literal("("), Currency("$"), Integer("0"), Literal(")")]},
+ ],
+ },
+
+ // "never": Show the sign on neither positive nor negative numbers.
+ {
+ locale: "en",
+ options: {
+ style: "currency",
+ currency: "USD",
+ currencySign: "accounting",
+ signDisplay: "never",
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ },
+ values: [
+ {value: +0.1, string: "$0", parts: [Currency("$"), Integer("0")]},
+ {value: -0.1, string: "$0", parts: [Currency("$"), Integer("0")]},
+ ],
+ },
+
+ // "always": Show the sign on positive and negative numbers including zero.
+ {
+ locale: "en",
+ options: {
+ style: "currency",
+ currency: "USD",
+ currencySign: "accounting",
+ signDisplay: "always",
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ },
+ values: [
+ {value: +0.1, string: "+$0", parts: [PlusSign("+"), Currency("$"), Integer("0")]},
+ {value: -0.1, string: "($0)", parts: [Literal("("), Currency("$"), Integer("0"), Literal(")")]},
+ ],
+ },
+
+ // "exceptZero": Show the sign on positive and negative numbers but not zero.
+ {
+ locale: "en",
+ options: {
+ style: "currency",
+ currency: "USD",
+ currencySign: "accounting",
+ signDisplay: "exceptZero",
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ },
+
+ values: [
+ {value: +0.1, string: "$0", parts: [Currency("$"), Integer("0")]},
+ {value: -0.1, string: "$0", parts: [Currency("$"), Integer("0")]},
+ ],
+ }
+];
+
+runNumberFormattingTestcases(testcases);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/duplicate-singleton-variant.js b/js/src/tests/non262/Intl/NumberFormat/duplicate-singleton-variant.js
new file mode 100644
index 0000000000..42bf78c3fe
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/duplicate-singleton-variant.js
@@ -0,0 +1,49 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Check for duplicate variants and singletons case-insensitively, but don't
+// check in privateuse components.
+
+function checkInvalidLocale(locale)
+{
+ try
+ {
+ new Intl.NumberFormat(locale);
+ throw new Error("didn't throw");
+ }
+ catch (e)
+ {
+ assertEq(e instanceof RangeError, true,
+ "expected RangeError for locale '" + locale + "', got " + e);
+ }
+}
+
+var badLocales =
+ [
+ "en-u-foo-U-foo",
+ "en-tester-Tester",
+ "en-tesTER-TESter",
+ "de-DE-u-kn-true-U-kn-true",
+ "ar-u-foo-q-bar-u-baz",
+ "ar-z-moo-u-foo-q-bar-z-eit-u-baz",
+ ];
+
+for (var locale of badLocales)
+ checkInvalidLocale(locale);
+
+// Fully-privateuse locales are rejected.
+for (var locale of badLocales)
+ assertThrowsInstanceOf(() => new Intl.NumberFormat("x-" + locale), RangeError);
+
+// Locales with trailing privateuse also okay.
+for (var locale of badLocales)
+{
+ new Intl.NumberFormat("en-x-" + locale).format(5);
+ new Intl.NumberFormat("en-u-foo-x-u-" + locale).format(5);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/format-as-code-or-name.js b/js/src/tests/non262/Intl/NumberFormat/format-as-code-or-name.js
new file mode 100644
index 0000000000..ba257ecd71
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/format-as-code-or-name.js
@@ -0,0 +1,75 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 1093421;
+var summary =
+ "new Intl.NumberFormat(..., { style: 'currency', currency: '...', " +
+ "currencyDisplay: 'name' or 'code' }) should have behavior other than " +
+ "throwing";
+
+print(BUGNUMBER + ": " + summary);
+
+//-----------------------------------------------------------------------------
+
+// Test that currencyDisplay: "code" behaves correctly and doesn't throw.
+
+var usdCodeOptions =
+ {
+ style: "currency",
+ currency: "USD",
+ currencyDisplay: "code",
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ };
+var usDollarsCode = new Intl.NumberFormat("en-US", usdCodeOptions);
+assertEq(/USD/.test(usDollarsCode.format(25)), true);
+
+// ISO 4217 currency codes are formed from an ISO 3166-1 alpha-2 country code
+// followed by a third letter. ISO 3166 guarantees that no country code
+// starting with "X" will ever be assigned. Stepping carefully around a few
+// 4217-designated special "currencies", XQQ will never have a representation.
+// Thus, yes: this really is specified to work, as unrecognized or unsupported
+// codes pass into the string unmodified.
+var xqqCodeOptions =
+ {
+ style: "currency",
+ currency: "XQQ",
+ currencyDisplay: "code",
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ };
+var xqqMoneyCode = new Intl.NumberFormat("en-US", xqqCodeOptions);
+assertEq(/XQQ/.test(xqqMoneyCode.format(25)), true);
+
+// Test that currencyDisplay: "name" behaves without throwing. (Unlike the two
+// above tests, the results here aren't guaranteed as the name is
+// implementation-defined.)
+var usdNameOptions =
+ {
+ style: "currency",
+ currency: "USD",
+ currencyDisplay: "name",
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ };
+var usDollarsName = new Intl.NumberFormat("en-US", usdNameOptions);
+assertEq(usDollarsName.format(25), "25 US dollars");
+
+// But if the implementation doesn't recognize the currency, the provided code
+// is used in place of a proper name, unmolested.
+var xqqNameOptions =
+ {
+ style: "currency",
+ currency: "XQQ",
+ currencyDisplay: "name",
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ };
+var xqqMoneyName = new Intl.NumberFormat("en-US", xqqNameOptions);
+assertEq(/XQQ/.test(xqqMoneyName.format(25)), true);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/format-string.js b/js/src/tests/non262/Intl/NumberFormat/format-string.js
new file mode 100644
index 0000000000..88b11008d9
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/format-string.js
@@ -0,0 +1,150 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||release_or_beta)
+
+function groupByThree(s) {
+ return String(s).split("").reduceRight((acc, x) => x + (acc.match(/^\d{3}/) ? "," : "") + acc, "");
+}
+
+const tests = [
+ {value: "", expected: "0"},
+ {value: "0", expected: "0"},
+ {value: "+0", expected: "0"},
+ {value: "-0", expected: "-0"},
+
+ {value: "Infinity", expected: "∞"},
+ {value: "+Infinity", expected: "∞"},
+ {value: "-Infinity", expected: "-∞"},
+
+ {value: "NaN", expected: "NaN"},
+ {value: "invalid", expected: "NaN"},
+
+ // Integer 1 with and without fractional/exponent part.
+ {value: "1", expected: "1"},
+ {value: "1.", expected: "1"},
+ {value: "1.0", expected: "1"},
+ {value: "1.00", expected: "1"},
+ {value: "1e0", expected: "1"},
+ {value: "1e+0", expected: "1"},
+ {value: "1e-0", expected: "1"},
+
+ // Leading zeros.
+ {value: "01", expected: "1"},
+ {value: "01.", expected: "1"},
+ {value: "01.0", expected: "1"},
+ {value: "01.00", expected: "1"},
+ {value: "01e0", expected: "1"},
+ {value: "01e+0", expected: "1"},
+ {value: "01e-0", expected: "1"},
+
+ // Large values.
+ {value: "1e300", expected: "1" + ",000".repeat(100)},
+ {value: "1e3000", expected: "1" + ",000".repeat(1000)},
+ {value: "9007199254740991", expected: "9,007,199,254,740,991"},
+ {value: "9007199254740992", expected: "9,007,199,254,740,992"},
+ {value: "9007199254740993", expected: "9,007,199,254,740,993"},
+
+ {value: "-1e300", expected: "-1" + ",000".repeat(100)},
+ {value: "-1e3000", expected: "-1" + ",000".repeat(1000)},
+ {value: "-9007199254740991", expected: "-9,007,199,254,740,991"},
+ {value: "-9007199254740992", expected: "-9,007,199,254,740,992"},
+ {value: "-9007199254740993", expected: "-9,007,199,254,740,993"},
+
+ // Small values.
+ {value: "0.10000000000000000001", expected: "0.10000000000000000001"},
+ {value: "0.00000000000000000001", expected: "0.00000000000000000001"},
+ {value: "1e-20", expected: "0.00000000000000000001"},
+ {value: "1e-30", expected: "0"},
+
+ {value: "-0.10000000000000000001", expected: "-0.10000000000000000001"},
+ {value: "-0.00000000000000000001", expected: "-0.00000000000000000001"},
+ {value: "-1e-20", expected: "-0.00000000000000000001"},
+ {value: "-1e-30", expected: "-0"},
+
+ // Non-standard exponent notation.
+ {value: ".001e-2", expected: "0.00001"},
+ {value: "123.001e-2", expected: "1.23001"},
+ {value: "1000e-2", expected: "10"},
+ {value: "1000e+2", expected: "100,000"},
+ {value: "1000e-0", expected: "1,000"},
+
+ // Non-decimal strings.
+ {value: "0b101", expected: "5"},
+ {value: "0o377", expected: "255"},
+ {value: "0xdeadBEEF", expected: "3,735,928,559"},
+ {value: "0B0011", expected: "3"},
+ {value: "0O0777", expected: "511"},
+ {value: "0X0ABC", expected: "2,748"},
+ {value: "0b" + "1".repeat(1000), expected: groupByThree((2n ** 1000n) - 1n)},
+ {value: "0o1" + "7".repeat(333), expected: groupByThree((2n ** 1000n) - 1n)},
+ {value: "0x" + "f".repeat(250), expected: groupByThree((2n ** 1000n) - 1n)},
+
+ // Non-decimal strings don't accept a sign.
+ {value: "+0xbad", expected: "NaN"},
+ {value: "-0xbad", expected: "NaN"},
+];
+
+// https://tc39.es/ecma262/#prod-StrWhiteSpaceChar
+const strWhiteSpaceChar = [
+ "",
+
+ // https://tc39.es/ecma262/#sec-white-space
+ "\t", "\v", "\f", " ", "\u00A0", "\uFEFF",
+ "\u1680", "\u2000", "\u2001", "\u2002", "\u2003", "\u2004", "\u2005", "\u2006",
+ "\u2007", "\u2008", "\u2009", "\u200A", "\u202F", "\u205F", "\u3000",
+
+ // https://tc39.es/ecma262/#sec-line-terminators
+ "\n", "\r", "\u2028", "\u2029",
+];
+
+let nf = new Intl.NumberFormat("en", {maximumFractionDigits: 20});
+for (let {value, expected} of tests) {
+ for (let ws of strWhiteSpaceChar) {
+ assertEq(nf.format(ws + value), expected);
+ assertEq(nf.format(value + ws), expected);
+ assertEq(nf.format(ws + value + ws), expected);
+ }
+}
+
+// The specification doesn't impose any limits for the exponent, but we throw
+// an error if the exponent is too large.
+{
+ let nf = new Intl.NumberFormat("en", {useGrouping: false});
+ for (let value of [
+ // ICU limit is 999'999'999 (exclusive).
+ ".1e-999999999",
+ ".1e+999999999",
+
+ // We limit positive exponents to 9'999'999 (inclusive).
+ "1e+9999999",
+ "1e+99999999",
+
+ // Int32 overflow when computing the exponent.
+ ".1e-2147483649",
+ ".1e-2147483648",
+ ".1e-2147483647",
+ ".1e+2147483647",
+ ".1e+2147483648",
+ ".1e+2147483649",
+ ]) {
+ assertThrowsInstanceOf(() => nf.format(value), RangeError);
+ }
+
+ // We allow up to ±9'999'999.
+ assertEq(nf.format(".1e-9999999"), "0");
+ assertEq(nf.format(".1e+9999999"), "1" + "0".repeat(9_999_999 - 1));
+
+ // Negative exponents are even valid up to -999'999'998
+ assertEq(nf.format(".1e-999999998"), "0");
+}
+
+// Combine extreme values with other rounding modes.
+{
+ let nf = new Intl.NumberFormat("en", {
+ minimumFractionDigits: 20,
+ roundingMode: "ceil",
+ roundingIncrement: 5000,
+ });
+ assertEq(nf.format(".1e-999999998"), "0.00000000000000005000");
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/format.js b/js/src/tests/non262/Intl/NumberFormat/format.js
new file mode 100644
index 0000000000..db35251b20
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/format.js
@@ -0,0 +1,55 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests the format function with a diverse set of locales and options.
+
+var format;
+
+// Locale en-US; default options.
+format = new Intl.NumberFormat("en-us");
+assertEq(format.format(0), "0");
+assertEq(format.format(-1), "-1");
+assertEq(format.format(123456789.123456789), "123,456,789.123");
+
+// Locale en-US; currency USD.
+// The US dollar uses two fractional digits, and negative values are commonly
+// parenthesized.
+format = new Intl.NumberFormat("en-us", {style: "currency", currency: "USD"});
+assertEq(format.format(0), "$0.00");
+assertEq(format.format(-1), "-$1.00");
+assertEq(format.format(123456789.123456789), "$123,456,789.12");
+
+// Locale ja-JP; currency JPY.
+// The Japanese yen has no subunit in real life.
+format = new Intl.NumberFormat("ja-jp", {style: "currency", currency: "JPY"});
+assertEq(format.format(0), "¥0");
+assertEq(format.format(-1), "-¥1");
+assertEq(format.format(123456789.123456789), "¥123,456,789");
+
+// Locale ar-JO; currency JOD.
+// The Jordanian Dinar divides into 1000 fils. Jordan uses (real) Arabic digits.
+format = new Intl.NumberFormat("ar-jo", {style: "currency", currency: "JOD"});
+assertEq(format.format(0), "\u{200F}٠٫٠٠٠ د.أ.\u{200F}");
+assertEq(format.format(-1), "\u{061C}-\u{200F}١٫٠٠٠ د.أ.\u{200F}");
+assertEq(format.format(123456789.123456789), "\u{200F}١٢٣٬٤٥٦٬٧٨٩٫١٢٣ د.أ.\u{200F}");
+
+// Locale th-TH; Thai digits, percent, two significant digits.
+format = new Intl.NumberFormat("th-th-u-nu-thai",
+ {style: "percent",
+ minimumSignificantDigits: 2,
+ maximumSignificantDigits: 2});
+assertEq(format.format(0), "๐.๐%");
+assertEq(format.format(-0.01), "-๑.๐%");
+assertEq(format.format(1.10), "๑๑๐%");
+
+
+// Test the .name property of the "format" getter.
+var desc = Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, "format");
+assertEq(desc !== undefined, true);
+assertEq(typeof desc.get, "function");
+assertEq(desc.get.name, "get format");
+
+
+reportCompare(0, 0, 'ok');
diff --git a/js/src/tests/non262/Intl/NumberFormat/formatRange-BigInt.js b/js/src/tests/non262/Intl/NumberFormat/formatRange-BigInt.js
new file mode 100644
index 0000000000..36ccdf59e3
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/formatRange-BigInt.js
@@ -0,0 +1,150 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||release_or_beta)
+
+// Int64-BigInts which can be exactly represented as doubles receive a fast-path.
+
+const tests = {
+ "en": {
+ options: {},
+ ranges: [
+ // BigInt around Number.MIN_SAFE_INTEGER.
+ {
+ start: -0x20000000000001n,
+ end: -0x20000000000000n,
+ result: "-9,007,199,254,740,993 – -9,007,199,254,740,992",
+ },
+ {
+ start: -0x20000000000000n,
+ end: -0x20000000000000n,
+ result: "~-9,007,199,254,740,992",
+ },
+ {
+ start: -0x20000000000000n,
+ end: -0x1fffffffffffffn,
+ result: "-9,007,199,254,740,992 – -9,007,199,254,740,991",
+ },
+ {
+ start: -0x1fffffffffffffn,
+ end: -0x1fffffffffffffn,
+ result: "~-9,007,199,254,740,991",
+ },
+ {
+ start: -0x1fffffffffffffn,
+ end: -0x1ffffffffffffen,
+ result: "-9,007,199,254,740,991 – -9,007,199,254,740,990",
+ },
+ {
+ start: -0x1ffffffffffffen,
+ end: -0x1ffffffffffffen,
+ result: "~-9,007,199,254,740,990",
+ },
+
+ // BigInt around Number.MAX_SAFE_INTEGER.
+ {
+ start: 0x1ffffffffffffen,
+ end: 0x1ffffffffffffen,
+ result: "~9,007,199,254,740,990",
+ },
+ {
+ start: 0x1ffffffffffffen,
+ end: 0x1fffffffffffffn,
+ result: "9,007,199,254,740,990–9,007,199,254,740,991",
+ },
+ {
+ start: 0x1fffffffffffffn,
+ end: 0x1fffffffffffffn,
+ result: "~9,007,199,254,740,991",
+ },
+ {
+ start: 0x1fffffffffffffn,
+ end: 0x20000000000000n,
+ result: "9,007,199,254,740,991–9,007,199,254,740,992",
+ },
+ {
+ start: 0x20000000000000n,
+ end: 0x20000000000000n,
+ result: "~9,007,199,254,740,992",
+ },
+ {
+ start: 0x20000000000000n,
+ end: 0x20000000000001n,
+ result: "9,007,199,254,740,992–9,007,199,254,740,993",
+ },
+
+ // BigInt around INT64_MIN.
+ {
+ start: -0x8000000000000002n,
+ end: -0x8000000000000001n,
+ result: "-9,223,372,036,854,775,810 – -9,223,372,036,854,775,809",
+ },
+ {
+ start: -0x8000000000000001n,
+ end: -0x8000000000000001n,
+ result: "~-9,223,372,036,854,775,809",
+ },
+ {
+ start: -0x8000000000000001n,
+ end: -0x8000000000000000n,
+ result: "-9,223,372,036,854,775,809 – -9,223,372,036,854,775,808",
+ },
+ {
+ start: -0x8000000000000000n,
+ end: -0x8000000000000000n,
+ result: "~-9,223,372,036,854,775,808",
+ },
+ {
+ start: -0x8000000000000000n,
+ end: -0x7fffffffffffffffn,
+ result: "-9,223,372,036,854,775,808 – -9,223,372,036,854,775,807",
+ },
+ {
+ start: -0x7fffffffffffffffn,
+ end: -0x7fffffffffffffffn,
+ result: "~-9,223,372,036,854,775,807",
+ },
+
+ // BigInt around INT64_MAX.
+ {
+ start: 0x7ffffffffffffffen,
+ end: 0x7ffffffffffffffen,
+ result: "~9,223,372,036,854,775,806",
+ },
+ {
+ start: 0x7ffffffffffffffen,
+ end: 0x7fffffffffffffffn,
+ result: "9,223,372,036,854,775,806–9,223,372,036,854,775,807",
+ },
+ {
+ start: 0x7fffffffffffffffn,
+ end: 0x7fffffffffffffffn,
+ result: "~9,223,372,036,854,775,807",
+ },
+ {
+ start: 0x7fffffffffffffffn,
+ end: 0x8000000000000000n,
+ result: "9,223,372,036,854,775,807–9,223,372,036,854,775,808",
+ },
+ {
+ start: 0x8000000000000000n,
+ end: 0x8000000000000000n,
+ result: "~9,223,372,036,854,775,808",
+ },
+ {
+ start: 0x8000000000000000n,
+ end: 0x8000000000000001n,
+ result: "9,223,372,036,854,775,808–9,223,372,036,854,775,809",
+ },
+ ],
+ },
+};
+
+for (let [locale, {options, ranges}] of Object.entries(tests)) {
+ let nf = new Intl.NumberFormat(locale, options);
+ for (let {start, end, result} of ranges) {
+ assertEq(nf.formatRange(start, end), result, `${start}-${end}`);
+ assertEq(nf.formatRangeToParts(start, end).reduce((acc, part) => acc + part.value, ""),
+ result, `${start}-${end}`);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/formatRange.js b/js/src/tests/non262/Intl/NumberFormat/formatRange.js
new file mode 100644
index 0000000000..da5a940ca8
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/formatRange.js
@@ -0,0 +1,296 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||release_or_beta)
+
+// String representation for Number.MAX_VALUE.
+const en_Number_MAX_VALUE = "179,769,313,486,231,570" + ",000".repeat(97);
+const de_Number_MAX_VALUE = en_Number_MAX_VALUE.replaceAll(",", ".");
+const fr_Number_MAX_VALUE = en_Number_MAX_VALUE.replaceAll(",", " ");
+
+const tests = {
+ "en": {
+ options: {},
+ ranges: [
+ // Values around zero.
+ {start: 0, end: 0, result: "~0"},
+ {start: 0, end: -0, result: "0–-0"},
+ {start: -0, end: 0, result: "-0 – 0"},
+ {start: -0, end: 0.1e-3, result: "-0 – 0"},
+ {start: -0, end: "0.1e-3", result: "-0 – 0"},
+ {start: "-0", end: 0.1e-3, result: "-0 – 0"},
+ {start: -0, end: -0, result: "~-0"},
+ {start: -0, end: -0.1, result: "-0 – -0.1"},
+
+ // Values starting at negative infinity.
+ {start: -Infinity, end: -Infinity, result: "~-∞"},
+ {start: -Infinity, end: -0, result: "-∞ – -0"},
+ {start: -Infinity, end: +0, result: "-∞ – 0"},
+ {start: -Infinity, end: +Infinity, result: "-∞ – ∞"},
+
+ // Values ending at negative infinity.
+ {start: -Number.MAX_VALUE, end: -Infinity, result: "-" + en_Number_MAX_VALUE + " – -∞"},
+ {start: -0, end: -Infinity, result: "-0 – -∞"},
+ {start: 0, end: -Infinity, result: "0–-∞"},
+ {start: Number.MAX_VALUE, end: -Infinity, result: en_Number_MAX_VALUE + "–-∞"},
+
+ // Values starting at positive infinity.
+ {start: Infinity, end: Number.MAX_VALUE, result: "∞–" + en_Number_MAX_VALUE},
+ {start: Infinity, end: 0, result: "∞–0"},
+ {start: Infinity, end: -0, result: "∞–-0"},
+ {start: Infinity, end: -Number.MAX_VALUE, result: "∞–-" + en_Number_MAX_VALUE},
+ {start: Infinity, end: -Infinity, result: "∞–-∞"},
+
+ // Values ending at positive infinity.
+ {start: Infinity, end: Infinity, result: "~∞"},
+
+ // Non-special cases.
+ {start: 1, end: 100, result: "1–100"},
+ {start: -100, end: 100, result: "-100 – 100"},
+ {start: -1000, end: -100, result: "-1,000 – -100"},
+ {start: Math.PI, end: 123_456.789, result: "3.142–123,456.789"},
+ {start: -Math.PI, end: Math.E, result: "-3.142 – 2.718"},
+ {
+ start: Number.MAX_SAFE_INTEGER,
+ end: 9007199254740993,
+ result: "9,007,199,254,740,991–9,007,199,254,740,992",
+ },
+ {
+ start: Number.MAX_SAFE_INTEGER,
+ end: "9007199254740993",
+ result: "9,007,199,254,740,991–9,007,199,254,740,993",
+ },
+
+ // Start value is larger than end value.
+ {start: -0, end: -0.1, result: "-0 – -0.1"},
+ {start: -0, end: -Number.MAX_VALUE, result: "-0 – -" + en_Number_MAX_VALUE},
+ {start: 1, end: 0, result: "1–0"},
+ {start: 0, end: -1, result: "0–-1"},
+ {start: 1, end: -1, result: "1–-1"},
+ {start: -1, end: -2, result: "-1 – -2"},
+ {start: "10e2", end: "1e-3", result: "1,000–0.001"},
+ {start: "0x100", end: "1e1", result: "256–10"},
+ {start: ".1e-999999", end: ".01e-999999", result: "~0"},
+ {start: ".1e99999", end: "0", result: "100" + ",000".repeat(33332) + "–0"},
+ // Number.MAX_VALUE is 1.7976931348623157e+308.
+ {
+ start: "1.7976931348623158e+308",
+ end: Number.MAX_VALUE,
+ result: "179,769,313,486,231,580" + ",000".repeat(97) + "–" + en_Number_MAX_VALUE,
+ },
+ // Number.MIN_VALUE is 5e-324.
+ {start: "6e-324", end: Number.MIN_VALUE, result: "~0"},
+ ],
+ },
+ "de": {
+ options: {style: "currency", currency: "EUR"},
+ ranges: [
+ // Values around zero.
+ {start: 0, end: 0, result: "≈0,00 €"},
+ {start: 0, end: -0, result: "0,00 € – -0,00 €"},
+ {start: -0, end: 0, result: "-0,00 € – 0,00 €"},
+ {start: -0, end: 0.1e-3, result: "-0,00 € – 0,00 €"},
+ {start: -0, end: "0.1e-3", result: "-0,00 € – 0,00 €"},
+ {start: "-0", end: 0.1e-3, result: "-0,00 € – 0,00 €"},
+ {start: -0, end: -0, result: "≈-0,00 €"},
+ {start: -0, end: -0.1, result: "-0,00–0,10 €"},
+
+ // Values starting at negative infinity.
+ {start: -Infinity, end: -Infinity, result: "≈-∞ €"},
+ {start: -Infinity, end: -0, result: "-∞–0,00 €"},
+ {start: -Infinity, end: +0, result: "-∞ € – 0,00 €"},
+ {start: -Infinity, end: +Infinity, result: "-∞ € – ∞ €"},
+
+ // Values ending at negative infinity.
+ {start: -Number.MAX_VALUE, end: -Infinity, result: "-" + de_Number_MAX_VALUE + ",00–∞ €"},
+ {start: -0, end: -Infinity, result: "-0,00–∞ €"},
+ {start: 0, end: -Infinity, result: "0,00 € – -∞ €"},
+ {start: Number.MAX_VALUE, end: -Infinity, result: de_Number_MAX_VALUE + ",00 € – -∞ €"},
+
+ // Values starting at positive infinity.
+ {start: Infinity, end: Number.MAX_VALUE, result: "∞–" + de_Number_MAX_VALUE + ",00 €"},
+ {start: Infinity, end: 0, result: "∞–0,00 €"},
+ {start: Infinity, end: -0, result: "∞ € – -0,00 €"},
+ {start: Infinity, end: -Number.MAX_VALUE, result: "∞ € – -" + de_Number_MAX_VALUE + ",00 €"},
+ {start: Infinity, end: -Infinity, result: "∞ € – -∞ €"},
+
+ // Values ending at positive infinity.
+ {start: Infinity, end: Infinity, result: "≈∞ €"},
+
+ // Non-special cases.
+ {start: 1, end: 100, result: "1,00–100,00 €"},
+ {start: -100, end: 100, result: "-100,00 € – 100,00 €"},
+ {start: -1000, end: -100, result: "-1.000,00–100,00 €"},
+ {start: Math.PI, end: 123_456.789, result: "3,14–123.456,79 €"},
+ {start: -Math.PI, end: Math.E, result: "-3,14 € – 2,72 €"},
+ {
+ start: Number.MAX_SAFE_INTEGER,
+ end: 9007199254740993,
+ result: "9.007.199.254.740.991,00–9.007.199.254.740.992,00 €",
+ },
+ {
+ start: Number.MAX_SAFE_INTEGER,
+ end: "9007199254740993",
+ result: "9.007.199.254.740.991,00–9.007.199.254.740.993,00 €",
+ },
+
+ // Start value is larger than end value.
+ {start: -0, end: -0.1, result: "-0,00–0,10 €"},
+ {start: -0, end: -Number.MAX_VALUE, result: "-0,00–" + de_Number_MAX_VALUE + ",00 €"},
+ {start: 1, end: 0, result: "1,00–0,00 €"},
+ {start: 0, end: -1, result: "0,00 € – -1,00 €"},
+ {start: 1, end: -1, result: "1,00 € – -1,00 €"},
+ {start: -1, end: -2, result: "-1,00–2,00 €"},
+ {start: "10e2", end: "1e-3", result: "1.000,00–0,00 €"},
+ {start: "0x100", end: "1e1", result: "256,00–10,00 €"},
+ {start: ".1e-999999", end: ".01e-999999", result: "≈0,00 €"},
+ {start: ".1e99999", end: "0", result: "100" + ".000".repeat(33332) + ",00–0,00 €"},
+ // Number.MAX_VALUE is 1.7976931348623157e+308.
+ {
+ start: "1.7976931348623158e+308",
+ end: Number.MAX_VALUE,
+ result: "179.769.313.486.231.580" + ".000".repeat(97) + ",00–" + de_Number_MAX_VALUE + ",00 €",
+ },
+ // Number.MIN_VALUE is 5e-324.
+ {start: "6e-324", end: Number.MIN_VALUE, result: "≈0,00 €"},
+ ],
+ },
+ "fr": {
+ options: {style: "unit", unit: "meter"},
+ ranges: [
+ // Values around zero.
+ {start: 0, end: 0, result: "≃0 m"},
+ {start: -0, end: 0, result: "-0 – 0 m"},
+ {start: -0, end: 0, result: "-0 – 0 m"},
+ {start: -0, end: 0.1e-3, result: "-0 – 0 m"},
+ {start: -0, end: "0.1e-3", result: "-0 – 0 m"},
+ {start: "-0", end: 0.1e-3, result: "-0 – 0 m"},
+ {start: -0, end: -0, result: "≃-0 m"},
+ {start: -0, end: -0.1, result: "-0 – -0,1 m"},
+
+ // Values starting at negative infinity.
+ {start: -Infinity, end: -Infinity, result: "≃-∞ m"},
+ {start: -Infinity, end: -0, result: "-∞ – -0 m"},
+ {start: -Infinity, end: +0, result: "-∞ – 0 m"},
+ {start: -Infinity, end: +Infinity, result: "-∞ – ∞ m"},
+
+ // Values ending at negative infinity.
+ {start: -Number.MAX_VALUE, end: -Infinity, result: "-" + fr_Number_MAX_VALUE + " – -∞ m"},
+ {start: -0, end: -Infinity, result: "-0 – -∞ m"},
+ {start: 0, end: -Infinity, result: "0–-∞ m"},
+ {start: Number.MAX_VALUE, end: -Infinity, result: fr_Number_MAX_VALUE + "–-∞ m"},
+
+ // Values starting at positive infinity.
+ {start: Infinity, end: Number.MAX_VALUE, result: "∞–" + fr_Number_MAX_VALUE + " m"},
+ {start: Infinity, end: 0, result: "∞–0 m"},
+ {start: Infinity, end: -0, result: "∞–-0 m"},
+ {start: Infinity, end: -Number.MAX_VALUE, result: "∞–-" + fr_Number_MAX_VALUE + " m"},
+ {start: Infinity, end: -Infinity, result: "∞–-∞ m"},
+
+ // Values ending at positive infinity.
+ {start: Infinity, end: Infinity, result: "≃∞ m"},
+
+ // Non-special cases.
+ {start: 1, end: 100, result: "1–100 m"},
+ {start: -100, end: 100, result: "-100 – 100 m"},
+ {start: -1000, end: -100, result: "-1 000 – -100 m"},
+ {start: Math.PI, end: 123_456.789, result: "3,142–123 456,789 m"},
+ {start: -Math.PI, end: Math.E, result: "-3,142 – 2,718 m"},
+ {
+ start: Number.MAX_SAFE_INTEGER,
+ end: 9007199254740993,
+ result: "9 007 199 254 740 991–9 007 199 254 740 992 m",
+ },
+ {
+ start: Number.MAX_SAFE_INTEGER,
+ end: "9007199254740993",
+ result: "9 007 199 254 740 991–9 007 199 254 740 993 m",
+ },
+
+ // Start value is larger than end value.
+ {start: -0, end: -0.1, result: "-0 – -0,1 m"},
+ {start: -0, end: -Number.MAX_VALUE, result: "-0 – -" + fr_Number_MAX_VALUE + " m"},
+ {start: 1, end: 0, result: "1–0 m"},
+ {start: 0, end: -1, result: "0–-1 m"},
+ {start: 1, end: -1, result: "1–-1 m"},
+ {start: -1, end: -2, result: "-1 – -2 m"},
+ {start: "10e2", end: "1e-3", result: "1 000–0,001 m"},
+ {start: "0x100", end: "1e1", result: "256–10 m"},
+ {start: ".1e-999999", end: ".01e-999999", result: "≃0 m"},
+ {start: ".1e99999", end: "0", result: "100" + " 000".repeat(33332) + "–0 m"},
+ // Number.MAX_VALUE is 1.7976931348623157e+308.
+ {
+ start: "1.7976931348623158e+308",
+ end: Number.MAX_VALUE,
+ result: "179 769 313 486 231 580" + " 000".repeat(97) + "–" + fr_Number_MAX_VALUE + " m",
+ },
+ // Number.MIN_VALUE is 5e-324.
+ {start: "6e-324", end: Number.MIN_VALUE, result: "≃0 m"},
+ ],
+ },
+ // Non-ASCII digits.
+ "ar": {
+ options: {},
+ ranges: [
+ {start: -2, end: -1, result: "؜-٢–١"},
+ {start: -1, end: -1, result: "~؜-١"},
+ {start: -1, end: 0, result: "؜-١ – ٠"},
+ {start: 0, end: 0, result: "~٠"},
+ {start: 0, end: 1, result: "٠–١"},
+ {start: 1, end: 1, result: "~١"},
+ {start: 1, end: 2, result: "١–٢"},
+ ],
+ },
+ "th-u-nu-thai": {
+ options: {},
+ ranges: [
+ {start: -2, end: -1, result: "-๒ - -๑"},
+ {start: -1, end: -1, result: "~-๑"},
+ {start: -1, end: 0, result: "-๑ - ๐"},
+ {start: 0, end: 0, result: "~๐"},
+ {start: 0, end: 1, result: "๐-๑"},
+ {start: 1, end: 1, result: "~๑"},
+ {start: 1, end: 2, result: "๑-๒"},
+ ],
+ },
+ // Approximation sign may consist of multiple characters.
+ "no": {
+ options: {},
+ ranges: [
+ {start: 1, end: 1, result: "ca.1"},
+ ],
+ },
+ // Approximation sign can be a word.
+ "ja": {
+ options: {},
+ ranges: [
+ {start: 1, end: 1, result: "約1"},
+ ],
+ },
+};
+
+for (let [locale, {options, ranges}] of Object.entries(tests)) {
+ let nf = new Intl.NumberFormat(locale, options);
+ for (let {start, end, result} of ranges) {
+ assertEq(nf.formatRange(start, end), result, `${start}-${end}`);
+ assertEq(nf.formatRangeToParts(start, end).reduce((acc, part) => acc + part.value, ""),
+ result, `${start}-${end}`);
+ }
+}
+
+// Throws an error if either value is NaN.
+{
+ const errorTests = [
+ {start: NaN, end: NaN},
+ {start: 0, end: NaN},
+ {start: NaN, end: 0},
+ {start: Infinity, end: NaN},
+ {start: NaN, end: Infinity},
+ ];
+
+ let nf = new Intl.NumberFormat("en");
+ for (let {start, end} of errorTests) {
+ assertThrowsInstanceOf(() => nf.formatRange(start, end), RangeError);
+ assertThrowsInstanceOf(() => nf.formatRangeToParts(start, end), RangeError);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-compact.js b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-compact.js
new file mode 100644
index 0000000000..b3ee5aedf3
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-compact.js
@@ -0,0 +1,34 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||release_or_beta)
+
+if (typeof getAvailableLocalesOf === "undefined") {
+ var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf;
+}
+
+const numbers = [
+ 0, 1, 2, 5, 10, 100, 1000, 10_000, 100_000, 1_000_000,
+ 0.1, 0.2, 0.5, 1.5,
+ -0, -1, -2, -5,
+ Infinity, -Infinity,
+];
+
+const options = {notation: "compact"};
+
+// List of known approximately sign in CLDR 40.
+const approximatelySigns = [
+ "~", "∼", "≈", "≃", "ca.", "約", "dáàṣì", "dáàshì",
+];
+
+// Iterate over all locales and ensure we find exactly one approximately sign.
+for (let locale of getAvailableLocalesOf("NumberFormat").sort()) {
+ let nf = new Intl.NumberFormat(locale, options);
+ for (let number of numbers) {
+ let parts = nf.formatRangeToParts(number, number);
+ let approx = parts.filter(part => part.type === "approximatelySign");
+
+ assertEq(approx.length, 1);
+ assertEq(approximatelySigns.some(approxSign => approx[0].value.includes(approxSign)), true);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-currency.js b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-currency.js
new file mode 100644
index 0000000000..72722b3b18
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-currency.js
@@ -0,0 +1,34 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||release_or_beta)
+
+if (typeof getAvailableLocalesOf === "undefined") {
+ var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf;
+}
+
+const numbers = [
+ 0, 1, 2, 5, 10, 100, 1000, 10_000, 100_000, 1_000_000,
+ 0.1, 0.2, 0.5, 1.5,
+ -0, -1, -2, -5,
+ Infinity, -Infinity,
+];
+
+const options = {style: "currency", currency: "EUR"};
+
+// List of known approximately sign in CLDR 40.
+const approximatelySigns = [
+ "~", "∼", "≈", "≃", "ca.", "約", "dáàṣì", "dáàshì",
+];
+
+// Iterate over all locales and ensure we find exactly one approximately sign.
+for (let locale of getAvailableLocalesOf("NumberFormat").sort()) {
+ let nf = new Intl.NumberFormat(locale, options);
+ for (let number of numbers) {
+ let parts = nf.formatRangeToParts(number, number);
+ let approx = parts.filter(part => part.type === "approximatelySign");
+
+ assertEq(approx.length, 1);
+ assertEq(approximatelySigns.some(approxSign => approx[0].value.includes(approxSign)), true);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-percent.js b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-percent.js
new file mode 100644
index 0000000000..f93ae25de8
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-percent.js
@@ -0,0 +1,34 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||release_or_beta)
+
+if (typeof getAvailableLocalesOf === "undefined") {
+ var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf;
+}
+
+const numbers = [
+ 0, 1, 2, 5, 10, 100, 1000, 10_000, 100_000, 1_000_000,
+ 0.1, 0.2, 0.5, 1.5,
+ -0, -1, -2, -5,
+ Infinity, -Infinity,
+];
+
+const options = {style: "percent"};
+
+// List of known approximately sign in CLDR 40.
+const approximatelySigns = [
+ "~", "∼", "≈", "≃", "ca.", "約", "dáàṣì", "dáàshì",
+];
+
+// Iterate over all locales and ensure we find exactly one approximately sign.
+for (let locale of getAvailableLocalesOf("NumberFormat").sort()) {
+ let nf = new Intl.NumberFormat(locale, options);
+ for (let number of numbers) {
+ let parts = nf.formatRangeToParts(number, number);
+ let approx = parts.filter(part => part.type === "approximatelySign");
+
+ assertEq(approx.length, 1);
+ assertEq(approximatelySigns.some(approxSign => approx[0].value.includes(approxSign)), true);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-signDisplay.js b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-signDisplay.js
new file mode 100644
index 0000000000..197f6f9f0d
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-signDisplay.js
@@ -0,0 +1,34 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||release_or_beta)
+
+if (typeof getAvailableLocalesOf === "undefined") {
+ var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf;
+}
+
+const numbers = [
+ 0, 1, 2, 5, 10, 100, 1000, 10_000, 100_000, 1_000_000,
+ 0.1, 0.2, 0.5, 1.5,
+ -0, -1, -2, -5,
+ Infinity, -Infinity,
+];
+
+const options = {signDisplay: "always"};
+
+// List of known approximately sign in CLDR 40.
+const approximatelySigns = [
+ "~", "∼", "≈", "≃", "ca.", "約", "dáàṣì", "dáàshì",
+];
+
+// Iterate over all locales and ensure we find exactly one approximately sign.
+for (let locale of getAvailableLocalesOf("NumberFormat").sort()) {
+ let nf = new Intl.NumberFormat(locale, options);
+ for (let number of numbers) {
+ let parts = nf.formatRangeToParts(number, number);
+ let approx = parts.filter(part => part.type === "approximatelySign");
+
+ assertEq(approx.length, 1);
+ assertEq(approximatelySigns.some(approxSign => approx[0].value.includes(approxSign)), true);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-unit.js b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-unit.js
new file mode 100644
index 0000000000..51507e57df
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-unit.js
@@ -0,0 +1,41 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||release_or_beta)
+
+if (typeof getAvailableLocalesOf === "undefined") {
+ var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf;
+}
+
+const numbers = [
+ 0, 1, 2, 5, 10, 100, 1000, 10_000, 100_000, 1_000_000,
+ 0.1, 0.2, 0.5, 1.5,
+ -0, -1, -2, -5,
+ Infinity, -Infinity,
+];
+
+const options = {style: "unit", unit: "meter"};
+
+// List of known approximately sign in CLDR 40.
+const approximatelySigns = [
+ "~", "∼", "≈", "≃", "ca.", "約", "dáàṣì", "dáàshì",
+];
+
+// Iterate over all locales and ensure we find exactly one approximately sign.
+for (let locale of getAvailableLocalesOf("NumberFormat").sort()) {
+ let nf = new Intl.NumberFormat(locale, options);
+ for (let number of numbers) {
+ let parts = nf.formatRangeToParts(number, number);
+ let approx = parts.filter(part => part.type === "approximatelySign");
+
+ // Known failure case.
+ // - https://github.com/tc39/proposal-intl-numberformat-v3/issues/64
+ // - https://unicode-org.atlassian.net/browse/CLDR-14918
+ if (approx.length === 0 && new Intl.Locale(locale).language === "ar") {
+ continue;
+ }
+
+ assertEq(approx.length, 1);
+ assertEq(approximatelySigns.some(approxSign => approx[0].value.includes(approxSign)), true);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign.js b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign.js
new file mode 100644
index 0000000000..edb63c2b00
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign.js
@@ -0,0 +1,34 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||release_or_beta)
+
+if (typeof getAvailableLocalesOf === "undefined") {
+ var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf;
+}
+
+const numbers = [
+ 0, 1, 2, 5, 10, 100, 1000, 10_000, 100_000, 1_000_000,
+ 0.1, 0.2, 0.5, 1.5,
+ -0, -1, -2, -5,
+ Infinity, -Infinity,
+];
+
+const options = {};
+
+// List of known approximately sign in CLDR 40.
+const approximatelySigns = [
+ "~", "∼", "≈", "≃", "ca.", "約", "dáàṣì", "dáàshì",
+];
+
+// Iterate over all locales and ensure we find exactly one approximately sign.
+for (let locale of getAvailableLocalesOf("NumberFormat").sort()) {
+ let nf = new Intl.NumberFormat(locale, options);
+ for (let number of numbers) {
+ let parts = nf.formatRangeToParts(number, number);
+ let approx = parts.filter(part => part.type === "approximatelySign");
+
+ assertEq(approx.length, 1);
+ assertEq(approximatelySigns.some(approxSign => approx[0].value.includes(approxSign)), true);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts.js b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts.js
new file mode 100644
index 0000000000..264dab910c
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts.js
@@ -0,0 +1,174 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||release_or_beta)
+
+const Start = NumberRangeFormatParts("startRange");
+const End = NumberRangeFormatParts("endRange");
+const Shared = NumberRangeFormatParts("shared");
+
+const tests = {
+ "en": {
+ options: {},
+ ranges: [
+ // Approximation sign present.
+ {
+ start: 0,
+ end: 0,
+ result: [Shared.Approx("~"), Shared.Integer("0")],
+ },
+ {
+ start: -0,
+ end: -0,
+ result: [Shared.Approx("~"), Shared.MinusSign("-"), Shared.Integer("0")],
+ },
+ {
+ start: -1,
+ end: -1,
+ result: [Shared.Approx("~"), Shared.MinusSign("-"), Shared.Integer("1")],
+ },
+ {
+ start: 0.5,
+ end: 0.5,
+ result: [Shared.Approx("~"), Shared.Integer("0"), Shared.Decimal("."), Shared.Fraction("5")],
+ },
+ {
+ start: Infinity,
+ end: Infinity,
+ result: [Shared.Approx("~"), Shared.Inf("∞")],
+ },
+ {
+ start: -Infinity,
+ end: -Infinity,
+ result: [Shared.Approx("~"), Shared.MinusSign("-"), Shared.Inf("∞")],
+ },
+
+ // Proper ranges.
+ {
+ start: -2,
+ end: -1,
+ result: [Start.MinusSign("-"), Start.Integer("2"), Shared.Literal(" – "), End.MinusSign("-"), End.Integer("1")],
+ },
+ {
+ start: -1,
+ end: 1,
+ result: [Start.MinusSign("-"), Start.Integer("1"), Shared.Literal(" – "), End.Integer("1")],
+ },
+ {
+ start: 1,
+ end: 2,
+ result: [Start.Integer("1"), Shared.Literal("–"), End.Integer("2")],
+ },
+ ],
+ },
+ // Non-ASCII digits.
+ "ar": {
+ options: {},
+ ranges: [
+ {
+ start: -2,
+ end: -1,
+ result: [Shared.Literal("\u061C"), Shared.MinusSign("-"), Start.Integer("٢"), Shared.Literal("–"), End.Integer("١")],
+ },
+ {
+ start: -1,
+ end: -1,
+ result: [Shared.Approx("~"), Shared.Literal("\u061C"), Shared.MinusSign("-"), Shared.Integer("١")],
+ },
+ {
+ start: -1,
+ end: 0,
+ result: [Start.Literal("\u061C"), Start.MinusSign("-"), Start.Integer("١"), Shared.Literal(" – "), End.Integer("٠")],
+ },
+ {
+ start: 0,
+ end: 0,
+ result: [Shared.Approx("~"), Shared.Integer("٠")],
+ },
+ {
+ start: 0,
+ end: 1,
+ result: [Start.Integer("٠"), Shared.Literal("–"), End.Integer("١")],
+ },
+ {
+ start: 1,
+ end: 1,
+ result: [Shared.Approx("~"), Shared.Integer("١")],
+ },
+ {
+ start: 1,
+ end: 2,
+ result: [Start.Integer("١"), Shared.Literal("–"), End.Integer("٢")],
+ },
+ ],
+ },
+ "th-u-nu-thai": {
+ options: {},
+ ranges: [
+ {
+ start: -2,
+ end: -1,
+ result: [Start.MinusSign("-"), Start.Integer("๒"), Shared.Literal(" - "), End.MinusSign("-"), End.Integer("๑")],
+ },
+ {
+ start: -1,
+ end: -1,
+ result: [Shared.Approx("~"), Shared.MinusSign("-"), Shared.Integer("๑")],
+ },
+ {
+ start: -1,
+ end: 0,
+ result: [Start.MinusSign("-"), Start.Integer("๑"), Shared.Literal(" - "), End.Integer("๐")],
+ },
+ {
+ start: 0,
+ end: 0,
+ result: [Shared.Approx("~"), Shared.Integer("๐")],
+ },
+ {
+ start: 0,
+ end: 1,
+ result: [Start.Integer("๐"), Shared.Literal("-"), End.Integer("๑")],
+ },
+ {
+ start: 1,
+ end: 1,
+ result: [Shared.Approx("~"), Shared.Integer("๑")],
+ },
+ {
+ start: 1,
+ end: 2,
+ result: [Start.Integer("๑"), Shared.Literal("-"), End.Integer("๒")],
+ },
+ ],
+ },
+ // Approximation sign may consist of multiple characters.
+ "no": {
+ options: {},
+ ranges: [
+ {
+ start: 1,
+ end: 1,
+ result: [Shared.Approx("ca."), Shared.Integer("1")],
+ },
+ ],
+ },
+ // Approximation sign can be a word.
+ "ja": {
+ options: {},
+ ranges: [
+ {
+ start: 1,
+ end: 1,
+ result: [Shared.Approx("約"), Shared.Integer("1")],
+ },
+ ],
+ },
+};
+
+for (let [locale, {options, ranges}] of Object.entries(tests)) {
+ let nf = new Intl.NumberFormat(locale, options);
+ for (let {start, end, result} of ranges) {
+ assertRangeParts(nf, start, end, result);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/formatToParts.js b/js/src/tests/non262/Intl/NumberFormat/formatToParts.js
new file mode 100644
index 0000000000..3ac7c3f4d3
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/formatToParts.js
@@ -0,0 +1,357 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 1289882;
+var summary = "Implement Intl.NumberFormat.prototype.formatToParts";
+
+print(BUGNUMBER + ": " + summary);
+
+//-----------------------------------------------------------------------------
+
+assertEq("formatToParts" in Intl.NumberFormat(), true);
+
+// NOTE: Some of these tests exercise standard behavior (e.g. that format and
+// formatToParts expose the same formatted string). But much of this,
+// like the exact-formatted-string expectations, is technically
+// implementation-dependent. This is necessary as a practical matter to
+// properly test the conversion from ICU's nested-field exposure to
+// ECMA-402's sequential-parts exposure.
+
+var {
+ Nan, Inf, Integer, Group, Decimal, Fraction,
+ MinusSign, PlusSign, PercentSign, Currency, Literal,
+} = NumberFormatParts;
+
+//-----------------------------------------------------------------------------
+
+// Test -0's partitioning now that it's not treated like +0.
+// https://github.com/tc39/ecma402/pull/232
+
+var deadSimpleFormatter = new Intl.NumberFormat("en-US");
+
+assertParts(deadSimpleFormatter, -0,
+ [MinusSign("-"), Integer("0")]);
+
+// Test behavior of a currency with code formatting.
+var usdCodeOptions =
+ {
+ style: "currency",
+ currency: "USD",
+ currencyDisplay: "code",
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ };
+var usDollarsCode = new Intl.NumberFormat("en-US", usdCodeOptions);
+
+assertParts(usDollarsCode, 25,
+ [Currency("USD"), Literal("\xA0"), Integer("25")]);
+
+// ISO 4217 currency codes are formed from an ISO 3166-1 alpha-2 country code
+// followed by a third letter. ISO 3166 guarantees that no country code
+// starting with "X" will ever be assigned. Stepping carefully around a few
+// 4217-designated special "currencies", XQQ will never have a representation.
+// Thus, yes: this really is specified to work, as unrecognized or unsupported
+// codes pass into the string unmodified.
+var xqqCodeOptions =
+ {
+ style: "currency",
+ currency: "XQQ",
+ currencyDisplay: "code",
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ };
+var xqqMoneyCode = new Intl.NumberFormat("en-US", xqqCodeOptions);
+
+assertParts(xqqMoneyCode, 25,
+ [Currency("XQQ"), Literal("\xA0"), Integer("25")]);
+
+// Test currencyDisplay: "name".
+var usdNameOptions =
+ {
+ style: "currency",
+ currency: "USD",
+ currencyDisplay: "name",
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ };
+var usDollarsName = new Intl.NumberFormat("en-US", usdNameOptions);
+
+assertParts(usDollarsName, 25,
+ [Integer("25"), Literal(" "), Currency("US dollars")]);
+
+var usdNameGroupingOptions =
+ {
+ style: "currency",
+ currency: "USD",
+ currencyDisplay: "name",
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ };
+var usDollarsNameGrouping =
+ new Intl.NumberFormat("en-US", usdNameGroupingOptions);
+
+assertParts(usDollarsNameGrouping, 12345678,
+ [Integer("12"),
+ Group(","),
+ Integer("345"),
+ Group(","),
+ Integer("678"),
+ Literal(" "),
+ Currency("US dollars")]);
+
+// But if the implementation doesn't recognize the currency, the provided code
+// is used in place of a proper name, unmolested.
+var xqqNameOptions =
+ {
+ style: "currency",
+ currency: "XQQ",
+ currencyDisplay: "name",
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ };
+var xqqMoneyName = new Intl.NumberFormat("en-US", xqqNameOptions);
+
+assertParts(xqqMoneyName, 25,
+ [Integer("25"), Literal(" "), Currency("XQQ")]);
+
+// Test some currencies with fractional components.
+
+var usdNameFractionOptions =
+ {
+ style: "currency",
+ currency: "USD",
+ currencyDisplay: "name",
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ };
+var usdNameFractionFormatter =
+ new Intl.NumberFormat("en-US", usdNameFractionOptions);
+
+// The US national surplus (i.e. debt) as of October 18, 2016. (Replicating
+// data from a comment in builtin/Intl/NumberFormat.cpp.)
+var usNationalSurplus = -19766580028249.41;
+
+assertParts(usdNameFractionFormatter, usNationalSurplus,
+ [MinusSign("-"),
+ Integer("19"),
+ Group(","),
+ Integer("766"),
+ Group(","),
+ Integer("580"),
+ Group(","),
+ Integer("028"),
+ Group(","),
+ Integer("249"),
+ Decimal("."),
+ Fraction("41"),
+ Literal(" "),
+ Currency("US dollars")]);
+
+// Percents in various forms.
+
+var usPercentOptions =
+ {
+ style: "percent",
+ minimumFractionDigits: 1,
+ maximumFractionDigits: 1,
+ };
+var usPercentFormatter =
+ new Intl.NumberFormat("en-US", usPercentOptions);
+
+assertParts(usPercentFormatter, 0.375,
+ [Integer("37"), Decimal("."), Fraction("5"), PercentSign("%")]);
+
+assertParts(usPercentFormatter, -1284.375,
+ [MinusSign("-"),
+ Integer("128"),
+ Group(","),
+ Integer("437"),
+ Decimal("."),
+ Fraction("5"),
+ PercentSign("%")]);
+
+assertParts(usPercentFormatter, NaN,
+ [Nan("NaN"), PercentSign("%")]);
+
+assertParts(usPercentFormatter, Infinity,
+ [Inf("∞"), PercentSign("%")]);
+
+assertParts(usPercentFormatter, -Infinity,
+ [MinusSign("-"), Inf("∞"), PercentSign("%")]);
+
+var dePercentOptions =
+ {
+ style: "percent",
+ minimumFractionDigits: 1,
+ maximumFractionDigits: 1,
+ };
+var dePercentFormatter =
+ new Intl.NumberFormat("de", dePercentOptions);
+
+assertParts(dePercentFormatter, 0.375,
+ [Integer("37"), Decimal(","), Fraction("5"), Literal("\xA0"), PercentSign("%")]);
+
+assertParts(dePercentFormatter, -1284.375,
+ [MinusSign("-"),
+ Integer("128"),
+ Group("."),
+ Integer("437"),
+ Decimal(","),
+ Fraction("5"),
+ Literal("\xA0"),
+ PercentSign("%")]);
+
+assertParts(dePercentFormatter, NaN,
+ [Nan("NaN"), Literal("\xA0"), PercentSign("%")]);
+
+assertParts(dePercentFormatter, Infinity,
+ [Inf("∞"), Literal("\xA0"), PercentSign("%")]);
+
+assertParts(dePercentFormatter, -Infinity,
+ [MinusSign("-"), Inf("∞"), Literal("\xA0"), PercentSign("%")]);
+
+var arPercentOptions =
+ {
+ style: "percent",
+ minimumFractionDigits: 2,
+ };
+var arPercentFormatter =
+ new Intl.NumberFormat("ar-IQ", arPercentOptions);
+
+assertParts(arPercentFormatter, -135.32,
+ [Literal("\u{061C}"),
+ MinusSign("-"),
+ Integer("١٣"),
+ Group("٬"),
+ Integer("٥٣٢"),
+ Decimal("٫"),
+ Fraction("٠٠"),
+ PercentSign("٪"),
+ Literal("\u{061C}")]);
+
+// Decimals.
+
+var usDecimalOptions =
+ {
+ style: "decimal",
+ maximumFractionDigits: 7 // minimum defaults to 0
+ };
+var usDecimalFormatter =
+ new Intl.NumberFormat("en-US", usDecimalOptions);
+
+assertParts(usDecimalFormatter, 42,
+ [Integer("42")]);
+
+assertParts(usDecimalFormatter, 1337,
+ [Integer("1"), Group(","), Integer("337")]);
+
+assertParts(usDecimalFormatter, -6.25,
+ [MinusSign("-"), Integer("6"), Decimal("."), Fraction("25")]);
+
+assertParts(usDecimalFormatter, -1376.25,
+ [MinusSign("-"),
+ Integer("1"),
+ Group(","),
+ Integer("376"),
+ Decimal("."),
+ Fraction("25")]);
+
+assertParts(usDecimalFormatter, 124816.8359375,
+ [Integer("124"),
+ Group(","),
+ Integer("816"),
+ Decimal("."),
+ Fraction("8359375")]);
+
+var usNoGroupingDecimalOptions =
+ {
+ style: "decimal",
+ useGrouping: false,
+ maximumFractionDigits: 7 // minimum defaults to 0
+ };
+var usNoGroupingDecimalFormatter =
+ new Intl.NumberFormat("en-US", usNoGroupingDecimalOptions);
+
+assertParts(usNoGroupingDecimalFormatter, 1337,
+ [Integer("1337")]);
+
+assertParts(usNoGroupingDecimalFormatter, -6.25,
+ [MinusSign("-"), Integer("6"), Decimal("."), Fraction("25")]);
+
+assertParts(usNoGroupingDecimalFormatter, -1376.25,
+ [MinusSign("-"),
+ Integer("1376"),
+ Decimal("."),
+ Fraction("25")]);
+
+assertParts(usNoGroupingDecimalFormatter, 124816.8359375,
+ [Integer("124816"),
+ Decimal("."),
+ Fraction("8359375")]);
+
+var deDecimalOptions =
+ {
+ style: "decimal",
+ maximumFractionDigits: 7 // minimum defaults to 0
+ };
+var deDecimalFormatter =
+ new Intl.NumberFormat("de-DE", deDecimalOptions);
+
+assertParts(deDecimalFormatter, 42,
+ [Integer("42")]);
+
+assertParts(deDecimalFormatter, 1337,
+ [Integer("1"), Group("."), Integer("337")]);
+
+assertParts(deDecimalFormatter, -6.25,
+ [MinusSign("-"), Integer("6"), Decimal(","), Fraction("25")]);
+
+assertParts(deDecimalFormatter, -1376.25,
+ [MinusSign("-"),
+ Integer("1"),
+ Group("."),
+ Integer("376"),
+ Decimal(","),
+ Fraction("25")]);
+
+assertParts(deDecimalFormatter, 124816.8359375,
+ [Integer("124"),
+ Group("."),
+ Integer("816"),
+ Decimal(","),
+ Fraction("8359375")]);
+
+var deNoGroupingDecimalOptions =
+ {
+ style: "decimal",
+ useGrouping: false,
+ maximumFractionDigits: 7 // minimum defaults to 0
+ };
+var deNoGroupingDecimalFormatter =
+ new Intl.NumberFormat("de-DE", deNoGroupingDecimalOptions);
+
+assertParts(deNoGroupingDecimalFormatter, 1337,
+ [Integer("1337")]);
+
+assertParts(deNoGroupingDecimalFormatter, -6.25,
+ [MinusSign("-"), Integer("6"), Decimal(","), Fraction("25")]);
+
+assertParts(deNoGroupingDecimalFormatter, -1376.25,
+ [MinusSign("-"),
+ Integer("1376"),
+ Decimal(","),
+ Fraction("25")]);
+
+assertParts(deNoGroupingDecimalFormatter, 124816.8359375,
+ [Integer("124816"),
+ Decimal(","),
+ Fraction("8359375")]);
+
+//-----------------------------------------------------------------------------
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, 'ok');
+
+print("Tests complete");
diff --git a/js/src/tests/non262/Intl/NumberFormat/formatting-NaN.js b/js/src/tests/non262/Intl/NumberFormat/formatting-NaN.js
new file mode 100644
index 0000000000..430d74222e
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/formatting-NaN.js
@@ -0,0 +1,35 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 1484943;
+var summary = "Don't crash doing format/formatToParts on -NaN";
+
+print(BUGNUMBER + ": " + summary);
+
+//-----------------------------------------------------------------------------
+
+assertEq("formatToParts" in Intl.NumberFormat(), true);
+
+var nf = new Intl.NumberFormat("en-US");
+var parts;
+
+var values = [NaN, -NaN];
+
+for (var v of values)
+{
+ assertEq(nf.format(v), "NaN");
+
+ parts = nf.formatToParts(v);
+ assertEq(parts.length, 1);
+ assertEq(parts[0].type, "nan");
+ assertEq(parts[0].value, "NaN");
+}
+
+//-----------------------------------------------------------------------------
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, 'ok');
+
+print("Tests complete");
diff --git a/js/src/tests/non262/Intl/NumberFormat/negativeZeroFractionDigits.js b/js/src/tests/non262/Intl/NumberFormat/negativeZeroFractionDigits.js
new file mode 100644
index 0000000000..0db461f50e
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/negativeZeroFractionDigits.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const optionsList = [
+ {minimumFractionDigits: -0, maximumFractionDigits: -0},
+ {minimumFractionDigits: -0, maximumFractionDigits: +0},
+ {minimumFractionDigits: +0, maximumFractionDigits: -0},
+ {minimumFractionDigits: +0, maximumFractionDigits: +0},
+];
+
+for (let options of optionsList) {
+ let numberFormat = new Intl.NumberFormat("en-US", options);
+
+ let {minimumFractionDigits, maximumFractionDigits} = numberFormat.resolvedOptions();
+ assertEq(minimumFractionDigits, +0);
+ assertEq(maximumFractionDigits, +0);
+
+ assertEq(numberFormat.format(123), "123");
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/notation-compact-long.js b/js/src/tests/non262/Intl/NumberFormat/notation-compact-long.js
new file mode 100644
index 0000000000..80c3416afb
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/notation-compact-long.js
@@ -0,0 +1,139 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const {
+ Nan, Inf, Integer, MinusSign, PlusSign, Decimal, Fraction, Group, Literal,
+ Compact,
+} = NumberFormatParts;
+
+const testcases = [
+ {
+ locale: "en",
+ options: {
+ notation: "compact",
+ compactDisplay: "long",
+ },
+ values: [
+ {value: +0, string: "0", parts: [Integer("0")]},
+ {value: -0, string: "-0", parts: [MinusSign("-"), Integer("0")]},
+ {value: 0n, string: "0", parts: [Integer("0")]},
+
+ {value: 1, string: "1", parts: [Integer("1")]},
+ {value: 10, string: "10", parts: [Integer("10")]},
+ {value: 100, string: "100", parts: [Integer("100")]},
+ {value: 1000, string: "1 thousand", parts: [Integer("1"), Literal(" "), Compact("thousand")]},
+ {value: 10000, string: "10 thousand", parts: [Integer("10"), Literal(" "), Compact("thousand")]},
+ {value: 100000, string: "100 thousand", parts: [Integer("100"), Literal(" "), Compact("thousand")]},
+ {value: 1000000, string: "1 million", parts: [Integer("1"), Literal(" "), Compact("million")]},
+ {value: 10000000, string: "10 million", parts: [Integer("10"), Literal(" "), Compact("million")]},
+ {value: 100000000, string: "100 million", parts: [Integer("100"), Literal(" "), Compact("million")]},
+ {value: 1000000000, string: "1 billion", parts: [Integer("1"), Literal(" "), Compact("billion")]},
+ {value: 10000000000, string: "10 billion", parts: [Integer("10"), Literal(" "), Compact("billion")]},
+ {value: 100000000000, string: "100 billion", parts: [Integer("100"), Literal(" "), Compact("billion")]},
+ {value: 1000000000000, string: "1 trillion", parts: [Integer("1"), Literal(" "), Compact("trillion")]},
+ {value: 10000000000000, string: "10 trillion", parts: [Integer("10"), Literal(" "), Compact("trillion")]},
+ {value: 100000000000000, string: "100 trillion", parts: [Integer("100"), Literal(" "), Compact("trillion")]},
+ {value: 1000000000000000, string: "1000 trillion", parts: [Integer("1000"), Literal(" "), Compact("trillion")]},
+ {value: 10000000000000000, string: "10,000 trillion", parts: [Integer("10"), Group(","), Integer("000"), Literal(" "), Compact("trillion")]},
+ {value: 100000000000000000, string: "100,000 trillion", parts: [Integer("100"), Group(","), Integer("000"), Literal(" "), Compact("trillion")]},
+
+ {value: 1n, string: "1", parts: [Integer("1")]},
+ {value: 10n, string: "10", parts: [Integer("10")]},
+ {value: 100n, string: "100", parts: [Integer("100")]},
+ {value: 1000n, string: "1 thousand", parts: [Integer("1"), Literal(" "), Compact("thousand")]},
+ {value: 10000n, string: "10 thousand", parts: [Integer("10"), Literal(" "), Compact("thousand")]},
+ {value: 100000n, string: "100 thousand", parts: [Integer("100"), Literal(" "), Compact("thousand")]},
+ {value: 1000000n, string: "1 million", parts: [Integer("1"), Literal(" "), Compact("million")]},
+ {value: 10000000n, string: "10 million", parts: [Integer("10"), Literal(" "), Compact("million")]},
+ {value: 100000000n, string: "100 million", parts: [Integer("100"), Literal(" "), Compact("million")]},
+ {value: 1000000000n, string: "1 billion", parts: [Integer("1"), Literal(" "), Compact("billion")]},
+ {value: 10000000000n, string: "10 billion", parts: [Integer("10"), Literal(" "), Compact("billion")]},
+ {value: 100000000000n, string: "100 billion", parts: [Integer("100"), Literal(" "), Compact("billion")]},
+ {value: 1000000000000n, string: "1 trillion", parts: [Integer("1"), Literal(" "), Compact("trillion")]},
+ {value: 10000000000000n, string: "10 trillion", parts: [Integer("10"), Literal(" "), Compact("trillion")]},
+ {value: 100000000000000n, string: "100 trillion", parts: [Integer("100"), Literal(" "), Compact("trillion")]},
+ {value: 1000000000000000n, string: "1000 trillion", parts: [Integer("1000"), Literal(" "), Compact("trillion")]},
+ {value: 10000000000000000n, string: "10,000 trillion", parts: [Integer("10"), Group(","), Integer("000"), Literal(" "), Compact("trillion")]},
+ {value: 100000000000000000n, string: "100,000 trillion", parts: [Integer("100"), Group(","), Integer("000"), Literal(" "), Compact("trillion")]},
+
+ {value: 0.1, string: "0.1", parts: [Integer("0"), Decimal("."), Fraction("1")]},
+ {value: 0.01, string: "0.01", parts: [Integer("0"), Decimal("."), Fraction("01")]},
+ {value: 0.001, string: "0.001", parts: [Integer("0"), Decimal("."), Fraction("001")]},
+ {value: 0.0001, string: "0.0001", parts: [Integer("0"), Decimal("."), Fraction("0001")]},
+ {value: 0.00001, string: "0.00001", parts: [Integer("0"), Decimal("."), Fraction("00001")]},
+ {value: 0.000001, string: "0.000001", parts: [Integer("0"), Decimal("."), Fraction("000001")]},
+ {value: 0.0000001, string: "0.0000001", parts: [Integer("0"), Decimal("."), Fraction("0000001")]},
+
+ {value: 12, string: "12", parts: [Integer("12")]},
+ {value: 123, string: "123", parts: [Integer("123")]},
+ {value: 1234, string: "1.2 thousand", parts: [Integer("1"), Decimal("."), Fraction("2"), Literal(" "), Compact("thousand")]},
+ {value: 12345, string: "12 thousand", parts: [Integer("12"), Literal(" "), Compact("thousand")]},
+ {value: 123456, string: "123 thousand", parts: [Integer("123"), Literal(" "), Compact("thousand")]},
+ {value: 1234567, string: "1.2 million", parts: [Integer("1"), Decimal("."), Fraction("2"), Literal(" "), Compact("million")]},
+ {value: 12345678, string: "12 million", parts: [Integer("12"), Literal(" "), Compact("million")]},
+ {value: 123456789, string: "123 million", parts: [Integer("123"), Literal(" "), Compact("million")]},
+
+ {value: Infinity, string: "∞", parts: [Inf("∞")]},
+ {value: -Infinity, string: "-∞", parts: [MinusSign("-"), Inf("∞")]},
+
+ {value: NaN, string: "NaN", parts: [Nan("NaN")]},
+ {value: -NaN, string: "NaN", parts: [Nan("NaN")]},
+ ],
+ },
+
+ // The "{compactName}" placeholder may have different plural forms.
+ {
+ locale: "de",
+ options: {
+ notation: "compact",
+ compactDisplay: "long",
+ },
+ values: [
+ {value: 1e6, string: "1 Million", parts: [Integer("1"), Literal(" "), Compact("Million")]},
+ {value: 2e6, string: "2 Millionen", parts: [Integer("2"), Literal(" "), Compact("Millionen")]},
+ {value: 1e9, string: "1 Milliarde", parts: [Integer("1"), Literal(" "), Compact("Milliarde")]},
+ {value: 2e9, string: "2 Milliarden", parts: [Integer("2"), Literal(" "), Compact("Milliarden")]},
+ ],
+ },
+
+ // Digits are grouped in myriads (every 10,000) in Japanese.
+ {
+ locale: "ja",
+ options: {
+ notation: "compact",
+ compactDisplay: "long",
+ },
+ values: [
+ {value: 1, string: "1", parts: [Integer("1")]},
+ {value: 10, string: "10", parts: [Integer("10")]},
+ {value: 100, string: "100", parts: [Integer("100")]},
+ {value: 1000, string: "1000", parts: [Integer("1000")]},
+
+ {value: 10e3, string: "1\u4E07", parts: [Integer("1"), Compact("\u4E07")]},
+ {value: 100e3, string: "10\u4E07", parts: [Integer("10"), Compact("\u4E07")]},
+ {value: 1000e3, string: "100\u4E07", parts: [Integer("100"), Compact("\u4E07")]},
+ {value: 10000e3, string: "1000\u4E07", parts: [Integer("1000"), Compact("\u4E07")]},
+
+ {value: 10e7, string: "1\u5104", parts: [Integer("1"), Compact("\u5104")]},
+ {value: 100e7, string: "10\u5104", parts: [Integer("10"), Compact("\u5104")]},
+ {value: 1000e7, string: "100\u5104", parts: [Integer("100"), Compact("\u5104")]},
+ {value: 10000e7, string: "1000\u5104", parts: [Integer("1000"), Compact("\u5104")]},
+
+ {value: 10e11, string: "1\u5146", parts: [Integer("1"), Compact("\u5146")]},
+ {value: 100e11, string: "10\u5146", parts: [Integer("10"), Compact("\u5146")]},
+ {value: 1000e11, string: "100\u5146", parts: [Integer("100"), Compact("\u5146")]},
+ {value: 10000e11, string: "1000\u5146", parts: [Integer("1000"), Compact("\u5146")]},
+
+ {value: 10e15, string: "1\u4EAC", parts: [Integer("1"), Compact("\u4EAC")]},
+ {value: 100e15, string: "10\u4EAC", parts: [Integer("10"), Compact("\u4EAC")]},
+ {value: 1000e15, string: "100\u4EAC", parts: [Integer("100"), Compact("\u4EAC")]},
+ {value: 10000e15, string: "1000\u4EAC", parts: [Integer("1000"), Compact("\u4EAC")]},
+
+ {value: 100000e15, string: "10,000\u4EAC", parts: [Integer("10"), Group(","), Integer("000"), Compact("\u4EAC")]},
+ ],
+ },
+];
+
+runNumberFormattingTestcases(testcases);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/notation-compact-short.js b/js/src/tests/non262/Intl/NumberFormat/notation-compact-short.js
new file mode 100644
index 0000000000..f3a546294d
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/notation-compact-short.js
@@ -0,0 +1,136 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const {
+ Nan, Inf, Integer, MinusSign, PlusSign, Decimal, Fraction, Group, Literal,
+ Compact,
+} = NumberFormatParts;
+
+const testcases = [
+ {
+ locale: "en",
+ options: {
+ notation: "compact",
+ compactDisplay: "short",
+ },
+ values: [
+ {value: +0, string: "0", parts: [Integer("0")]},
+ {value: -0, string: "-0", parts: [MinusSign("-"), Integer("0")]},
+ {value: 0n, string: "0", parts: [Integer("0")]},
+
+ {value: 1, string: "1", parts: [Integer("1")]},
+ {value: 10, string: "10", parts: [Integer("10")]},
+ {value: 100, string: "100", parts: [Integer("100")]},
+ {value: 1000, string: "1K", parts: [Integer("1"), Compact("K")]},
+ {value: 10000, string: "10K", parts: [Integer("10"), Compact("K")]},
+ {value: 100000, string: "100K", parts: [Integer("100"), Compact("K")]},
+ {value: 1000000, string: "1M", parts: [Integer("1"), Compact("M")]},
+ {value: 10000000, string: "10M", parts: [Integer("10"), Compact("M")]},
+ {value: 100000000, string: "100M", parts: [Integer("100"), Compact("M")]},
+ {value: 1000000000, string: "1B", parts: [Integer("1"), Compact("B")]},
+ {value: 10000000000, string: "10B", parts: [Integer("10"), Compact("B")]},
+ {value: 100000000000, string: "100B", parts: [Integer("100"), Compact("B")]},
+ {value: 1000000000000, string: "1T", parts: [Integer("1"), Compact("T")]},
+ {value: 10000000000000, string: "10T", parts: [Integer("10"), Compact("T")]},
+ {value: 100000000000000, string: "100T", parts: [Integer("100"), Compact("T")]},
+ {value: 1000000000000000, string: "1000T", parts: [Integer("1000"), Compact("T")]},
+ {value: 10000000000000000, string: "10,000T", parts: [Integer("10"), Group(","), Integer("000"), Compact("T")]},
+ {value: 100000000000000000, string: "100,000T", parts: [Integer("100"), Group(","), Integer("000"), Compact("T")]},
+
+ {value: 1n, string: "1", parts: [Integer("1")]},
+ {value: 10n, string: "10", parts: [Integer("10")]},
+ {value: 100n, string: "100", parts: [Integer("100")]},
+ {value: 1000n, string: "1K", parts: [Integer("1"), Compact("K")]},
+ {value: 10000n, string: "10K", parts: [Integer("10"), Compact("K")]},
+ {value: 100000n, string: "100K", parts: [Integer("100"), Compact("K")]},
+ {value: 1000000n, string: "1M", parts: [Integer("1"), Compact("M")]},
+ {value: 10000000n, string: "10M", parts: [Integer("10"), Compact("M")]},
+ {value: 100000000n, string: "100M", parts: [Integer("100"), Compact("M")]},
+ {value: 1000000000n, string: "1B", parts: [Integer("1"), Compact("B")]},
+ {value: 10000000000n, string: "10B", parts: [Integer("10"), Compact("B")]},
+ {value: 100000000000n, string: "100B", parts: [Integer("100"), Compact("B")]},
+ {value: 1000000000000n, string: "1T", parts: [Integer("1"), Compact("T")]},
+ {value: 10000000000000n, string: "10T", parts: [Integer("10"), Compact("T")]},
+ {value: 100000000000000n, string: "100T", parts: [Integer("100"), Compact("T")]},
+ {value: 1000000000000000n, string: "1000T", parts: [Integer("1000"), Compact("T")]},
+ {value: 10000000000000000n, string: "10,000T", parts: [Integer("10"), Group(","), Integer("000"), Compact("T")]},
+ {value: 100000000000000000n, string: "100,000T", parts: [Integer("100"), Group(","), Integer("000"), Compact("T")]},
+
+ {value: 0.1, string: "0.1", parts: [Integer("0"), Decimal("."), Fraction("1")]},
+ {value: 0.01, string: "0.01", parts: [Integer("0"), Decimal("."), Fraction("01")]},
+ {value: 0.001, string: "0.001", parts: [Integer("0"), Decimal("."), Fraction("001")]},
+ {value: 0.0001, string: "0.0001", parts: [Integer("0"), Decimal("."), Fraction("0001")]},
+ {value: 0.00001, string: "0.00001", parts: [Integer("0"), Decimal("."), Fraction("00001")]},
+ {value: 0.000001, string: "0.000001", parts: [Integer("0"), Decimal("."), Fraction("000001")]},
+ {value: 0.0000001, string: "0.0000001", parts: [Integer("0"), Decimal("."), Fraction("0000001")]},
+
+ {value: 12, string: "12", parts: [Integer("12")]},
+ {value: 123, string: "123", parts: [Integer("123")]},
+ {value: 1234, string: "1.2K", parts: [Integer("1"), Decimal("."), Fraction("2"), Compact("K")]},
+ {value: 12345, string: "12K", parts: [Integer("12"), Compact("K")]},
+ {value: 123456, string: "123K", parts: [Integer("123"), Compact("K")]},
+ {value: 1234567, string: "1.2M", parts: [Integer("1"), Decimal("."), Fraction("2"), Compact("M")]},
+ {value: 12345678, string: "12M", parts: [Integer("12"), Compact("M")]},
+ {value: 123456789, string: "123M", parts: [Integer("123"), Compact("M")]},
+
+ {value: Infinity, string: "∞", parts: [Inf("∞")]},
+ {value: -Infinity, string: "-∞", parts: [MinusSign("-"), Inf("∞")]},
+
+ {value: NaN, string: "NaN", parts: [Nan("NaN")]},
+ {value: -NaN, string: "NaN", parts: [Nan("NaN")]},
+ ],
+ },
+
+ // Compact symbol can consist of multiple characters, e.g. when it's an abbreviation.
+ {
+ locale: "de",
+ options: {
+ notation: "compact",
+ compactDisplay: "short",
+ },
+ values: [
+ {value: 1e6, string: "1\u00A0Mio.", parts: [Integer("1"), Literal("\u00A0"), Compact("Mio.")]},
+ {value: 1e9, string: "1\u00A0Mrd.", parts: [Integer("1"), Literal("\u00A0"), Compact("Mrd.")]},
+ {value: 1e12, string: "1\u00A0Bio.", parts: [Integer("1"), Literal("\u00A0"), Compact("Bio.")]},
+
+ // CLDR doesn't support "Billiarde" (Brd.), Trillion (Trill.), etc.
+ {value: 1e15, string: "1000\u00A0Bio.", parts: [Integer("1000"), Literal("\u00A0"), Compact("Bio.")]},
+ ],
+ },
+
+ // Digits are grouped in myriads (every 10,000) in Chinese.
+ {
+ locale: "zh",
+ options: {
+ notation: "compact",
+ compactDisplay: "short",
+ },
+ values: [
+ {value: 1, string: "1", parts: [Integer("1")]},
+ {value: 10, string: "10", parts: [Integer("10")]},
+ {value: 100, string: "100", parts: [Integer("100")]},
+ {value: 1000, string: "1000", parts: [Integer("1000")]},
+
+ {value: 10e3, string: "1\u4E07", parts: [Integer("1"), Compact("\u4E07")]},
+ {value: 100e3, string: "10\u4E07", parts: [Integer("10"), Compact("\u4E07")]},
+ {value: 1000e3, string: "100\u4E07", parts: [Integer("100"), Compact("\u4E07")]},
+ {value: 10000e3, string: "1000\u4E07", parts: [Integer("1000"), Compact("\u4E07")]},
+
+ {value: 10e7, string: "1\u4EBF", parts: [Integer("1"), Compact("\u4EBF")]},
+ {value: 100e7, string: "10\u4EBF", parts: [Integer("10"), Compact("\u4EBF")]},
+ {value: 1000e7, string: "100\u4EBF", parts: [Integer("100"), Compact("\u4EBF")]},
+ {value: 10000e7, string: "1000\u4EBF", parts: [Integer("1000"), Compact("\u4EBF")]},
+
+ {value: 10e11, string: "1\u4E07\u4EBF", parts: [Integer("1"), Compact("\u4E07\u4EBF")]},
+ {value: 100e11, string: "10\u4E07\u4EBF", parts: [Integer("10"), Compact("\u4E07\u4EBF")]},
+ {value: 1000e11, string: "100\u4E07\u4EBF", parts: [Integer("100"), Compact("\u4E07\u4EBF")]},
+ {value: 10000e11, string: "1000\u4E07\u4EBF", parts: [Integer("1000"), Compact("\u4E07\u4EBF")]},
+
+ {value: 100000e11, string: "10,000\u4E07\u4EBF", parts: [Integer("10"), Group(","), Integer("000"), Compact("\u4E07\u4EBF")]},
+ ],
+ },
+];
+
+runNumberFormattingTestcases(testcases);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/notation-compact-with-fraction-digits.js b/js/src/tests/non262/Intl/NumberFormat/notation-compact-with-fraction-digits.js
new file mode 100644
index 0000000000..4bdf26b9ad
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/notation-compact-with-fraction-digits.js
@@ -0,0 +1,17 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+let nf = new Intl.NumberFormat("en", {
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 2,
+ notation: "compact",
+});
+
+assertEq(nf.format(1500), "1.5K");
+assertEq(nf.format(1520), "1.52K");
+assertEq(nf.format(1540), "1.54K");
+assertEq(nf.format(1550), "1.55K");
+assertEq(nf.format(1560), "1.56K");
+assertEq(nf.format(1580), "1.58K");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/notation-engineering.js b/js/src/tests/non262/Intl/NumberFormat/notation-engineering.js
new file mode 100644
index 0000000000..b4c0e19e53
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/notation-engineering.js
@@ -0,0 +1,136 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const {
+ Nan, Inf, Integer, MinusSign, PlusSign, Decimal, Fraction, Group,
+ ExponentSeparator, ExponentInteger, ExponentMinusSign,
+} = NumberFormatParts;
+
+const testcases = [
+ {
+ locale: "en",
+ options: {
+ notation: "engineering",
+ },
+ values: [
+ {value: +0, string: "0E0", parts: [Integer("0"), ExponentSeparator("E"), ExponentInteger("0")]},
+ {value: -0, string: "-0E0", parts: [MinusSign("-"), Integer("0"), ExponentSeparator("E"), ExponentInteger("0")]},
+ {value: 0n, string: "0E0", parts: [Integer("0"), ExponentSeparator("E"), ExponentInteger("0")]},
+
+ {value: 1, string: "1E0", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("0")]},
+ {value: 10, string: "10E0", parts: [Integer("10"), ExponentSeparator("E"), ExponentInteger("0")]},
+ {value: 100, string: "100E0", parts: [Integer("100"), ExponentSeparator("E"), ExponentInteger("0")]},
+ {value: 1000, string: "1E3", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("3")]},
+ {value: 10000, string: "10E3", parts: [Integer("10"), ExponentSeparator("E"), ExponentInteger("3")]},
+ {value: 100000, string: "100E3", parts: [Integer("100"), ExponentSeparator("E"), ExponentInteger("3")]},
+ {value: 1000000, string: "1E6", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("6")]},
+
+ {value: 1n, string: "1E0", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("0")]},
+ {value: 10n, string: "10E0", parts: [Integer("10"), ExponentSeparator("E"), ExponentInteger("0")]},
+ {value: 100n, string: "100E0", parts: [Integer("100"), ExponentSeparator("E"), ExponentInteger("0")]},
+ {value: 1000n, string: "1E3", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("3")]},
+ {value: 10000n, string: "10E3", parts: [Integer("10"), ExponentSeparator("E"), ExponentInteger("3")]},
+ {value: 100000n, string: "100E3", parts: [Integer("100"), ExponentSeparator("E"), ExponentInteger("3")]},
+ {value: 1000000n, string: "1E6", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("6")]},
+
+ {value: 0.1, string: "100E-3", parts: [Integer("100"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("3")]},
+ {value: 0.01, string: "10E-3", parts: [Integer("10"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("3")]},
+ {value: 0.001, string: "1E-3", parts: [Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("3")]},
+ {value: 0.0001, string: "100E-6", parts: [Integer("100"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("6")]},
+ {value: 0.00001, string: "10E-6", parts: [Integer("10"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("6")]},
+ {value: 0.000001, string: "1E-6", parts: [Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("6")]},
+ {value: 0.0000001, string: "100E-9", parts: [Integer("100"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("9")]},
+
+ {value: Infinity, string: "∞", parts: [Inf("∞")]},
+ {value: -Infinity, string: "-∞", parts: [MinusSign("-"), Inf("∞")]},
+
+ {value: NaN, string: "NaN", parts: [Nan("NaN")]},
+ {value: -NaN, string: "NaN", parts: [Nan("NaN")]},
+ ],
+ },
+
+ // Exponent modifications take place early, so while in the "standard" notation
+ // `Intl.NumberFormat("en", {maximumFractionDigits: 0}).format(0.1)` returns "0", for
+ // "engineering" notation the result string is not "0", but instead "100E-3".
+
+ {
+ locale: "en",
+ options: {
+ notation: "engineering",
+ maximumFractionDigits: 0,
+ },
+ values: [
+ {value: 0.1, string: "100E-3", parts: [
+ Integer("100"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("3")
+ ]},
+ ],
+ },
+
+ {
+ locale: "en",
+ options: {
+ notation: "engineering",
+ minimumFractionDigits: 4,
+ },
+ values: [
+ {value: 10, string: "10.0000E0", parts: [
+ Integer("10"), Decimal("."), Fraction("0000"), ExponentSeparator("E"), ExponentInteger("0")
+ ]},
+ {value: 0.1, string: "100.0000E-3", parts: [
+ Integer("100"), Decimal("."), Fraction("0000"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("3")
+ ]},
+ ],
+ },
+
+ {
+ locale: "en",
+ options: {
+ notation: "engineering",
+ minimumIntegerDigits: 4,
+ },
+ values: [
+ {value: 10, string: "0,010E0", parts: [
+ Integer("0"), Group(","), Integer("010"), ExponentSeparator("E"), ExponentInteger("0")
+ ]},
+ {value: 0.1, string: "0,100E-3", parts: [
+ Integer("0"), Group(","), Integer("100"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("3")
+ ]},
+ ],
+ },
+
+ {
+ locale: "en",
+ options: {
+ notation: "engineering",
+ minimumSignificantDigits: 4,
+ },
+ values: [
+ {value: 10, string: "10.00E0", parts: [
+ Integer("10"), Decimal("."), Fraction("00"), ExponentSeparator("E"), ExponentInteger("0")
+ ]},
+ {value: 0.1, string: "100.0E-3", parts: [
+ Integer("100"), Decimal("."), Fraction("0"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("3")
+ ]},
+ ],
+ },
+
+ {
+ locale: "en",
+ options: {
+ notation: "engineering",
+ maximumSignificantDigits: 1,
+ },
+ values: [
+ {value: 12, string: "10E0", parts: [
+ Integer("10"), ExponentSeparator("E"), ExponentInteger("0")
+ ]},
+ {value: 0.12, string: "100E-3", parts: [
+ Integer("100"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("3")
+ ]},
+ ],
+ },
+];
+
+runNumberFormattingTestcases(testcases);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/notation-scientific.js b/js/src/tests/non262/Intl/NumberFormat/notation-scientific.js
new file mode 100644
index 0000000000..f14a660129
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/notation-scientific.js
@@ -0,0 +1,136 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const {
+ Nan, Inf, Integer, MinusSign, PlusSign, Decimal, Fraction, Group,
+ ExponentSeparator, ExponentInteger, ExponentMinusSign,
+} = NumberFormatParts;
+
+const testcases = [
+ {
+ locale: "en",
+ options: {
+ notation: "scientific",
+ },
+ values: [
+ {value: +0, string: "0E0", parts: [Integer("0"), ExponentSeparator("E"), ExponentInteger("0")]},
+ {value: -0, string: "-0E0", parts: [MinusSign("-"), Integer("0"), ExponentSeparator("E"), ExponentInteger("0")]},
+ {value: 0n, string: "0E0", parts: [Integer("0"), ExponentSeparator("E"), ExponentInteger("0")]},
+
+ {value: 1, string: "1E0", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("0")]},
+ {value: 10, string: "1E1", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("1")]},
+ {value: 100, string: "1E2", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("2")]},
+ {value: 1000, string: "1E3", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("3")]},
+ {value: 10000, string: "1E4", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("4")]},
+ {value: 100000, string: "1E5", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("5")]},
+ {value: 1000000, string: "1E6", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("6")]},
+
+ {value: 1n, string: "1E0", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("0")]},
+ {value: 10n, string: "1E1", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("1")]},
+ {value: 100n, string: "1E2", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("2")]},
+ {value: 1000n, string: "1E3", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("3")]},
+ {value: 10000n, string: "1E4", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("4")]},
+ {value: 100000n, string: "1E5", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("5")]},
+ {value: 1000000n, string: "1E6", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("6")]},
+
+ {value: 0.1, string: "1E-1", parts: [Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("1")]},
+ {value: 0.01, string: "1E-2", parts: [Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("2")]},
+ {value: 0.001, string: "1E-3", parts: [Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("3")]},
+ {value: 0.0001, string: "1E-4", parts: [Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("4")]},
+ {value: 0.00001, string: "1E-5", parts: [Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("5")]},
+ {value: 0.000001, string: "1E-6", parts: [Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("6")]},
+ {value: 0.0000001, string: "1E-7", parts: [Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("7")]},
+
+ {value: Infinity, string: "∞", parts: [Inf("∞")]},
+ {value: -Infinity, string: "-∞", parts: [MinusSign("-"), Inf("∞")]},
+
+ {value: NaN, string: "NaN", parts: [Nan("NaN")]},
+ {value: -NaN, string: "NaN", parts: [Nan("NaN")]},
+ ],
+ },
+
+ // Exponent modifications take place early, so while in the "standard" notation
+ // `Intl.NumberFormat("en", {maximumFractionDigits: 0}).format(0.1)` returns "0", for
+ // "scientific" notation the result string is not "0", but instead "1E-1".
+
+ {
+ locale: "en",
+ options: {
+ notation: "scientific",
+ maximumFractionDigits: 0,
+ },
+ values: [
+ {value: 0.1, string: "1E-1", parts: [
+ Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("1")
+ ]},
+ ],
+ },
+
+ {
+ locale: "en",
+ options: {
+ notation: "scientific",
+ minimumFractionDigits: 4,
+ },
+ values: [
+ {value: 10, string: "1.0000E1", parts: [
+ Integer("1"), Decimal("."), Fraction("0000"), ExponentSeparator("E"), ExponentInteger("1")
+ ]},
+ {value: 0.1, string: "1.0000E-1", parts: [
+ Integer("1"), Decimal("."), Fraction("0000"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("1")
+ ]},
+ ],
+ },
+
+ {
+ locale: "en",
+ options: {
+ notation: "scientific",
+ minimumIntegerDigits: 4,
+ },
+ values: [
+ {value: 10, string: "0,001E1", parts: [
+ Integer("0"), Group(","), Integer("001"), ExponentSeparator("E"), ExponentInteger("1")
+ ]},
+ {value: 0.1, string: "0,001E-1", parts: [
+ Integer("0"), Group(","), Integer("001"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("1")
+ ]},
+ ],
+ },
+
+ {
+ locale: "en",
+ options: {
+ notation: "scientific",
+ minimumSignificantDigits: 4,
+ },
+ values: [
+ {value: 10, string: "1.000E1", parts: [
+ Integer("1"), Decimal("."), Fraction("000"), ExponentSeparator("E"), ExponentInteger("1")
+ ]},
+ {value: 0.1, string: "1.000E-1", parts: [
+ Integer("1"), Decimal("."), Fraction("000"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("1")
+ ]},
+ ],
+ },
+
+ {
+ locale: "en",
+ options: {
+ notation: "scientific",
+ maximumSignificantDigits: 1,
+ },
+ values: [
+ {value: 12, string: "1E1", parts: [
+ Integer("1"), ExponentSeparator("E"), ExponentInteger("1")
+ ]},
+ {value: 0.12, string: "1E-1", parts: [
+ Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("1")
+ ]},
+ ],
+ },
+];
+
+runNumberFormattingTestcases(testcases);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/numberingSystem-format.js b/js/src/tests/non262/Intl/NumberFormat/numberingSystem-format.js
new file mode 100644
index 0000000000..c0b9ba78ed
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/numberingSystem-format.js
@@ -0,0 +1,18 @@
+for (let [numberingSystem, {digits, algorithmic}] of Object.entries(numberingSystems)) {
+ if (algorithmic) {
+ // We don't yet support algorithmic numbering systems.
+ continue;
+ }
+
+ let nf = new Intl.NumberFormat("en", {numberingSystem});
+
+ assertEq([...digits].length, 10, "expect exactly ten digits for each numbering system");
+
+ let i = 0;
+ for (let digit of digits) {
+ assertEq(nf.format(i++), digit);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/numberingSystem-option.js b/js/src/tests/non262/Intl/NumberFormat/numberingSystem-option.js
new file mode 100644
index 0000000000..4624ee5192
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/numberingSystem-option.js
@@ -0,0 +1,60 @@
+const defaultLocale = "en";
+const defaultNumberingSystem = new Intl.NumberFormat(defaultLocale).resolvedOptions().numberingSystem;
+
+function createWithLocale(locale, numberingSystem) {
+ return new Intl.NumberFormat(locale, {numberingSystem});
+}
+
+function create(numberingSystem) {
+ return createWithLocale(defaultLocale, numberingSystem);
+}
+
+// Empty string should throw.
+assertThrowsInstanceOf(() => create(""), RangeError);
+
+// Trailing \0 should throw.
+assertThrowsInstanceOf(() => create("latn\0"), RangeError);
+
+// Too short or too long strings should throw.
+assertThrowsInstanceOf(() => create("a"), RangeError);
+assertThrowsInstanceOf(() => create("toolongstring"), RangeError);
+
+// Throw even when prefix is valid.
+assertThrowsInstanceOf(() => create("latn-toolongstring"), RangeError);
+
+// |numberingSystem| can be set to |undefined|.
+let nf = create(undefined);
+assertEq(nf.resolvedOptions().numberingSystem, defaultNumberingSystem);
+
+// Unsupported numbering systems are ignored.
+nf = create("xxxxxxxx");
+assertEq(nf.resolvedOptions().numberingSystem, defaultNumberingSystem);
+
+// Numbering system in options overwrite Unicode extension keyword.
+nf = createWithLocale(`${defaultLocale}-u-nu-thai`, "arab");
+assertEq(nf.resolvedOptions().locale, defaultLocale);
+assertEq(nf.resolvedOptions().numberingSystem, "arab");
+
+// |numberingSystem| option ignores case.
+nf = create("ARAB");
+assertEq(nf.resolvedOptions().locale, defaultLocale);
+assertEq(nf.resolvedOptions().numberingSystem, "arab");
+
+for (let [numberingSystem, {algorithmic}] of Object.entries(numberingSystems)) {
+ let nf1 = new Intl.NumberFormat(`${defaultLocale}-u-nu-${numberingSystem}`);
+ let nf2 = new Intl.NumberFormat(defaultLocale, {numberingSystem});
+
+ if (!algorithmic) {
+ assertEq(nf1.resolvedOptions().numberingSystem, numberingSystem);
+ assertEq(nf2.resolvedOptions().numberingSystem, numberingSystem);
+ } else {
+ // We don't yet support algorithmic numbering systems.
+ assertEq(nf1.resolvedOptions().numberingSystem, defaultNumberingSystem);
+ assertEq(nf2.resolvedOptions().numberingSystem, defaultNumberingSystem);
+ }
+
+ assertEq(nf2.format(0), nf1.format(0));
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/options-emulate-undefined.js b/js/src/tests/non262/Intl/NumberFormat/options-emulate-undefined.js
new file mode 100644
index 0000000000..ddb2d61350
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/options-emulate-undefined.js
@@ -0,0 +1,13 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// createIsHTMLDDA is only available when running tests in the shell,
+// not the browser
+if (typeof createIsHTMLDDA === "function") {
+ let nf = new Intl.NumberFormat('en-US', createIsHTMLDDA());
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/remove-unicode-extensions.js b/js/src/tests/non262/Intl/NumberFormat/remove-unicode-extensions.js
new file mode 100644
index 0000000000..87cfc317cb
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/remove-unicode-extensions.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Locale processing is supposed to internally remove any Unicode extension
+// sequences in the locale. Test that various weird testcases invoking
+// algorithmic edge cases don't assert or throw exceptions.
+
+var weirdCases =
+ [
+ "en-x-u-foo",
+ "en-a-bar-x-u-foo",
+ "en-x-u-foo-a-bar",
+ "en-a-bar-u-baz-x-u-foo",
+ ];
+
+for (var locale of weirdCases)
+ Intl.NumberFormat(locale).format(5);
+
+assertThrowsInstanceOf(() => Intl.NumberFormat("x-u-foo"), RangeError);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/rounding-increment.js b/js/src/tests/non262/Intl/NumberFormat/rounding-increment.js
new file mode 100644
index 0000000000..84d4480227
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/rounding-increment.js
@@ -0,0 +1,102 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||release_or_beta)
+
+// Nickel rounding.
+{
+ let nf = new Intl.NumberFormat("en", {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ roundingIncrement: 5,
+ });
+
+ assertEq(nf.format(1.22), "1.20");
+ assertEq(nf.format(1.224), "1.20");
+ assertEq(nf.format(1.225), "1.25");
+ assertEq(nf.format(1.23), "1.25");
+}
+
+// Dime rounding.
+{
+ let nf = new Intl.NumberFormat("en", {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ roundingIncrement: 10,
+ });
+
+ assertEq(nf.format(1.24), "1.20");
+ assertEq(nf.format(1.249), "1.20");
+ assertEq(nf.format(1.250), "1.30");
+ assertEq(nf.format(1.25), "1.30");
+}
+
+// Rounding increment option is rounded down.
+{
+ let nf1 = new Intl.NumberFormat("en", {
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ roundingIncrement: 10,
+ });
+
+ let nf2 = new Intl.NumberFormat("en", {
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ roundingIncrement: 10.1,
+ });
+
+ let nf3 = new Intl.NumberFormat("en", {
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ roundingIncrement: 10.9,
+ });
+
+ assertEq(nf1.resolvedOptions().roundingIncrement, 10);
+ assertEq(nf2.resolvedOptions().roundingIncrement, 10);
+ assertEq(nf3.resolvedOptions().roundingIncrement, 10);
+
+ assertEq(nf1.format(123), "120");
+ assertEq(nf2.format(123), "120");
+ assertEq(nf3.format(123), "120");
+}
+
+// |minimumFractionDigits| must be equal to |maximumFractionDigits| when
+// |roundingIncrement| is used.
+//
+// |minimumFractionDigits| defaults to zero.
+{
+ let nf = new Intl.NumberFormat("en", {
+ roundingIncrement: 10,
+ // minimumFractionDigits: 0, (default)
+ maximumFractionDigits: 0,
+ });
+
+ let resolved = nf.resolvedOptions();
+ assertEq(resolved.minimumFractionDigits, 0);
+ assertEq(resolved.maximumFractionDigits, 0);
+ assertEq(resolved.roundingIncrement, 10);
+
+ assertEq(nf.format(123), "120");
+ assertEq(nf.format(123.456), "120");
+}
+
+// |maximumFractionDigits| defaults to three. And because |0 !== 3|, a
+// RangeError is thrown.
+{
+ let options = {
+ roundingIncrement: 10,
+ // minimumFractionDigits: 0, (default)
+ // maximumFractionDigits: 3, (default)
+ };
+ assertThrowsInstanceOf(() => new Intl.NumberFormat("en", options), RangeError);
+}
+
+// Invalid values.
+for (let roundingIncrement of [-1, 0, Infinity, NaN]){
+ let options = {
+ roundingIncrement,
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ };
+ assertThrowsInstanceOf(() => new Intl.NumberFormat("en", options), RangeError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/rounding-mode.js b/js/src/tests/non262/Intl/NumberFormat/rounding-mode.js
new file mode 100644
index 0000000000..e4b85b0172
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/rounding-mode.js
@@ -0,0 +1,287 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||release_or_beta)
+
+const tests = [
+ // Special values: Zeros and non-finite values.
+ {
+ value: 0,
+ options: {},
+ roundingModes: {
+ ceil: "0",
+ floor: "0",
+ expand: "0",
+ trunc: "0",
+ halfCeil: "0",
+ halfFloor: "0",
+ halfExpand: "0",
+ halfTrunc: "0",
+ halfEven: "0",
+ },
+ },
+ {
+ value: -0,
+ options: {},
+ roundingModes: {
+ ceil: "-0",
+ floor: "-0",
+ expand: "-0",
+ trunc: "-0",
+ halfCeil: "-0",
+ halfFloor: "-0",
+ halfExpand: "-0",
+ halfTrunc: "-0",
+ halfEven: "-0",
+ },
+ },
+ {
+ value: -Infinity,
+ options: {},
+ roundingModes: {
+ ceil: "-∞",
+ floor: "-∞",
+ expand: "-∞",
+ trunc: "-∞",
+ halfCeil: "-∞",
+ halfFloor: "-∞",
+ halfExpand: "-∞",
+ halfTrunc: "-∞",
+ halfEven: "-∞",
+ },
+ },
+ {
+ value: Infinity,
+ options: {},
+ roundingModes: {
+ ceil: "∞",
+ floor: "∞",
+ expand: "∞",
+ trunc: "∞",
+ halfCeil: "∞",
+ halfFloor: "∞",
+ halfExpand: "∞",
+ halfTrunc: "∞",
+ halfEven: "∞",
+ },
+ },
+ {
+ value: NaN,
+ options: {},
+ roundingModes: {
+ ceil: "NaN",
+ floor: "NaN",
+ expand: "NaN",
+ trunc: "NaN",
+ halfCeil: "NaN",
+ halfFloor: "NaN",
+ halfExpand: "NaN",
+ halfTrunc: "NaN",
+ halfEven: "NaN",
+ },
+ },
+
+ // Integer rounding with positive values.
+ {
+ value: 0.4,
+ options: {maximumFractionDigits: 0},
+ roundingModes: {
+ ceil: "1",
+ floor: "0",
+ expand: "1",
+ trunc: "0",
+ halfCeil: "0",
+ halfFloor: "0",
+ halfExpand: "0",
+ halfTrunc: "0",
+ halfEven: "0",
+ },
+ },
+ {
+ value: 0.5,
+ options: {maximumFractionDigits: 0},
+ roundingModes: {
+ ceil: "1",
+ floor: "0",
+ expand: "1",
+ trunc: "0",
+ halfCeil: "1",
+ halfFloor: "0",
+ halfExpand: "1",
+ halfTrunc: "0",
+ halfEven: "0",
+ },
+ },
+ {
+ value: 0.6,
+ options: {maximumFractionDigits: 0},
+ roundingModes: {
+ ceil: "1",
+ floor: "0",
+ expand: "1",
+ trunc: "0",
+ halfCeil: "1",
+ halfFloor: "1",
+ halfExpand: "1",
+ halfTrunc: "1",
+ halfEven: "1",
+ },
+ },
+
+ // Integer rounding with negative values.
+ {
+ value: -0.4,
+ options: {maximumFractionDigits: 0},
+ roundingModes: {
+ ceil: "-0",
+ floor: "-1",
+ expand: "-1",
+ trunc: "-0",
+ halfCeil: "-0",
+ halfFloor: "-0",
+ halfExpand: "-0",
+ halfTrunc: "-0",
+ halfEven: "-0",
+ },
+ },
+ {
+ value: -0.5,
+ options: {maximumFractionDigits: 0},
+ roundingModes: {
+ ceil: "-0",
+ floor: "-1",
+ expand: "-1",
+ trunc: "-0",
+ halfCeil: "-0",
+ halfFloor: "-1",
+ halfExpand: "-1",
+ halfTrunc: "-0",
+ halfEven: "-0",
+ },
+ },
+ {
+ value: -0.6,
+ options: {maximumFractionDigits: 0},
+ roundingModes: {
+ ceil: "-0",
+ floor: "-1",
+ expand: "-1",
+ trunc: "-0",
+ halfCeil: "-1",
+ halfFloor: "-1",
+ halfExpand: "-1",
+ halfTrunc: "-1",
+ halfEven: "-1",
+ },
+ },
+
+ // Fractional digits rounding with positive values.
+ {
+ value: 0.04,
+ options: {maximumFractionDigits: 1},
+ roundingModes: {
+ ceil: "0.1",
+ floor: "0",
+ expand: "0.1",
+ trunc: "0",
+ halfCeil: "0",
+ halfFloor: "0",
+ halfExpand: "0",
+ halfTrunc: "0",
+ halfEven: "0",
+ },
+ },
+ {
+ value: 0.05,
+ options: {maximumFractionDigits: 1},
+ roundingModes: {
+ ceil: "0.1",
+ floor: "0",
+ expand: "0.1",
+ trunc: "0",
+ halfCeil: "0.1",
+ halfFloor: "0",
+ halfExpand: "0.1",
+ halfTrunc: "0",
+ halfEven: "0",
+ },
+ },
+ {
+ value: 0.06,
+ options: {maximumFractionDigits: 1},
+ roundingModes: {
+ ceil: "0.1",
+ floor: "0",
+ expand: "0.1",
+ trunc: "0",
+ halfCeil: "0.1",
+ halfFloor: "0.1",
+ halfExpand: "0.1",
+ halfTrunc: "0.1",
+ halfEven: "0.1",
+ },
+ },
+
+ // Fractional digits rounding with negative values.
+ {
+ value: -0.04,
+ options: {maximumFractionDigits: 1},
+ roundingModes: {
+ ceil: "-0",
+ floor: "-0.1",
+ expand: "-0.1",
+ trunc: "-0",
+ halfCeil: "-0",
+ halfFloor: "-0",
+ halfExpand: "-0",
+ halfTrunc: "-0",
+ halfEven: "-0",
+ },
+ },
+ {
+ value: -0.05,
+ options: {maximumFractionDigits: 1},
+ roundingModes: {
+ ceil: "-0",
+ floor: "-0.1",
+ expand: "-0.1",
+ trunc: "-0",
+ halfCeil: "-0",
+ halfFloor: "-0.1",
+ halfExpand: "-0.1",
+ halfTrunc: "-0",
+ halfEven: "-0",
+ },
+ },
+ {
+ value: -0.06,
+ options: {maximumFractionDigits: 1},
+ roundingModes: {
+ ceil: "-0",
+ floor: "-0.1",
+ expand: "-0.1",
+ trunc: "-0",
+ halfCeil: "-0.1",
+ halfFloor: "-0.1",
+ halfExpand: "-0.1",
+ halfTrunc: "-0.1",
+ halfEven: "-0.1",
+ },
+ },
+];
+
+for (let {value, options, roundingModes} of tests) {
+ for (let [roundingMode, expected] of Object.entries(roundingModes)) {
+ let nf = new Intl.NumberFormat("en", {...options, roundingMode});
+ assertEq(nf.format(value), expected, `value=${value}, roundingMode=${roundingMode}`);
+ assertEq(nf.resolvedOptions().roundingMode, roundingMode);
+ }
+}
+
+// Default value is "halfExpand".
+assertEq(new Intl.NumberFormat().resolvedOptions().roundingMode, "halfExpand");
+
+// Invalid values.
+for (let roundingMode of ["", null, "halfOdd", "halfUp", "Up", "up"]){
+ assertThrowsInstanceOf(() => new Intl.NumberFormat("en", {roundingMode}), RangeError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/rounding-priority.js b/js/src/tests/non262/Intl/NumberFormat/rounding-priority.js
new file mode 100644
index 0000000000..49c9e1b274
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/rounding-priority.js
@@ -0,0 +1,132 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||release_or_beta)
+
+const tests = [
+ // Rounding conflict with maximum fraction/significand digits.
+ {
+ value: 4.321,
+ options: {
+ maximumFractionDigits: 2,
+ maximumSignificantDigits: 2,
+ },
+ roundingPriorities: {
+ auto: "4.3",
+ lessPrecision: "4.3",
+ morePrecision: "4.32",
+ },
+ },
+ {
+ value: 4.321,
+ options: {
+ maximumFractionDigits: 2,
+ minimumFractionDigits: 2,
+ maximumSignificantDigits: 2,
+ },
+ roundingPriorities: {
+ auto: "4.3",
+ lessPrecision: "4.3",
+ morePrecision: "4.32",
+ },
+ },
+ {
+ value: 4.321,
+ options: {
+ maximumFractionDigits: 2,
+ maximumSignificantDigits: 2,
+ minimumSignificantDigits: 2,
+ },
+ roundingPriorities: {
+ auto: "4.3",
+ lessPrecision: "4.3",
+ morePrecision: "4.32",
+ },
+ },
+ {
+ value: 4.321,
+ options: {
+ maximumFractionDigits: 2,
+ minimumFractionDigits: 2,
+ maximumSignificantDigits: 2,
+ minimumSignificantDigits: 2,
+ },
+ roundingPriorities: {
+ auto: "4.3",
+ lessPrecision: "4.3",
+ morePrecision: "4.32",
+ },
+ },
+
+ // Rounding conflict with minimum fraction/significand digits.
+ {
+ value: 1.0,
+ options: {
+ minimumFractionDigits: 2,
+ minimumSignificantDigits: 2,
+ },
+ roundingPriorities: {
+ auto: "1.0",
+ // Returning "1.00" for both options seems unexpected. Also filed at
+ // <https://github.com/tc39/proposal-intl-numberformat-v3/issues/52>.
+ lessPrecision: "1.00",
+ morePrecision: "1.0",
+ },
+ },
+ {
+ value: 1.0,
+ options: {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ minimumSignificantDigits: 2,
+ },
+ roundingPriorities: {
+ auto: "1.0",
+ lessPrecision: "1.00",
+ morePrecision: "1.0",
+ },
+ },
+ {
+ value: 1.0,
+ options: {
+ minimumFractionDigits: 2,
+ minimumSignificantDigits: 2,
+ maximumSignificantDigits: 2,
+ },
+ roundingPriorities: {
+ auto: "1.0",
+ lessPrecision: "1.0",
+ morePrecision: "1.00",
+ },
+ },
+ {
+ value: 1.0,
+ options: {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ minimumSignificantDigits: 2,
+ maximumSignificantDigits: 2,
+ },
+ roundingPriorities: {
+ auto: "1.0",
+ lessPrecision: "1.0",
+ morePrecision: "1.00",
+ },
+ },
+];
+
+for (let {value, options, roundingPriorities} of tests) {
+ for (let [roundingPriority, expected] of Object.entries(roundingPriorities)) {
+ let nf = new Intl.NumberFormat("en", {...options, roundingPriority});
+ assertEq(nf.resolvedOptions().roundingPriority, roundingPriority);
+ assertEq(nf.format(value), expected, `value=${value}, roundingPriority=${roundingPriority}`);
+ }
+}
+
+// Default value of "auto".
+assertEq(new Intl.NumberFormat().resolvedOptions().roundingPriority, "auto");
+
+// Invalid values.
+for (let roundingPriority of ["", null, "more", "less", "never"]){
+ assertThrowsInstanceOf(() => new Intl.NumberFormat("en", {roundingPriority}), RangeError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/shell.js b/js/src/tests/non262/Intl/NumberFormat/shell.js
new file mode 100644
index 0000000000..471fdad71b
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/shell.js
@@ -0,0 +1,77 @@
+function GenericPartCreator(type) {
+ return str => ({ type, value: str });
+}
+
+const NumberFormatParts = {
+ Nan: GenericPartCreator("nan"),
+ Inf: GenericPartCreator("infinity"),
+ Integer: GenericPartCreator("integer"),
+ Group: GenericPartCreator("group"),
+ Decimal: GenericPartCreator("decimal"),
+ Fraction: GenericPartCreator("fraction"),
+ MinusSign: GenericPartCreator("minusSign"),
+ PlusSign: GenericPartCreator("plusSign"),
+ PercentSign: GenericPartCreator("percentSign"),
+ Currency: GenericPartCreator("currency"),
+ Literal: GenericPartCreator("literal"),
+ ExponentSeparator: GenericPartCreator("exponentSeparator"),
+ ExponentMinusSign: GenericPartCreator("exponentMinusSign"),
+ ExponentInteger: GenericPartCreator("exponentInteger"),
+ Compact: GenericPartCreator("compact"),
+ Unit: GenericPartCreator("unit"),
+};
+
+function NumberRangeFormatParts(source) {
+ let entries = Object.entries(NumberFormatParts)
+
+ entries.push(["Approx", GenericPartCreator("approximatelySign")]);
+
+ return Object.fromEntries(entries.map(([key, part]) => {
+ let partWithSource = str => {
+ return Object.defineProperty(part(str), "source", {
+ value: source, writable: true, enumerable: true, configurable: true
+ });
+ };
+ return [key, partWithSource];
+ }));
+}
+
+function assertParts(nf, x, expected) {
+ var parts = nf.formatToParts(x);
+ assertEq(parts.map(part => part.value).join(""), nf.format(x),
+ "formatToParts and format must agree");
+
+ var len = parts.length;
+ assertEq(len, expected.length, "parts count mismatch");
+ for (var i = 0; i < len; i++) {
+ assertEq(parts[i].type, expected[i].type, "type mismatch at " + i);
+ assertEq(parts[i].value, expected[i].value, "value mismatch at " + i);
+ }
+}
+
+function assertRangeParts(nf, start, end, expected) {
+ var parts = nf.formatRangeToParts(start, end);
+ assertEq(parts.map(part => part.value).join(""), nf.formatRange(start, end),
+ "formatRangeToParts and formatRange must agree");
+
+ var len = parts.length;
+ assertEq(len, expected.length, "parts count mismatch");
+ for (var i = 0; i < len; i++) {
+ assertEq(parts[i].type, expected[i].type, "type mismatch at " + i);
+ assertEq(parts[i].value, expected[i].value, "value mismatch at " + i);
+ assertEq(parts[i].source, expected[i].source, "source mismatch at " + i);
+ }
+}
+
+function runNumberFormattingTestcases(testcases) {
+ for (let {locale, options, values} of testcases) {
+ let nf = new Intl.NumberFormat(locale, options);
+
+ for (let {value, string, parts} of values) {
+ assertEq(nf.format(value), string,
+ `locale=${locale}, options=${JSON.stringify(options)}, value=${value}`);
+
+ assertParts(nf, value, parts);
+ }
+ }
+}
diff --git a/js/src/tests/non262/Intl/NumberFormat/sign-display.js b/js/src/tests/non262/Intl/NumberFormat/sign-display.js
new file mode 100644
index 0000000000..b18517d847
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/sign-display.js
@@ -0,0 +1,187 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const {
+ Nan, Inf, Integer, MinusSign, PlusSign, Decimal, Fraction
+} = NumberFormatParts;
+
+const testcases = [
+ // "auto": Show the sign on negative numbers only.
+ {
+ locale: "en",
+ options: {
+ signDisplay: "auto",
+ },
+ values: [
+ {value: +0, string: "0", parts: [Integer("0")]},
+ {value: -0, string: "-0", parts: [MinusSign("-"), Integer("0")]},
+ {value: 0n, string: "0", parts: [Integer("0")]},
+
+ {value: 1, string: "1", parts: [Integer("1")]},
+ {value: -1, string: "-1", parts: [MinusSign("-"), Integer("1")]},
+ {value: 1n, string: "1", parts: [Integer("1")]},
+ {value: -1n, string: "-1", parts: [MinusSign("-"), Integer("1")]},
+
+ {value: 0.1, string: "0.1", parts: [Integer("0"), Decimal("."), Fraction("1")]},
+ {value: -0.1, string: "-0.1", parts: [MinusSign("-"), Integer("0"), Decimal("."), Fraction("1")]},
+
+ {value: 0.9, string: "0.9", parts: [Integer("0"), Decimal("."), Fraction("9")]},
+ {value: -0.9, string: "-0.9", parts: [MinusSign("-"), Integer("0"), Decimal("."), Fraction("9")]},
+
+ {value: Infinity, string: "∞", parts: [Inf("∞")]},
+ {value: -Infinity, string: "-∞", parts: [MinusSign("-"), Inf("∞")]},
+
+ {value: NaN, string: "NaN", parts: [Nan("NaN")]},
+ {value: -NaN, string: "NaN", parts: [Nan("NaN")]},
+ ],
+ },
+
+ // "never": Show the sign on neither positive nor negative numbers.
+ {
+ locale: "en",
+ options: {
+ signDisplay: "never",
+ },
+ values: [
+ {value: +0, string: "0", parts: [Integer("0")]},
+ {value: -0, string: "0", parts: [Integer("0")]},
+ {value: 0n, string: "0", parts: [Integer("0")]},
+
+ {value: 1, string: "1", parts: [Integer("1")]},
+ {value: -1, string: "1", parts: [Integer("1")]},
+ {value: 1n, string: "1", parts: [Integer("1")]},
+ {value: -1n, string: "1", parts: [Integer("1")]},
+
+ {value: 0.1, string: "0.1", parts: [Integer("0"), Decimal("."), Fraction("1")]},
+ {value: -0.1, string: "0.1", parts: [Integer("0"), Decimal("."), Fraction("1")]},
+
+ {value: 0.9, string: "0.9", parts: [Integer("0"), Decimal("."), Fraction("9")]},
+ {value: -0.9, string: "0.9", parts: [Integer("0"), Decimal("."), Fraction("9")]},
+
+ {value: Infinity, string: "∞", parts: [Inf("∞")]},
+ {value: -Infinity, string: "∞", parts: [Inf("∞")]},
+
+ {value: NaN, string: "NaN", parts: [Nan("NaN")]},
+ {value: -NaN, string: "NaN", parts: [Nan("NaN")]},
+ ],
+ },
+
+ // "always": Show the sign on positive and negative numbers including zero.
+ {
+ locale: "en",
+ options: {
+ signDisplay: "always",
+ },
+ values: [
+ {value: +0, string: "+0", parts: [PlusSign("+"), Integer("0")]},
+ {value: -0, string: "-0", parts: [MinusSign("-"), Integer("0")]},
+ {value: 0n, string: "+0", parts: [PlusSign("+"), Integer("0")]},
+
+ {value: 1, string: "+1", parts: [PlusSign("+"), Integer("1")]},
+ {value: -1, string: "-1", parts: [MinusSign("-"), Integer("1")]},
+ {value: 1n, string: "+1", parts: [PlusSign("+"), Integer("1")]},
+ {value: -1n, string: "-1", parts: [MinusSign("-"), Integer("1")]},
+
+ {value: 0.1, string: "+0.1", parts: [PlusSign("+"), Integer("0"), Decimal("."), Fraction("1")]},
+ {value: -0.1, string: "-0.1", parts: [MinusSign("-"), Integer("0"), Decimal("."), Fraction("1")]},
+
+ {value: 0.9, string: "+0.9", parts: [PlusSign("+"), Integer("0"), Decimal("."), Fraction("9")]},
+ {value: -0.9, string: "-0.9", parts: [MinusSign("-"), Integer("0"), Decimal("."), Fraction("9")]},
+
+ {value: Infinity, string: "+∞", parts: [PlusSign("+"), Inf("∞")]},
+ {value: -Infinity, string: "-∞", parts: [MinusSign("-"), Inf("∞")]},
+
+ {value: NaN, string: "+NaN", parts: [PlusSign("+"), Nan("NaN")]},
+ {value: -NaN, string: "+NaN", parts: [PlusSign("+"), Nan("NaN")]},
+ ],
+ },
+
+ // "exceptZero": Show the sign on positive and negative numbers but not zero.
+ {
+ locale: "en",
+ options: {
+ signDisplay: "exceptZero",
+ },
+ values: [
+ {value: +0, string: "0", parts: [Integer("0")]},
+ {value: -0, string: "0", parts: [Integer("0")]},
+ {value: 0n, string: "0", parts: [Integer("0")]},
+
+ {value: 1, string: "+1", parts: [PlusSign("+"), Integer("1")]},
+ {value: -1, string: "-1", parts: [MinusSign("-"), Integer("1")]},
+ {value: 1n, string: "+1", parts: [PlusSign("+"), Integer("1")]},
+ {value: -1n, string: "-1", parts: [MinusSign("-"), Integer("1")]},
+
+ {value: 0.1, string: "+0.1", parts: [PlusSign("+"), Integer("0"), Decimal("."), Fraction("1")]},
+ {value: -0.1, string: "-0.1", parts: [MinusSign("-"), Integer("0"), Decimal("."), Fraction("1")]},
+
+ {value: 0.9, string: "+0.9", parts: [PlusSign("+"), Integer("0"), Decimal("."), Fraction("9")]},
+ {value: -0.9, string: "-0.9", parts: [MinusSign("-"), Integer("0"), Decimal("."), Fraction("9")]},
+
+ {value: Infinity, string: "+∞", parts: [PlusSign("+"), Inf("∞")]},
+ {value: -Infinity, string: "-∞", parts: [MinusSign("-"), Inf("∞")]},
+
+ {value: NaN, string: "NaN", parts: [Nan("NaN")]},
+ {value: -NaN, string: "NaN", parts: [Nan("NaN")]},
+ ],
+ },
+
+ // Tests with suppressed fractional digits.
+
+ // "auto": Show the sign on negative numbers only.
+ {
+ locale: "en",
+ options: {
+ signDisplay: "auto",
+ maximumFractionDigits: 0,
+ },
+ values: [
+ {value: +0.1, string: "0", parts: [Integer("0")]},
+ {value: -0.1, string: "-0", parts: [MinusSign("-"), Integer("0")]},
+ ],
+ },
+
+ // "never": Show the sign on neither positive nor negative numbers.
+ {
+ locale: "en",
+ options: {
+ signDisplay: "never",
+ maximumFractionDigits: 0,
+ },
+ values: [
+ {value: +0.1, string: "0", parts: [Integer("0")]},
+ {value: -0.1, string: "0", parts: [Integer("0")]},
+ ],
+ },
+
+ // "always": Show the sign on positive and negative numbers including zero.
+ {
+ locale: "en",
+ options: {
+ signDisplay: "always",
+ maximumFractionDigits: 0,
+ },
+ values: [
+ {value: +0.1, string: "+0", parts: [PlusSign("+"), Integer("0")]},
+ {value: -0.1, string: "-0", parts: [MinusSign("-"), Integer("0")]},
+ ],
+ },
+
+ // "exceptZero": Show the sign on positive and negative numbers but not zero.
+ {
+ locale: "en",
+ options: {
+ signDisplay: "exceptZero",
+ maximumFractionDigits: 0,
+ },
+
+ values: [
+ {value: +0.1, string: "0", parts: [Integer("0")]},
+ {value: -0.1, string: "0", parts: [Integer("0")]},
+ ],
+ }
+];
+
+runNumberFormattingTestcases(testcases);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/significantDigitsOfZero.js b/js/src/tests/non262/Intl/NumberFormat/significantDigitsOfZero.js
new file mode 100644
index 0000000000..c569313266
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/significantDigitsOfZero.js
@@ -0,0 +1,38 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+// -- test that NumberFormat correctly formats 0 with various numbers of significant digits
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+var testData = [
+ {minimumSignificantDigits: 1, maximumSignificantDigits: 1, expected: "0"},
+ {minimumSignificantDigits: 1, maximumSignificantDigits: 2, expected: "0"},
+ {minimumSignificantDigits: 1, maximumSignificantDigits: 3, expected: "0"},
+ {minimumSignificantDigits: 1, maximumSignificantDigits: 4, expected: "0"},
+ {minimumSignificantDigits: 1, maximumSignificantDigits: 5, expected: "0"},
+ {minimumSignificantDigits: 2, maximumSignificantDigits: 2, expected: "0.0"},
+ {minimumSignificantDigits: 2, maximumSignificantDigits: 3, expected: "0.0"},
+ {minimumSignificantDigits: 2, maximumSignificantDigits: 4, expected: "0.0"},
+ {minimumSignificantDigits: 2, maximumSignificantDigits: 5, expected: "0.0"},
+ {minimumSignificantDigits: 3, maximumSignificantDigits: 3, expected: "0.00"},
+ {minimumSignificantDigits: 3, maximumSignificantDigits: 4, expected: "0.00"},
+ {minimumSignificantDigits: 3, maximumSignificantDigits: 5, expected: "0.00"},
+];
+
+for (var i = 0; i < testData.length; i++) {
+ var min = testData[i].minimumSignificantDigits;
+ var max = testData[i].maximumSignificantDigits;
+ var options = {minimumSignificantDigits: min, maximumSignificantDigits: max};
+ var format = new Intl.NumberFormat("en-US", options);
+ var actual = format.format(0);
+ var expected = testData[i].expected;
+ assertEq(actual, expected,
+ "Wrong formatted string for 0 with " +
+ "minimumSignificantDigits " + min +
+ ", maximumSignificantDigits " + max +
+ ": expected \"" + expected +
+ "\", actual \"" + actual + "\"");
+}
+
+reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/supportedLocalesOf.js b/js/src/tests/non262/Intl/NumberFormat/supportedLocalesOf.js
new file mode 100644
index 0000000000..5ba4470a98
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/supportedLocalesOf.js
@@ -0,0 +1,371 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||xulRuntime.shell)
+// -- test in browser only that ICU has locale data for all Mozilla languages
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This array contains the locales that ICU supports in
+// number formatting whose languages Mozilla localizes Firefox into.
+// Current as of ICU 50.1.2 and Firefox March 2013.
+var locales = [
+ "af",
+ "af-NA",
+ "af-ZA",
+ "ar",
+ "ar-001",
+ "ar-AE",
+ "ar-BH",
+ "ar-DJ",
+ "ar-DZ",
+ "ar-EG",
+ "ar-EH",
+ "ar-ER",
+ "ar-IL",
+ "ar-IQ",
+ "ar-JO",
+ "ar-KM",
+ "ar-KW",
+ "ar-LB",
+ "ar-LY",
+ "ar-MA",
+ "ar-MR",
+ "ar-OM",
+ "ar-PS",
+ "ar-QA",
+ "ar-SA",
+ "ar-SD",
+ "ar-SO",
+ "ar-SY",
+ "ar-TD",
+ "ar-TN",
+ "ar-YE",
+ "as",
+ "as-IN",
+ "be",
+ "be-BY",
+ "bg",
+ "bg-BG",
+ "bn",
+ "bn-BD",
+ "bn-IN",
+ "br",
+ "br-FR",
+ "bs",
+ "bs-Cyrl",
+ "bs-Cyrl-BA",
+ "bs-Latn",
+ "bs-Latn-BA",
+ "ca",
+ "ca-AD",
+ "ca-ES",
+ "cs",
+ "cs-CZ",
+ "cy",
+ "cy-GB",
+ "da",
+ "da-DK",
+ "de",
+ "de-AT",
+ "de-BE",
+ "de-CH",
+ "de-DE",
+ "de-LI",
+ "de-LU",
+ "el",
+ "el-CY",
+ "el-GR",
+ "en",
+ "en-150",
+ "en-AG",
+ "en-AS",
+ "en-AU",
+ "en-BB",
+ "en-BE",
+ "en-BM",
+ "en-BS",
+ "en-BW",
+ "en-BZ",
+ "en-CA",
+ "en-CM",
+ "en-DM",
+ "en-FJ",
+ "en-FM",
+ "en-GB",
+ "en-GD",
+ "en-GG",
+ "en-GH",
+ "en-GI",
+ "en-GM",
+ "en-GU",
+ "en-GY",
+ "en-HK",
+ "en-IE",
+ "en-IM",
+ "en-IN",
+ "en-JE",
+ "en-JM",
+ "en-KE",
+ "en-KI",
+ "en-KN",
+ "en-KY",
+ "en-LC",
+ "en-LR",
+ "en-LS",
+ "en-MG",
+ "en-MH",
+ "en-MP",
+ "en-MT",
+ "en-MU",
+ "en-MW",
+ "en-NA",
+ "en-NG",
+ "en-NZ",
+ "en-PG",
+ "en-PH",
+ "en-PK",
+ "en-PR",
+ "en-PW",
+ "en-SB",
+ "en-SC",
+ "en-SG",
+ "en-SL",
+ "en-SS",
+ "en-SZ",
+ "en-TC",
+ "en-TO",
+ "en-TT",
+ "en-TZ",
+ "en-UG",
+ "en-UM",
+ "en-US",
+ "en-US-POSIX",
+ "en-VC",
+ "en-VG",
+ "en-VI",
+ "en-VU",
+ "en-WS",
+ "en-ZA",
+ "en-ZM",
+ "en-ZW",
+ "eo",
+ "es",
+ "es-419",
+ "es-AR",
+ "es-BO",
+ "es-CL",
+ "es-CO",
+ "es-CR",
+ "es-CU",
+ "es-DO",
+ "es-EA",
+ "es-EC",
+ "es-ES",
+ "es-GQ",
+ "es-GT",
+ "es-HN",
+ "es-IC",
+ "es-MX",
+ "es-NI",
+ "es-PA",
+ "es-PE",
+ "es-PH",
+ "es-PR",
+ "es-PY",
+ "es-SV",
+ "es-US",
+ "es-UY",
+ "es-VE",
+ "et",
+ "et-EE",
+ "eu",
+ "eu-ES",
+ "fa",
+ "fa-AF",
+ "fa-IR",
+ "ff",
+ "ff-SN",
+ "fi",
+ "fi-FI",
+ "fr",
+ "fr-BE",
+ "fr-BF",
+ "fr-BI",
+ "fr-BJ",
+ "fr-BL",
+ "fr-CA",
+ "fr-CD",
+ "fr-CF",
+ "fr-CG",
+ "fr-CH",
+ "fr-CI",
+ "fr-CM",
+ "fr-DJ",
+ "fr-DZ",
+ "fr-FR",
+ "fr-GA",
+ "fr-GF",
+ "fr-GN",
+ "fr-GP",
+ "fr-GQ",
+ "fr-HT",
+ "fr-KM",
+ "fr-LU",
+ "fr-MA",
+ "fr-MC",
+ "fr-MF",
+ "fr-MG",
+ "fr-ML",
+ "fr-MQ",
+ "fr-MR",
+ "fr-MU",
+ "fr-NC",
+ "fr-NE",
+ "fr-PF",
+ "fr-RE",
+ "fr-RW",
+ "fr-SC",
+ "fr-SN",
+ "fr-SY",
+ "fr-TD",
+ "fr-TG",
+ "fr-TN",
+ "fr-VU",
+ "fr-YT",
+ "ga",
+ "ga-IE",
+ "gl",
+ "gl-ES",
+ "gu",
+ "gu-IN",
+ "he",
+ "he-IL",
+ "hi",
+ "hi-IN",
+ "hr",
+ "hr-BA",
+ "hr-HR",
+ "hu",
+ "hu-HU",
+ "hy",
+ "hy-AM",
+ "id",
+ "id-ID",
+ "is",
+ "is-IS",
+ "it",
+ "it-CH",
+ "it-IT",
+ "it-SM",
+ "ja",
+ "ja-JP",
+ "kk",
+ "kk-Cyrl",
+ "kk-Cyrl-KZ",
+ "km",
+ "km-KH",
+ "kn",
+ "kn-IN",
+ "ko",
+ "ko-KP",
+ "ko-KR",
+ "lt",
+ "lt-LT",
+ "lv",
+ "lv-LV",
+ "mk",
+ "mk-MK",
+ "ml",
+ "ml-IN",
+ "mr",
+ "mr-IN",
+ "nb",
+ "nb-NO",
+ "nl",
+ "nl-AW",
+ "nl-BE",
+ "nl-CW",
+ "nl-NL",
+ "nl-SR",
+ "nl-SX",
+ "nn",
+ "nn-NO",
+ "or",
+ "or-IN",
+ "pa",
+ "pa-Arab",
+ "pa-Arab-PK",
+ "pa-Guru",
+ "pa-Guru-IN",
+ "pl",
+ "pl-PL",
+ "pt",
+ "pt-AO",
+ "pt-BR",
+ "pt-CV",
+ "pt-GW",
+ "pt-MO",
+ "pt-MZ",
+ "pt-PT",
+ "pt-ST",
+ "pt-TL",
+ "rm",
+ "rm-CH",
+ "ro",
+ "ro-MD",
+ "ro-RO",
+ "ru",
+ "ru-BY",
+ "ru-KG",
+ "ru-KZ",
+ "ru-MD",
+ "ru-RU",
+ "ru-UA",
+ "si",
+ "si-LK",
+ "sk",
+ "sk-SK",
+ "sl",
+ "sl-SI",
+ "sq",
+ "sq-AL",
+ "sq-MK",
+ "sr",
+ "sr-Cyrl",
+ "sr-Cyrl-BA",
+ "sr-Cyrl-ME",
+ "sr-Cyrl-RS",
+ "sr-Latn",
+ "sr-Latn-BA",
+ "sr-Latn-ME",
+ "sr-Latn-RS",
+ "sv",
+ "sv-AX",
+ "sv-FI",
+ "sv-SE",
+ "te",
+ "te-IN",
+ "th",
+ "th-TH",
+ "tr",
+ "tr-CY",
+ "tr-TR",
+ "uk",
+ "uk-UA",
+ "vi",
+ "vi-VN",
+ "zh",
+ "zh-Hans",
+ "zh-Hans-CN",
+ "zh-Hans-HK",
+ "zh-Hans-MO",
+ "zh-Hans-SG",
+ "zh-Hant",
+ "zh-Hant-HK",
+ "zh-Hant-MO",
+ "zh-Hant-TW",
+];
+
+var count = Intl.NumberFormat.supportedLocalesOf(locales).length;
+
+reportCompare(locales.length, count, "Number of supported locales in Intl.NumberFormat");
diff --git a/js/src/tests/non262/Intl/NumberFormat/toStringTag.js b/js/src/tests/non262/Intl/NumberFormat/toStringTag.js
new file mode 100644
index 0000000000..9ad0901a0b
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/toStringTag.js
@@ -0,0 +1,29 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+var desc = Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, Symbol.toStringTag);
+
+assertEq(desc !== undefined, true);
+assertEq(desc.value, "Intl.NumberFormat");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+
+assertEq(Object.prototype.toString.call(Intl.NumberFormat.prototype), "[object Intl.NumberFormat]");
+assertEq(Object.prototype.toString.call(new Intl.NumberFormat), "[object Intl.NumberFormat]");
+
+Object.defineProperty(Intl.NumberFormat.prototype, Symbol.toStringTag, {value: "NumberFormat"});
+
+assertEq(Object.prototype.toString.call(Intl.NumberFormat.prototype), "[object NumberFormat]");
+assertEq(Object.prototype.toString.call(new Intl.NumberFormat), "[object NumberFormat]");
+
+delete Intl.NumberFormat.prototype[Symbol.toStringTag];
+
+assertEq(Object.prototype.toString.call(Intl.NumberFormat.prototype), "[object Object]");
+assertEq(Object.prototype.toString.call(new Intl.NumberFormat), "[object Object]");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/trailing-zero-display.js b/js/src/tests/non262/Intl/NumberFormat/trailing-zero-display.js
new file mode 100644
index 0000000000..5e3113285a
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/trailing-zero-display.js
@@ -0,0 +1,98 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||release_or_beta)
+
+// "stripIfInteger" with fractional digits.
+{
+ let nf1 = new Intl.NumberFormat("en", {
+ minimumFractionDigits: 2,
+ });
+
+ let nf2 = new Intl.NumberFormat("en", {
+ minimumFractionDigits: 2,
+ trailingZeroDisplay: "auto",
+ });
+
+ let nf3 = new Intl.NumberFormat("en", {
+ minimumFractionDigits: 2,
+ trailingZeroDisplay: "stripIfInteger",
+ });
+
+ assertEq(nf1.resolvedOptions().trailingZeroDisplay, "auto");
+ assertEq(nf2.resolvedOptions().trailingZeroDisplay, "auto");
+ assertEq(nf3.resolvedOptions().trailingZeroDisplay, "stripIfInteger");
+
+ assertEq(nf1.format(123), "123.00");
+ assertEq(nf2.format(123), "123.00");
+ assertEq(nf3.format(123), "123");
+}
+
+// "stripIfInteger" with significand digits.
+{
+ let nf1 = new Intl.NumberFormat("en", {
+ minimumSignificantDigits: 2,
+ });
+
+ let nf2 = new Intl.NumberFormat("en", {
+ minimumSignificantDigits: 2,
+ trailingZeroDisplay: "auto",
+ });
+
+ let nf3 = new Intl.NumberFormat("en", {
+ minimumSignificantDigits: 2,
+ trailingZeroDisplay: "stripIfInteger",
+ });
+
+ assertEq(nf1.resolvedOptions().trailingZeroDisplay, "auto");
+ assertEq(nf2.resolvedOptions().trailingZeroDisplay, "auto");
+ assertEq(nf3.resolvedOptions().trailingZeroDisplay, "stripIfInteger");
+
+ assertEq(nf1.format(1), "1.0");
+ assertEq(nf2.format(1), "1.0");
+ assertEq(nf3.format(1), "1");
+}
+
+// "stripIfInteger" with rounding increment.
+{
+ let nf1 = new Intl.NumberFormat("en", {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ roundingIncrement: 5,
+ });
+ let nf2 = new Intl.NumberFormat("en", {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ roundingIncrement: 5,
+ trailingZeroDisplay: "auto",
+ });
+ let nf3 = new Intl.NumberFormat("en", {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ roundingIncrement: 5,
+ trailingZeroDisplay: "stripIfInteger",
+ });
+
+ assertEq(nf1.resolvedOptions().trailingZeroDisplay, "auto");
+ assertEq(nf2.resolvedOptions().trailingZeroDisplay, "auto");
+ assertEq(nf3.resolvedOptions().trailingZeroDisplay, "stripIfInteger");
+
+ // NB: Tests 1.975 twice b/c of <https://unicode-org.atlassian.net/browse/ICU-21674>.
+
+ assertEq(nf1.format(1.975), "2.00");
+ assertEq(nf1.format(1.97), "1.95");
+ assertEq(nf1.format(1.975), "2.00");
+
+ assertEq(nf2.format(1.975), "2.00");
+ assertEq(nf2.format(1.97), "1.95");
+ assertEq(nf2.format(1.975), "2.00");
+
+ assertEq(nf3.format(1.975), "2");
+ assertEq(nf3.format(1.97), "1.95");
+ assertEq(nf3.format(1.975), "2");
+}
+
+// Invalid values.
+for (let trailingZeroDisplay of ["", "true", true, "none", "yes", "no"]){
+ assertThrowsInstanceOf(() => new Intl.NumberFormat("en", {trailingZeroDisplay}), RangeError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/unit-compound-combinations.js b/js/src/tests/non262/Intl/NumberFormat/unit-compound-combinations.js
new file mode 100644
index 0000000000..2aad94b98e
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/unit-compound-combinations.js
@@ -0,0 +1,65 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Generated by make_intl_data.py. DO NOT EDIT.
+
+const sanctionedSimpleUnitIdentifiers = [
+ "acre",
+ "bit",
+ "byte",
+ "celsius",
+ "centimeter",
+ "day",
+ "degree",
+ "fahrenheit",
+ "fluid-ounce",
+ "foot",
+ "gallon",
+ "gigabit",
+ "gigabyte",
+ "gram",
+ "hectare",
+ "hour",
+ "inch",
+ "kilobit",
+ "kilobyte",
+ "kilogram",
+ "kilometer",
+ "liter",
+ "megabit",
+ "megabyte",
+ "meter",
+ "microsecond",
+ "mile",
+ "mile-scandinavian",
+ "milliliter",
+ "millimeter",
+ "millisecond",
+ "minute",
+ "month",
+ "nanosecond",
+ "ounce",
+ "percent",
+ "petabyte",
+ "pound",
+ "second",
+ "stone",
+ "terabit",
+ "terabyte",
+ "week",
+ "yard",
+ "year"
+];
+
+// Test all simple unit identifier combinations are allowed.
+
+for (const numerator of sanctionedSimpleUnitIdentifiers) {
+ for (const denominator of sanctionedSimpleUnitIdentifiers) {
+ const unit = `${numerator}-per-${denominator}`;
+ const nf = new Intl.NumberFormat("en", {style: "unit", unit});
+
+ assertEq(nf.format(1), nf.formatToParts(1).map(p => p.value).join(""));
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/unit-formatToParts-has-unit-field.js b/js/src/tests/non262/Intl/NumberFormat/unit-formatToParts-has-unit-field.js
new file mode 100644
index 0000000000..9292c8ac73
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/unit-formatToParts-has-unit-field.js
@@ -0,0 +1,90 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Generated by make_intl_data.py. DO NOT EDIT.
+
+const sanctionedSimpleUnitIdentifiers = [
+ "acre",
+ "bit",
+ "byte",
+ "celsius",
+ "centimeter",
+ "day",
+ "degree",
+ "fahrenheit",
+ "fluid-ounce",
+ "foot",
+ "gallon",
+ "gigabit",
+ "gigabyte",
+ "gram",
+ "hectare",
+ "hour",
+ "inch",
+ "kilobit",
+ "kilobyte",
+ "kilogram",
+ "kilometer",
+ "liter",
+ "megabit",
+ "megabyte",
+ "meter",
+ "microsecond",
+ "mile",
+ "mile-scandinavian",
+ "milliliter",
+ "millimeter",
+ "millisecond",
+ "minute",
+ "month",
+ "nanosecond",
+ "ounce",
+ "percent",
+ "petabyte",
+ "pound",
+ "second",
+ "stone",
+ "terabit",
+ "terabyte",
+ "week",
+ "yard",
+ "year"
+];
+
+// Test only English and Chinese to keep the overall runtime reasonable.
+//
+// Chinese is included because it contains more than one "unit" element for
+// certain unit combinations.
+const locales = ["en", "zh"];
+
+// Plural rules for English only differentiate between "one" and "other". Plural
+// rules for Chinese only use "other". That means we only need to test two values
+// per unit.
+const values = [0, 1];
+
+// Ensure unit formatters contain at least one "unit" element.
+
+for (const locale of locales) {
+ for (const unit of sanctionedSimpleUnitIdentifiers) {
+ const nf = new Intl.NumberFormat(locale, {style: "unit", unit});
+
+ for (const value of values) {
+ assertEq(nf.formatToParts(value).some(e => e.type === "unit"), true,
+ `locale=${locale}, unit=${unit}`);
+ }
+ }
+
+ for (const numerator of sanctionedSimpleUnitIdentifiers) {
+ for (const denominator of sanctionedSimpleUnitIdentifiers) {
+ const unit = `${numerator}-per-${denominator}`;
+ const nf = new Intl.NumberFormat(locale, {style: "unit", unit});
+
+ for (const value of values) {
+ assertEq(nf.formatToParts(value).some(e => e.type === "unit"), true,
+ `locale=${locale}, unit=${unit}`);
+ }
+ }
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/unit-well-formed.js b/js/src/tests/non262/Intl/NumberFormat/unit-well-formed.js
new file mode 100644
index 0000000000..8eca3b58cf
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/unit-well-formed.js
@@ -0,0 +1,267 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Generated by make_intl_data.py. DO NOT EDIT.
+
+const sanctionedSimpleUnitIdentifiers = [
+ "acre",
+ "bit",
+ "byte",
+ "celsius",
+ "centimeter",
+ "day",
+ "degree",
+ "fahrenheit",
+ "fluid-ounce",
+ "foot",
+ "gallon",
+ "gigabit",
+ "gigabyte",
+ "gram",
+ "hectare",
+ "hour",
+ "inch",
+ "kilobit",
+ "kilobyte",
+ "kilogram",
+ "kilometer",
+ "liter",
+ "megabit",
+ "megabyte",
+ "meter",
+ "microsecond",
+ "mile",
+ "mile-scandinavian",
+ "milliliter",
+ "millimeter",
+ "millisecond",
+ "minute",
+ "month",
+ "nanosecond",
+ "ounce",
+ "percent",
+ "petabyte",
+ "pound",
+ "second",
+ "stone",
+ "terabit",
+ "terabyte",
+ "week",
+ "yard",
+ "year"
+];
+
+const allUnits = [
+ "acceleration-g-force",
+ "acceleration-meter-per-square-second",
+ "angle-arc-minute",
+ "angle-arc-second",
+ "angle-degree",
+ "angle-radian",
+ "angle-revolution",
+ "area-acre",
+ "area-dunam",
+ "area-hectare",
+ "area-square-centimeter",
+ "area-square-foot",
+ "area-square-inch",
+ "area-square-kilometer",
+ "area-square-meter",
+ "area-square-mile",
+ "area-square-yard",
+ "concentr-item",
+ "concentr-karat",
+ "concentr-milligram-ofglucose-per-deciliter",
+ "concentr-millimole-per-liter",
+ "concentr-mole",
+ "concentr-percent",
+ "concentr-permille",
+ "concentr-permillion",
+ "concentr-permyriad",
+ "consumption-liter-per-100-kilometer",
+ "consumption-liter-per-kilometer",
+ "consumption-mile-per-gallon",
+ "consumption-mile-per-gallon-imperial",
+ "digital-bit",
+ "digital-byte",
+ "digital-gigabit",
+ "digital-gigabyte",
+ "digital-kilobit",
+ "digital-kilobyte",
+ "digital-megabit",
+ "digital-megabyte",
+ "digital-petabyte",
+ "digital-terabit",
+ "digital-terabyte",
+ "duration-century",
+ "duration-day",
+ "duration-day-person",
+ "duration-decade",
+ "duration-hour",
+ "duration-microsecond",
+ "duration-millisecond",
+ "duration-minute",
+ "duration-month",
+ "duration-month-person",
+ "duration-nanosecond",
+ "duration-quarter",
+ "duration-second",
+ "duration-week",
+ "duration-week-person",
+ "duration-year",
+ "duration-year-person",
+ "electric-ampere",
+ "electric-milliampere",
+ "electric-ohm",
+ "electric-volt",
+ "energy-british-thermal-unit",
+ "energy-calorie",
+ "energy-electronvolt",
+ "energy-foodcalorie",
+ "energy-joule",
+ "energy-kilocalorie",
+ "energy-kilojoule",
+ "energy-kilowatt-hour",
+ "energy-therm-us",
+ "force-kilowatt-hour-per-100-kilometer",
+ "force-newton",
+ "force-pound-force",
+ "frequency-gigahertz",
+ "frequency-hertz",
+ "frequency-kilohertz",
+ "frequency-megahertz",
+ "graphics-dot",
+ "graphics-dot-per-centimeter",
+ "graphics-dot-per-inch",
+ "graphics-em",
+ "graphics-megapixel",
+ "graphics-pixel",
+ "graphics-pixel-per-centimeter",
+ "graphics-pixel-per-inch",
+ "length-astronomical-unit",
+ "length-centimeter",
+ "length-decimeter",
+ "length-earth-radius",
+ "length-fathom",
+ "length-foot",
+ "length-furlong",
+ "length-inch",
+ "length-kilometer",
+ "length-light-year",
+ "length-meter",
+ "length-micrometer",
+ "length-mile",
+ "length-mile-scandinavian",
+ "length-millimeter",
+ "length-nanometer",
+ "length-nautical-mile",
+ "length-parsec",
+ "length-picometer",
+ "length-point",
+ "length-solar-radius",
+ "length-yard",
+ "light-candela",
+ "light-lumen",
+ "light-lux",
+ "light-solar-luminosity",
+ "mass-carat",
+ "mass-dalton",
+ "mass-earth-mass",
+ "mass-grain",
+ "mass-gram",
+ "mass-kilogram",
+ "mass-microgram",
+ "mass-milligram",
+ "mass-ounce",
+ "mass-ounce-troy",
+ "mass-pound",
+ "mass-solar-mass",
+ "mass-stone",
+ "mass-ton",
+ "mass-tonne",
+ "power-gigawatt",
+ "power-horsepower",
+ "power-kilowatt",
+ "power-megawatt",
+ "power-milliwatt",
+ "power-watt",
+ "pressure-atmosphere",
+ "pressure-bar",
+ "pressure-hectopascal",
+ "pressure-inch-ofhg",
+ "pressure-kilopascal",
+ "pressure-megapascal",
+ "pressure-millibar",
+ "pressure-millimeter-ofhg",
+ "pressure-pascal",
+ "pressure-pound-force-per-square-inch",
+ "speed-kilometer-per-hour",
+ "speed-knot",
+ "speed-meter-per-second",
+ "speed-mile-per-hour",
+ "temperature-celsius",
+ "temperature-fahrenheit",
+ "temperature-generic",
+ "temperature-kelvin",
+ "torque-newton-meter",
+ "torque-pound-force-foot",
+ "volume-acre-foot",
+ "volume-barrel",
+ "volume-bushel",
+ "volume-centiliter",
+ "volume-cubic-centimeter",
+ "volume-cubic-foot",
+ "volume-cubic-inch",
+ "volume-cubic-kilometer",
+ "volume-cubic-meter",
+ "volume-cubic-mile",
+ "volume-cubic-yard",
+ "volume-cup",
+ "volume-cup-metric",
+ "volume-deciliter",
+ "volume-dessert-spoon",
+ "volume-dessert-spoon-imperial",
+ "volume-dram",
+ "volume-drop",
+ "volume-fluid-ounce",
+ "volume-fluid-ounce-imperial",
+ "volume-gallon",
+ "volume-gallon-imperial",
+ "volume-hectoliter",
+ "volume-jigger",
+ "volume-liter",
+ "volume-megaliter",
+ "volume-milliliter",
+ "volume-pinch",
+ "volume-pint",
+ "volume-pint-metric",
+ "volume-quart",
+ "volume-quart-imperial",
+ "volume-tablespoon",
+ "volume-teaspoon"
+];
+
+// Test only sanctioned unit identifiers are allowed.
+
+for (const typeAndUnit of allUnits) {
+ const [_, type, unit] = typeAndUnit.match(/(\w+)-(.+)/);
+
+ let allowed;
+ if (unit.includes("-per-")) {
+ const [numerator, denominator] = unit.split("-per-");
+ allowed = sanctionedSimpleUnitIdentifiers.includes(numerator) &&
+ sanctionedSimpleUnitIdentifiers.includes(denominator);
+ } else {
+ allowed = sanctionedSimpleUnitIdentifiers.includes(unit);
+ }
+
+ if (allowed) {
+ const nf = new Intl.NumberFormat("en", {style: "unit", unit});
+ assertEq(nf.format(1), nf.formatToParts(1).map(p => p.value).join(""));
+ } else {
+ assertThrowsInstanceOf(() => new Intl.NumberFormat("en", {style: "unit", unit}),
+ RangeError, `Missing error for "${typeAndUnit}"`);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/unit.js b/js/src/tests/non262/Intl/NumberFormat/unit.js
new file mode 100644
index 0000000000..7abc5142e0
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/unit.js
@@ -0,0 +1,104 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const {
+ Nan, Inf, Integer, MinusSign, PlusSign, Literal,
+ Unit
+} = NumberFormatParts;
+
+const testcases = [
+ {
+ locale: "en",
+ options: {
+ style: "unit",
+ unit: "meter",
+ unitDisplay: "short",
+ },
+ values: [
+ {value: +0, string: "0 m", parts: [Integer("0"), Literal(" "), Unit("m")]},
+ {value: -0, string: "-0 m", parts: [MinusSign("-"), Integer("0"), Literal(" "), Unit("m")]},
+ {value: 0n, string: "0 m", parts: [Integer("0"), Literal(" "), Unit("m")]},
+
+ {value: 1, string: "1 m", parts: [Integer("1"), Literal(" "), Unit("m")]},
+ {value: -1, string: "-1 m", parts: [MinusSign("-"), Integer("1"), Literal(" "), Unit("m")]},
+ {value: 1n, string: "1 m", parts: [Integer("1"), Literal(" "), Unit("m")]},
+ {value: -1n, string: "-1 m", parts: [MinusSign("-"), Integer("1"), Literal(" "), Unit("m")]},
+
+ {value: Infinity, string: "∞ m", parts: [Inf("∞"), Literal(" "), Unit("m")]},
+ {value: -Infinity, string: "-∞ m", parts: [MinusSign("-"), Inf("∞"), Literal(" "), Unit("m")]},
+
+ {value: NaN, string: "NaN m", parts: [Nan("NaN"), Literal(" "), Unit("m")]},
+ {value: -NaN, string: "NaN m", parts: [Nan("NaN"), Literal(" "), Unit("m")]},
+ ],
+ },
+
+ {
+ locale: "en",
+ options: {
+ style: "unit",
+ unit: "meter",
+ unitDisplay: "narrow",
+ },
+ values: [
+ {value: +0, string: "0m", parts: [Integer("0"), Unit("m")]},
+ {value: -0, string: "-0m", parts: [MinusSign("-"), Integer("0"), Unit("m")]},
+ {value: 0n, string: "0m", parts: [Integer("0"), Unit("m")]},
+
+ {value: 1, string: "1m", parts: [Integer("1"), Unit("m")]},
+ {value: -1, string: "-1m", parts: [MinusSign("-"), Integer("1"), Unit("m")]},
+ {value: 1n, string: "1m", parts: [Integer("1"), Unit("m")]},
+ {value: -1n, string: "-1m", parts: [MinusSign("-"), Integer("1"), Unit("m")]},
+
+ {value: Infinity, string: "∞m", parts: [Inf("∞"), Unit("m")]},
+ {value: -Infinity, string: "-∞m", parts: [MinusSign("-"), Inf("∞"), Unit("m")]},
+
+ {value: NaN, string: "NaNm", parts: [Nan("NaN"), Unit("m")]},
+ {value: -NaN, string: "NaNm", parts: [Nan("NaN"), Unit("m")]},
+ ],
+ },
+
+ {
+ locale: "en",
+ options: {
+ style: "unit",
+ unit: "meter",
+ unitDisplay: "long",
+ },
+ values: [
+ {value: +0, string: "0 meters", parts: [Integer("0"), Literal(" "), Unit("meters")]},
+ {value: -0, string: "-0 meters", parts: [MinusSign("-"), Integer("0"), Literal(" "), Unit("meters")]},
+ {value: 0n, string: "0 meters", parts: [Integer("0"), Literal(" "), Unit("meters")]},
+
+ {value: 1, string: "1 meter", parts: [Integer("1"), Literal(" "), Unit("meter")]},
+ {value: -1, string: "-1 meter", parts: [MinusSign("-"), Integer("1"), Literal(" "), Unit("meter")]},
+ {value: 1n, string: "1 meter", parts: [Integer("1"), Literal(" "), Unit("meter")]},
+ {value: -1n, string: "-1 meter", parts: [MinusSign("-"), Integer("1"), Literal(" "), Unit("meter")]},
+
+ {value: Infinity, string: "∞ meters", parts: [Inf("∞"), Literal(" "), Unit("meters")]},
+ {value: -Infinity, string: "-∞ meters", parts: [MinusSign("-"), Inf("∞"), Literal(" "), Unit("meters")]},
+
+ {value: NaN, string: "NaN meters", parts: [Nan("NaN"), Literal(" "), Unit("meters")]},
+ {value: -NaN, string: "NaN meters", parts: [Nan("NaN"), Literal(" "), Unit("meters")]},
+ ],
+ },
+
+ // Ensure the correct compound unit is automatically selected by ICU. For
+ // example instead of "50 chilometri al orari", 50 km/h should return
+ // "50 chilometri orari" in Italian.
+
+ {
+ locale: "it",
+ options: {
+ style: "unit",
+ unit: "kilometer-per-hour",
+ unitDisplay: "long",
+ },
+ values: [
+ {value: 50, string: "50 chilometri orari", parts: [Integer("50"), Literal(" "), Unit("chilometri orari")]},
+ ],
+ },
+];
+
+runNumberFormattingTestcases(testcases);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/unwrapping.js b/js/src/tests/non262/Intl/NumberFormat/unwrapping.js
new file mode 100644
index 0000000000..df0b15d6fc
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/unwrapping.js
@@ -0,0 +1,248 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Test UnwrapNumberFormat operation.
+
+const numberFormatFunctions = [];
+numberFormatFunctions.push({
+ function: Intl.NumberFormat.prototype.resolvedOptions,
+ unwrap: true,
+});
+numberFormatFunctions.push({
+ function: Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, "format").get,
+ unwrap: true,
+});
+numberFormatFunctions.push({
+ function: Intl.NumberFormat.prototype.formatToParts,
+ unwrap: false,
+});
+
+function IsIntlService(c) {
+ return typeof c === "function" &&
+ c.hasOwnProperty("prototype") &&
+ c.prototype.hasOwnProperty("resolvedOptions");
+}
+
+function IsObject(o) {
+ return Object(o) === o;
+}
+
+function IsPrimitive(o) {
+ return Object(o) !== o;
+}
+
+function intlObjects(ctor) {
+ let args = [];
+ if (ctor === Intl.DisplayNames) {
+ // Intl.DisplayNames can't be constructed without any arguments.
+ args = [undefined, {type: "language"}];
+ }
+
+ return [
+ // Instance of an Intl constructor.
+ new ctor(...args),
+
+ // Instance of a subclassed Intl constructor.
+ new class extends ctor {}(...args),
+
+ // Intl object not inheriting from its default prototype.
+ Object.setPrototypeOf(new ctor(...args), Object.prototype),
+ ];
+}
+
+function thisValues(C) {
+ const intlConstructors = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService);
+
+ return [
+ // Primitive values.
+ ...[undefined, null, true, "abc", Symbol(), 123],
+
+ // Object values.
+ ...[{}, [], /(?:)/, function(){}, new Proxy({}, {})],
+
+ // Intl objects.
+ ...[].concat(...intlConstructors.filter(ctor => ctor !== C).map(intlObjects)),
+
+ // Object inheriting from an Intl constructor prototype.
+ ...intlConstructors.map(ctor => Object.create(ctor.prototype)),
+ ];
+}
+
+const intlFallbackSymbol = Object.getOwnPropertySymbols(Intl.NumberFormat.call(Object.create(Intl.NumberFormat.prototype)))[0];
+
+// Test Intl.NumberFormat.prototype methods.
+for (let {function: numberFormatFunction, unwrap} of numberFormatFunctions) {
+ // Test a TypeError is thrown when the this-value isn't an initialized
+ // Intl.NumberFormat instance.
+ for (let thisValue of thisValues(Intl.NumberFormat)) {
+ assertThrowsInstanceOf(() => numberFormatFunction.call(thisValue), TypeError);
+ }
+
+ // And test no error is thrown for initialized Intl.NumberFormat instances.
+ for (let thisValue of intlObjects(Intl.NumberFormat)) {
+ numberFormatFunction.call(thisValue);
+ }
+
+ // Manually add [[FallbackSymbol]] to objects and then repeat the tests from above.
+ for (let thisValue of thisValues(Intl.NumberFormat)) {
+ assertThrowsInstanceOf(() => numberFormatFunction.call({
+ __proto__: Intl.NumberFormat.prototype,
+ [intlFallbackSymbol]: thisValue,
+ }), TypeError);
+ }
+
+ for (let thisValue of intlObjects(Intl.NumberFormat)) {
+ let obj = {
+ __proto__: Intl.NumberFormat.prototype,
+ [intlFallbackSymbol]: thisValue,
+ };
+ if (unwrap) {
+ numberFormatFunction.call(obj);
+ } else {
+ assertThrowsInstanceOf(() => numberFormatFunction.call(obj), TypeError);
+ }
+ }
+
+ // Ensure [[FallbackSymbol]] isn't retrieved for Intl.NumberFormat instances.
+ for (let thisValue of intlObjects(Intl.NumberFormat)) {
+ Object.defineProperty(thisValue, intlFallbackSymbol, {
+ get() { assertEq(false, true); }
+ });
+ numberFormatFunction.call(thisValue);
+ }
+
+ // Ensure [[FallbackSymbol]] is only retrieved for objects inheriting from Intl.NumberFormat.prototype.
+ for (let thisValue of thisValues(Intl.NumberFormat).filter(IsObject)) {
+ if (Intl.NumberFormat.prototype.isPrototypeOf(thisValue))
+ continue;
+ Object.defineProperty(thisValue, intlFallbackSymbol, {
+ get() { assertEq(false, true); }
+ });
+ assertThrowsInstanceOf(() => numberFormatFunction.call(thisValue), TypeError);
+ }
+
+ // Repeat the test from above, but also change Intl.NumberFormat[@@hasInstance]
+ // so it always returns |true|.
+ for (let thisValue of thisValues(Intl.NumberFormat).filter(IsObject)) {
+ let isPrototypeOf = Intl.NumberFormat.prototype.isPrototypeOf(thisValue);
+ let hasInstanceCalled = false, symbolGetterCalled = false;
+ Object.defineProperty(Intl.NumberFormat, Symbol.hasInstance, {
+ value() {
+ assertEq(hasInstanceCalled, false);
+ hasInstanceCalled = true;
+ return true;
+ }, configurable: true
+ });
+ Object.defineProperty(thisValue, intlFallbackSymbol, {
+ get() {
+ assertEq(symbolGetterCalled, false);
+ symbolGetterCalled = true;
+ return null;
+ }, configurable: true
+ });
+
+ assertThrowsInstanceOf(() => numberFormatFunction.call(thisValue), TypeError);
+
+ delete Intl.NumberFormat[Symbol.hasInstance];
+
+ assertEq(hasInstanceCalled, false);
+ assertEq(symbolGetterCalled, unwrap && isPrototypeOf);
+ }
+
+ // Test with primitive values.
+ for (let thisValue of thisValues(Intl.NumberFormat).filter(IsPrimitive)) {
+ // Ensure @@hasInstance is not called.
+ Object.defineProperty(Intl.NumberFormat, Symbol.hasInstance, {
+ value() { assertEq(true, false); }, configurable: true
+ });
+ let isUndefinedOrNull = thisValue === undefined || thisValue === null;
+ let symbolHolder;
+ if (!isUndefinedOrNull) {
+ // Ensure the fallback symbol isn't retrieved from the primitive wrapper prototype.
+ symbolHolder = Object.getPrototypeOf(thisValue);
+ Object.defineProperty(symbolHolder, intlFallbackSymbol, {
+ get() { assertEq(true, false); }, configurable: true
+ });
+ }
+
+ assertThrowsInstanceOf(() => numberFormatFunction.call(thisValue), TypeError);
+
+ delete Intl.NumberFormat[Symbol.hasInstance];
+ if (!isUndefinedOrNull)
+ delete symbolHolder[intlFallbackSymbol];
+ }
+}
+
+// Test format() returns the correct result for objects initialized as Intl.NumberFormat instances.
+{
+ // An actual Intl.NumberFormat instance.
+ let numberFormat = new Intl.NumberFormat();
+
+ // An object initialized as a NumberFormat instance.
+ let thisValue = Object.create(Intl.NumberFormat.prototype);
+ Intl.NumberFormat.call(thisValue);
+
+ // Object with [[FallbackSymbol]] set to NumberFormat instance.
+ let fakeObj = {
+ __proto__: Intl.NumberFormat.prototype,
+ [intlFallbackSymbol]: numberFormat,
+ };
+
+ for (let number of [0, 1, 1.5, Infinity, NaN]) {
+ let expected = numberFormat.format(number);
+ assertEq(thisValue.format(number), expected);
+ assertEq(thisValue[intlFallbackSymbol].format(number), expected);
+ assertEq(fakeObj.format(number), expected);
+ }
+}
+
+// Ensure formatToParts() doesn't use the fallback semantics.
+{
+ let formatToParts = Intl.NumberFormat.prototype.formatToParts;
+
+ // An object initialized as a NumberFormat instance.
+ let thisValue = Object.create(Intl.NumberFormat.prototype);
+ Intl.NumberFormat.call(thisValue);
+ assertThrowsInstanceOf(() => formatToParts.call(thisValue), TypeError);
+
+ // Object with [[FallbackSymbol]] set to NumberFormat instance.
+ let fakeObj = {
+ __proto__: Intl.NumberFormat.prototype,
+ [intlFallbackSymbol]: new Intl.NumberFormat(),
+ };
+ assertThrowsInstanceOf(() => formatToParts.call(fakeObj), TypeError);
+}
+
+// Test resolvedOptions() returns the same results.
+{
+ // An actual Intl.NumberFormat instance.
+ let numberFormat = new Intl.NumberFormat();
+
+ // An object initialized as a NumberFormat instance.
+ let thisValue = Object.create(Intl.NumberFormat.prototype);
+ Intl.NumberFormat.call(thisValue);
+
+ // Object with [[FallbackSymbol]] set to NumberFormat instance.
+ let fakeObj = {
+ __proto__: Intl.NumberFormat.prototype,
+ [intlFallbackSymbol]: numberFormat,
+ };
+
+ function assertEqOptions(actual, expected) {
+ actual = Object.entries(actual);
+ expected = Object.entries(expected);
+
+ assertEq(actual.length, expected.length, "options count mismatch");
+ for (var i = 0; i < expected.length; i++) {
+ assertEq(actual[i][0], expected[i][0], "key mismatch at " + i);
+ assertEq(actual[i][1], expected[i][1], "value mismatch at " + i);
+ }
+ }
+
+ let expected = numberFormat.resolvedOptions();
+ assertEqOptions(thisValue.resolvedOptions(), expected);
+ assertEqOptions(thisValue[intlFallbackSymbol].resolvedOptions(), expected);
+ assertEqOptions(fakeObj.resolvedOptions(), expected);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/use-grouping-bool-string.js b/js/src/tests/non262/Intl/NumberFormat/use-grouping-bool-string.js
new file mode 100644
index 0000000000..4216c874f0
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/use-grouping-bool-string.js
@@ -0,0 +1,10 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+let nf1 = new Intl.NumberFormat("en", {useGrouping: "true"});
+assertEq(nf1.format(1000), "1,000");
+
+let nf2 = new Intl.NumberFormat("en", {useGrouping: "false"});
+assertEq(nf2.format(1000), "1,000");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/NumberFormat/use-grouping.js b/js/src/tests/non262/Intl/NumberFormat/use-grouping.js
new file mode 100644
index 0000000000..8fcb2fb51e
--- /dev/null
+++ b/js/src/tests/non262/Intl/NumberFormat/use-grouping.js
@@ -0,0 +1,97 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||release_or_beta)
+
+const tests = {
+ // minimumGroupingDigits is one for "en" (English).
+ "en": {
+ values: [
+ {
+ value: 1000,
+ useGroupings: {
+ auto: "1,000",
+ always: "1,000",
+ min2: "1000",
+ "": "1000",
+ },
+ },
+ {
+ value: 10000,
+ useGroupings: {
+ auto: "10,000",
+ always: "10,000",
+ min2: "10,000",
+ "": "10000",
+ },
+ },
+ ],
+ },
+
+ // minimumGroupingDigits is two for "pl" (Polish).
+ "pl": {
+ values: [
+ {
+ value: 1000,
+ useGroupings: {
+ auto: "1000",
+ always: "1 000",
+ min2: "1000",
+ "": "1000",
+ },
+ },
+ {
+ value: 10000,
+ useGroupings: {
+ auto: "10 000",
+ always: "10 000",
+ min2: "10 000",
+ "": "10000",
+ },
+ },
+ ],
+ },
+};
+
+for (let [locale, {options = {}, values}] of Object.entries(tests)) {
+ for (let {value, useGroupings} of values) {
+ for (let [useGrouping, expected] of Object.entries(useGroupings)) {
+ let nf = new Intl.NumberFormat(locale, {...options, useGrouping});
+ assertEq(nf.format(value), expected, `locale=${locale}, value=${value}, useGrouping=${useGrouping}`);
+ }
+ }
+}
+
+// Resolved options.
+for (let [useGrouping, expected] of [
+ [false, false],
+ ["", false],
+ [0, false],
+ [null, false],
+
+ ["auto", "auto"],
+ [undefined, "auto"],
+
+ ["always", "always"],
+ [true, "always"],
+
+ ["min2", "min2"],
+
+ // Unsupported values fallback to "auto"
+ ["true", "auto"],
+ ["false", "auto"],
+ ["none", "auto"],
+ ["yes", "auto"],
+ ["no", "auto"],
+ [{}, "auto"],
+ [123, "auto"],
+ [123n, "auto"],
+]) {
+ let nf = new Intl.NumberFormat("en", {useGrouping});
+ assertEq(nf.resolvedOptions().useGrouping , expected);
+}
+
+// Throws a TypeError if ToString fails.
+for (let useGrouping of [Object.create(null), Symbol()]) {
+ assertThrowsInstanceOf(() => new Intl.NumberFormat("en", {useGrouping}), TypeError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/PluralRules/browser.js b/js/src/tests/non262/Intl/PluralRules/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Intl/PluralRules/browser.js
diff --git a/js/src/tests/non262/Intl/PluralRules/call.js b/js/src/tests/non262/Intl/PluralRules/call.js
new file mode 100644
index 0000000000..9412fa44d0
--- /dev/null
+++ b/js/src/tests/non262/Intl/PluralRules/call.js
@@ -0,0 +1,53 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+function IsIntlService(c) {
+ return typeof c === "function" &&
+ c.hasOwnProperty("prototype") &&
+ c.prototype.hasOwnProperty("resolvedOptions");
+}
+
+function thisValues() {
+ const intlConstructors = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService);
+
+ return [
+ // Primitive values.
+ ...[undefined, null, true, "abc", Symbol(), 123],
+
+ // Object values.
+ ...[{}, [], /(?:)/, function(){}, new Proxy({}, {})],
+
+ // Intl objects.
+ ...[].concat(...intlConstructors.map(ctor => {
+ let args = [];
+ if (ctor === Intl.DisplayNames) {
+ // Intl.DisplayNames can't be constructed without any arguments.
+ args = [undefined, {type: "language"}];
+ }
+
+ return [
+ // Instance of an Intl constructor.
+ new ctor(...args),
+
+ // Instance of a subclassed Intl constructor.
+ new class extends ctor {}(...args),
+
+ // Object inheriting from an Intl constructor prototype.
+ Object.create(ctor.prototype),
+
+ // Intl object not inheriting from its default prototype.
+ Object.setPrototypeOf(new ctor(...args), Object.prototype),
+ ];
+ })),
+ ];
+}
+
+// Intl.PluralRules cannot be invoked as a function.
+assertThrowsInstanceOf(() => Intl.PluralRules(), TypeError);
+
+// Also test with explicit this-value.
+for (let thisValue of thisValues()) {
+ assertThrowsInstanceOf(() => Intl.PluralRules.call(thisValue), TypeError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/PluralRules/construct-newtarget.js b/js/src/tests/non262/Intl/PluralRules/construct-newtarget.js
new file mode 100644
index 0000000000..356c2dd221
--- /dev/null
+++ b/js/src/tests/non262/Intl/PluralRules/construct-newtarget.js
@@ -0,0 +1,76 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Test subclassing %Intl.PluralRules% works correctly.
+class MyPluralRules extends Intl.PluralRules {}
+
+var obj = new MyPluralRules();
+assertEq(obj instanceof MyPluralRules, true);
+assertEq(obj instanceof Intl.PluralRules, true);
+assertEq(Object.getPrototypeOf(obj), MyPluralRules.prototype);
+
+obj = Reflect.construct(MyPluralRules, []);
+assertEq(obj instanceof MyPluralRules, true);
+assertEq(obj instanceof Intl.PluralRules, true);
+assertEq(Object.getPrototypeOf(obj), MyPluralRules.prototype);
+
+obj = Reflect.construct(MyPluralRules, [], MyPluralRules);
+assertEq(obj instanceof MyPluralRules, true);
+assertEq(obj instanceof Intl.PluralRules, true);
+assertEq(Object.getPrototypeOf(obj), MyPluralRules.prototype);
+
+obj = Reflect.construct(MyPluralRules, [], Intl.PluralRules);
+assertEq(obj instanceof MyPluralRules, false);
+assertEq(obj instanceof Intl.PluralRules, true);
+assertEq(Object.getPrototypeOf(obj), Intl.PluralRules.prototype);
+
+
+// Set a different constructor as NewTarget.
+obj = Reflect.construct(MyPluralRules, [], Array);
+assertEq(obj instanceof MyPluralRules, false);
+assertEq(obj instanceof Intl.PluralRules, false);
+assertEq(obj instanceof Array, true);
+assertEq(Object.getPrototypeOf(obj), Array.prototype);
+
+obj = Reflect.construct(Intl.PluralRules, [], Array);
+assertEq(obj instanceof Intl.PluralRules, false);
+assertEq(obj instanceof Array, true);
+assertEq(Object.getPrototypeOf(obj), Array.prototype);
+
+
+// The prototype defaults to %PluralRulesPrototype% if null.
+function NewTargetNullPrototype() {}
+NewTargetNullPrototype.prototype = null;
+
+obj = Reflect.construct(Intl.PluralRules, [], NewTargetNullPrototype);
+assertEq(obj instanceof Intl.PluralRules, true);
+assertEq(Object.getPrototypeOf(obj), Intl.PluralRules.prototype);
+
+obj = Reflect.construct(MyPluralRules, [], NewTargetNullPrototype);
+assertEq(obj instanceof MyPluralRules, false);
+assertEq(obj instanceof Intl.PluralRules, true);
+assertEq(Object.getPrototypeOf(obj), Intl.PluralRules.prototype);
+
+
+// "prototype" property is retrieved exactly once.
+var trapLog = [], getLog = [];
+var ProxiedConstructor = new Proxy(Intl.PluralRules, new Proxy({
+ get(target, propertyKey, receiver) {
+ getLog.push(propertyKey);
+ return Reflect.get(target, propertyKey, receiver);
+ }
+}, {
+ get(target, propertyKey, receiver) {
+ trapLog.push(propertyKey);
+ return Reflect.get(target, propertyKey, receiver);
+ }
+}));
+
+obj = Reflect.construct(Intl.PluralRules, [], ProxiedConstructor);
+assertEqArray(trapLog, ["get"]);
+assertEqArray(getLog, ["prototype"]);
+assertEq(obj instanceof Intl.PluralRules, true);
+assertEq(Object.getPrototypeOf(obj), Intl.PluralRules.prototype);
+
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/PluralRules/cross-compartment.js b/js/src/tests/non262/Intl/PluralRules/cross-compartment.js
new file mode 100644
index 0000000000..ff59f35957
--- /dev/null
+++ b/js/src/tests/non262/Intl/PluralRules/cross-compartment.js
@@ -0,0 +1,22 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+var otherGlobal = newGlobal();
+
+var pluralRules = new Intl.PluralRules();
+var ccwPluralRules = new otherGlobal.Intl.PluralRules();
+
+// Test Intl.PluralRules.prototype.select with a CCW object.
+var Intl_PluralRules_select = Intl.PluralRules.prototype.select;
+
+assertEq(Intl_PluralRules_select.call(ccwPluralRules, 0),
+ Intl_PluralRules_select.call(pluralRules, 0));
+
+// Test Intl.PluralRules.prototype.resolvedOptions with a CCW object.
+var Intl_PluralRules_resolvedOptions = Intl.PluralRules.prototype.resolvedOptions;
+
+assertEq(deepEqual(Intl_PluralRules_resolvedOptions.call(ccwPluralRules),
+ Intl_PluralRules_resolvedOptions.call(pluralRules)),
+ true);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/PluralRules/negativeZeroFractionDigits.js b/js/src/tests/non262/Intl/PluralRules/negativeZeroFractionDigits.js
new file mode 100644
index 0000000000..615e533466
--- /dev/null
+++ b/js/src/tests/non262/Intl/PluralRules/negativeZeroFractionDigits.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const optionsList = [
+ {minimumFractionDigits: -0, maximumFractionDigits: -0},
+ {minimumFractionDigits: -0, maximumFractionDigits: +0},
+ {minimumFractionDigits: +0, maximumFractionDigits: -0},
+ {minimumFractionDigits: +0, maximumFractionDigits: +0},
+];
+
+for (let options of optionsList) {
+ let pluralRules = new Intl.PluralRules("en-US", options);
+
+ let {minimumFractionDigits, maximumFractionDigits} = pluralRules.resolvedOptions();
+ assertEq(minimumFractionDigits, +0);
+ assertEq(maximumFractionDigits, +0);
+
+ assertEq(pluralRules.select(123), "other");
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/PluralRules/pluralrules.js b/js/src/tests/non262/Intl/PluralRules/pluralrules.js
new file mode 100644
index 0000000000..20d6117b3b
--- /dev/null
+++ b/js/src/tests/non262/Intl/PluralRules/pluralrules.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Tests the format function with a diverse set of locales and options.
+
+var pr;
+
+pr = new Intl.PluralRules("en-us");
+assertEq(pr.resolvedOptions().locale, "en-US");
+assertEq(pr.resolvedOptions().type, "cardinal");
+assertEq(pr.resolvedOptions().pluralCategories.length, 2);
+
+pr = new Intl.PluralRules("de", {type: 'cardinal'});
+assertEq(pr.resolvedOptions().pluralCategories.length, 2);
+
+pr = new Intl.PluralRules("de", {type: 'ordinal'});
+assertEq(pr.resolvedOptions().pluralCategories.length, 1);
+
+reportCompare(0, 0, 'ok');
diff --git a/js/src/tests/non262/Intl/PluralRules/resolvedOptions-overridden-species.js b/js/src/tests/non262/Intl/PluralRules/resolvedOptions-overridden-species.js
new file mode 100644
index 0000000000..3591aba32b
--- /dev/null
+++ b/js/src/tests/non262/Intl/PluralRules/resolvedOptions-overridden-species.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Tests the PluralRules.resolvedOptions function for overriden Array[Symbol.species].
+
+var pl = new Intl.PluralRules("de");
+
+Object.defineProperty(Array, Symbol.species, {
+ value: function() {
+ return new Proxy(["?"], {
+ get(t, pk, r) {
+ return Reflect.get(t, pk, r);
+ },
+ defineProperty(t, pk) {
+ return true;
+ }
+ });
+ }
+});
+
+var pluralCategories = pl.resolvedOptions().pluralCategories;
+
+assertEqArray(pluralCategories, ["one", "other"]);
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/PluralRules/rounding.js b/js/src/tests/non262/Intl/PluralRules/rounding.js
new file mode 100644
index 0000000000..6f9b5f9936
--- /dev/null
+++ b/js/src/tests/non262/Intl/PluralRules/rounding.js
@@ -0,0 +1,17 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// The rounding mode defaults to half-up for both NumberFormat and PluralRules.
+
+var locale = "en";
+var options = {maximumFractionDigits: 0};
+
+assertEq(new Intl.NumberFormat(locale, options).format(0), "0");
+assertEq(new Intl.NumberFormat(locale, options).format(0.5), "1");
+assertEq(new Intl.NumberFormat(locale, options).format(1), "1");
+
+assertEq(new Intl.PluralRules(locale, options).select(0), "other");
+assertEq(new Intl.PluralRules(locale, options).select(0.5), "one");
+assertEq(new Intl.PluralRules(locale, options).select(1), "one");
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, 'ok');
diff --git a/js/src/tests/non262/Intl/PluralRules/select.js b/js/src/tests/non262/Intl/PluralRules/select.js
new file mode 100644
index 0000000000..dcc057ec3c
--- /dev/null
+++ b/js/src/tests/non262/Intl/PluralRules/select.js
@@ -0,0 +1,63 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+// Tests the format function with a diverse set of locales and options.
+
+var pr;
+
+pr = new Intl.PluralRules("en-us");
+assertEq(pr.select(0), "other");
+assertEq(pr.select(0.5), "other");
+assertEq(pr.select(1.2), "other");
+assertEq(pr.select(1.5), "other");
+assertEq(pr.select(1.7), "other");
+assertEq(pr.select(-1), "one");
+assertEq(pr.select(1), "one");
+assertEq(pr.select("1"), "one");
+assertEq(pr.select(123456789.123456789), "other");
+
+pr = new Intl.PluralRules("de", {type: "cardinal"});
+assertEq(pr.select(0), "other");
+assertEq(pr.select(0.5), "other");
+assertEq(pr.select(1.2), "other");
+assertEq(pr.select(1.5), "other");
+assertEq(pr.select(1.7), "other");
+assertEq(pr.select(-1), "one");
+
+pr = new Intl.PluralRules("de", {type: "ordinal"});
+assertEq(pr.select(0), "other");
+assertEq(pr.select(0.5), "other");
+assertEq(pr.select(1.2), "other");
+assertEq(pr.select(1.5), "other");
+assertEq(pr.select(1.7), "other");
+assertEq(pr.select(-1), "other");
+
+pr = new Intl.PluralRules("pl", {type: "cardinal"});
+assertEq(pr.select(0), "many");
+assertEq(pr.select(0.5), "other");
+assertEq(pr.select(1), "one");
+
+pr = new Intl.PluralRules("pl", {type: "cardinal", maximumFractionDigits: 0});
+assertEq(pr.select(1.1), "one");
+
+pr = new Intl.PluralRules("pl", {type: "cardinal", maximumFractionDigits: 1});
+assertEq(pr.select(1.1), "other");
+
+pr = new Intl.PluralRules("en", {type: "cardinal", minimumFractionDigits: 0});
+assertEq(pr.select(1), "one");
+
+pr = new Intl.PluralRules("en", {type: "cardinal", minimumFractionDigits: 2});
+assertEq(pr.select(1), "other");
+
+var weirdCases = [
+ NaN,
+ Infinity,
+ "word",
+ [0,2],
+ {},
+];
+
+for (let c of weirdCases) {
+ assertEq(pr.select(c), "other");
+};
+
+reportCompare(0, 0, 'ok');
diff --git a/js/src/tests/non262/Intl/PluralRules/selectRange.js b/js/src/tests/non262/Intl/PluralRules/selectRange.js
new file mode 100644
index 0000000000..59faf621e2
--- /dev/null
+++ b/js/src/tests/non262/Intl/PluralRules/selectRange.js
@@ -0,0 +1,84 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl')||release_or_beta)
+
+// Any combination returns "other" for "en-US".
+{
+ let numbers = [0, 0.5, 1.2, 1.5, 1.7, -1, 1, "1", 123456789.123456789, Infinity, -Infinity];
+
+ const weirdCases = [
+ NaN,
+ "word",
+ [0, 2],
+ {},
+ ];
+
+ for (let type of ["ordinal", "cardinal"]) {
+ let pr = new Intl.PluralRules("en-US", {type});
+ for (let start of numbers) {
+ for (let end of numbers) {
+ assertEq(pr.selectRange(start, end), "other");
+ }
+ }
+
+ for (let c of weirdCases) {
+ assertThrowsInstanceOf(() => pr.selectRange(c, 0), RangeError);
+ assertThrowsInstanceOf(() => pr.selectRange(0, c), RangeError);
+ assertThrowsInstanceOf(() => pr.selectRange(c, c), RangeError);
+ }
+ }
+}
+
+// fr (French) returns different results.
+{
+ let ordinal = new Intl.PluralRules("fr", {type: "ordinal"});
+ let cardinal = new Intl.PluralRules("fr", {type: "cardinal"});
+
+ assertEq(ordinal.selectRange(1, 1), "one");
+ assertEq(ordinal.selectRange(0, 1), "other");
+
+ assertEq(cardinal.selectRange(1, 1), "one");
+ assertEq(cardinal.selectRange(0, 1), "one");
+}
+
+// cy (Cymraeg) can return any combination.
+{
+ let ordinal = new Intl.PluralRules("cy", {type: "ordinal"});
+
+ assertEq(ordinal.selectRange(0, 0), "other");
+ assertEq(ordinal.selectRange(0, 1), "one");
+ assertEq(ordinal.selectRange(0, 2), "two");
+ assertEq(ordinal.selectRange(0, 3), "few");
+ assertEq(ordinal.selectRange(0, 5), "many");
+ assertEq(ordinal.selectRange(0, 10), "other");
+
+ assertEq(ordinal.selectRange(1, 1), "other");
+ assertEq(ordinal.selectRange(1, 2), "two");
+ assertEq(ordinal.selectRange(1, 3), "few");
+ assertEq(ordinal.selectRange(1, 5), "many");
+ assertEq(ordinal.selectRange(1, 10), "other");
+
+ assertEq(ordinal.selectRange(2, 2), "other");
+ assertEq(ordinal.selectRange(2, 3), "few");
+ assertEq(ordinal.selectRange(2, 5), "many");
+ assertEq(ordinal.selectRange(2, 10), "other");
+
+ assertEq(ordinal.selectRange(3, 3), "other");
+ assertEq(ordinal.selectRange(3, 5), "many");
+ assertEq(ordinal.selectRange(3, 10), "other");
+
+ assertEq(ordinal.selectRange(5, 5), "other");
+ assertEq(ordinal.selectRange(5, 10), "other");
+
+ assertEq(ordinal.selectRange(10, 10), "other");
+}
+
+// BigInt inputs aren't allowed.
+{
+ let pr = new Intl.PluralRules("en-US");
+
+ assertThrowsInstanceOf(() => pr.selectRange(0, 0n), TypeError);
+ assertThrowsInstanceOf(() => pr.selectRange(0n, 0), TypeError);
+ assertThrowsInstanceOf(() => pr.selectRange(0n, 0n), TypeError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/PluralRules/shell.js b/js/src/tests/non262/Intl/PluralRules/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Intl/PluralRules/shell.js
diff --git a/js/src/tests/non262/Intl/PluralRules/supportedLocalesOf.js b/js/src/tests/non262/Intl/PluralRules/supportedLocalesOf.js
new file mode 100644
index 0000000000..7c6ebe8c45
--- /dev/null
+++ b/js/src/tests/non262/Intl/PluralRules/supportedLocalesOf.js
@@ -0,0 +1,369 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl')||xulRuntime.shell)
+// -- test in browser only that ICU has locale data for all Mozilla languages
+
+// This array contains the locales that ICU supports in
+// number formatting whose languages Mozilla localizes Firefox into.
+// Current as of ICU 50.1.2 and Firefox March 2013.
+var locales = [
+ "af",
+ "af-NA",
+ "af-ZA",
+ "ar",
+ "ar-001",
+ "ar-AE",
+ "ar-BH",
+ "ar-DJ",
+ "ar-DZ",
+ "ar-EG",
+ "ar-EH",
+ "ar-ER",
+ "ar-IL",
+ "ar-IQ",
+ "ar-JO",
+ "ar-KM",
+ "ar-KW",
+ "ar-LB",
+ "ar-LY",
+ "ar-MA",
+ "ar-MR",
+ "ar-OM",
+ "ar-PS",
+ "ar-QA",
+ "ar-SA",
+ "ar-SD",
+ "ar-SO",
+ "ar-SY",
+ "ar-TD",
+ "ar-TN",
+ "ar-YE",
+ "as",
+ "as-IN",
+ "be",
+ "be-BY",
+ "bg",
+ "bg-BG",
+ "bn",
+ "bn-BD",
+ "bn-IN",
+ "br",
+ "br-FR",
+ "bs",
+ "bs-Cyrl",
+ "bs-Cyrl-BA",
+ "bs-Latn",
+ "bs-Latn-BA",
+ "ca",
+ "ca-AD",
+ "ca-ES",
+ "cs",
+ "cs-CZ",
+ "cy",
+ "cy-GB",
+ "da",
+ "da-DK",
+ "de",
+ "de-AT",
+ "de-BE",
+ "de-CH",
+ "de-DE",
+ "de-LI",
+ "de-LU",
+ "el",
+ "el-CY",
+ "el-GR",
+ "en",
+ "en-150",
+ "en-AG",
+ "en-AS",
+ "en-AU",
+ "en-BB",
+ "en-BE",
+ "en-BM",
+ "en-BS",
+ "en-BW",
+ "en-BZ",
+ "en-CA",
+ "en-CM",
+ "en-DM",
+ "en-FJ",
+ "en-FM",
+ "en-GB",
+ "en-GD",
+ "en-GG",
+ "en-GH",
+ "en-GI",
+ "en-GM",
+ "en-GU",
+ "en-GY",
+ "en-HK",
+ "en-IE",
+ "en-IM",
+ "en-IN",
+ "en-JE",
+ "en-JM",
+ "en-KE",
+ "en-KI",
+ "en-KN",
+ "en-KY",
+ "en-LC",
+ "en-LR",
+ "en-LS",
+ "en-MG",
+ "en-MH",
+ "en-MP",
+ "en-MT",
+ "en-MU",
+ "en-MW",
+ "en-NA",
+ "en-NG",
+ "en-NZ",
+ "en-PG",
+ "en-PH",
+ "en-PK",
+ "en-PR",
+ "en-PW",
+ "en-SB",
+ "en-SC",
+ "en-SG",
+ "en-SL",
+ "en-SS",
+ "en-SZ",
+ "en-TC",
+ "en-TO",
+ "en-TT",
+ "en-TZ",
+ "en-UG",
+ "en-UM",
+ "en-US",
+ "en-US-posix",
+ "en-VC",
+ "en-VG",
+ "en-VI",
+ "en-VU",
+ "en-WS",
+ "en-ZA",
+ "en-ZM",
+ "en-ZW",
+ "eo",
+ "es",
+ "es-419",
+ "es-AR",
+ "es-BO",
+ "es-CL",
+ "es-CO",
+ "es-CR",
+ "es-CU",
+ "es-DO",
+ "es-EA",
+ "es-EC",
+ "es-ES",
+ "es-GQ",
+ "es-GT",
+ "es-HN",
+ "es-IC",
+ "es-MX",
+ "es-NI",
+ "es-PA",
+ "es-PE",
+ "es-PH",
+ "es-PR",
+ "es-PY",
+ "es-SV",
+ "es-US",
+ "es-UY",
+ "es-VE",
+ "et",
+ "et-EE",
+ "eu",
+ "eu-ES",
+ "fa",
+ "fa-AF",
+ "fa-IR",
+ "ff",
+ "ff-SN",
+ "fi",
+ "fi-FI",
+ "fr",
+ "fr-BE",
+ "fr-BF",
+ "fr-BI",
+ "fr-BJ",
+ "fr-BL",
+ "fr-CA",
+ "fr-CD",
+ "fr-CF",
+ "fr-CG",
+ "fr-CH",
+ "fr-CI",
+ "fr-CM",
+ "fr-DJ",
+ "fr-DZ",
+ "fr-FR",
+ "fr-GA",
+ "fr-GF",
+ "fr-GN",
+ "fr-GP",
+ "fr-GQ",
+ "fr-HT",
+ "fr-KM",
+ "fr-LU",
+ "fr-MA",
+ "fr-MC",
+ "fr-MF",
+ "fr-MG",
+ "fr-ML",
+ "fr-MQ",
+ "fr-MR",
+ "fr-MU",
+ "fr-NC",
+ "fr-NE",
+ "fr-PF",
+ "fr-RE",
+ "fr-RW",
+ "fr-SC",
+ "fr-SN",
+ "fr-SY",
+ "fr-TD",
+ "fr-TG",
+ "fr-TN",
+ "fr-VU",
+ "fr-YT",
+ "ga",
+ "ga-IE",
+ "gl",
+ "gl-ES",
+ "gu",
+ "gu-IN",
+ "he",
+ "he-IL",
+ "hi",
+ "hi-IN",
+ "hr",
+ "hr-BA",
+ "hr-HR",
+ "hu",
+ "hu-HU",
+ "hy",
+ "hy-AM",
+ "id",
+ "id-ID",
+ "is",
+ "is-IS",
+ "it",
+ "it-CH",
+ "it-IT",
+ "it-SM",
+ "ja",
+ "ja-JP",
+ "kk",
+ "kk-Cyrl",
+ "kk-Cyrl-KZ",
+ "km",
+ "km-KH",
+ "kn",
+ "kn-IN",
+ "ko",
+ "ko-KP",
+ "ko-KR",
+ "lt",
+ "lt-LT",
+ "lv",
+ "lv-LV",
+ "mk",
+ "mk-MK",
+ "ml",
+ "ml-IN",
+ "mr",
+ "mr-IN",
+ "nb",
+ "nb-NO",
+ "nl",
+ "nl-AW",
+ "nl-BE",
+ "nl-CW",
+ "nl-NL",
+ "nl-SR",
+ "nl-SX",
+ "nn",
+ "nn-NO",
+ "or",
+ "or-IN",
+ "pa",
+ "pa-Arab",
+ "pa-Arab-PK",
+ "pa-Guru",
+ "pa-Guru-IN",
+ "pl",
+ "pl-PL",
+ "pt",
+ "pt-AO",
+ "pt-BR",
+ "pt-CV",
+ "pt-GW",
+ "pt-MO",
+ "pt-MZ",
+ "pt-PT",
+ "pt-ST",
+ "pt-TL",
+ "rm",
+ "rm-CH",
+ "ro",
+ "ro-MD",
+ "ro-RO",
+ "ru",
+ "ru-BY",
+ "ru-KG",
+ "ru-KZ",
+ "ru-MD",
+ "ru-RU",
+ "ru-UA",
+ "si",
+ "si-LK",
+ "sk",
+ "sk-SK",
+ "sl",
+ "sl-SI",
+ "sq",
+ "sq-AL",
+ "sq-MK",
+ "sr",
+ "sr-Cyrl",
+ "sr-Cyrl-BA",
+ "sr-Cyrl-ME",
+ "sr-Cyrl-RS",
+ "sr-Latn",
+ "sr-Latn-BA",
+ "sr-Latn-ME",
+ "sr-Latn-RS",
+ "sv",
+ "sv-AX",
+ "sv-FI",
+ "sv-SE",
+ "te",
+ "te-IN",
+ "th",
+ "th-TH",
+ "tr",
+ "tr-CY",
+ "tr-TR",
+ "uk",
+ "uk-UA",
+ "vi",
+ "vi-VN",
+ "zh",
+ "zh-Hans",
+ "zh-Hans-CN",
+ "zh-Hans-HK",
+ "zh-Hans-MO",
+ "zh-Hans-SG",
+ "zh-Hant",
+ "zh-Hant-HK",
+ "zh-Hant-MO",
+ "zh-Hant-TW",
+];
+
+const result = Intl.PluralRules.supportedLocalesOf(locales);
+
+assertEqArray(locales, result);
+
+reportCompare(0, 0, 'ok');
diff --git a/js/src/tests/non262/Intl/README.txt b/js/src/tests/non262/Intl/README.txt
new file mode 100644
index 0000000000..797b49ab5c
--- /dev/null
+++ b/js/src/tests/non262/Intl/README.txt
@@ -0,0 +1,27 @@
+Integration Tests for ECMAScript Internationalization API
+=========================================================
+
+The tests in this directory test the integration of the ICU library
+(Internationalization Components for Unicode) into the implementation of the
+ECMAScript Internationalization API in SpiderMonkey.
+
+These integration tests are complementary to:
+
+- The Test402 test suite maintained by Ecma TC39, which tests conformance of
+ an implementation to standard ECMA-402, ECMAScript Internationalization API
+ Specification. Test402 is currently maintained as part of Test262, the overall
+ conformance test suite for ECMAScript; for more information, see
+ http://wiki.ecmascript.org/doku.php?id=test262:test262
+
+- The test suite of the ICU library, which tests the implementation of ICU
+ itself and correct interpretation of the locale data it obtains from CLDR
+ (Common Locale Data Repository). For information on ICU, see
+ http://site.icu-project.org
+
+The integration tests check for a variety of locales and options whether the
+results are localized in a way that indicates correct integration with ICU.
+Such tests are somewhat fragile because the underlying locale data reflects
+real world usage and is therefore subject to change. When the ICU library used
+by Mozilla is upgraded, it is likely that some of the integration tests will
+fail because of locale data changes; however, others might fail because of
+actual software bugs. Failures therefore have to be examined carefully.
diff --git a/js/src/tests/non262/Intl/RelativeTimeFormat/browser.js b/js/src/tests/non262/Intl/RelativeTimeFormat/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Intl/RelativeTimeFormat/browser.js
diff --git a/js/src/tests/non262/Intl/RelativeTimeFormat/construct-newtarget.js b/js/src/tests/non262/Intl/RelativeTimeFormat/construct-newtarget.js
new file mode 100644
index 0000000000..c20c07434e
--- /dev/null
+++ b/js/src/tests/non262/Intl/RelativeTimeFormat/construct-newtarget.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+var obj = new Intl.RelativeTimeFormat();
+
+// Test that new RTF produces an object with the right prototype.
+assertEq(Object.getPrototypeOf(obj), Intl.RelativeTimeFormat.prototype);
+
+// Test subclassing %Intl.RelativeTimeFormat% works correctly.
+class MyRelativeTimeFormat extends Intl.RelativeTimeFormat {}
+
+var obj = new MyRelativeTimeFormat();
+assertEq(obj instanceof MyRelativeTimeFormat, true);
+assertEq(obj instanceof Intl.RelativeTimeFormat, true);
+assertEq(Object.getPrototypeOf(obj), MyRelativeTimeFormat.prototype);
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/RelativeTimeFormat/cross-compartment.js b/js/src/tests/non262/Intl/RelativeTimeFormat/cross-compartment.js
new file mode 100644
index 0000000000..c826538f39
--- /dev/null
+++ b/js/src/tests/non262/Intl/RelativeTimeFormat/cross-compartment.js
@@ -0,0 +1,22 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+var otherGlobal = newGlobal();
+
+var relativeTimeFormat = new Intl.RelativeTimeFormat();
+var ccwRelativeTimeFormat = new otherGlobal.Intl.RelativeTimeFormat();
+
+// Test Intl.RelativeTimeFormat.prototype.format with a CCW object.
+var Intl_RelativeTimeFormat_format = Intl.RelativeTimeFormat.prototype.format;
+
+assertEq(Intl_RelativeTimeFormat_format.call(ccwRelativeTimeFormat, 0, "hour"),
+ Intl_RelativeTimeFormat_format.call(relativeTimeFormat, 0, "hour"));
+
+// Test Intl.RelativeTimeFormat.prototype.resolvedOptions with a CCW object.
+var Intl_RelativeTimeFormat_resolvedOptions = Intl.RelativeTimeFormat.prototype.resolvedOptions;
+
+assertEq(deepEqual(Intl_RelativeTimeFormat_resolvedOptions.call(ccwRelativeTimeFormat),
+ Intl_RelativeTimeFormat_resolvedOptions.call(relativeTimeFormat)),
+ true);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/RelativeTimeFormat/format.js b/js/src/tests/non262/Intl/RelativeTimeFormat/format.js
new file mode 100644
index 0000000000..244dbb5c56
--- /dev/null
+++ b/js/src/tests/non262/Intl/RelativeTimeFormat/format.js
@@ -0,0 +1,145 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests the format function with a diverse set of locales and options.
+
+var rtf;
+
+{
+ // Numeric format
+ rtf = new Intl.RelativeTimeFormat("en-US");
+ assertEq(rtf.format(0, "second"), "in 0 seconds");
+ assertEq(rtf.format(-0, "second"), "0 seconds ago");
+ assertEq(rtf.format(-1, "second"), "1 second ago");
+ assertEq(rtf.format(1, "second"), "in 1 second");
+
+ assertEq(rtf.format(0, "minute"), "in 0 minutes");
+ assertEq(rtf.format(-0, "minute"), "0 minutes ago");
+ assertEq(rtf.format(-1, "minute"), "1 minute ago");
+ assertEq(rtf.format(1, "minute"), "in 1 minute");
+
+ assertEq(rtf.format(0, "hour"), "in 0 hours");
+ assertEq(rtf.format(-0, "hour"), "0 hours ago");
+ assertEq(rtf.format(-1, "hour"), "1 hour ago");
+ assertEq(rtf.format(1, "hour"), "in 1 hour");
+
+ assertEq(rtf.format(0, "day"), "in 0 days");
+ assertEq(rtf.format(-0, "day"), "0 days ago");
+ assertEq(rtf.format(-1, "day"), "1 day ago");
+ assertEq(rtf.format(1, "day"), "in 1 day");
+
+ assertEq(rtf.format(0, "week"), "in 0 weeks");
+ assertEq(rtf.format(-0, "week"), "0 weeks ago");
+ assertEq(rtf.format(-1, "week"), "1 week ago");
+ assertEq(rtf.format(1, "week"), "in 1 week");
+
+ assertEq(rtf.format(0, "month"), "in 0 months");
+ assertEq(rtf.format(-0, "month"), "0 months ago");
+ assertEq(rtf.format(-1, "month"), "1 month ago");
+ assertEq(rtf.format(1, "month"), "in 1 month");
+
+ assertEq(rtf.format(0, "year"), "in 0 years");
+ assertEq(rtf.format(-0, "year"), "0 years ago");
+ assertEq(rtf.format(-1, "year"), "1 year ago");
+ assertEq(rtf.format(1, "year"), "in 1 year");
+}
+
+{
+ // Text format
+ rtf = new Intl.RelativeTimeFormat("en-US", {
+ numeric: "auto"
+ });
+ assertEq(rtf.format(0, "second"), "now");
+ assertEq(rtf.format(-0, "second"), "now");
+ assertEq(rtf.format(-1, "second"), "1 second ago");
+ assertEq(rtf.format(1, "second"), "in 1 second");
+
+ assertEq(rtf.format(0, "minute"), "this minute");
+ assertEq(rtf.format(-0, "minute"), "this minute");
+ assertEq(rtf.format(-1, "minute"), "1 minute ago");
+ assertEq(rtf.format(1, "minute"), "in 1 minute");
+
+ assertEq(rtf.format(0, "hour"), "this hour");
+ assertEq(rtf.format(-0, "hour"), "this hour");
+ assertEq(rtf.format(-1, "hour"), "1 hour ago");
+ assertEq(rtf.format(1, "hour"), "in 1 hour");
+
+ assertEq(rtf.format(0, "day"), "today");
+ assertEq(rtf.format(-0, "day"), "today");
+ assertEq(rtf.format(-1, "day"), "yesterday");
+ assertEq(rtf.format(1, "day"), "tomorrow");
+
+ assertEq(rtf.format(0, "week"), "this week");
+ assertEq(rtf.format(-0, "week"), "this week");
+ assertEq(rtf.format(-1, "week"), "last week");
+ assertEq(rtf.format(1, "week"), "next week");
+
+ assertEq(rtf.format(0, "month"), "this month");
+ assertEq(rtf.format(-0, "month"), "this month");
+ assertEq(rtf.format(-1, "month"), "last month");
+ assertEq(rtf.format(1, "month"), "next month");
+
+ assertEq(rtf.format(0, "year"), "this year");
+ assertEq(rtf.format(-0, "year"), "this year");
+ assertEq(rtf.format(-1, "year"), "last year");
+ assertEq(rtf.format(1, "year"), "next year");
+}
+
+{
+ // Plural specifier
+ rtf = new Intl.RelativeTimeFormat("en-US");
+ assertEq(rtf.format(1, "seconds"), "in 1 second");
+ assertEq(rtf.format(1, "minutes"), "in 1 minute");
+ assertEq(rtf.format(1, "hours"), "in 1 hour");
+ assertEq(rtf.format(1, "days"), "in 1 day");
+ assertEq(rtf.format(1, "weeks"), "in 1 week");
+ assertEq(rtf.format(1, "months"), "in 1 month");
+ assertEq(rtf.format(1, "years"), "in 1 year");
+}
+
+rtf = new Intl.RelativeTimeFormat("de", {numeric: "auto"});
+assertEq(rtf.format(-1, "day"), "gestern");
+assertEq(rtf.format(1, "day"), "morgen");
+
+rtf = new Intl.RelativeTimeFormat("ar", {numeric: "auto"});
+assertEq(rtf.format(-1, "day"), "أمس");
+assertEq(rtf.format(1, "day"), "غدًا");
+
+
+rtf = new Intl.RelativeTimeFormat("en-US");
+
+var weirdValueCases = [
+ Infinity,
+ -Infinity,
+ NaN,
+ "word",
+ [0,2],
+ {},
+];
+
+for (let c of weirdValueCases) {
+ assertThrowsInstanceOf(() => rtf.format(c, "year"), RangeError);
+};
+
+var weirdUnitCases = [
+ "test",
+ "SECOND",
+ "sEcOnD",
+ 1,
+ NaN,
+ undefined,
+ null,
+ {},
+];
+
+for (let u of weirdUnitCases) {
+ assertThrowsInstanceOf(function() {
+ var rtf = new Intl.RelativeTimeFormat("en-US");
+ rtf.format(1, u);
+ }, RangeError);
+};
+
+
+reportCompare(0, 0, 'ok');
diff --git a/js/src/tests/non262/Intl/RelativeTimeFormat/locale-fallback-handling.js b/js/src/tests/non262/Intl/RelativeTimeFormat/locale-fallback-handling.js
new file mode 100644
index 0000000000..76917c6fa0
--- /dev/null
+++ b/js/src/tests/non262/Intl/RelativeTimeFormat/locale-fallback-handling.js
@@ -0,0 +1,15 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// In locales that don't have a relative-date/time formatter -- and presently
+// "ak" is such a locale -- behavior is expected to fall back to the root-locale
+// formatter. This test verifies such fallback works as long as "ak" satisfies
+// these properties; "ak" may safely be changed to a different locale if that
+// ever changes. See bug 1504656.
+assertEq(new Intl.RelativeTimeFormat("ak").format(1, "second"),
+ "+1 s");
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, 'ok');
diff --git a/js/src/tests/non262/Intl/RelativeTimeFormat/numbering-system.js b/js/src/tests/non262/Intl/RelativeTimeFormat/numbering-system.js
new file mode 100644
index 0000000000..d9a860bb01
--- /dev/null
+++ b/js/src/tests/non262/Intl/RelativeTimeFormat/numbering-system.js
@@ -0,0 +1,22 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Ensure passing the default numbering system leads to the same result as when
+// no explicit numbering system is present.
+//
+// This is a regression test for the ICU issue reported at
+// <https://unicode-org.atlassian.net/browse/ICU-20280>.
+
+for (var requestedLocale of [undefined, "en", "de", "fr"]) {
+ var rtf = new Intl.RelativeTimeFormat(requestedLocale);
+ var {locale, numberingSystem} = rtf.resolvedOptions();
+ var rtfNu = new Intl.RelativeTimeFormat(`${locale}-u-nu-${numberingSystem}`);
+
+ for (var unit of ["year", "quarter", "month", "week", "day", "hour", "minute", "second"]) {
+ for (var value of [-10, -3, -2, -1, 0, 1, 2, 3, 10]) {
+ assertEq(rtfNu.format(value, unit), rtf.format(value, unit));
+ }
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/RelativeTimeFormat/numberingSystem-option.js b/js/src/tests/non262/Intl/RelativeTimeFormat/numberingSystem-option.js
new file mode 100644
index 0000000000..bbde290dfa
--- /dev/null
+++ b/js/src/tests/non262/Intl/RelativeTimeFormat/numberingSystem-option.js
@@ -0,0 +1,60 @@
+const defaultLocale = "en";
+const defaultNumberingSystem = new Intl.RelativeTimeFormat(defaultLocale).resolvedOptions().numberingSystem;
+
+function createWithLocale(locale, numberingSystem) {
+ return new Intl.RelativeTimeFormat(locale, {numberingSystem});
+}
+
+function create(numberingSystem) {
+ return createWithLocale(defaultLocale, numberingSystem);
+}
+
+// Empty string should throw.
+assertThrowsInstanceOf(() => create(""), RangeError);
+
+// Trailing \0 should throw.
+assertThrowsInstanceOf(() => create("latn\0"), RangeError);
+
+// Too short or too long strings should throw.
+assertThrowsInstanceOf(() => create("a"), RangeError);
+assertThrowsInstanceOf(() => create("toolongstring"), RangeError);
+
+// Throw even when prefix is valid.
+assertThrowsInstanceOf(() => create("latn-toolongstring"), RangeError);
+
+// |numberingSystem| can be set to |undefined|.
+let nf = create(undefined);
+assertEq(nf.resolvedOptions().numberingSystem, defaultNumberingSystem);
+
+// Unsupported numbering systems are ignored.
+nf = create("xxxxxxxx");
+assertEq(nf.resolvedOptions().numberingSystem, defaultNumberingSystem);
+
+// Numbering system in options overwrite Unicode extension keyword.
+nf = createWithLocale(`${defaultLocale}-u-nu-thai`, "arab");
+assertEq(nf.resolvedOptions().locale, defaultLocale);
+assertEq(nf.resolvedOptions().numberingSystem, "arab");
+
+// |numberingSystem| option ignores case.
+nf = create("ARAB");
+assertEq(nf.resolvedOptions().locale, defaultLocale);
+assertEq(nf.resolvedOptions().numberingSystem, "arab");
+
+for (let [numberingSystem, {algorithmic}] of Object.entries(numberingSystems)) {
+ let nf1 = new Intl.RelativeTimeFormat(`${defaultLocale}-u-nu-${numberingSystem}`);
+ let nf2 = new Intl.RelativeTimeFormat(defaultLocale, {numberingSystem});
+
+ if (!algorithmic) {
+ assertEq(nf1.resolvedOptions().numberingSystem, numberingSystem);
+ assertEq(nf2.resolvedOptions().numberingSystem, numberingSystem);
+ } else {
+ // We don't yet support algorithmic numbering systems.
+ assertEq(nf1.resolvedOptions().numberingSystem, defaultNumberingSystem);
+ assertEq(nf2.resolvedOptions().numberingSystem, defaultNumberingSystem);
+ }
+
+ assertEq(nf2.format(0, "second"), nf1.format(0, "second"));
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/RelativeTimeFormat/relativetimeformat.js b/js/src/tests/non262/Intl/RelativeTimeFormat/relativetimeformat.js
new file mode 100644
index 0000000000..fb30e5a9ce
--- /dev/null
+++ b/js/src/tests/non262/Intl/RelativeTimeFormat/relativetimeformat.js
@@ -0,0 +1,15 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests the format function with a diverse set of locales and options.
+
+var rtf;
+
+rtf = new Intl.RelativeTimeFormat("en-us");
+assertEq(rtf.resolvedOptions().locale, "en-US");
+assertEq(rtf.resolvedOptions().style, "long");
+assertEq(rtf.resolvedOptions().numeric, "always");
+
+reportCompare(0, 0, 'ok');
diff --git a/js/src/tests/non262/Intl/RelativeTimeFormat/shell.js b/js/src/tests/non262/Intl/RelativeTimeFormat/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Intl/RelativeTimeFormat/shell.js
diff --git a/js/src/tests/non262/Intl/RelativeTimeFormat/supportedLocalesOf.js b/js/src/tests/non262/Intl/RelativeTimeFormat/supportedLocalesOf.js
new file mode 100644
index 0000000000..214b12570e
--- /dev/null
+++ b/js/src/tests/non262/Intl/RelativeTimeFormat/supportedLocalesOf.js
@@ -0,0 +1,373 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl')||xulRuntime.shell)
+// -- test in browser only that ICU has locale data for all Mozilla languages
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This array contains the locales that ICU supports in
+// number formatting whose languages Mozilla localizes Firefox into.
+// Current as of ICU 50.1.2 and Firefox March 2013.
+var locales = [
+ "af",
+ "af-NA",
+ "af-ZA",
+ "ar",
+ "ar-001",
+ "ar-AE",
+ "ar-BH",
+ "ar-DJ",
+ "ar-DZ",
+ "ar-EG",
+ "ar-EH",
+ "ar-ER",
+ "ar-IL",
+ "ar-IQ",
+ "ar-JO",
+ "ar-KM",
+ "ar-KW",
+ "ar-LB",
+ "ar-LY",
+ "ar-MA",
+ "ar-MR",
+ "ar-OM",
+ "ar-PS",
+ "ar-QA",
+ "ar-SA",
+ "ar-SD",
+ "ar-SO",
+ "ar-SY",
+ "ar-TD",
+ "ar-TN",
+ "ar-YE",
+ "as",
+ "as-IN",
+ "be",
+ "be-BY",
+ "bg",
+ "bg-BG",
+ "bn",
+ "bn-BD",
+ "bn-IN",
+ "br",
+ "br-FR",
+ "bs",
+ "bs-Cyrl",
+ "bs-Cyrl-BA",
+ "bs-Latn",
+ "bs-Latn-BA",
+ "ca",
+ "ca-AD",
+ "ca-ES",
+ "cs",
+ "cs-CZ",
+ "cy",
+ "cy-GB",
+ "da",
+ "da-DK",
+ "de",
+ "de-AT",
+ "de-BE",
+ "de-CH",
+ "de-DE",
+ "de-LI",
+ "de-LU",
+ "el",
+ "el-CY",
+ "el-GR",
+ "en",
+ "en-150",
+ "en-AG",
+ "en-AS",
+ "en-AU",
+ "en-BB",
+ "en-BE",
+ "en-BM",
+ "en-BS",
+ "en-BW",
+ "en-BZ",
+ "en-CA",
+ "en-CM",
+ "en-DM",
+ "en-FJ",
+ "en-FM",
+ "en-GB",
+ "en-GD",
+ "en-GG",
+ "en-GH",
+ "en-GI",
+ "en-GM",
+ "en-GU",
+ "en-GY",
+ "en-HK",
+ "en-IE",
+ "en-IM",
+ "en-IN",
+ "en-JE",
+ "en-JM",
+ "en-KE",
+ "en-KI",
+ "en-KN",
+ "en-KY",
+ "en-LC",
+ "en-LR",
+ "en-LS",
+ "en-MG",
+ "en-MH",
+ "en-MP",
+ "en-MT",
+ "en-MU",
+ "en-MW",
+ "en-NA",
+ "en-NG",
+ "en-NZ",
+ "en-PG",
+ "en-PH",
+ "en-PK",
+ "en-PR",
+ "en-PW",
+ "en-SB",
+ "en-SC",
+ "en-SG",
+ "en-SL",
+ "en-SS",
+ "en-SZ",
+ "en-TC",
+ "en-TO",
+ "en-TT",
+ "en-TZ",
+ "en-UG",
+ "en-UM",
+ "en-US",
+ "en-US-posix",
+ "en-VC",
+ "en-VG",
+ "en-VI",
+ "en-VU",
+ "en-WS",
+ "en-ZA",
+ "en-ZM",
+ "en-ZW",
+ "eo",
+ "es",
+ "es-419",
+ "es-AR",
+ "es-BO",
+ "es-CL",
+ "es-CO",
+ "es-CR",
+ "es-CU",
+ "es-DO",
+ "es-EA",
+ "es-EC",
+ "es-ES",
+ "es-GQ",
+ "es-GT",
+ "es-HN",
+ "es-IC",
+ "es-MX",
+ "es-NI",
+ "es-PA",
+ "es-PE",
+ "es-PH",
+ "es-PR",
+ "es-PY",
+ "es-SV",
+ "es-US",
+ "es-UY",
+ "es-VE",
+ "et",
+ "et-EE",
+ "eu",
+ "eu-ES",
+ "fa",
+ "fa-AF",
+ "fa-IR",
+ "ff",
+ "ff-SN",
+ "fi",
+ "fi-FI",
+ "fr",
+ "fr-BE",
+ "fr-BF",
+ "fr-BI",
+ "fr-BJ",
+ "fr-BL",
+ "fr-CA",
+ "fr-CD",
+ "fr-CF",
+ "fr-CG",
+ "fr-CH",
+ "fr-CI",
+ "fr-CM",
+ "fr-DJ",
+ "fr-DZ",
+ "fr-FR",
+ "fr-GA",
+ "fr-GF",
+ "fr-GN",
+ "fr-GP",
+ "fr-GQ",
+ "fr-HT",
+ "fr-KM",
+ "fr-LU",
+ "fr-MA",
+ "fr-MC",
+ "fr-MF",
+ "fr-MG",
+ "fr-ML",
+ "fr-MQ",
+ "fr-MR",
+ "fr-MU",
+ "fr-NC",
+ "fr-NE",
+ "fr-PF",
+ "fr-RE",
+ "fr-RW",
+ "fr-SC",
+ "fr-SN",
+ "fr-SY",
+ "fr-TD",
+ "fr-TG",
+ "fr-TN",
+ "fr-VU",
+ "fr-YT",
+ "ga",
+ "ga-IE",
+ "gl",
+ "gl-ES",
+ "gu",
+ "gu-IN",
+ "he",
+ "he-IL",
+ "hi",
+ "hi-IN",
+ "hr",
+ "hr-BA",
+ "hr-HR",
+ "hu",
+ "hu-HU",
+ "hy",
+ "hy-AM",
+ "id",
+ "id-ID",
+ "is",
+ "is-IS",
+ "it",
+ "it-CH",
+ "it-IT",
+ "it-SM",
+ "ja",
+ "ja-JP",
+ "kk",
+ "kk-Cyrl",
+ "kk-Cyrl-KZ",
+ "km",
+ "km-KH",
+ "kn",
+ "kn-IN",
+ "ko",
+ "ko-KP",
+ "ko-KR",
+ "lt",
+ "lt-LT",
+ "lv",
+ "lv-LV",
+ "mk",
+ "mk-MK",
+ "ml",
+ "ml-IN",
+ "mr",
+ "mr-IN",
+ "nb",
+ "nb-NO",
+ "nl",
+ "nl-AW",
+ "nl-BE",
+ "nl-CW",
+ "nl-NL",
+ "nl-SR",
+ "nl-SX",
+ "nn",
+ "nn-NO",
+ "or",
+ "or-IN",
+ "pa",
+ "pa-Arab",
+ "pa-Arab-PK",
+ "pa-Guru",
+ "pa-Guru-IN",
+ "pl",
+ "pl-PL",
+ "pt",
+ "pt-AO",
+ "pt-BR",
+ "pt-CV",
+ "pt-GW",
+ "pt-MO",
+ "pt-MZ",
+ "pt-PT",
+ "pt-ST",
+ "pt-TL",
+ "rm",
+ "rm-CH",
+ "ro",
+ "ro-MD",
+ "ro-RO",
+ "ru",
+ "ru-BY",
+ "ru-KG",
+ "ru-KZ",
+ "ru-MD",
+ "ru-RU",
+ "ru-UA",
+ "si",
+ "si-LK",
+ "sk",
+ "sk-SK",
+ "sl",
+ "sl-SI",
+ "sq",
+ "sq-AL",
+ "sq-MK",
+ "sr",
+ "sr-Cyrl",
+ "sr-Cyrl-BA",
+ "sr-Cyrl-ME",
+ "sr-Cyrl-RS",
+ "sr-Latn",
+ "sr-Latn-BA",
+ "sr-Latn-ME",
+ "sr-Latn-RS",
+ "sv",
+ "sv-AX",
+ "sv-FI",
+ "sv-SE",
+ "te",
+ "te-IN",
+ "th",
+ "th-TH",
+ "tr",
+ "tr-CY",
+ "tr-TR",
+ "uk",
+ "uk-UA",
+ "vi",
+ "vi-VN",
+ "zh",
+ "zh-Hans",
+ "zh-Hans-CN",
+ "zh-Hans-HK",
+ "zh-Hans-MO",
+ "zh-Hans-SG",
+ "zh-Hant",
+ "zh-Hant-HK",
+ "zh-Hant-MO",
+ "zh-Hant-TW",
+];
+
+const result = Intl.RelativeTimeFormat.supportedLocalesOf(locales);
+
+assertEqArray(locales, result);
+
+reportCompare(0, 0, 'ok');
diff --git a/js/src/tests/non262/Intl/String/shell.js b/js/src/tests/non262/Intl/String/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Intl/String/shell.js
diff --git a/js/src/tests/non262/Intl/String/toLocaleLowerCase.js b/js/src/tests/non262/Intl/String/toLocaleLowerCase.js
new file mode 100644
index 0000000000..bd81717d22
--- /dev/null
+++ b/js/src/tests/non262/Intl/String/toLocaleLowerCase.js
@@ -0,0 +1,64 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Test language dependent special casing with different language tags.
+for (let locale of ["tr", "TR", "tr-TR", "tr-u-co-search", "tr-x-turkish"]) {
+ assertEq("\u0130".toLocaleLowerCase(locale), "i");
+ assertEq("\u0130".toLocaleLowerCase([locale]), "i");
+
+ // Additional language tags are ignored.
+ assertEq("\u0130".toLocaleLowerCase([locale, "und"]), "i");
+ assertEq("\u0130".toLocaleLowerCase(["und", locale]), "\u0069\u0307");
+}
+
+// Ensure "trl" (Traveller Scottish) isn't misrecognized as "tr", even though
+// both share the same prefix.
+assertEq("\u0130".toLocaleLowerCase("trl"), "\u0069\u0307");
+assertEq("\u0130".toLocaleLowerCase(["trl"]), "\u0069\u0307");
+
+// Language tag is always verified.
+for (let locale of ["no_locale", "tr-invalid_ext", ["no_locale"], ["en", "no_locale"]]) {
+ // Empty input string.
+ assertThrowsInstanceOf(() => "".toLocaleLowerCase(locale), RangeError);
+
+ // Non-empty input string.
+ assertThrowsInstanceOf(() => "x".toLocaleLowerCase(locale), RangeError);
+}
+
+// No locale argument, undefined as locale, and empty array or array-like all
+// return the same result. Testing with "a/A" because it has only simple case
+// mappings.
+assertEq("A".toLocaleLowerCase(), "a");
+assertEq("A".toLocaleLowerCase(undefined), "a");
+assertEq("A".toLocaleLowerCase([]), "a");
+assertEq("A".toLocaleLowerCase({}), "a");
+assertEq("A".toLocaleLowerCase({length: 0}), "a");
+assertEq("A".toLocaleLowerCase({length: -1}), "a");
+
+// Test with incorrect locale type.
+for (let locale of [null, 0, Math.PI, NaN, Infinity, true, false, Symbol()]) {
+ // Empty input string.
+ assertThrowsInstanceOf(() => "".toLocaleLowerCase([locale]), TypeError);
+
+ // Non-empty input string.
+ assertThrowsInstanceOf(() => "A".toLocaleLowerCase([locale]), TypeError);
+}
+
+// Primitives are converted with ToObject and then queried for .length property.
+for (let locale of [null]) {
+ // Empty input string.
+ assertThrowsInstanceOf(() => "".toLocaleLowerCase([locale]), TypeError);
+
+ // Non-empty input string.
+ assertThrowsInstanceOf(() => "A".toLocaleLowerCase([locale]), TypeError);
+}
+// ToLength(ToObject(<primitive>)) returns 0.
+for (let locale of [0, Math.PI, NaN, Infinity, true, false, Symbol()]) {
+ // Empty input string.
+ assertEq("".toLocaleLowerCase(locale), "");
+
+ // Non-empty input string.
+ assertEq("A".toLocaleLowerCase(locale), "a");
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/String/toLocaleUpperCase.js b/js/src/tests/non262/Intl/String/toLocaleUpperCase.js
new file mode 100644
index 0000000000..0a33320dc7
--- /dev/null
+++ b/js/src/tests/non262/Intl/String/toLocaleUpperCase.js
@@ -0,0 +1,64 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Test language dependent special casing with different language tags.
+for (let locale of ["lt", "LT", "lt-LT", "lt-u-co-phonebk", "lt-x-lietuva"]) {
+ assertEq("i\u0307".toLocaleUpperCase(locale), "I");
+ assertEq("i\u0307".toLocaleUpperCase([locale]), "I");
+
+ // Additional language tags are ignored.
+ assertEq("i\u0307".toLocaleUpperCase([locale, "und"]), "I");
+ assertEq("i\u0307".toLocaleUpperCase(["und", locale]), "I\u0307");
+}
+
+// Ensure "lti" (Leti) isn't misrecognized as "lt", even though both share the
+// same prefix.
+assertEq("i\u0307".toLocaleUpperCase("lti"), "I\u0307");
+assertEq("i\u0307".toLocaleUpperCase(["lti"]), "I\u0307");
+
+// Language tag is always verified.
+for (let locale of ["no_locale", "lt-invalid_ext", ["no_locale"], ["en", "no_locale"]]) {
+ // Empty input string.
+ assertThrowsInstanceOf(() => "".toLocaleUpperCase(locale), RangeError);
+
+ // Non-empty input string.
+ assertThrowsInstanceOf(() => "a".toLocaleUpperCase(locale), RangeError);
+}
+
+// No locale argument, undefined as locale, and empty array or array-like all
+// return the same result. Testing with "a/A" because it has only simple case
+// mappings.
+assertEq("a".toLocaleUpperCase(), "A");
+assertEq("a".toLocaleUpperCase(undefined), "A");
+assertEq("a".toLocaleUpperCase([]), "A");
+assertEq("a".toLocaleUpperCase({}), "A");
+assertEq("a".toLocaleUpperCase({length: 0}), "A");
+assertEq("a".toLocaleUpperCase({length: -1}), "A");
+
+// Test with incorrect locale type.
+for (let locale of [null, 0, Math.PI, NaN, Infinity, true, false, Symbol()]) {
+ // Empty input string.
+ assertThrowsInstanceOf(() => "".toLocaleUpperCase([locale]), TypeError);
+
+ // Non-empty input string.
+ assertThrowsInstanceOf(() => "a".toLocaleUpperCase([locale]), TypeError);
+}
+
+// Primitives are converted with ToObject and then queried for .length property.
+for (let locale of [null]) {
+ // Empty input string.
+ assertThrowsInstanceOf(() => "".toLocaleUpperCase([locale]), TypeError);
+
+ // Non-empty input string.
+ assertThrowsInstanceOf(() => "a".toLocaleUpperCase([locale]), TypeError);
+}
+// ToLength(ToObject(<primitive>)) returns 0.
+for (let locale of [0, Math.PI, NaN, Infinity, true, false, Symbol()]) {
+ // Empty input string.
+ assertEq("".toLocaleUpperCase(locale), "");
+
+ // Non-empty input string.
+ assertEq("a".toLocaleUpperCase(locale), "A");
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
diff --git a/js/src/tests/non262/Intl/TypedArray/shell.js b/js/src/tests/non262/Intl/TypedArray/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Intl/TypedArray/shell.js
diff --git a/js/src/tests/non262/Intl/TypedArray/toLocaleString.js b/js/src/tests/non262/Intl/TypedArray/toLocaleString.js
new file mode 100644
index 0000000000..7a5d0be30a
--- /dev/null
+++ b/js/src/tests/non262/Intl/TypedArray/toLocaleString.js
@@ -0,0 +1,103 @@
+if (typeof Intl === "object") {
+ const constructors = [
+ Int8Array,
+ Uint8Array,
+ Uint8ClampedArray,
+ Int16Array,
+ Uint16Array,
+ Int32Array,
+ Uint32Array,
+ Float32Array,
+ Float64Array,
+ ];
+
+ const localeSep = [,,].toLocaleString();
+
+ const originalNumberToLocaleString = Number.prototype.toLocaleString;
+
+ // Missing arguments are passed as |undefined|.
+ for (let constructor of constructors) {
+ Number.prototype.toLocaleString = function() {
+ assertEq(arguments.length, 2);
+ assertEq(arguments[0], undefined);
+ assertEq(arguments[1], undefined);
+ return "pass";
+ };
+
+ // Single element case.
+ assertEq(new constructor(1).toLocaleString(), "pass");
+
+ // More than one element.
+ assertEq(new constructor(2).toLocaleString(), "pass" + localeSep + "pass");
+ }
+ Number.prototype.toLocaleString = originalNumberToLocaleString;
+
+ // Missing options is passed as |undefined|.
+ for (let constructor of constructors) {
+ Number.prototype.toLocaleString = function() {
+ assertEq(arguments.length, 2);
+ assertEq(arguments[0], locales);
+ assertEq(arguments[1], undefined);
+ return "pass";
+ };
+ let locales = {};
+
+ // Single element case.
+ assertEq(new constructor(1).toLocaleString(locales), "pass");
+
+ // More than one element.
+ assertEq(new constructor(2).toLocaleString(locales), "pass" + localeSep + "pass");
+ }
+ Number.prototype.toLocaleString = originalNumberToLocaleString;
+
+ // Ensure "locales" and "options" arguments are passed to the array elements.
+ for (let constructor of constructors) {
+ Number.prototype.toLocaleString = function() {
+ assertEq(arguments.length, 2);
+ assertEq(arguments[0], locales);
+ assertEq(arguments[1], options);
+ return "pass";
+ };
+ let locales = {};
+ let options = {};
+
+ // Single element case.
+ assertEq(new constructor(1).toLocaleString(locales, options), "pass");
+
+ // More than one element.
+ assertEq(new constructor(2).toLocaleString(locales, options), "pass" + localeSep + "pass");
+ }
+ Number.prototype.toLocaleString = originalNumberToLocaleString;
+
+ assertEq(new Float32Array([NaN]).toLocaleString("ar"), "ليس رقم");
+ assertEq(new Float64Array([NaN]).toLocaleString(["zh-hant", "ar"]), "非數值");
+ assertEq(new Float32Array([Infinity]).toLocaleString(["dz"]), "གྲངས་མེད");
+ assertEq(new Float64Array([-Infinity]).toLocaleString(["fr", "en"]), "-∞");
+
+ const sampleValues = [-0, +0, -1, +1, -2, +2, -0.5, +0.5];
+ const sampleLocales = [
+ void 0,
+ "en",
+ "th-th-u-nu-thai",
+ ["tlh", "de"],
+ ];
+ const sampleOptions = [
+ void 0,
+ {},
+ {style: "percent"},
+ {style: "currency", currency: "USD", minimumIntegerDigits: 4},
+ ];
+ for (let locale of sampleLocales) {
+ for (let options of sampleOptions) {
+ let nf = new Intl.NumberFormat(locale, options);
+ for (let constructor of constructors) {
+ let typedArray = new constructor(sampleValues);
+ let expected = [].map.call(typedArray, nf.format).join(localeSep);
+ assertEq(typedArray.toLocaleString(locale, options), expected);
+ }
+ }
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/available-locales-implied-script.js b/js/src/tests/non262/Intl/available-locales-implied-script.js
new file mode 100644
index 0000000000..d9abbebf49
--- /dev/null
+++ b/js/src/tests/non262/Intl/available-locales-implied-script.js
@@ -0,0 +1,35 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+if (typeof getAvailableLocalesOf === "undefined") {
+ var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf;
+}
+
+function IsIntlService(c) {
+ return typeof c === "function" &&
+ c.hasOwnProperty("prototype") &&
+ c.prototype.hasOwnProperty("resolvedOptions");
+}
+
+const intlConstructors = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService);
+
+// Test all Intl service constructors.
+for (let intlConstructor of intlConstructors) {
+ // Retrieve all available locales of the given Intl service constructor.
+ let available = getAvailableLocalesOf(intlConstructor.name);
+ let availableSet = new Set(available);
+
+ available.filter(x => {
+ return new Intl.Locale(x);
+ }).filter(loc => {
+ // Find all locales which have both a script and a region subtag.
+ return loc.script && loc.region;
+ }).forEach(loc => {
+ let noScript = `${loc.language}-${loc.region}`;
+
+ // The locale without a script subtag must also be available.
+ assertEq(availableSet.has(noScript), true, `Missing locale ${noScript} for ${loc}`);
+ });
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/available-locales-resolved.js b/js/src/tests/non262/Intl/available-locales-resolved.js
new file mode 100644
index 0000000000..76b144d275
--- /dev/null
+++ b/js/src/tests/non262/Intl/available-locales-resolved.js
@@ -0,0 +1,41 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+if (typeof getAvailableLocalesOf === "undefined") {
+ var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf;
+}
+
+function IsIntlService(c) {
+ return typeof c === "function" &&
+ c.hasOwnProperty("prototype") &&
+ c.prototype.hasOwnProperty("resolvedOptions");
+}
+
+const intlConstructors = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService);
+
+// Test all Intl service constructors.
+for (let intlConstructor of intlConstructors) {
+ // Retrieve all available locales of the given Intl service constructor.
+ let available = getAvailableLocalesOf(intlConstructor.name);
+
+ // "best fit" matchers could potentially return a different locale, so we only
+ // test with "lookup" locale matchers. (NB: We don't yet support "best fit"
+ // matchers.)
+ let options = {localeMatcher: "lookup"};
+
+ if (intlConstructor === Intl.DisplayNames) {
+ // Intl.DisplayNames can't be constructed without the "type" option.
+ options.type = "language";
+ }
+
+ for (let locale of available) {
+ let obj = new intlConstructor(locale, options);
+ let resolved = obj.resolvedOptions();
+
+ // If |locale| is an available locale, the "lookup" locale matcher should
+ // pick exactly that locale.
+ assertEq(resolved.locale, locale);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/available-locales-supported.js b/js/src/tests/non262/Intl/available-locales-supported.js
new file mode 100644
index 0000000000..d11b5d714f
--- /dev/null
+++ b/js/src/tests/non262/Intl/available-locales-supported.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+if (typeof getAvailableLocalesOf === "undefined") {
+ var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf;
+}
+
+function IsIntlService(c) {
+ return typeof c === "function" &&
+ c.hasOwnProperty("prototype") &&
+ c.prototype.hasOwnProperty("resolvedOptions");
+}
+
+const intlConstructors = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService);
+
+// Test all Intl service constructors.
+for (let intlConstructor of intlConstructors) {
+ // Retrieve all available locales of the given Intl service constructor.
+ let available = getAvailableLocalesOf(intlConstructor.name);
+
+ // All available locales must be reported as supported.
+ let supported = intlConstructor.supportedLocalesOf(available);
+ assertEqArray(supported, available);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/best-available-locale-from-default-locale.js b/js/src/tests/non262/Intl/best-available-locale-from-default-locale.js
new file mode 100644
index 0000000000..16a0e0348f
--- /dev/null
+++ b/js/src/tests/non262/Intl/best-available-locale-from-default-locale.js
@@ -0,0 +1,107 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+if (typeof getDefaultLocale === "undefined") {
+ var getDefaultLocale = SpecialPowers.Cu.getJSTestingFunctions().getDefaultLocale;
+}
+if (typeof setDefaultLocale === "undefined") {
+ var setDefaultLocale = SpecialPowers.Cu.getJSTestingFunctions().setDefaultLocale;
+}
+
+let defaultLocale = null;
+
+function withLocale(locale, fn) {
+ if (defaultLocale === null)
+ defaultLocale = getDefaultLocale();
+
+ setDefaultLocale(locale);
+ try {
+ fn();
+ } finally {
+ setDefaultLocale(defaultLocale);
+ }
+}
+
+// This test assumes Azerbaijani ("az") is a supported locale.
+const supported = Intl.Collator.supportedLocalesOf("az");
+assertEq(supported.length, 1);
+assertEq(supported[0], "az");
+
+withLocale("az", () => {
+ // Ensure the new default locale is now active.
+ assertEq(new Intl.Collator().resolvedOptions().locale, "az");
+
+ // "az" is the active default locale, so explicitly requesting "az" should succeed.
+ assertEq(new Intl.Collator("az").resolvedOptions().locale, "az");
+
+ // ICU doesn't provide a specialised "az-Cyrl" locale, so we fallback to "az".
+ assertEq(new Intl.Collator("az-Cyrl").resolvedOptions().locale, "az");
+
+ // ICU doesn't provide a specialised "az-Cyrl-AZ" locale, so we fallback to "az".
+ assertEq(new Intl.Collator("az-Cyrl-AZ").resolvedOptions().locale, "az");
+});
+
+// As demonstrated above, "az-Cyrl-AZ" normally isn't a supported Intl.Collator locale. But when
+// used as the default locale, it gets promoted to being supported, because its parent locale "az"
+// is supported and can act as a fallback.
+//
+// This works as follows:
+// We accept any default locale as long as it can be supported either explicitly or implicitly
+// through a fallback. But when we claim a default locale is supported, we also need to make sure
+// we report any parent locale as being supported. So when "az-Cyrl-AZ" is accepted as the
+// default locale, we also need to report its parent locale "az-Cyrl" as a supported locale.
+//
+// The reason we're doing this, is to make sure we aren't limiting the supported default locale to
+// the intersection of the sets of supported locales for each Intl service constructor. Also see
+// the requirements in <https://tc39.es/ecma402/#sec-internal-slots>, which state that the default
+// locale must be a member of [[AvailableLocales]] for every Intl service constructor.
+//
+// So the following statement must hold:
+//
+// ∀ Constructor ∈ IntlConstructors: DefaultLocale ∈ Constructor.[[AvailableLocales]]
+//
+// This can trivially be achieved when we restrict the default locale to:
+//
+// { RequestedLocale if RequestedLocale ∈ (∩ C.[[AvailableLocales]])
+// { C ∈ IntlConstructors
+// {
+// DefaultLocale = { Fallback(RequestedLocale) if Fallback(RequestedLocale) ∈ (∩ C.[[AvailableLocales]])
+// { C ∈ IntlConstructors
+// {
+// { LastDitchLocale otherwise
+//
+// But that severely restricts the possible default locales. For example, "az-Cyrl-AZ" is supported
+// by all Intl constructors except Intl.Collator. Intl.Collator itself only provides explicit
+// support for the parent locale "az". So with the trivial solution we'd need to mark "az-Cyrl-AZ"
+// as an invalid default locale and instead use its fallback locale "az".
+//
+// So instead of that we're using the following approach:
+//
+// { RequestedLocale if RequestedLocale ∈ (∩ C.[[AvailableLocales]])
+// { C ∈ IntlConstructors
+// {
+// DefaultLocale = { RequestedLocale if Fallback(RequestedLocale) ∈ (∩ C.[[AvailableLocales]])
+// { C ∈ IntlConstructors
+// {
+// { LastDitchLocale otherwise
+//
+// So even when the requested default locale is only implicitly supported through a fallback, we
+// still accept it as a valid default locale.
+withLocale("az-Cyrl-AZ", () => {
+ // Ensure the new default locale is now active.
+ assertEq(new Intl.Collator().resolvedOptions().locale, "az-Cyrl-AZ");
+
+ // "az-Cyrl-AZ" is the active default locale, so explicitly requesting the parent locale
+ // "az" should succeed.
+ assertEq(new Intl.Collator("az").resolvedOptions().locale, "az");
+
+ // "az-Cyrl-AZ" is the active default locale, so explicitly requesting the parent locale
+ // "az-Cyrl" should succeed.
+ assertEq(new Intl.Collator("az-Cyrl").resolvedOptions().locale, "az-Cyrl");
+
+ // "az-Cyrl-AZ" is the active default locale, so explicitly requesting "az-Cyrl-AZ"
+ // should succeed.
+ assertEq(new Intl.Collator("az-Cyrl-AZ").resolvedOptions().locale, "az-Cyrl-AZ");
+});
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/browser.js b/js/src/tests/non262/Intl/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Intl/browser.js
diff --git a/js/src/tests/non262/Intl/default-locale-shell.js b/js/src/tests/non262/Intl/default-locale-shell.js
new file mode 100644
index 0000000000..ea3f6d17db
--- /dev/null
+++ b/js/src/tests/non262/Intl/default-locale-shell.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||!xulRuntime.shell)
+
+// js/src/tests/lib/tests.py sets the default locale to "en-US" for shell tests.
+// Ensure it's correctly set in the runtime and for the Intl service constructors.
+const defaultLocale = "en-US";
+
+assertEq(getDefaultLocale(), defaultLocale);
+
+assertEq(new Intl.Collator().resolvedOptions().locale, defaultLocale);
+assertEq(new Intl.DateTimeFormat().resolvedOptions().locale, defaultLocale);
+assertEq(new Intl.NumberFormat().resolvedOptions().locale, defaultLocale);
+assertEq(new Intl.PluralRules().resolvedOptions().locale, defaultLocale);
+assertEq(new Intl.RelativeTimeFormat().resolvedOptions().locale, defaultLocale);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/duplicate-variants.js b/js/src/tests/non262/Intl/duplicate-variants.js
new file mode 100644
index 0000000000..5d07a9b109
--- /dev/null
+++ b/js/src/tests/non262/Intl/duplicate-variants.js
@@ -0,0 +1,46 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// RFC 5646 section 2.1
+// variant = 5*8alphanum ; registered variants
+// / (DIGIT 3alphanum)
+
+// Duplicate variants are forbidden.
+assertEqArray(Intl.getCanonicalLocales("de-1996"), ["de-1996"]);
+assertThrowsInstanceOf(() => Intl.getCanonicalLocales("de-1996-1996"), RangeError);
+
+// Multiple different variants are allowed.
+assertEqArray(Intl.getCanonicalLocales("sl-rozaj-solba"), ["sl-rozaj-solba"]);
+
+// Variants can have the same prefix.
+assertEqArray(Intl.getCanonicalLocales("zh-Latn-pinyin-pinyin2"), ["zh-Latn-pinyin-pinyin2"]);
+
+// Values in extension sequences are not counted as variants.
+assertEqArray(Intl.getCanonicalLocales("en-u-kf-false-kn-false"), ["en-u-kf-false-kn-false"]);
+
+// Also test duplicates in Unicode extension keywords and attributes.
+// From https://tools.ietf.org/html/rfc6067#section-2.1
+//
+// An 'attribute' is a subtag with a length of three to eight
+// characters following the singleton and preceding any 'keyword'
+// sequences. No attributes were defined at the time of this
+// document's publication.
+//
+// A 'keyword' is a sequence of subtags consisting of a 'key' subtag,
+// followed by zero or more 'type' subtags (so a 'key' might appear
+// alone and not be accompanied by a 'type' subtag). A 'key' MUST
+// NOT appear more than once in a language tag's extension string.
+//
+// ...
+//
+// Only the first occurrence of an attribute or key conveys meaning in a
+// language tag. When interpreting tags containing the Unicode locale
+// extension, duplicate attributes or keywords are ignored in the
+// following way: ignore any attribute that has already appeared in the
+// tag and ignore any keyword whose key has already occurred in the tag.
+//
+// The duplicates itself are removed in CanonicalizeUnicodeLocaleId, step 2-3.
+assertEqArray(Intl.getCanonicalLocales("en-u-kn-false-kn-false"), ["en-u-kn-false"]);
+assertEqArray(Intl.getCanonicalLocales("en-u-attr1-attr2-attr2"), ["en-u-attr1-attr2"]);
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/extensions/browser.js b/js/src/tests/non262/Intl/extensions/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Intl/extensions/browser.js
diff --git a/js/src/tests/non262/Intl/extensions/options-value-emulates-undefined.js b/js/src/tests/non262/Intl/extensions/options-value-emulates-undefined.js
new file mode 100644
index 0000000000..5b2ee124aa
--- /dev/null
+++ b/js/src/tests/non262/Intl/extensions/options-value-emulates-undefined.js
@@ -0,0 +1,29 @@
+// |reftest| skip-if(!xulRuntime.shell||!this.hasOwnProperty('Intl'))
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 843004;
+var summary =
+ "Use of an object that emulates |undefined| as the sole option must " +
+ "preclude imputing default values";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+var opt = createIsHTMLDDA();
+opt.toString = function() { return "long"; };
+
+var str = new Date(2013, 12 - 1, 14).toLocaleString("en-US", { weekday: opt });
+
+// Because "weekday" was present and not undefined (stringifying to "long"),
+// this must be a string like "Saturday" (in this implementation, that is).
+assertEq(str, "Saturday");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+print("Tests complete");
diff --git a/js/src/tests/non262/Intl/extensions/shell.js b/js/src/tests/non262/Intl/extensions/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/non262/Intl/extensions/shell.js
diff --git a/js/src/tests/non262/Intl/extensions/unicode-extension-sequences.js b/js/src/tests/non262/Intl/extensions/unicode-extension-sequences.js
new file mode 100644
index 0000000000..ead69a4632
--- /dev/null
+++ b/js/src/tests/non262/Intl/extensions/unicode-extension-sequences.js
@@ -0,0 +1,74 @@
+// |reftest| skip-if(!this.getSelfHostedValue)
+
+const startOfUnicodeExtensions = getSelfHostedValue("startOfUnicodeExtensions");
+const endOfUnicodeExtensions = getSelfHostedValue("endOfUnicodeExtensions");
+
+const testcases = [
+ // Language tag without Unicode extension.
+ { locale: "en", start: -1, end: 0 },
+ { locale: "en-Latn", start: -1, end: 0 },
+ { locale: "en-x-y", start: -1, end: 0 },
+ { locale: "en-x-yz", start: -1, end: 0 },
+ { locale: "en-x-u-kf", start: -1, end: 0 },
+
+ // Unicode extension sequence starts with key subtag.
+ // - no suceeding key or type subtags.
+ { locale: "en-u-ab", start: 2, end: 7 },
+ { locale: "en-u-ab-x-y", start: 2, end: 7 },
+ { locale: "en-u-ab-x-yz", start: 2, end: 7 },
+ { locale: "en-u-ab-x-u-kn", start: 2, end: 7 },
+ // - followed by key subtag.
+ { locale: "en-u-ab-cd", start: 2, end: 10 },
+ { locale: "en-u-ab-cd-x-y", start: 2, end: 10 },
+ { locale: "en-u-ab-cd-x-yz", start: 2, end: 10 },
+ { locale: "en-u-ab-cd-x-u-kn", start: 2, end: 10 },
+ // - followed by type subtag.
+ { locale: "en-u-ab-cdef", start: 2, end: 12 },
+ { locale: "en-u-ab-cdef-x-y", start: 2, end: 12 },
+ { locale: "en-u-ab-cdef-x-yz", start: 2, end: 12 },
+ { locale: "en-u-ab-cdef-x-y-u-kn", start: 2, end: 12 },
+
+ // Unicode extension sequence starts with attribute subtag.
+ // - no suceeding attribute or key subtags.
+ { locale: "en-u-abc", start: 2, end: 8 },
+ { locale: "en-u-abc-x-y", start: 2, end: 8 },
+ { locale: "en-u-abc-x-yz", start: 2, end: 8 },
+ { locale: "en-u-abc-x-y-u-kn", start: 2, end: 8 },
+ // - followed by attribute subtag.
+ { locale: "en-u-abc-def", start: 2, end: 12 },
+ { locale: "en-u-abc-def-x-y", start: 2, end: 12 },
+ { locale: "en-u-abc-def-x-yz", start: 2, end: 12 },
+ { locale: "en-u-abc-def-x-y-u-kn", start: 2, end: 12 },
+ // - followed by key subtag.
+ { locale: "en-u-abc-de", start: 2, end: 11 },
+ { locale: "en-u-abc-de-x-y", start: 2, end: 11 },
+ { locale: "en-u-abc-de-x-yz", start: 2, end: 11 },
+ { locale: "en-u-abc-de-x-y-u-kn", start: 2, end: 11 },
+ // - followed by two key subtags.
+ { locale: "en-u-abc-de-fg", start: 2, end: 14 },
+ { locale: "en-u-abc-de-fg-x-y", start: 2, end: 14 },
+ { locale: "en-u-abc-de-fg-x-yz", start: 2, end: 14 },
+ { locale: "en-u-abc-de-fg-x-y-u-kn", start: 2, end: 14 },
+ // - followed by key and type subtag.
+ { locale: "en-u-abc-de-fgh", start: 2, end: 15 },
+ { locale: "en-u-abc-de-fgh-x-y", start: 2, end: 15 },
+ { locale: "en-u-abc-de-fgh-x-yz", start: 2, end: 15 },
+ { locale: "en-u-abc-de-fgh-x-y-u-kn", start: 2, end: 15 },
+
+ // Also test when the Unicode extension doesn't start at index 2.
+ { locale: "en-Latn-u-kf", start: 7, end: 12 },
+ { locale: "und-u-kf", start: 3, end: 8 },
+];
+
+for (const {locale, start, end} of testcases) {
+ // Ensure the input is a valid language tag.
+ assertEqArray(Intl.getCanonicalLocales(locale), [locale]);
+
+ assertEq(startOfUnicodeExtensions(locale), start);
+
+ if (start >= 0)
+ assertEq(endOfUnicodeExtensions(locale, start), end);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/fallback-symbol.js b/js/src/tests/non262/Intl/fallback-symbol.js
new file mode 100644
index 0000000000..87943257ce
--- /dev/null
+++ b/js/src/tests/non262/Intl/fallback-symbol.js
@@ -0,0 +1,22 @@
+// |reftest| skip-if(!this.hasOwnProperty('Intl'))
+
+function IntlFallbackSymbol(constructor) {
+ return Object.getOwnPropertySymbols(constructor.call(Object.create(constructor.prototype)))[0];
+}
+
+const dateTimeFormatIntlFallbackSymbol = IntlFallbackSymbol(Intl.DateTimeFormat);
+const numberFormatIntlFallbackSymbol = IntlFallbackSymbol(Intl.NumberFormat);
+
+// Intl.DateTimeFormat and Intl.NumberFormat both use the same fallback symbol.
+assertEq(dateTimeFormatIntlFallbackSymbol, numberFormatIntlFallbackSymbol);
+
+const intlFallbackSymbol = dateTimeFormatIntlFallbackSymbol;
+
+// The fallback symbol is a Symbol value.
+assertEq(typeof intlFallbackSymbol, "symbol");
+
+// Test the description of the fallback symbol.
+assertEq(Symbol.prototype.toString.call(intlFallbackSymbol), "Symbol(IntlLegacyConstructedSymbol)");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/four-letter-language-codes.js b/js/src/tests/non262/Intl/four-letter-language-codes.js
new file mode 100644
index 0000000000..394efacf29
--- /dev/null
+++ b/js/src/tests/non262/Intl/four-letter-language-codes.js
@@ -0,0 +1,22 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Four letter language subtags are not allowed.
+const languageTags = [
+ "root", // Special meaning in Unicode CLDR locale identifiers.
+ "Latn", // Unicode CLDR locale identifiers can start with a script subtag.
+ "Flob", // And now some non-sense input.
+ "ZORK",
+ "Blah-latn",
+ "QuuX-latn-us",
+ "SPAM-gb-x-Sausages-BACON-eggs",
+];
+
+for (let tag of languageTags) {
+ assertThrowsInstanceOf(() => Intl.getCanonicalLocales(tag), RangeError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/getCalendarInfo.js b/js/src/tests/non262/Intl/getCalendarInfo.js
new file mode 100644
index 0000000000..5c9a8e24da
--- /dev/null
+++ b/js/src/tests/non262/Intl/getCalendarInfo.js
@@ -0,0 +1,76 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl")||!this.hasOwnProperty("addIntlExtras"))
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests the getCalendarInfo function with a diverse set of arguments.
+
+function checkCalendarInfo(info, expected)
+{
+ assertEq(Object.getPrototypeOf(info), Object.prototype);
+
+ assertEq(info.firstDayOfWeek, expected.firstDayOfWeek);
+ assertEq(info.minDays, expected.minDays);
+ assertDeepEq(info.weekend, expected.weekend);
+ assertEq(info.calendar, expected.calendar);
+ assertEq(info.locale, expected.locale);
+}
+
+addIntlExtras(Intl);
+
+let gCI = Intl.getCalendarInfo;
+
+assertEq(gCI.length, 1);
+
+checkCalendarInfo(gCI('en-US'), {
+ firstDayOfWeek: 7,
+ minDays: 1,
+ weekend: [6, 7],
+ calendar: "gregory",
+ locale: "en-US"
+});
+
+checkCalendarInfo(gCI('en-IL'), {
+ firstDayOfWeek: 7,
+ minDays: 1,
+ weekend: [5, 6],
+ calendar: "gregory",
+ locale: "en-IL"
+});
+
+
+checkCalendarInfo(gCI('en-GB'), {
+ firstDayOfWeek: 1,
+ minDays: 4,
+ weekend: [6, 7],
+ calendar: "gregory",
+ locale: "en-GB"
+});
+
+
+checkCalendarInfo(gCI('pl'), {
+ firstDayOfWeek: 1,
+ minDays: 4,
+ weekend: [6, 7],
+ calendar: "gregory",
+ locale: "pl"
+});
+
+checkCalendarInfo(gCI('ar-IQ'), {
+ firstDayOfWeek: 6,
+ minDays: 1,
+ weekend: [5, 6],
+ calendar: "gregory",
+ locale: "ar-IQ"
+});
+
+checkCalendarInfo(gCI('fa-IR'), {
+ firstDayOfWeek: 6,
+ minDays: 1,
+ weekend: [5],
+ calendar: "persian",
+ locale: "fa-IR"
+});
+
+if (typeof reportCompare === 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/getCanonicalLocales-overridden-arg-length.js b/js/src/tests/non262/Intl/getCanonicalLocales-overridden-arg-length.js
new file mode 100644
index 0000000000..f0cb3d4ee3
--- /dev/null
+++ b/js/src/tests/non262/Intl/getCanonicalLocales-overridden-arg-length.js
@@ -0,0 +1,20 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests the getCanonicalLocales function for overridden argument's length.
+
+var count = 0;
+var locs = { get length() { if (count++ > 0) throw 42; return 0; } };
+var locales = Intl.getCanonicalLocales(locs); // shouldn't throw 42
+assertEq(locales.length, 0);
+
+
+var obj = { get 0() { throw new Error("must not be gotten!"); },
+ length: -Math.pow(2, 32) + 1 };
+
+assertEq(Intl.getCanonicalLocales(obj).length, 0);
+
+if (typeof reportCompare === 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/getCanonicalLocales-overridden-push.js b/js/src/tests/non262/Intl/getCanonicalLocales-overridden-push.js
new file mode 100644
index 0000000000..36f53ebf06
--- /dev/null
+++ b/js/src/tests/non262/Intl/getCanonicalLocales-overridden-push.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests the getCanonicalLocales function for overriden Array.push.
+
+Array.prototype.push = () => { throw 42; };
+
+// must not throw 42, might if push is used
+var arr = Intl.getCanonicalLocales(["en-US"]);
+
+assertEqArray(arr, ["en-US"]);
+
+if (typeof reportCompare === 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/getCanonicalLocales-overridden-set.js b/js/src/tests/non262/Intl/getCanonicalLocales-overridden-set.js
new file mode 100644
index 0000000000..396f3a9483
--- /dev/null
+++ b/js/src/tests/non262/Intl/getCanonicalLocales-overridden-set.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests the getCanonicalLocales function for overridden set().
+
+Object.defineProperty(Array.prototype, 0, { set() { throw 42; } });
+
+// must not throw 42, might if push is used
+var arr = Intl.getCanonicalLocales(["en-US"]);
+
+assertEqArray(arr, ["en-US"]);
+
+if (typeof reportCompare === 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/getCanonicalLocales-overridden-species.js b/js/src/tests/non262/Intl/getCanonicalLocales-overridden-species.js
new file mode 100644
index 0000000000..858735b581
--- /dev/null
+++ b/js/src/tests/non262/Intl/getCanonicalLocales-overridden-species.js
@@ -0,0 +1,23 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Tests the getCanonicalLocales function for overriden Array[Symbol.species].
+
+Object.defineProperty(Array, Symbol.species, {
+ value: function() {
+ return new Proxy(["?"], {
+ get(t, pk, r) {
+ return Reflect.get(t, pk, r);
+ },
+ defineProperty(t, pk) {
+ return true;
+ }
+ });
+ }
+});
+
+var arr = Intl.getCanonicalLocales("de-x-private");
+
+assertEqArray(arr, ["de-x-private"]);
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/getCanonicalLocales-weird-cases.js b/js/src/tests/non262/Intl/getCanonicalLocales-weird-cases.js
new file mode 100644
index 0000000000..d67fda355f
--- /dev/null
+++ b/js/src/tests/non262/Intl/getCanonicalLocales-weird-cases.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Locale processing is supposed to internally remove any Unicode extension
+// sequences in the locale. Test that various weird testcases invoking
+// algorithmic edge cases don't assert or throw exceptions.
+
+var weirdCases =
+ [
+ "en-x-u-foo",
+ "en-a-bar-x-u-foo",
+ "en-x-u-foo-a-bar",
+ "en-a-bar-u-baz-x-u-foo",
+ ];
+
+for (let weird of weirdCases)
+ assertEqArray(Intl.getCanonicalLocales(weird), [weird]);
+
+assertThrowsInstanceOf(() => Intl.getCanonicalLocales("x-u-foo"), RangeError);
+
+if (typeof reportCompare === 'function')
+ reportCompare(0, 0);
+
diff --git a/js/src/tests/non262/Intl/getCanonicalLocales-with-duplicates.js b/js/src/tests/non262/Intl/getCanonicalLocales-with-duplicates.js
new file mode 100644
index 0000000000..c029569482
--- /dev/null
+++ b/js/src/tests/non262/Intl/getCanonicalLocales-with-duplicates.js
@@ -0,0 +1,15 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests the getCanonicalLocales function for duplicate locales scenario.
+
+assertEqArray(Intl.getCanonicalLocales(['ab-cd', 'ff', 'de-rt', 'ab-Cd']),
+ ['ab-CD', 'ff', 'de-RT']);
+
+var locales = Intl.getCanonicalLocales(["en-US", "en-US"]);
+assertEqArray(locales, ['en-US']);
+
+if (typeof reportCompare === 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/getCanonicalLocales.js b/js/src/tests/non262/Intl/getCanonicalLocales.js
new file mode 100644
index 0000000000..66e9b87c5c
--- /dev/null
+++ b/js/src/tests/non262/Intl/getCanonicalLocales.js
@@ -0,0 +1,37 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Tests the getCanonicalLocales function with a diverse set of arguments.
+
+let gCL = Intl.getCanonicalLocales;
+
+assertEq(Intl.getCanonicalLocales.length, 1);
+
+assertEqArray(gCL(), []);
+
+assertEqArray(gCL('ab-cd'), ['ab-CD']);
+
+assertEqArray(gCL(['ab-cd']), ['ab-CD']);
+
+assertEqArray(gCL(['ab-cd', 'FF']), ['ab-CD', 'ff']);
+
+assertEqArray(gCL({'a': 0}), []);
+
+assertEqArray(gCL({}), []);
+
+assertEqArray(gCL(['ar-ma-u-ca-islamicc']), ['ar-MA-u-ca-islamic-civil']);
+
+assertEqArray(gCL(['th-th-u-nu-thai']), ['th-TH-u-nu-thai']);
+
+assertEqArray(gCL(NaN), []);
+
+assertEqArray(gCL(1), []);
+
+Number.prototype[0] = "en-US";
+Number.prototype.length = 1;
+assertEqArray(gCL(NaN), ["en-US"]);
+
+if (typeof reportCompare === 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/legacy-and-sign-locales-with-unicode-extensions.js b/js/src/tests/non262/Intl/legacy-and-sign-locales-with-unicode-extensions.js
new file mode 100644
index 0000000000..2421d9bb09
--- /dev/null
+++ b/js/src/tests/non262/Intl/legacy-and-sign-locales-with-unicode-extensions.js
@@ -0,0 +1,79 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const languageTags = {
+ // Case 1: legacy, regular tags.
+ "art-lojban": "jbo",
+ "cel-gaulish": "xtg",
+ "zh-guoyu": "zh",
+ "zh-hakka": "hak",
+ "zh-xiang": "hsn",
+
+ // Case 2: redundant language tags.
+ "sgn-BR": "bzs",
+ "sgn-CO": "csn",
+ "sgn-DE": "gsg",
+ "sgn-DK": "dsl",
+ "sgn-ES": "ssp",
+ "sgn-FR": "fsl",
+ "sgn-GB": "bfi",
+ "sgn-GR": "gss",
+ "sgn-IE": "isg",
+ "sgn-IT": "ise",
+ "sgn-JP": "jsl",
+ "sgn-MX": "mfs",
+ "sgn-NI": "ncs",
+ "sgn-NL": "dse",
+ "sgn-NO": "nsi",
+ "sgn-PT": "psr",
+ "sgn-SE": "swl",
+ "sgn-US": "ase",
+ "sgn-ZA": "sfs",
+
+ // Case 3: the special case.
+ "ja-Latn-hepburn-heploc": "ja-Latn-alalc97",
+};
+const extensions = ["-u-attr", "-u-nu-latn"];
+const intlConstructors = [Intl.Collator, Intl.DateTimeFormat, Intl.NumberFormat];
+const options = [{localeMatcher: "best fit"}, {localeMatcher: "lookup"}];
+
+for (let [tag, canonical] of Object.entries(languageTags)) {
+ // Ensure Intl.getCanonicalLocales canonicalizes the language tag correctly.
+ assertEq(Intl.getCanonicalLocales(tag)[0], canonical);
+
+ // Unicode extensions don't change the canonicalization result.
+ for (let ext of extensions) {
+ assertEq(Intl.getCanonicalLocales(tag + ext)[0], canonical + ext);
+ assertEq(Intl.getCanonicalLocales(canonical + ext)[0], canonical + ext);
+ }
+
+ for (let intlCtor of intlConstructors) {
+ for (let opt of options) {
+ // The non-canonical tag is supported iff the canonical tag is supported.
+ let supported = intlCtor.supportedLocalesOf(tag, opt);
+ let supportedCanonical = intlCtor.supportedLocalesOf(canonical, opt);
+ assertEq(supported.length, supportedCanonical.length);
+
+ let isSupported = supported.length > 0;
+ if (isSupported) {
+ assertEq(supported[0], canonical);
+ assertEq(supportedCanonical[0], canonical);
+ }
+
+ // Unicode extensions don't change the result of supportedLocalesOf().
+ for (let ext of extensions) {
+ let supportedExt = intlCtor.supportedLocalesOf(tag + ext, opt);
+ let supportedCanonicalExt = intlCtor.supportedLocalesOf(canonical + ext, opt);
+ assertEq(supportedExt.length, supportedCanonical.length);
+ assertEq(supportedCanonicalExt.length, supportedCanonical.length);
+
+ if (isSupported) {
+ assertEq(supportedExt[0], canonical + ext);
+ assertEq(supportedCanonicalExt[0], canonical + ext);
+ }
+ }
+ }
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/resolved-locale-sorted-unicode-extension-keys.js b/js/src/tests/non262/Intl/resolved-locale-sorted-unicode-extension-keys.js
new file mode 100644
index 0000000000..400f7f0f63
--- /dev/null
+++ b/js/src/tests/non262/Intl/resolved-locale-sorted-unicode-extension-keys.js
@@ -0,0 +1,109 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+function IsIntlService(c) {
+ return typeof c === "function" &&
+ c.hasOwnProperty("prototype") &&
+ c.prototype.hasOwnProperty("resolvedOptions");
+}
+
+const IntlServices = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService);
+
+// Examples for all possible Unicode extension keys (with the exception of deprecated "vt").
+const unicodeExtensions = [
+ // calendar
+ "ca-gregory",
+ "fw-mon",
+ "hc-h23",
+
+ // collation
+ "co-phonebk",
+ "ka-noignore",
+ "kb-false",
+ "kc-false",
+ "kf-false",
+ "kh-false",
+ "kk-false",
+ "kn-false",
+ "kr-space",
+ "ks-level1",
+ "kv-space",
+
+ // currency
+ "cf-standard",
+ "cu-eur",
+
+ // measure
+ "ms-metric",
+
+ // number
+ "nu-latn",
+
+ // segmentation
+ "lb-strict",
+ "lw-normal",
+ "ss-none",
+
+ // timezone
+ "tz-atvie",
+
+ // variant
+ "em-default",
+ "rg-atzzzz",
+ "sd-atat1",
+ "va-posix",
+];
+
+function reverse(a, b) {
+ if (a < b) {
+ return 1;
+ }
+ if (a > b) {
+ return -1;
+ }
+ return 0;
+}
+
+function findUnicodeExtensionKeys(locale) {
+ // Find the Unicode extension key subtag.
+ var extension = locale.match(/.*-u-(.*)/);
+ if (extension === null) {
+ return [];
+ }
+
+ // Replace all types in the Unicode extension keywords.
+ return extension[1].replace(/-\w{3,}/g, "").split("-");
+}
+
+// Test all Intl service constructors and ensure the Unicode extension keys in
+// the resolved locale are sorted alphabetically.
+
+for (let IntlService of IntlServices) {
+ let options = undefined;
+ if (IntlService === Intl.DisplayNames) {
+ // Intl.DisplayNames requires the "type" option to be set.
+ options = {type: "language"};
+ }
+
+ // sort() modifies the input array, so create a copy.
+ let ext = unicodeExtensions.slice(0);
+
+ let locale, keys;
+
+ // Input keys unsorted.
+ locale = new IntlService(`de-u-${ext.join("-")}`, options).resolvedOptions().locale;
+ keys = findUnicodeExtensionKeys(locale);
+ assertEqArray(keys, keys.slice(0).sort());
+
+ // Input keys sorted alphabetically.
+ locale = new IntlService(`de-u-${ext.sort().join("-")}`, options).resolvedOptions().locale;
+ keys = findUnicodeExtensionKeys(locale);
+ assertEqArray(keys, keys.slice(0).sort());
+
+ // Input keys sorted alphabetically in reverse order.
+ locale = new IntlService(`de-u-${ext.sort(reverse).join("-")}`, options).resolvedOptions().locale;
+ keys = findUnicodeExtensionKeys(locale);
+ assertEqArray(keys, keys.slice(0).sort());
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/shell.js b/js/src/tests/non262/Intl/shell.js
new file mode 100644
index 0000000000..1659e39e12
--- /dev/null
+++ b/js/src/tests/non262/Intl/shell.js
@@ -0,0 +1,340 @@
+// Generated by make_intl_data.py. DO NOT EDIT.
+
+// source: CLDR file common/bcp47/number.xml; version CLDR 43.
+// https://github.com/unicode-org/cldr/blob/master/common/bcp47/number.xml
+// https://github.com/unicode-org/cldr/blob/master/common/supplemental/numberingSystems.xml
+const numberingSystems = {
+ "adlm": {
+ "algorithmic": false,
+ "digits": "𞥐𞥑𞥒𞥓𞥔𞥕𞥖𞥗𞥘𞥙"
+ },
+ "ahom": {
+ "algorithmic": false,
+ "digits": "𑜰𑜱𑜲𑜳𑜴𑜵𑜶𑜷𑜸𑜹"
+ },
+ "arab": {
+ "algorithmic": false,
+ "digits": "٠١٢٣٤٥٦٧٨٩"
+ },
+ "arabext": {
+ "algorithmic": false,
+ "digits": "۰۱۲۳۴۵۶۷۸۹"
+ },
+ "armn": {
+ "algorithmic": true
+ },
+ "armnlow": {
+ "algorithmic": true
+ },
+ "bali": {
+ "algorithmic": false,
+ "digits": "᭐᭑᭒᭓᭔᭕᭖᭗᭘᭙"
+ },
+ "beng": {
+ "algorithmic": false,
+ "digits": "০১২৩৪৫৬৭৮৯"
+ },
+ "bhks": {
+ "algorithmic": false,
+ "digits": "𑱐𑱑𑱒𑱓𑱔𑱕𑱖𑱗𑱘𑱙"
+ },
+ "brah": {
+ "algorithmic": false,
+ "digits": "𑁦𑁧𑁨𑁩𑁪𑁫𑁬𑁭𑁮𑁯"
+ },
+ "cakm": {
+ "algorithmic": false,
+ "digits": "𑄶𑄷𑄸𑄹𑄺𑄻𑄼𑄽𑄾𑄿"
+ },
+ "cham": {
+ "algorithmic": false,
+ "digits": "꩐꩑꩒꩓꩔꩕꩖꩗꩘꩙"
+ },
+ "cyrl": {
+ "algorithmic": true
+ },
+ "deva": {
+ "algorithmic": false,
+ "digits": "०१२३४५६७८९"
+ },
+ "diak": {
+ "algorithmic": false,
+ "digits": "𑥐𑥑𑥒𑥓𑥔𑥕𑥖𑥗𑥘𑥙"
+ },
+ "ethi": {
+ "algorithmic": true
+ },
+ "fullwide": {
+ "algorithmic": false,
+ "digits": "0123456789"
+ },
+ "geor": {
+ "algorithmic": true
+ },
+ "gong": {
+ "algorithmic": false,
+ "digits": "𑶠𑶡𑶢𑶣𑶤𑶥𑶦𑶧𑶨𑶩"
+ },
+ "gonm": {
+ "algorithmic": false,
+ "digits": "𑵐𑵑𑵒𑵓𑵔𑵕𑵖𑵗𑵘𑵙"
+ },
+ "grek": {
+ "algorithmic": true
+ },
+ "greklow": {
+ "algorithmic": true
+ },
+ "gujr": {
+ "algorithmic": false,
+ "digits": "૦૧૨૩૪૫૬૭૮૯"
+ },
+ "guru": {
+ "algorithmic": false,
+ "digits": "੦੧੨੩੪੫੬੭੮੯"
+ },
+ "hanidays": {
+ "algorithmic": true
+ },
+ "hanidec": {
+ "algorithmic": false,
+ "digits": "〇一二三四五六七八九"
+ },
+ "hans": {
+ "algorithmic": true
+ },
+ "hansfin": {
+ "algorithmic": true
+ },
+ "hant": {
+ "algorithmic": true
+ },
+ "hantfin": {
+ "algorithmic": true
+ },
+ "hebr": {
+ "algorithmic": true
+ },
+ "hmng": {
+ "algorithmic": false,
+ "digits": "𖭐𖭑𖭒𖭓𖭔𖭕𖭖𖭗𖭘𖭙"
+ },
+ "hmnp": {
+ "algorithmic": false,
+ "digits": "𞅀𞅁𞅂𞅃𞅄𞅅𞅆𞅇𞅈𞅉"
+ },
+ "java": {
+ "algorithmic": false,
+ "digits": "꧐꧑꧒꧓꧔꧕꧖꧗꧘꧙"
+ },
+ "jpan": {
+ "algorithmic": true
+ },
+ "jpanfin": {
+ "algorithmic": true
+ },
+ "jpanyear": {
+ "algorithmic": true
+ },
+ "kali": {
+ "algorithmic": false,
+ "digits": "꤀꤁꤂꤃꤄꤅꤆꤇꤈꤉"
+ },
+ "kawi": {
+ "algorithmic": false,
+ "digits": "𑽐𑽑𑽒𑽓𑽔𑽕𑽖𑽗𑽘𑽙"
+ },
+ "khmr": {
+ "algorithmic": false,
+ "digits": "០១២៣៤៥៦៧៨៩"
+ },
+ "knda": {
+ "algorithmic": false,
+ "digits": "೦೧೨೩೪೫೬೭೮೯"
+ },
+ "lana": {
+ "algorithmic": false,
+ "digits": "᪀᪁᪂᪃᪄᪅᪆᪇᪈᪉"
+ },
+ "lanatham": {
+ "algorithmic": false,
+ "digits": "᪐᪑᪒᪓᪔᪕᪖᪗᪘᪙"
+ },
+ "laoo": {
+ "algorithmic": false,
+ "digits": "໐໑໒໓໔໕໖໗໘໙"
+ },
+ "latn": {
+ "algorithmic": false,
+ "digits": "0123456789"
+ },
+ "lepc": {
+ "algorithmic": false,
+ "digits": "᱀᱁᱂᱃᱄᱅᱆᱇᱈᱉"
+ },
+ "limb": {
+ "algorithmic": false,
+ "digits": "᥆᥇᥈᥉᥊᥋᥌᥍᥎᥏"
+ },
+ "mathbold": {
+ "algorithmic": false,
+ "digits": "𝟎𝟏𝟐𝟑𝟒𝟓𝟔𝟕𝟖𝟗"
+ },
+ "mathdbl": {
+ "algorithmic": false,
+ "digits": "𝟘𝟙𝟚𝟛𝟜𝟝𝟞𝟟𝟠𝟡"
+ },
+ "mathmono": {
+ "algorithmic": false,
+ "digits": "𝟶𝟷𝟸𝟹𝟺𝟻𝟼𝟽𝟾𝟿"
+ },
+ "mathsanb": {
+ "algorithmic": false,
+ "digits": "𝟬𝟭𝟮𝟯𝟰𝟱𝟲𝟳𝟴𝟵"
+ },
+ "mathsans": {
+ "algorithmic": false,
+ "digits": "𝟢𝟣𝟤𝟥𝟦𝟧𝟨𝟩𝟪𝟫"
+ },
+ "mlym": {
+ "algorithmic": false,
+ "digits": "൦൧൨൩൪൫൬൭൮൯"
+ },
+ "modi": {
+ "algorithmic": false,
+ "digits": "𑙐𑙑𑙒𑙓𑙔𑙕𑙖𑙗𑙘𑙙"
+ },
+ "mong": {
+ "algorithmic": false,
+ "digits": "᠐᠑᠒᠓᠔᠕᠖᠗᠘᠙"
+ },
+ "mroo": {
+ "algorithmic": false,
+ "digits": "𖩠𖩡𖩢𖩣𖩤𖩥𖩦𖩧𖩨𖩩"
+ },
+ "mtei": {
+ "algorithmic": false,
+ "digits": "꯰꯱꯲꯳꯴꯵꯶꯷꯸꯹"
+ },
+ "mymr": {
+ "algorithmic": false,
+ "digits": "၀၁၂၃၄၅၆၇၈၉"
+ },
+ "mymrshan": {
+ "algorithmic": false,
+ "digits": "႐႑႒႓႔႕႖႗႘႙"
+ },
+ "mymrtlng": {
+ "algorithmic": false,
+ "digits": "꧰꧱꧲꧳꧴꧵꧶꧷꧸꧹"
+ },
+ "nagm": {
+ "algorithmic": false,
+ "digits": "𞓰𞓱𞓲𞓳𞓴𞓵𞓶𞓷𞓸𞓹"
+ },
+ "newa": {
+ "algorithmic": false,
+ "digits": "𑑐𑑑𑑒𑑓𑑔𑑕𑑖𑑗𑑘𑑙"
+ },
+ "nkoo": {
+ "algorithmic": false,
+ "digits": "߀߁߂߃߄߅߆߇߈߉"
+ },
+ "olck": {
+ "algorithmic": false,
+ "digits": "᱐᱑᱒᱓᱔᱕᱖᱗᱘᱙"
+ },
+ "orya": {
+ "algorithmic": false,
+ "digits": "୦୧୨୩୪୫୬୭୮୯"
+ },
+ "osma": {
+ "algorithmic": false,
+ "digits": "𐒠𐒡𐒢𐒣𐒤𐒥𐒦𐒧𐒨𐒩"
+ },
+ "rohg": {
+ "algorithmic": false,
+ "digits": "𐴰𐴱𐴲𐴳𐴴𐴵𐴶𐴷𐴸𐴹"
+ },
+ "roman": {
+ "algorithmic": true
+ },
+ "romanlow": {
+ "algorithmic": true
+ },
+ "saur": {
+ "algorithmic": false,
+ "digits": "꣐꣑꣒꣓꣔꣕꣖꣗꣘꣙"
+ },
+ "segment": {
+ "algorithmic": false,
+ "digits": "🯰🯱🯲🯳🯴🯵🯶🯷🯸🯹"
+ },
+ "shrd": {
+ "algorithmic": false,
+ "digits": "𑇐𑇑𑇒𑇓𑇔𑇕𑇖𑇗𑇘𑇙"
+ },
+ "sind": {
+ "algorithmic": false,
+ "digits": "𑋰𑋱𑋲𑋳𑋴𑋵𑋶𑋷𑋸𑋹"
+ },
+ "sinh": {
+ "algorithmic": false,
+ "digits": "෦෧෨෩෪෫෬෭෮෯"
+ },
+ "sora": {
+ "algorithmic": false,
+ "digits": "𑃰𑃱𑃲𑃳𑃴𑃵𑃶𑃷𑃸𑃹"
+ },
+ "sund": {
+ "algorithmic": false,
+ "digits": "᮰᮱᮲᮳᮴᮵᮶᮷᮸᮹"
+ },
+ "takr": {
+ "algorithmic": false,
+ "digits": "𑛀𑛁𑛂𑛃𑛄𑛅𑛆𑛇𑛈𑛉"
+ },
+ "talu": {
+ "algorithmic": false,
+ "digits": "᧐᧑᧒᧓᧔᧕᧖᧗᧘᧙"
+ },
+ "taml": {
+ "algorithmic": true
+ },
+ "tamldec": {
+ "algorithmic": false,
+ "digits": "௦௧௨௩௪௫௬௭௮௯"
+ },
+ "telu": {
+ "algorithmic": false,
+ "digits": "౦౧౨౩౪౫౬౭౮౯"
+ },
+ "thai": {
+ "algorithmic": false,
+ "digits": "๐๑๒๓๔๕๖๗๘๙"
+ },
+ "tibt": {
+ "algorithmic": false,
+ "digits": "༠༡༢༣༤༥༦༧༨༩"
+ },
+ "tirh": {
+ "algorithmic": false,
+ "digits": "𑓐𑓑𑓒𑓓𑓔𑓕𑓖𑓗𑓘𑓙"
+ },
+ "tnsa": {
+ "algorithmic": false,
+ "digits": "𖫀𖫁𖫂𖫃𖫄𖫅𖫆𖫇𖫈𖫉"
+ },
+ "vaii": {
+ "algorithmic": false,
+ "digits": "꘠꘡꘢꘣꘤꘥꘦꘧꘨꘩"
+ },
+ "wara": {
+ "algorithmic": false,
+ "digits": "𑣠𑣡𑣢𑣣𑣤𑣥𑣦𑣧𑣨𑣩"
+ },
+ "wcho": {
+ "algorithmic": false,
+ "digits": "𞋰𞋱𞋲𞋳𞋴𞋵𞋶𞋷𞋸𞋹"
+ }
+};
diff --git a/js/src/tests/non262/Intl/supportedValuesOf-calendar.js b/js/src/tests/non262/Intl/supportedValuesOf-calendar.js
new file mode 100644
index 0000000000..24a4ac3a57
--- /dev/null
+++ b/js/src/tests/non262/Intl/supportedValuesOf-calendar.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const calendars = Intl.supportedValuesOf("calendar");
+
+assertEq(new Set(calendars).size, calendars.length, "No duplicates are present");
+assertEqArray(calendars, [...calendars].sort(), "The list is sorted");
+
+const typeRE = /^[a-z0-9]{3,8}(-[a-z0-9]{3,8})*$/;
+for (let calendar of calendars) {
+ assertEq(typeRE.test(calendar), true, `${calendar} matches the 'type' production`);
+}
+
+for (let calendar of calendars) {
+ assertEq(new Intl.Locale("und", {calendar}).calendar, calendar, `${calendar} is canonicalised`);
+}
+
+for (let calendar of calendars) {
+ let obj = new Intl.DateTimeFormat("en", {calendar});
+ assertEq(obj.resolvedOptions().calendar, calendar, `${calendar} is supported by DateTimeFormat`);
+}
+
+assertEq(calendars.includes("gregory"), true, `Includes the Gregorian calendar`);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/supportedValuesOf-collation.js b/js/src/tests/non262/Intl/supportedValuesOf-collation.js
new file mode 100644
index 0000000000..626bb28c20
--- /dev/null
+++ b/js/src/tests/non262/Intl/supportedValuesOf-collation.js
@@ -0,0 +1,44 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const collations = Intl.supportedValuesOf("collation");
+
+assertEq(new Set(collations).size, collations.length, "No duplicates are present");
+assertEqArray(collations, [...collations].sort(), "The list is sorted");
+
+const typeRE = /^[a-z0-9]{3,8}(-[a-z0-9]{3,8})*$/;
+for (let collation of collations) {
+ assertEq(typeRE.test(collation), true, `${collation} matches the 'type' production`);
+}
+
+for (let collation of collations) {
+ assertEq(new Intl.Locale("und", {collation}).collation, collation, `${collation} is canonicalised`);
+}
+
+// Not all locales support all possible collations, so test the minimal set to
+// cover all supported collations.
+const locales = [
+ "en", // "emoji", "eor"
+ "ar", // compat
+ "de", // phonebk
+ "es", // trad
+ "ko", // searchjl
+ "ln", // phonetic
+ "si", // dict
+ "sv", // reformed
+ "zh", // big5han, gb2312, pinyin, stroke, unihan, zhuyin
+];
+
+for (let collation of collations) {
+ let supported = false;
+ for (let locale of locales) {
+ let obj = new Intl.Collator(locale, {collation});
+ if (obj.resolvedOptions().collation === collation) {
+ supported = true;
+ }
+ }
+
+ assertEq(supported, true, `${collation} is supported by Collator`);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/supportedValuesOf-currency.js b/js/src/tests/non262/Intl/supportedValuesOf-currency.js
new file mode 100644
index 0000000000..e2bf659e49
--- /dev/null
+++ b/js/src/tests/non262/Intl/supportedValuesOf-currency.js
@@ -0,0 +1,24 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const currencies = Intl.supportedValuesOf("currency");
+
+assertEq(new Set(currencies).size, currencies.length, "No duplicates are present");
+assertEqArray(currencies, [...currencies].sort(), "The list is sorted");
+
+const codeRE = /^[A-Z]{3}$/;
+for (let currency of currencies) {
+ assertEq(codeRE.test(currency), true, `${currency} is a 3-letter ISO 4217 currency code`);
+}
+
+for (let currency of currencies) {
+ let obj = new Intl.NumberFormat("en", {style: "currency", currency});
+ assertEq(obj.resolvedOptions().currency, currency, `${currency} is supported by NumberFormat`);
+}
+
+for (let currency of currencies) {
+ let obj = new Intl.DisplayNames("en", {type: "currency", fallback: "none"});
+ assertEq(typeof obj.of(currency), "string", `${currency} is supported by DisplayNames`);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/supportedValuesOf-numberingSystem.js b/js/src/tests/non262/Intl/supportedValuesOf-numberingSystem.js
new file mode 100644
index 0000000000..dd04094976
--- /dev/null
+++ b/js/src/tests/non262/Intl/supportedValuesOf-numberingSystem.js
@@ -0,0 +1,37 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const numSystems = Intl.supportedValuesOf("numberingSystem");
+
+assertEq(new Set(numSystems).size, numSystems.length, "No duplicates are present");
+assertEqArray(numSystems, [...numSystems].sort(), "The list is sorted");
+
+const typeRE = /^[a-z0-9]{3,8}(-[a-z0-9]{3,8})*$/;
+for (let numberingSystem of numSystems) {
+ assertEq(typeRE.test(numberingSystem), true, `${numberingSystem} matches the 'type' production`);
+}
+
+for (let numberingSystem of numSystems) {
+ assertEq(new Intl.Locale("und", {numberingSystem}).numberingSystem, numberingSystem,
+ `${numberingSystem} is canonicalised`);
+}
+
+for (let numberingSystem of numSystems) {
+ let obj = new Intl.DateTimeFormat("en", {numberingSystem});
+ assertEq(obj.resolvedOptions().numberingSystem, numberingSystem,
+ `${numberingSystem} is supported by DateTimeFormat`);
+}
+
+for (let numberingSystem of numSystems) {
+ let obj = new Intl.NumberFormat("en", {numberingSystem});
+ assertEq(obj.resolvedOptions().numberingSystem, numberingSystem,
+ `${numberingSystem} is supported by NumberFormat`);
+}
+
+for (let numberingSystem of numSystems) {
+ let obj = new Intl.RelativeTimeFormat("en", {numberingSystem});
+ assertEq(obj.resolvedOptions().numberingSystem, numberingSystem,
+ `${numberingSystem} is supported by RelativeTimeFormat`);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/supportedValuesOf-timeZones-canonical.js b/js/src/tests/non262/Intl/supportedValuesOf-timeZones-canonical.js
new file mode 100644
index 0000000000..333f220038
--- /dev/null
+++ b/js/src/tests/non262/Intl/supportedValuesOf-timeZones-canonical.js
@@ -0,0 +1,487 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Generated by make_intl_data.py. DO NOT EDIT.
+// tzdata version = 2023c
+
+// This file was generated with historical, pre-1970 backzone information
+// respected.
+
+const zones = [
+ "Africa/Abidjan",
+ "Africa/Accra",
+ "Africa/Addis_Ababa",
+ "Africa/Algiers",
+ "Africa/Asmara",
+ "Africa/Bamako",
+ "Africa/Bangui",
+ "Africa/Banjul",
+ "Africa/Bissau",
+ "Africa/Blantyre",
+ "Africa/Brazzaville",
+ "Africa/Bujumbura",
+ "Africa/Cairo",
+ "Africa/Casablanca",
+ "Africa/Ceuta",
+ "Africa/Conakry",
+ "Africa/Dakar",
+ "Africa/Dar_es_Salaam",
+ "Africa/Djibouti",
+ "Africa/Douala",
+ "Africa/El_Aaiun",
+ "Africa/Freetown",
+ "Africa/Gaborone",
+ "Africa/Harare",
+ "Africa/Johannesburg",
+ "Africa/Juba",
+ "Africa/Kampala",
+ "Africa/Khartoum",
+ "Africa/Kigali",
+ "Africa/Kinshasa",
+ "Africa/Lagos",
+ "Africa/Libreville",
+ "Africa/Lome",
+ "Africa/Luanda",
+ "Africa/Lubumbashi",
+ "Africa/Lusaka",
+ "Africa/Malabo",
+ "Africa/Maputo",
+ "Africa/Maseru",
+ "Africa/Mbabane",
+ "Africa/Mogadishu",
+ "Africa/Monrovia",
+ "Africa/Nairobi",
+ "Africa/Ndjamena",
+ "Africa/Niamey",
+ "Africa/Nouakchott",
+ "Africa/Ouagadougou",
+ "Africa/Porto-Novo",
+ "Africa/Sao_Tome",
+ "Africa/Timbuktu",
+ "Africa/Tripoli",
+ "Africa/Tunis",
+ "Africa/Windhoek",
+ "America/Adak",
+ "America/Anchorage",
+ "America/Anguilla",
+ "America/Antigua",
+ "America/Araguaina",
+ "America/Argentina/Buenos_Aires",
+ "America/Argentina/Catamarca",
+ "America/Argentina/ComodRivadavia",
+ "America/Argentina/Cordoba",
+ "America/Argentina/Jujuy",
+ "America/Argentina/La_Rioja",
+ "America/Argentina/Mendoza",
+ "America/Argentina/Rio_Gallegos",
+ "America/Argentina/Salta",
+ "America/Argentina/San_Juan",
+ "America/Argentina/San_Luis",
+ "America/Argentina/Tucuman",
+ "America/Argentina/Ushuaia",
+ "America/Aruba",
+ "America/Asuncion",
+ "America/Atikokan",
+ "America/Bahia",
+ "America/Bahia_Banderas",
+ "America/Barbados",
+ "America/Belem",
+ "America/Belize",
+ "America/Blanc-Sablon",
+ "America/Boa_Vista",
+ "America/Bogota",
+ "America/Boise",
+ "America/Cambridge_Bay",
+ "America/Campo_Grande",
+ "America/Cancun",
+ "America/Caracas",
+ "America/Cayenne",
+ "America/Cayman",
+ "America/Chicago",
+ "America/Chihuahua",
+ "America/Ciudad_Juarez",
+ "America/Coral_Harbour",
+ "America/Costa_Rica",
+ "America/Creston",
+ "America/Cuiaba",
+ "America/Curacao",
+ "America/Danmarkshavn",
+ "America/Dawson",
+ "America/Dawson_Creek",
+ "America/Denver",
+ "America/Detroit",
+ "America/Dominica",
+ "America/Edmonton",
+ "America/Eirunepe",
+ "America/El_Salvador",
+ "America/Ensenada",
+ "America/Fort_Nelson",
+ "America/Fortaleza",
+ "America/Glace_Bay",
+ "America/Goose_Bay",
+ "America/Grand_Turk",
+ "America/Grenada",
+ "America/Guadeloupe",
+ "America/Guatemala",
+ "America/Guayaquil",
+ "America/Guyana",
+ "America/Halifax",
+ "America/Havana",
+ "America/Hermosillo",
+ "America/Indiana/Indianapolis",
+ "America/Indiana/Knox",
+ "America/Indiana/Marengo",
+ "America/Indiana/Petersburg",
+ "America/Indiana/Tell_City",
+ "America/Indiana/Vevay",
+ "America/Indiana/Vincennes",
+ "America/Indiana/Winamac",
+ "America/Inuvik",
+ "America/Iqaluit",
+ "America/Jamaica",
+ "America/Juneau",
+ "America/Kentucky/Louisville",
+ "America/Kentucky/Monticello",
+ "America/La_Paz",
+ "America/Lima",
+ "America/Los_Angeles",
+ "America/Maceio",
+ "America/Managua",
+ "America/Manaus",
+ "America/Martinique",
+ "America/Matamoros",
+ "America/Mazatlan",
+ "America/Menominee",
+ "America/Merida",
+ "America/Metlakatla",
+ "America/Mexico_City",
+ "America/Miquelon",
+ "America/Moncton",
+ "America/Monterrey",
+ "America/Montevideo",
+ "America/Montreal",
+ "America/Montserrat",
+ "America/Nassau",
+ "America/New_York",
+ "America/Nipigon",
+ "America/Nome",
+ "America/Noronha",
+ "America/North_Dakota/Beulah",
+ "America/North_Dakota/Center",
+ "America/North_Dakota/New_Salem",
+ "America/Nuuk",
+ "America/Ojinaga",
+ "America/Panama",
+ "America/Pangnirtung",
+ "America/Paramaribo",
+ "America/Phoenix",
+ "America/Port-au-Prince",
+ "America/Port_of_Spain",
+ "America/Porto_Velho",
+ "America/Puerto_Rico",
+ "America/Punta_Arenas",
+ "America/Rainy_River",
+ "America/Rankin_Inlet",
+ "America/Recife",
+ "America/Regina",
+ "America/Resolute",
+ "America/Rio_Branco",
+ "America/Rosario",
+ "America/Santarem",
+ "America/Santiago",
+ "America/Santo_Domingo",
+ "America/Sao_Paulo",
+ "America/Scoresbysund",
+ "America/Sitka",
+ "America/St_Johns",
+ "America/St_Kitts",
+ "America/St_Lucia",
+ "America/St_Thomas",
+ "America/St_Vincent",
+ "America/Swift_Current",
+ "America/Tegucigalpa",
+ "America/Thule",
+ "America/Thunder_Bay",
+ "America/Tijuana",
+ "America/Toronto",
+ "America/Tortola",
+ "America/Vancouver",
+ "America/Whitehorse",
+ "America/Winnipeg",
+ "America/Yakutat",
+ "America/Yellowknife",
+ "Antarctica/Casey",
+ "Antarctica/Davis",
+ "Antarctica/DumontDUrville",
+ "Antarctica/Macquarie",
+ "Antarctica/Mawson",
+ "Antarctica/McMurdo",
+ "Antarctica/Palmer",
+ "Antarctica/Rothera",
+ "Antarctica/Syowa",
+ "Antarctica/Troll",
+ "Antarctica/Vostok",
+ "Asia/Aden",
+ "Asia/Almaty",
+ "Asia/Amman",
+ "Asia/Anadyr",
+ "Asia/Aqtau",
+ "Asia/Aqtobe",
+ "Asia/Ashgabat",
+ "Asia/Atyrau",
+ "Asia/Baghdad",
+ "Asia/Bahrain",
+ "Asia/Baku",
+ "Asia/Bangkok",
+ "Asia/Barnaul",
+ "Asia/Beirut",
+ "Asia/Bishkek",
+ "Asia/Brunei",
+ "Asia/Chita",
+ "Asia/Choibalsan",
+ "Asia/Chongqing",
+ "Asia/Colombo",
+ "Asia/Damascus",
+ "Asia/Dhaka",
+ "Asia/Dili",
+ "Asia/Dubai",
+ "Asia/Dushanbe",
+ "Asia/Famagusta",
+ "Asia/Gaza",
+ "Asia/Harbin",
+ "Asia/Hebron",
+ "Asia/Ho_Chi_Minh",
+ "Asia/Hong_Kong",
+ "Asia/Hovd",
+ "Asia/Irkutsk",
+ "Asia/Jakarta",
+ "Asia/Jayapura",
+ "Asia/Jerusalem",
+ "Asia/Kabul",
+ "Asia/Kamchatka",
+ "Asia/Karachi",
+ "Asia/Kashgar",
+ "Asia/Kathmandu",
+ "Asia/Khandyga",
+ "Asia/Kolkata",
+ "Asia/Krasnoyarsk",
+ "Asia/Kuala_Lumpur",
+ "Asia/Kuching",
+ "Asia/Kuwait",
+ "Asia/Macau",
+ "Asia/Magadan",
+ "Asia/Makassar",
+ "Asia/Manila",
+ "Asia/Muscat",
+ "Asia/Nicosia",
+ "Asia/Novokuznetsk",
+ "Asia/Novosibirsk",
+ "Asia/Omsk",
+ "Asia/Oral",
+ "Asia/Phnom_Penh",
+ "Asia/Pontianak",
+ "Asia/Pyongyang",
+ "Asia/Qatar",
+ "Asia/Qostanay",
+ "Asia/Qyzylorda",
+ "Asia/Riyadh",
+ "Asia/Sakhalin",
+ "Asia/Samarkand",
+ "Asia/Seoul",
+ "Asia/Shanghai",
+ "Asia/Singapore",
+ "Asia/Srednekolymsk",
+ "Asia/Taipei",
+ "Asia/Tashkent",
+ "Asia/Tbilisi",
+ "Asia/Tehran",
+ "Asia/Tel_Aviv",
+ "Asia/Thimphu",
+ "Asia/Tokyo",
+ "Asia/Tomsk",
+ "Asia/Ulaanbaatar",
+ "Asia/Urumqi",
+ "Asia/Ust-Nera",
+ "Asia/Vientiane",
+ "Asia/Vladivostok",
+ "Asia/Yakutsk",
+ "Asia/Yangon",
+ "Asia/Yekaterinburg",
+ "Asia/Yerevan",
+ "Atlantic/Azores",
+ "Atlantic/Bermuda",
+ "Atlantic/Canary",
+ "Atlantic/Cape_Verde",
+ "Atlantic/Faroe",
+ "Atlantic/Jan_Mayen",
+ "Atlantic/Madeira",
+ "Atlantic/Reykjavik",
+ "Atlantic/South_Georgia",
+ "Atlantic/St_Helena",
+ "Atlantic/Stanley",
+ "Australia/Adelaide",
+ "Australia/Brisbane",
+ "Australia/Broken_Hill",
+ "Australia/Currie",
+ "Australia/Darwin",
+ "Australia/Eucla",
+ "Australia/Hobart",
+ "Australia/Lindeman",
+ "Australia/Lord_Howe",
+ "Australia/Melbourne",
+ "Australia/Perth",
+ "Australia/Sydney",
+ "CET",
+ "CST6CDT",
+ "EET",
+ "EST",
+ "EST5EDT",
+ "Etc/GMT+1",
+ "Etc/GMT+10",
+ "Etc/GMT+11",
+ "Etc/GMT+12",
+ "Etc/GMT+2",
+ "Etc/GMT+3",
+ "Etc/GMT+4",
+ "Etc/GMT+5",
+ "Etc/GMT+6",
+ "Etc/GMT+7",
+ "Etc/GMT+8",
+ "Etc/GMT+9",
+ "Etc/GMT-1",
+ "Etc/GMT-10",
+ "Etc/GMT-11",
+ "Etc/GMT-12",
+ "Etc/GMT-13",
+ "Etc/GMT-14",
+ "Etc/GMT-2",
+ "Etc/GMT-3",
+ "Etc/GMT-4",
+ "Etc/GMT-5",
+ "Etc/GMT-6",
+ "Etc/GMT-7",
+ "Etc/GMT-8",
+ "Etc/GMT-9",
+ "Europe/Amsterdam",
+ "Europe/Andorra",
+ "Europe/Astrakhan",
+ "Europe/Athens",
+ "Europe/Belfast",
+ "Europe/Belgrade",
+ "Europe/Berlin",
+ "Europe/Brussels",
+ "Europe/Bucharest",
+ "Europe/Budapest",
+ "Europe/Chisinau",
+ "Europe/Copenhagen",
+ "Europe/Dublin",
+ "Europe/Gibraltar",
+ "Europe/Guernsey",
+ "Europe/Helsinki",
+ "Europe/Isle_of_Man",
+ "Europe/Istanbul",
+ "Europe/Jersey",
+ "Europe/Kaliningrad",
+ "Europe/Kirov",
+ "Europe/Kyiv",
+ "Europe/Lisbon",
+ "Europe/Ljubljana",
+ "Europe/London",
+ "Europe/Luxembourg",
+ "Europe/Madrid",
+ "Europe/Malta",
+ "Europe/Minsk",
+ "Europe/Monaco",
+ "Europe/Moscow",
+ "Europe/Oslo",
+ "Europe/Paris",
+ "Europe/Prague",
+ "Europe/Riga",
+ "Europe/Rome",
+ "Europe/Samara",
+ "Europe/Sarajevo",
+ "Europe/Saratov",
+ "Europe/Simferopol",
+ "Europe/Skopje",
+ "Europe/Sofia",
+ "Europe/Stockholm",
+ "Europe/Tallinn",
+ "Europe/Tirane",
+ "Europe/Tiraspol",
+ "Europe/Ulyanovsk",
+ "Europe/Uzhgorod",
+ "Europe/Vaduz",
+ "Europe/Vienna",
+ "Europe/Vilnius",
+ "Europe/Volgograd",
+ "Europe/Warsaw",
+ "Europe/Zagreb",
+ "Europe/Zaporozhye",
+ "Europe/Zurich",
+ "Factory",
+ "HST",
+ "Indian/Antananarivo",
+ "Indian/Chagos",
+ "Indian/Christmas",
+ "Indian/Cocos",
+ "Indian/Comoro",
+ "Indian/Kerguelen",
+ "Indian/Mahe",
+ "Indian/Maldives",
+ "Indian/Mauritius",
+ "Indian/Mayotte",
+ "Indian/Reunion",
+ "MET",
+ "MST",
+ "MST7MDT",
+ "PST8PDT",
+ "Pacific/Apia",
+ "Pacific/Auckland",
+ "Pacific/Bougainville",
+ "Pacific/Chatham",
+ "Pacific/Chuuk",
+ "Pacific/Easter",
+ "Pacific/Efate",
+ "Pacific/Enderbury",
+ "Pacific/Fakaofo",
+ "Pacific/Fiji",
+ "Pacific/Funafuti",
+ "Pacific/Galapagos",
+ "Pacific/Gambier",
+ "Pacific/Guadalcanal",
+ "Pacific/Guam",
+ "Pacific/Honolulu",
+ "Pacific/Johnston",
+ "Pacific/Kanton",
+ "Pacific/Kiritimati",
+ "Pacific/Kosrae",
+ "Pacific/Kwajalein",
+ "Pacific/Majuro",
+ "Pacific/Marquesas",
+ "Pacific/Midway",
+ "Pacific/Nauru",
+ "Pacific/Niue",
+ "Pacific/Norfolk",
+ "Pacific/Noumea",
+ "Pacific/Pago_Pago",
+ "Pacific/Palau",
+ "Pacific/Pitcairn",
+ "Pacific/Pohnpei",
+ "Pacific/Port_Moresby",
+ "Pacific/Rarotonga",
+ "Pacific/Saipan",
+ "Pacific/Tahiti",
+ "Pacific/Tarawa",
+ "Pacific/Tongatapu",
+ "Pacific/Wake",
+ "Pacific/Wallis",
+ "UTC",
+ "WET",
+];
+
+let supported = Intl.supportedValuesOf("timeZone");
+
+assertEqArray(supported, zones);
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0, "ok");
+
diff --git a/js/src/tests/non262/Intl/supportedValuesOf-timeZones.js b/js/src/tests/non262/Intl/supportedValuesOf-timeZones.js
new file mode 100644
index 0000000000..6a200cd199
--- /dev/null
+++ b/js/src/tests/non262/Intl/supportedValuesOf-timeZones.js
@@ -0,0 +1,20 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const timeZones = Intl.supportedValuesOf("timeZone");
+
+assertEq(new Set(timeZones).size, timeZones.length, "No duplicates are present");
+assertEqArray(timeZones, [...timeZones].sort(), "The list is sorted");
+
+// The pattern doesn't cover the complete time zone syntax, but gives a good first approximation.
+const timeZoneRE = /^[a-z0-9_+-]+(\/[a-z0-9_+-]+)*$/i;
+for (let timeZone of timeZones) {
+ assertEq(timeZoneRE.test(timeZone), true, `${timeZone} is ASCII`);
+}
+
+for (let timeZone of timeZones) {
+ let obj = new Intl.DateTimeFormat("en", {timeZone});
+ assertEq(obj.resolvedOptions().timeZone, timeZone, `${timeZone} is supported by DateTimeFormat`);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/supportedValuesOf-unit.js b/js/src/tests/non262/Intl/supportedValuesOf-unit.js
new file mode 100644
index 0000000000..01dc5bb05c
--- /dev/null
+++ b/js/src/tests/non262/Intl/supportedValuesOf-unit.js
@@ -0,0 +1,20 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const units = Intl.supportedValuesOf("unit");
+
+assertEq(new Set(units).size, units.length, "No duplicates are present");
+assertEqArray(units, [...units].sort(), "The list is sorted");
+
+const unitRE = /^[a-z]+(-[a-z]+)*$/;
+for (let unit of units) {
+ assertEq(unitRE.test(unit), true, `${unit} is ASCII lower-case, separated by hyphens`);
+ assertEq(unit.includes("-per-"), false, `${unit} is a simple unit identifier`);
+}
+
+for (let unit of units) {
+ let obj = new Intl.NumberFormat("en", {style: "unit", unit});
+ assertEq(obj.resolvedOptions().unit, unit, `${unit} is supported by NumberFormat`);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/tolower-ascii-equivalent.js b/js/src/tests/non262/Intl/tolower-ascii-equivalent.js
new file mode 100644
index 0000000000..ac3cbfb7d3
--- /dev/null
+++ b/js/src/tests/non262/Intl/tolower-ascii-equivalent.js
@@ -0,0 +1,47 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Language tags are processed case-insensitive, but unconditionally calling
+// the built-in String.prototype.toLowerCase() or toUpperCase() function
+// before parsing a language tag can map non-ASCII characters into the ASCII
+// range.
+//
+// Validate the Unicode BCP 47 locale identifier parser handles this case
+// (pun intended) correctly by passing language tags which contain
+// U+212A (KELVIN SIGN) and U+0131 (LATIN SMALL LETTER DOTLESS I) to
+// Intl.getCanonicalLocales().
+
+// The lower-case form of "i-ha\u212A" is "i-hak".
+assertEq("i-hak", "i-ha\u212A".toLowerCase());
+
+// The upper-case form of "\u0131-hak" is "I-HAK".
+assertEq("I-HAK", "\u0131-hak".toUpperCase());
+
+// "i-hak" is not a valid Unicode BCP 47 locale identifier.
+assertThrowsInstanceOf(() => Intl.getCanonicalLocales("i-hak"), RangeError);
+
+// And neither is "i-ha\u212A".
+assertThrowsInstanceOf(() => Intl.getCanonicalLocales("i-ha\u212A"), RangeError);
+
+// And also "\u0131-hak" isn't valid.
+assertThrowsInstanceOf(() => Intl.getCanonicalLocales("\u0131-hak"), RangeError);
+
+// The lower-case form of "zh-ha\u212A\u212Aa" is "zh-hakka".
+assertEq("zh-hakka", "zh-ha\u212A\u212Aa".toLowerCase());
+
+// "zh-hakka" is a valid Unicode BCP 47 locale identifier.
+assertEqArray(Intl.getCanonicalLocales("zh-hakka"), ["hak"]);
+
+// But "zh-ha\u212A\u212Aa" is not a valid locale identifier.
+assertThrowsInstanceOf(() => Intl.getCanonicalLocales("zh-ha\u212A\u212Aa"), RangeError);
+
+// The lower-case form of "zh-x\u0131ang" is "ZH-XIANG".
+assertEq("ZH-XIANG", "zh-x\u0131ang".toUpperCase());
+
+// "zh-xiang" is a valid Unicode BCP 47 locale identifier.
+assertEqArray(Intl.getCanonicalLocales("zh-xiang"), ["hsn"]);
+
+// But "zh-x\u0131ang" is not a valid locale identifier.
+assertThrowsInstanceOf(() => Intl.getCanonicalLocales("zh-x\u0131ang"), RangeError);
+
+if (typeof reportCompare === 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-extlangs.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-extlangs.js
new file mode 100644
index 0000000000..7e9aae5519
--- /dev/null
+++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-extlangs.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Unicode BCP 47 locale identifiers don't support extlang subtags.
+const invalid = [
+ // Two letter language code followed by extlang subtags.
+ "en-abc",
+ "en-abc-def",
+ "en-abc-def-ghi",
+
+ // Three letter language code followed by extlang subtags.
+ "und-abc",
+ "und-abc-def",
+ "und-abc-def-ghi",
+];
+
+for (let locale of invalid) {
+ assertThrowsInstanceOf(() => Intl.getCanonicalLocales(locale), RangeError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-language-mappings.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-language-mappings.js
new file mode 100644
index 0000000000..4f0a01a9cb
--- /dev/null
+++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-language-mappings.js
@@ -0,0 +1,39 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// For the most part the mappings from IANA are a subset of the CLDR mappings.
+// So there are mappings which are consistent across both databases.
+assertEq(Intl.getCanonicalLocales("iw")[0], "he");
+
+// But some languages are mapped differently.
+//
+// From the IANA language data registry:
+// Type: language
+// Subtag: drh
+// Description: Darkhat
+// Added: 2009-07-29
+// Deprecated: 2010-03-11
+// Preferred-Value: khk
+//
+// From CLDR:
+// <languageAlias type="drh" replacement="mn" reason="deprecated"/>
+//
+// because CLDR also maps macro-languages:
+// <languageAlias type="khk" replacement="mn" reason="macrolanguage"/>
+assertEq(Intl.getCanonicalLocales("drh")[0], "mn");
+
+// CLDR maps macro-languages:
+// <languageAlias type="cmn" replacement="zh" reason="macrolanguage"/>
+assertEq(Intl.getCanonicalLocales("cmn")[0], "zh");
+
+// CLDR also contains mappings from ISO-639-2 (B/T) to 639-1 codes:
+// <languageAlias type="dut" replacement="nl" reason="bibliographic"/>
+// <languageAlias type="nld" replacement="nl" reason="overlong"/>
+assertEq(Intl.getCanonicalLocales("dut")[0], "nl");
+assertEq(Intl.getCanonicalLocales("nld")[0], "nl");
+
+// CLDR has additional mappings for legacy language codes.
+// <languageAlias type="tl" replacement="fil" reason="legacy"/>
+assertEq(Intl.getCanonicalLocales("tl")[0], "fil");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-languages-mappings-complex.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-languages-mappings-complex.js
new file mode 100644
index 0000000000..320e1b02c0
--- /dev/null
+++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-languages-mappings-complex.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// CLDR contains language mappings where in addition to the language subtag also
+// the script or region subtag is modified, unless they're already present.
+
+// <languageAlias type="sh" replacement="sr_Latn" reason="legacy"/>
+assertEq(Intl.getCanonicalLocales("sh")[0], "sr-Latn");
+assertEq(Intl.getCanonicalLocales("sh-RS")[0], "sr-Latn-RS");
+assertEq(Intl.getCanonicalLocales("sh-Cyrl")[0], "sr-Cyrl");
+
+// <languageAlias type="cnr" replacement="sr_ME" reason="legacy"/>
+assertEq(Intl.getCanonicalLocales("cnr")[0], "sr-ME");
+assertEq(Intl.getCanonicalLocales("cnr-Latn")[0], "sr-Latn-ME");
+assertEq(Intl.getCanonicalLocales("cnr-RS")[0], "sr-RS");
+
+// Aliases where more than just a language subtag are present are ignored.
+// <languageAlias type="sr_RS" replacement="sr_Cyrl_RS" reason="legacy"/>
+assertEq(Intl.getCanonicalLocales("sr-RS")[0], "sr-RS");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-legacy.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-legacy.js
new file mode 100644
index 0000000000..b7eefe2b75
--- /dev/null
+++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-legacy.js
@@ -0,0 +1,52 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Unicode BCP 47 locale identifiers don't support irregular legacy tags.
+var irregularLegacy = [
+ "en-gb-oed",
+ "i-ami",
+ "i-bnn",
+ "i-default",
+ "i-enochian",
+ "i-hak",
+ "i-klingon",
+ "i-lux",
+ "i-mingo",
+ "i-navajo",
+ "i-pwn",
+ "i-tao",
+ "i-tay",
+ "i-tsu",
+ "sgn-be-fr",
+ "sgn-be-nl",
+ "sgn-ch-de",
+];
+
+// Unicode BCP 47 locale identifiers don't support regular legacy tags
+// which contain an extlang-like subtag.
+var regularLegacyWithExtlangLike = [
+ "no-bok",
+ "no-nyn",
+ "zh-min",
+ "zh-min-nan",
+];
+
+// Unicode BCP 47 locale identifiers do support regular legacy tags
+// which contain a variant-like subtag.
+var regularLegacyWithVariantLike = {
+ "art-lojban": "jbo",
+ "cel-gaulish": "xtg",
+ "zh-guoyu": "zh",
+ "zh-hakka": "hak",
+ "zh-xiang": "hsn",
+};
+
+for (let locale of [...irregularLegacy, ...regularLegacyWithExtlangLike]) {
+ assertThrowsInstanceOf(() => Intl.getCanonicalLocales(locale), RangeError);
+}
+
+for (let [locale, canonical] of Object.entries(regularLegacyWithVariantLike)) {
+ assertEq(Intl.getCanonicalLocales(locale)[0], canonical);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-and-subdivision.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-and-subdivision.js
new file mode 100644
index 0000000000..c9e1bd3951
--- /dev/null
+++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-and-subdivision.js
@@ -0,0 +1,12 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// <subdivisionAlias type="frg" replacement="frges" reason="deprecated"/>
+assertEq(Intl.getCanonicalLocales("fr-u-rg-frg")[0], "fr-u-rg-frges");
+assertEq(Intl.getCanonicalLocales("fr-u-sd-frg")[0], "fr-u-sd-frges");
+
+// <subdivisionAlias type="frgf" replacement="GF" reason="overlong"/>
+assertEq(Intl.getCanonicalLocales("fr-u-rg-frgf")[0], "fr-u-rg-gfzzzz");
+assertEq(Intl.getCanonicalLocales("fr-u-sd-frgf")[0], "fr-u-sd-gfzzzz");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-mappings-complex.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-mappings-complex.js
new file mode 100644
index 0000000000..22dbd17a1d
--- /dev/null
+++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-mappings-complex.js
@@ -0,0 +1,57 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// CLDR contains region mappings where the replacement region depends on the
+// likely subtags from the language and script subtags.
+//
+// For example, the breakup of the Soviet Union ("SU") means that the region of
+// the Soviet Union ("SU") is replaced by Russia ("RU"), Armenia ("AM"), or
+// many others -- depending on the specified (or merely likely) language and
+// script subtags:
+//
+// <territoryAlias type="SU" replacement="RU AM AZ BY EE GE KZ KG LV LT MD TJ TM UA UZ" reason="deprecated"/>
+//
+// Armenia can be the preferred region when the language is "hy" (Armenian) or
+// the script is "Armn" (Armenian).
+//
+// <likelySubtag from="hy" to="hy_Armn_AM"/>
+// <likelySubtag from="und_Armn" to="hy_Armn_AM"/>
+assertEq(Intl.getCanonicalLocales("ru-SU")[0], "ru-RU");
+assertEq(Intl.getCanonicalLocales("en-SU")[0], "en-RU");
+assertEq(Intl.getCanonicalLocales("und-SU")[0], "und-RU");
+assertEq(Intl.getCanonicalLocales("und-Latn-SU")[0], "und-Latn-RU");
+assertEq(Intl.getCanonicalLocales("hy-SU")[0], "hy-AM");
+assertEq(Intl.getCanonicalLocales("und-Armn-SU")[0], "und-Armn-AM");
+
+// <territoryAlias type="CS" replacement="RS ME" reason="deprecated"/>
+//
+// The following likely-subtags entries contain "RS" and "ME":
+//
+// <likelySubtag from="sr" to="sr_Cyrl_RS"/>
+// <likelySubtag from="sr_ME" to="sr_Latn_ME"/>
+// <likelySubtag from="und_RS" to="sr_Cyrl_RS"/>
+// <likelySubtag from="und_ME" to="sr_Latn_ME"/>
+//
+// In this case there is no language/script combination (without a region
+// subtag) where "ME" is ever chosen, so the replacement is always "RS".
+assertEq(Intl.getCanonicalLocales("sr-CS")[0], "sr-RS");
+assertEq(Intl.getCanonicalLocales("sr-Latn-CS")[0], "sr-Latn-RS");
+assertEq(Intl.getCanonicalLocales("sr-Cyrl-CS")[0], "sr-Cyrl-RS");
+
+// The existing region in the source locale identifier is ignored when selecting
+// the likely replacement region. For example take "az-NT", which is Azerbaijani
+// spoken in the Neutral Zone. The replacement region for "NT" is either
+// "SA" (Saudi-Arabia) or "IQ" (Iraq), and there is also a likely subtags entry
+// for "az-IQ". But when only looking at the language subtag in "az-NT", "az" is
+// always resolved to "az-Latn-AZ", and because "AZ" is not in the list ["SA",
+// "IQ"], the final replacement region is the default for "NT", namely "SA".
+// That means "az-NT" will be canonicalised to "az-SA" and not "az-IQ", even
+// though the latter may be a more sensible candidate based on the actual usage
+// of the target locales.
+//
+// <territoryAlias type="NT" replacement="SA IQ" reason="deprecated"/>
+// <likelySubtag from="az_IQ" to="az_Arab_IQ"/>
+// <likelySubtag from="az" to="az_Latn_AZ"/>
+assertEq(Intl.getCanonicalLocales("az-NT")[0], "az-SA");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-mappings.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-mappings.js
new file mode 100644
index 0000000000..affebb33b8
--- /dev/null
+++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-mappings.js
@@ -0,0 +1,22 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// For the most part the mappings from IANA are a subset of the CLDR mappings.
+// So there are mappings which are consistent across both databases.
+assertEq(Intl.getCanonicalLocales("de-DD")[0], "de-DE");
+
+// CLDR contains additional mappings:
+// <territoryAlias type="QU" replacement="EU" reason="deprecated"/>
+// <territoryAlias type="UK" replacement="GB" reason="deprecated"/>
+assertEq(Intl.getCanonicalLocales("und-QU")[0], "und-EU");
+assertEq(Intl.getCanonicalLocales("en-UK")[0], "en-GB");
+
+// CLDR additional maps ISO 3166-1 numeric to ISO 3166-1 alpha-2 codes:
+// <territoryAlias type="280" replacement="DE" reason="deprecated"/>
+// <territoryAlias type="278" replacement="DE" reason="overlong"/>
+// <territoryAlias type="276" replacement="DE" reason="overlong"/>
+assertEq(Intl.getCanonicalLocales("de-280")[0], "de-DE");
+assertEq(Intl.getCanonicalLocales("de-278")[0], "de-DE");
+assertEq(Intl.getCanonicalLocales("de-276")[0], "de-DE");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-sign-languages.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-sign-languages.js
new file mode 100644
index 0000000000..9f7b01c69e
--- /dev/null
+++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-sign-languages.js
@@ -0,0 +1,23 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// The IANA language subtag registry contains replacements for sign language
+// codes marked as redundant. For example:
+//
+// Type: redundant
+// Tag: sgn-DE
+// Description: German Sign Language
+// Added: 2001-11-11
+// Deprecated: 2009-07-29
+// Preferred-Value: gsg
+//
+// CLDR 38 added these mappings to CLDR, too.
+
+assertEq(Intl.getCanonicalLocales("sgn-DE")[0], "gsg");
+assertEq(Intl.getCanonicalLocales("sgn-DD")[0], "gsg");
+
+assertEq(Intl.getCanonicalLocales("sgn-276")[0], "gsg");
+assertEq(Intl.getCanonicalLocales("sgn-278")[0], "gsg");
+assertEq(Intl.getCanonicalLocales("sgn-280")[0], "gsg");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-transformed-ext.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-transformed-ext.js
new file mode 100644
index 0000000000..50ac20e58b
--- /dev/null
+++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-transformed-ext.js
@@ -0,0 +1,71 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+const invalid = [
+ // empty
+ "en-t",
+ "en-t-a",
+ "en-t-x",
+ "en-t-0",
+
+ // incomplete
+ "en-t-",
+ "en-t-en-",
+ "en-t-0x-",
+
+ // tlang: unicode_language_subtag must be 2-3 or 5-8 characters and mustn't
+ // contain extlang subtags.
+ "en-t-root",
+ "en-t-abcdefghi",
+ "en-t-ar-aao",
+
+ // tlang: unicode_script_subtag must be 4 alphabetical characters, can't
+ // be repeated.
+ "en-t-en-lat0",
+ "en-t-en-latn-latn",
+
+ // tlang: unicode_region_subtag must either be 2 alpha characters or a three
+ // digit code.
+ "en-t-en-0",
+ "en-t-en-00",
+ "en-t-en-0x",
+ "en-t-en-x0",
+ "en-t-en-latn-0",
+ "en-t-en-latn-00",
+ "en-t-en-latn-xyz",
+
+ // tlang: unicode_variant_subtag is either 5-8 alphanum characters or 4
+ // characters starting with a digit.
+ "en-t-en-abcdefghi",
+ "en-t-en-latn-gb-ab",
+ "en-t-en-latn-gb-abc",
+ "en-t-en-latn-gb-abcd",
+ "en-t-en-latn-gb-abcdefghi",
+];
+
+// Canonicalisation also applies for the transformation extension. But also
+// see <https://github.com/tc39/ecma402/issues/330>.
+const valid = [
+ {locale: "en-t-en", canonical: "en-t-en"},
+ {locale: "en-t-en-latn", canonical: "en-t-en-latn"},
+ {locale: "en-t-en-ca", canonical: "en-t-en-ca"},
+ {locale: "en-t-en-latn-ca", canonical: "en-t-en-latn-ca"},
+ {locale: "en-t-en-emodeng", canonical: "en-t-en-emodeng"},
+ {locale: "en-t-en-latn-emodeng", canonical: "en-t-en-latn-emodeng"},
+ {locale: "en-t-en-latn-ca-emodeng", canonical: "en-t-en-latn-ca-emodeng"},
+ {locale: "sl-t-sl-rozaj-biske-1994", canonical: "sl-t-sl-1994-biske-rozaj"},
+ {locale: "DE-T-M0-DIN-K0-QWERTZ", canonical: "de-t-k0-qwertz-m0-din"},
+ {locale: "en-t-m0-true", canonical: "en-t-m0-true"},
+ {locale: "en-t-iw", canonical: "en-t-he"},
+ {locale: "und-Latn-t-und-hani-m0-names", canonical: "und-Latn-t-und-hani-m0-prprname"},
+];
+
+for (let locale of invalid) {
+ assertThrowsInstanceOf(() => Intl.getCanonicalLocales(locale), RangeError);
+}
+
+for (let {locale, canonical} of valid) {
+ assertEq(Intl.getCanonicalLocales(locale)[0], canonical);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-unicode-ext.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-unicode-ext.js
new file mode 100644
index 0000000000..a46eba475e
--- /dev/null
+++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-unicode-ext.js
@@ -0,0 +1,12 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Unicode locale extension sequences don't allow keys with a digit as their
+// second character.
+assertThrowsInstanceOf(() => Intl.getCanonicalLocales("en-u-c0"), RangeError);
+assertThrowsInstanceOf(() => Intl.getCanonicalLocales("en-u-00"), RangeError);
+
+// The first character is allowed to be a digit.
+assertEq(Intl.getCanonicalLocales("en-u-0c")[0], "en-u-0c");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-variants-legacy-mappings.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-variants-legacy-mappings.js
new file mode 100644
index 0000000000..41b2a9a5cb
--- /dev/null
+++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-variants-legacy-mappings.js
@@ -0,0 +1,47 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// ECMA-402 includes mapping of legacy variants, as long as they're also present
+// in <variantAlias> in CLDR's supplementalMetadata.xml
+// <https://www.unicode.org/reports/tr35/#Legacy_Variants>
+
+assertEq(Intl.getCanonicalLocales("sv-AALAND")[0], "sv-AX");
+assertEq(Intl.getCanonicalLocales("no-BOKMAL")[0], "nb");
+assertEq(Intl.getCanonicalLocales("no-NYNORSK")[0], "nn");
+assertEq(Intl.getCanonicalLocales("en-POSIX")[0], "en-posix");
+assertEq(Intl.getCanonicalLocales("el-POLYTONI")[0], "el-polyton");
+assertEq(Intl.getCanonicalLocales("aa-SAAHO")[0], "ssy");
+
+// Additional cases from CLDR, version 38.
+
+assertEq(Intl.getCanonicalLocales("aar-saaho")[0], "ssy");
+assertEq(Intl.getCanonicalLocales("arm-arevmda")[0], "hyw");
+assertEq(Intl.getCanonicalLocales("hy-arevmda")[0], "hyw");
+assertEq(Intl.getCanonicalLocales("hye-arevmda")[0], "hyw");
+
+for (let language of ["chi", "cmn", "zh", "zho"]) {
+ assertEq(Intl.getCanonicalLocales(language)[0], "zh");
+
+ let mapping = {
+ "guoyu-hakka": "hak",
+ "guoyu-xiang": "hsn",
+ "guoyu": "zh",
+ "hakka": "hak",
+ "xiang": "hsn",
+ };
+ for (let [variant, canonical] of Object.entries(mapping)) {
+ assertEq(Intl.getCanonicalLocales(`${language}-${variant}`)[0], canonical);
+ }
+}
+
+// Most legacy variant subtags are simply removed in contexts they don't apply.
+for (let variant of ["arevela", "arevmda", "bokmal", "hakka", "lojban", "nynorsk", "saaho", "xiang"]) {
+ assertEq(Intl.getCanonicalLocales(`en-${variant}`)[0], "en");
+}
+
+// Except these three, whose replacement is always applied.
+assertEq(Intl.getCanonicalLocales("en-aaland")[0], "en-AX");
+assertEq(Intl.getCanonicalLocales("en-heploc")[0], "en-alalc97");
+assertEq(Intl.getCanonicalLocales("en-polytoni")[0], "en-polyton");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-variants-sorted.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-variants-sorted.js
new file mode 100644
index 0000000000..e50436a83c
--- /dev/null
+++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-variants-sorted.js
@@ -0,0 +1,31 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// UTS 35, 3.2.1 Canonical Unicode Locale Identifiers:
+// - Any variants are in alphabetical order.
+
+assertEq(Intl.getCanonicalLocales("en-scouse-fonipa")[0], "en-fonipa-scouse");
+
+// Sorting in alphabetical order may turn a valid BCP 47 language tag into a
+// BCP 47 language tag which is only well-formed, but no longer valid. This
+// means there are potential compatibility issues when converting between
+// Unicode BCP 47 locale identifiers and BCP 47 language tags.
+//
+// Spec: https://tools.ietf.org/html/rfc5646#section-2.2.9
+
+// <https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry>
+//
+// Type: variant
+// Subtag: 1994
+// Description: Standardized Resian orthography
+// Added: 2007-07-28
+// Prefix: sl-rozaj
+// Prefix: sl-rozaj-biske
+// Prefix: sl-rozaj-njiva
+// Prefix: sl-rozaj-osojs
+// Prefix: sl-rozaj-solba
+// Comments: For standardized Resian an orthography was published in 1994.
+
+assertEq(Intl.getCanonicalLocales("sl-rozaj-biske-1994")[0], "sl-1994-biske-rozaj");
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
diff --git a/js/src/tests/non262/Intl/variant-with-preferred-value.js b/js/src/tests/non262/Intl/variant-with-preferred-value.js
new file mode 100644
index 0000000000..751649a750
--- /dev/null
+++ b/js/src/tests/non262/Intl/variant-with-preferred-value.js
@@ -0,0 +1,58 @@
+// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+
+// Per UTS 35, computing the canonical form for Unicode BCP 47 locale identifiers
+// includes replacing deprecated variant mappings. The other UTS 35 canonicalisation
+// algorithm ("BCP 47 Language Tag to Unicode BCP 47 Locale Identifier") doesn't
+// support deprecated variant mappings.
+// https://github.com/tc39/ecma402/issues/330
+
+const languageTags = {
+ // The preferred value of "hy-arevela" is "hy" per CLDR.
+ "hy-arevela": "hy",
+ "hy-Armn-arevela": "hy-Armn",
+ "hy-AM-arevela": "hy-AM",
+ "hy-arevela-fonipa": "hy-fonipa",
+ "hy-fonipa-arevela": "hy-fonipa",
+
+ // The preferred value of "hy-arevmda" is "hyw" per CLDR.
+ "hy-arevmda": "hyw",
+ "hy-Armn-arevmda": "hyw-Armn",
+ "hy-AM-arevmda": "hyw-AM",
+ "hy-arevmda-fonipa": "hyw-fonipa",
+ "hy-fonipa-arevmda": "hyw-fonipa",
+
+ // The preferred value of "ja-Latn-hepburn-heploc" is "ja-Latn-alalc97" per CLDR and
+ // IANA.
+ "ja-Latn-hepburn-heploc": "ja-Latn-alalc97",
+ "ja-Latn-JP-hepburn-heploc": "ja-Latn-JP-alalc97",
+
+ // Variant subtag replacements not present in IANA.
+ "sv-aaland": "sv-AX",
+ "el-polytoni": "el-polyton",
+
+ // Additional cases when more variant subtags are present.
+
+ // 1. The preferred variant is already present.
+ "ja-Latn-alalc97-hepburn-heploc": "ja-Latn-alalc97",
+ "ja-Latn-hepburn-alalc97-heploc": "ja-Latn-alalc97",
+ "ja-Latn-hepburn-heploc-alalc97": "ja-Latn-alalc97",
+
+ // 2. The variant subtags aren't in the expected order per IANA. (CLDR doesn't care
+ // about the order of variant subtags.)
+ "ja-Latn-heploc-hepburn": "ja-Latn-alalc97",
+
+ // 3. IANA expects both variant subtags to be present, CLDR also accepts single "heploc".
+ "ja-Latn-heploc": "ja-Latn-alalc97",
+
+ // 4. Test for cases when the same variant subtag position needs to be checked more
+ // than once when replacing deprecated variant subtags.
+ "ja-Latn-aaland-heploc": "ja-Latn-AX-alalc97",
+ "ja-Latn-heploc-polytoni": "ja-Latn-alalc97-polyton",
+};
+
+for (let [tag, canonical] of Object.entries(languageTags)) {
+ assertEq(Intl.getCanonicalLocales(tag)[0], canonical);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);