@formatjs/intl-getcanonicallocales 3.2.11 → 3.2.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/polyfill.js CHANGED
@@ -1,4 +1,251 @@
1
+ //#region packages/intl-getcanonicallocales/appendToList.ts
2
+ function appendToList(list, ...values) {
3
+ for (const value of values) Object.defineProperty(list, list.length, {
4
+ value,
5
+ writable: true,
6
+ enumerable: true,
7
+ configurable: true
8
+ });
9
+ }
10
+ //#endregion
11
+ //#region packages/ecma262-abstract/ToString.js
12
+ /**
13
+ * https://tc39.es/ecma262/#sec-tostring
14
+ */
15
+ function ToString(o) {
16
+ if (typeof o === "symbol") throw TypeError("Cannot convert a Symbol value to a string");
17
+ return String(o);
18
+ }
19
+ //#endregion
1
20
  //#region node_modules/.aspect_rules_js/@formatjs_generated+cldr.core@0.0.0/node_modules/@formatjs_generated/cldr.core/aliases.js
21
+ const subdivisionAlias = {
22
+ "cn11": "cnbj",
23
+ "cn12": "cntj",
24
+ "cn13": "cnhe",
25
+ "cn14": "cnsx",
26
+ "cn15": "cnmn",
27
+ "cn21": "cnln",
28
+ "cn22": "cnjl",
29
+ "cn23": "cnhl",
30
+ "cn31": "cnsh",
31
+ "cn32": "cnjs",
32
+ "cn33": "cnzj",
33
+ "cn34": "cnah",
34
+ "cn35": "cnfj",
35
+ "cn36": "cnjx",
36
+ "cn37": "cnsd",
37
+ "cn41": "cnha",
38
+ "cn42": "cnhb",
39
+ "cn43": "cnhn",
40
+ "cn44": "cngd",
41
+ "cn45": "cngx",
42
+ "cn46": "cnhi",
43
+ "cn50": "cncq",
44
+ "cn51": "cnsc",
45
+ "cn52": "cngz",
46
+ "cn53": "cnyn",
47
+ "cn54": "cnxz",
48
+ "cn61": "cnsn",
49
+ "cn62": "cngs",
50
+ "cn63": "cnqh",
51
+ "cn64": "cnnx",
52
+ "cn65": "cnxj",
53
+ "cn71": "twzzzz",
54
+ "cn91": "hkzzzz",
55
+ "cn92": "mozzzz",
56
+ "cz10a": "cz110",
57
+ "cz10b": "cz111",
58
+ "cz10c": "cz112",
59
+ "cz10d": "cz113",
60
+ "cz10e": "cz114",
61
+ "cz10f": "cz115",
62
+ "cz611": "cz663",
63
+ "cz612": "cz632",
64
+ "cz613": "cz633",
65
+ "cz614": "cz634",
66
+ "cz615": "cz635",
67
+ "cz621": "cz641",
68
+ "cz622": "cz642",
69
+ "cz623": "cz643",
70
+ "cz624": "cz644",
71
+ "cz626": "cz646",
72
+ "cz627": "cz647",
73
+ "czjc": "cz31",
74
+ "czjm": "cz64",
75
+ "czka": "cz41",
76
+ "czkr": "cz52",
77
+ "czli": "cz51",
78
+ "czmo": "cz80",
79
+ "czol": "cz71",
80
+ "czpa": "cz53",
81
+ "czpl": "cz32",
82
+ "czpr": "cz10",
83
+ "czst": "cz20",
84
+ "czus": "cz42",
85
+ "czvy": "cz63",
86
+ "czzl": "cz72",
87
+ "fi01": "axzzzz",
88
+ "fra": "frges",
89
+ "frb": "frnaq",
90
+ "frbl": "blzzzz",
91
+ "frc": "frara",
92
+ "frcp": "cpzzzz",
93
+ "frd": "frbfc",
94
+ "fre": "frbre",
95
+ "frf": "frcvl",
96
+ "frg": "frges",
97
+ "frgf": "gfzzzz",
98
+ "frgp": "gpzzzz",
99
+ "frgua": "gpzzzz",
100
+ "frh": "frcor",
101
+ "fri": "frbfc",
102
+ "frj": "fridf",
103
+ "frk": "frocc",
104
+ "frl": "frnaq",
105
+ "frlre": "rezzzz",
106
+ "frm": "frges",
107
+ "frmay": "ytzzzz",
108
+ "frmf": "mfzzzz",
109
+ "frmq": "mqzzzz",
110
+ "frn": "frocc",
111
+ "frnc": "nczzzz",
112
+ "fro": "frhdf",
113
+ "frp": "frnor",
114
+ "frpf": "pfzzzz",
115
+ "frpm": "pmzzzz",
116
+ "frq": "frnor",
117
+ "frr": "frpdl",
118
+ "frre": "rezzzz",
119
+ "frs": "frhdf",
120
+ "frt": "frnaq",
121
+ "frtf": "tfzzzz",
122
+ "fru": "frpac",
123
+ "frv": "frara",
124
+ "frwf": "wfzzzz",
125
+ "fryt": "ytzzzz",
126
+ "laxn": "laxs",
127
+ "lud": "lucl",
128
+ "lug": "luec",
129
+ "lul": "luca",
130
+ "mrnkc": "mr13",
131
+ "nlaw": "awzzzz",
132
+ "nlcw": "cwzzzz",
133
+ "nlsx": "sxzzzz",
134
+ "no23": "no50",
135
+ "nzn": "nzauk",
136
+ "nzs": "nzcan",
137
+ "omba": "ombj",
138
+ "omsh": "omsj",
139
+ "plds": "pl02",
140
+ "plkp": "pl04",
141
+ "pllb": "pl08",
142
+ "plld": "pl10",
143
+ "pllu": "pl06",
144
+ "plma": "pl12",
145
+ "plmz": "pl14",
146
+ "plop": "pl16",
147
+ "plpd": "pl20",
148
+ "plpk": "pl18",
149
+ "plpm": "pl22",
150
+ "plsk": "pl26",
151
+ "plsl": "pl24",
152
+ "plwn": "pl28",
153
+ "plwp": "pl30",
154
+ "plzp": "pl32",
155
+ "shta": "tazzzz",
156
+ "tteto": "tttob",
157
+ "ttrcm": "ttmrc",
158
+ "ttwto": "tttob",
159
+ "twkhq": "twkhh",
160
+ "twtnq": "twtnn",
161
+ "twtpq": "twnwt",
162
+ "twtxq": "twtxg",
163
+ "usas": "aszzzz",
164
+ "usgu": "guzzzz",
165
+ "usmp": "mpzzzz",
166
+ "uspr": "przzzz",
167
+ "usum": "umzzzz",
168
+ "usvi": "vizzzz"
169
+ };
170
+ const extensionAlias = {
171
+ "t": {
172
+ "d0": { "name": "charname" },
173
+ "m0": {
174
+ "beta-metsehaf": "betamets",
175
+ "ies-jes": "iesjes",
176
+ "names": "prprname",
177
+ "tekie-alibekit": "tekieali"
178
+ }
179
+ },
180
+ "u": {
181
+ "ca": {
182
+ "ethiopic-amete-alem": "ethioaa",
183
+ "islamicc": "islamic-civil"
184
+ },
185
+ "kb": { "yes": "true" },
186
+ "kc": { "yes": "true" },
187
+ "kh": { "yes": "true" },
188
+ "kk": { "yes": "true" },
189
+ "kn": { "yes": "true" },
190
+ "ks": {
191
+ "primary": "level1",
192
+ "tertiary": "level3"
193
+ },
194
+ "ms": { "imperial": "uksystem" },
195
+ "tz": {
196
+ "aqams": "aqmcm",
197
+ "aukns": "auhba",
198
+ "caffs": "cawnp",
199
+ "camtr": "cator",
200
+ "canpg": "cator",
201
+ "capnt": "caiql",
202
+ "cathu": "cator",
203
+ "cayzf": "caedm",
204
+ "cet": "bebru",
205
+ "cnckg": "cnsha",
206
+ "cnhrb": "cnsha",
207
+ "cnkhg": "cnurc",
208
+ "cst6cdt": "uschi",
209
+ "cuba": "cuhav",
210
+ "eet": "grath",
211
+ "egypt": "egcai",
212
+ "eire": "iedub",
213
+ "est": "papty",
214
+ "est5edt": "usnyc",
215
+ "factory": "unk",
216
+ "gaza": "gazastrp",
217
+ "gmt0": "gmt",
218
+ "hongkong": "hkhkg",
219
+ "hst": "ushnl",
220
+ "iceland": "isrey",
221
+ "iran": "irthr",
222
+ "israel": "jeruslm",
223
+ "jamaica": "jmkin",
224
+ "japan": "jptyo",
225
+ "libya": "lytip",
226
+ "met": "bebru",
227
+ "mncoq": "mnuln",
228
+ "mst": "usphx",
229
+ "mst7mdt": "usden",
230
+ "mxstis": "mxtij",
231
+ "navajo": "usden",
232
+ "poland": "plwaw",
233
+ "portugal": "ptlis",
234
+ "prc": "cnsha",
235
+ "pst8pdt": "uslax",
236
+ "roc": "twtpe",
237
+ "rok": "krsel",
238
+ "turkey": "trist",
239
+ "uaozh": "uaiev",
240
+ "uauzh": "uaiev",
241
+ "uct": "utc",
242
+ "umjon": "ushnl",
243
+ "usnavajo": "usden",
244
+ "wet": "ptlis",
245
+ "zulu": "utc"
246
+ }
247
+ }
248
+ };
2
249
  const languageAlias = {
3
250
  "aa-saaho": "ssy",
4
251
  "aam": "aas",
@@ -1162,17 +1409,15 @@ function emitUnicodeLanguageId(lang) {
1162
1409
  function emitUnicodeLocaleId({ lang, extensions }) {
1163
1410
  const chunks = [emitUnicodeLanguageId(lang)];
1164
1411
  for (const ext of extensions) {
1165
- chunks.push(ext.type);
1412
+ appendToList(chunks, ext.type);
1166
1413
  switch (ext.type) {
1167
1414
  case "u":
1168
- chunks.push(...ext.attributes, ...ext.keywords.reduce((all, kv) => all.concat(kv), []));
1415
+ appendToList(chunks, ...ext.attributes, ...ext.keywords.reduce((all, kv) => all.concat(kv), []));
1169
1416
  break;
1170
1417
  case "t":
1171
- chunks.push(emitUnicodeLanguageId(ext.lang), ...ext.fields.reduce((all, kv) => all.concat(kv), []));
1172
- break;
1173
- default:
1174
- chunks.push(ext.value);
1418
+ appendToList(chunks, emitUnicodeLanguageId(ext.lang).toLowerCase(), ...ext.fields.reduce((all, kv) => all.concat(kv), []));
1175
1419
  break;
1420
+ default: appendToList(chunks, ext.value);
1176
1421
  }
1177
1422
  }
1178
1423
  return chunks.filter(Boolean).join("-");
@@ -8971,28 +9216,41 @@ const likelySubtags = {
8971
9216
  };
8972
9217
  //#endregion
8973
9218
  //#region packages/intl-getcanonicallocales/parser.ts
8974
- const ALPHANUM_1_8 = /^[a-z0-9]{1,8}$/i;
8975
- const ALPHANUM_2_8 = /^[a-z0-9]{2,8}$/i;
8976
- const ALPHANUM_3_8 = /^[a-z0-9]{3,8}$/i;
8977
- const KEY_REGEX = /^[a-z0-9][a-z]$/i;
8978
- const TYPE_REGEX = /^[a-z0-9]{3,8}$/i;
8979
- const ALPHA_4 = /^[a-z]{4}$/i;
8980
- const OTHER_EXTENSION_TYPE = /^[0-9a-svwyz]$/i;
8981
- const UNICODE_REGION_SUBTAG_REGEX = /^([a-z]{2}|[0-9]{3})$/i;
8982
- const UNICODE_VARIANT_SUBTAG_REGEX = /^([a-z0-9]{5,8}|[0-9][a-z0-9]{3})$/i;
8983
- const UNICODE_LANGUAGE_SUBTAG_REGEX = /^([a-z]{2,3}|[a-z]{5,8})$/i;
8984
- const TKEY_REGEX = /^[a-z][0-9]$/i;
9219
+ function isLetter(code) {
9220
+ return code >= 65 && code <= 90 || code >= 97 && code <= 122;
9221
+ }
9222
+ function isDigit(code) {
9223
+ return code >= 48 && code <= 57;
9224
+ }
9225
+ function isSubtag(value, min, max, digits = false) {
9226
+ if (value.length < min || value.length > max) return false;
9227
+ for (let i = 0; i < value.length; i++) {
9228
+ const code = value.charCodeAt(i);
9229
+ if (!isLetter(code) && !(digits && isDigit(code))) return false;
9230
+ }
9231
+ return true;
9232
+ }
9233
+ function isUnicodeKey(value) {
9234
+ return value.length === 2 && isSubtag(value, 2, 2, true) && isLetter(value.charCodeAt(1));
9235
+ }
9236
+ function isTransformedKey(value) {
9237
+ return value.length === 2 && isLetter(value.charCodeAt(0)) && isDigit(value.charCodeAt(1));
9238
+ }
9239
+ function isOtherExtensionType(value) {
9240
+ const type = value.toLowerCase();
9241
+ return isSubtag(type, 1, 1, true) && type !== "t" && type !== "u" && type !== "x";
9242
+ }
8985
9243
  function isUnicodeLanguageSubtag(lang) {
8986
- return UNICODE_LANGUAGE_SUBTAG_REGEX.test(lang);
9244
+ return lang.length !== 4 && isSubtag(lang, 2, 8);
8987
9245
  }
8988
9246
  function isUnicodeRegionSubtag(region) {
8989
- return UNICODE_REGION_SUBTAG_REGEX.test(region);
9247
+ return isSubtag(region, 2, 2) || region.length === 3 && isDigit(region.charCodeAt(0)) && isDigit(region.charCodeAt(1)) && isDigit(region.charCodeAt(2));
8990
9248
  }
8991
9249
  function isUnicodeScriptSubtag(script) {
8992
- return ALPHA_4.test(script);
9250
+ return isSubtag(script, 4, 4);
8993
9251
  }
8994
9252
  function isUnicodeVariantSubtag(variant) {
8995
- return UNICODE_VARIANT_SUBTAG_REGEX.test(variant);
9253
+ return isSubtag(variant, 5, 8, true) || isSubtag(variant, 4, 4, true) && isDigit(variant.charCodeAt(0));
8996
9254
  }
8997
9255
  function parseUnicodeLanguageId(chunks) {
8998
9256
  if (typeof chunks === "string") chunks = chunks.split("-");
@@ -9023,15 +9281,15 @@ function parseUnicodeLanguageId(chunks) {
9023
9281
  function parseUnicodeExtension(chunks) {
9024
9282
  const keywords = [];
9025
9283
  let keyword;
9026
- while (chunks.length && (keyword = parseKeyword(chunks))) keywords.push(keyword);
9284
+ while (chunks.length && (keyword = parseKeyword(chunks))) appendToList(keywords, keyword);
9027
9285
  if (keywords.length) return {
9028
9286
  type: "u",
9029
9287
  keywords,
9030
9288
  attributes: []
9031
9289
  };
9032
9290
  const attributes = [];
9033
- while (chunks.length && ALPHANUM_3_8.test(chunks[0])) attributes.push(chunks.shift());
9034
- while (chunks.length && (keyword = parseKeyword(chunks))) keywords.push(keyword);
9291
+ while (chunks.length && isSubtag(chunks[0], 3, 8, true)) appendToList(attributes, chunks.shift());
9292
+ while (chunks.length && (keyword = parseKeyword(chunks))) appendToList(keywords, keyword);
9035
9293
  if (keywords.length || attributes.length) return {
9036
9294
  type: "u",
9037
9295
  attributes,
@@ -9041,28 +9299,26 @@ function parseUnicodeExtension(chunks) {
9041
9299
  }
9042
9300
  function parseKeyword(chunks) {
9043
9301
  let key;
9044
- if (!KEY_REGEX.test(chunks[0])) return;
9302
+ if (!isUnicodeKey(chunks[0])) return;
9045
9303
  key = chunks.shift();
9046
9304
  const type = [];
9047
- while (chunks.length && TYPE_REGEX.test(chunks[0])) type.push(chunks.shift());
9305
+ while (chunks.length && isSubtag(chunks[0], 3, 8, true)) appendToList(type, chunks.shift());
9048
9306
  let value = "";
9049
9307
  if (type.length) value = type.join("-");
9050
9308
  return [key, value];
9051
9309
  }
9052
9310
  function parseTransformedExtension(chunks) {
9053
9311
  let lang;
9054
- try {
9055
- lang = parseUnicodeLanguageId(chunks);
9056
- } catch {}
9312
+ if (chunks.length && isUnicodeLanguageSubtag(chunks[0])) lang = parseUnicodeLanguageId(chunks);
9057
9313
  const fields = [];
9058
- while (chunks.length && TKEY_REGEX.test(chunks[0])) {
9314
+ while (chunks.length && isTransformedKey(chunks[0])) {
9059
9315
  const key = chunks.shift();
9060
9316
  const value = [];
9061
- while (chunks.length && ALPHANUM_3_8.test(chunks[0])) value.push(chunks.shift());
9317
+ while (chunks.length && isSubtag(chunks[0], 3, 8, true)) appendToList(value, chunks.shift());
9062
9318
  if (!value.length) throw new RangeError(`Missing tvalue for tkey "${key}"`);
9063
- fields.push([key, value.join("-")]);
9319
+ appendToList(fields, [key, value.join("-")]);
9064
9320
  }
9065
- if (fields.length) return {
9321
+ if (lang || fields.length) return {
9066
9322
  type: "t",
9067
9323
  fields,
9068
9324
  lang
@@ -9071,7 +9327,7 @@ function parseTransformedExtension(chunks) {
9071
9327
  }
9072
9328
  function parsePuExtension(chunks) {
9073
9329
  const exts = [];
9074
- while (chunks.length && ALPHANUM_1_8.test(chunks[0])) exts.push(chunks.shift());
9330
+ while (chunks.length && isSubtag(chunks[0], 1, 8, true)) appendToList(exts, chunks.shift());
9075
9331
  if (exts.length) return {
9076
9332
  type: "x",
9077
9333
  value: exts.join("-")
@@ -9080,9 +9336,9 @@ function parsePuExtension(chunks) {
9080
9336
  }
9081
9337
  function parseOtherExtensionValue(chunks) {
9082
9338
  const exts = [];
9083
- while (chunks.length && ALPHANUM_2_8.test(chunks[0])) exts.push(chunks.shift());
9339
+ while (chunks.length && isSubtag(chunks[0], 2, 8, true)) appendToList(exts, chunks.shift());
9084
9340
  if (exts.length) return exts.join("-");
9085
- return "";
9341
+ throw new RangeError("Missing extension value");
9086
9342
  }
9087
9343
  function parseExtensions(chunks) {
9088
9344
  if (!chunks.length) return { extensions: [] };
@@ -9092,36 +9348,35 @@ function parseExtensions(chunks) {
9092
9348
  let puExtension;
9093
9349
  const otherExtensionMap = {};
9094
9350
  do {
9095
- const type = chunks.shift();
9351
+ const type = chunks.shift().toLowerCase();
9096
9352
  switch (type) {
9097
9353
  case "u":
9098
9354
  case "U":
9099
9355
  if (unicodeExtension) throw new RangeError("There can only be 1 -u- extension");
9100
9356
  unicodeExtension = parseUnicodeExtension(chunks);
9101
- extensions.push(unicodeExtension);
9357
+ appendToList(extensions, unicodeExtension);
9102
9358
  break;
9103
9359
  case "t":
9104
9360
  case "T":
9105
9361
  if (transformedExtension) throw new RangeError("There can only be 1 -t- extension");
9106
9362
  transformedExtension = parseTransformedExtension(chunks);
9107
- extensions.push(transformedExtension);
9363
+ appendToList(extensions, transformedExtension);
9108
9364
  break;
9109
9365
  case "x":
9110
9366
  case "X":
9111
9367
  if (puExtension) throw new RangeError("There can only be 1 -x- extension");
9112
9368
  puExtension = parsePuExtension(chunks);
9113
- extensions.push(puExtension);
9369
+ appendToList(extensions, puExtension);
9114
9370
  break;
9115
9371
  default:
9116
- if (!OTHER_EXTENSION_TYPE.test(type)) throw new RangeError("Malformed extension type");
9372
+ if (!isOtherExtensionType(type)) throw new RangeError("Malformed extension type");
9117
9373
  if (type in otherExtensionMap) throw new RangeError(`There can only be 1 -${type}- extension`);
9118
9374
  const extension = {
9119
9375
  type,
9120
9376
  value: parseOtherExtensionValue(chunks)
9121
9377
  };
9122
9378
  otherExtensionMap[extension.type] = extension;
9123
- extensions.push(extension);
9124
- break;
9379
+ appendToList(extensions, extension);
9125
9380
  }
9126
9381
  } while (chunks.length);
9127
9382
  return { extensions };
@@ -9141,14 +9396,17 @@ function canonicalizeAttrs(strs) {
9141
9396
  return all;
9142
9397
  }, {})).sort();
9143
9398
  }
9144
- function canonicalizeKVs(arr) {
9145
- const all = {};
9399
+ function canonicalizeKVs(arr, extension) {
9400
+ const seen = /* @__PURE__ */ new Set();
9146
9401
  const result = [];
9147
- for (const kv of arr) {
9148
- if (kv[0] in all) continue;
9149
- all[kv[0]] = 1;
9150
- if (!kv[1] || kv[1] === "true") result.push([kv[0].toLowerCase()]);
9151
- else result.push([kv[0].toLowerCase(), kv[1].toLowerCase()]);
9402
+ for (const [rawKey, rawValue] of arr) {
9403
+ const key = rawKey.toLowerCase();
9404
+ if (seen.has(key)) continue;
9405
+ seen.add(key);
9406
+ const value = rawValue?.toLowerCase() || "";
9407
+ let canonical = extensionAlias[extension]?.[key]?.[value] || value;
9408
+ if (extension === "u" && (key === "rg" || key === "sd")) canonical = subdivisionAlias[canonical] || canonical;
9409
+ appendToList(result, !canonical || extension === "u" && canonical === "true" ? [key] : [key, canonical]);
9152
9410
  }
9153
9411
  return result.sort(compareKV);
9154
9412
  }
@@ -9160,89 +9418,69 @@ function compareExtension(e1, e2) {
9160
9418
  }
9161
9419
  function mergeVariants(v1, v2) {
9162
9420
  const result = [...v1];
9163
- for (const v of v2) if (v1.indexOf(v) < 0) result.push(v);
9421
+ for (const v of v2) if (v1.indexOf(v) < 0) appendToList(result, v);
9164
9422
  return result;
9165
9423
  }
9166
- /**
9167
- * CAVEAT: We don't do this section in the spec bc they have no JSON data
9168
- * Use the bcp47 data to replace keys, types, tfields, and tvalues by their canonical forms. See Section 3.6.4 U Extension Data Files) and Section 3.7.1 T Extension Data Files. The aliases are in the alias attribute value, while the canonical is in the name attribute value. For example,
9169
- Because of the following bcp47 data:
9170
- <key name="ms"…>…<type name="uksystem" … alias="imperial" … />…</key>
9171
- We get the following transformation:
9172
- en-u-ms-imperial ⇒ en-u-ms-uksystem
9173
- * @param lang
9174
- */
9424
+ function compareLanguageAliasRules(a, b) {
9425
+ const fields = (id) => [
9426
+ Number(id.lang !== "und"),
9427
+ Number(!!id.script),
9428
+ Number(!!id.region),
9429
+ id.variants.length
9430
+ ];
9431
+ const left = fields(a.type), right = fields(b.type);
9432
+ const difference = right.reduce((a, b) => a + b, 0) - left.reduce((a, b) => a + b, 0);
9433
+ if (difference) return difference;
9434
+ for (let i = 0; i < left.length; i++) if (!!left[i] !== !!right[i]) return right[i] ? 1 : -1;
9435
+ const leftTag = emitUnicodeLanguageId(a.type), rightTag = emitUnicodeLanguageId(b.type);
9436
+ return leftTag < rightTag ? -1 : leftTag > rightTag ? 1 : 0;
9437
+ }
9438
+ const languageAliasRules = Object.keys(languageAlias).reduce((rules, from) => {
9439
+ const to = languageAlias[from];
9440
+ let type;
9441
+ const source = from.split("-");
9442
+ try {
9443
+ type = parseUnicodeLanguageId(source);
9444
+ } catch {
9445
+ return rules;
9446
+ }
9447
+ if (source.length) return rules;
9448
+ const target = to.split("-");
9449
+ const replacement = parseUnicodeLanguageId(target);
9450
+ if (target.length) throw new Error(`Invalid language alias replacement: ${to}`);
9451
+ appendToList(rules, {
9452
+ type,
9453
+ replacement
9454
+ });
9455
+ return rules;
9456
+ }, []).sort(compareLanguageAliasRules).reduce((groups, rule) => {
9457
+ appendToList(groups[rule.type.lang] ||= [], rule);
9458
+ return groups;
9459
+ }, Object.create(null));
9175
9460
  function canonicalizeUnicodeLanguageId(unicodeLanguageId) {
9176
- /**
9177
- * If the language subtag matches the type attribute of a languageAlias element in Supplemental Data, replace the language subtag with the replacement value.
9178
- * 1. If there are additional subtags in the replacement value, add them to the result, but only if there is no corresponding subtag already in the tag.
9179
- * 2. Five special deprecated grandfathered codes (such as i-default) are in type attributes, and are also replaced.
9180
- */
9461
+ unicodeLanguageId.lang = unicodeLanguageId.lang.toLowerCase();
9462
+ if (unicodeLanguageId.script) unicodeLanguageId.script = unicodeLanguageId.script[0].toUpperCase() + unicodeLanguageId.script.slice(1).toLowerCase();
9463
+ if (unicodeLanguageId.region) unicodeLanguageId.region = unicodeLanguageId.region.toUpperCase();
9464
+ unicodeLanguageId.variants = unicodeLanguageId.variants.map((v) => v.toLowerCase());
9465
+ const original = emitUnicodeLanguageId(unicodeLanguageId);
9181
9466
  let finalLangAst = unicodeLanguageId;
9182
- if (unicodeLanguageId.variants.length) {
9183
- let replacedLang = "";
9184
- for (const variant of unicodeLanguageId.variants) if (replacedLang = languageAlias[emitUnicodeLanguageId({
9185
- lang: unicodeLanguageId.lang,
9186
- variants: [variant]
9187
- })]) {
9188
- const replacedLangAst = parseUnicodeLanguageId(replacedLang.split("-"));
9189
- finalLangAst = {
9190
- lang: replacedLangAst.lang,
9191
- script: finalLangAst.script || replacedLangAst.script,
9192
- region: finalLangAst.region || replacedLangAst.region,
9193
- variants: mergeVariants(finalLangAst.variants, replacedLangAst.variants)
9194
- };
9195
- break;
9196
- }
9197
- }
9198
- if (finalLangAst.script && finalLangAst.region) {
9199
- const replacedLang = languageAlias[emitUnicodeLanguageId({
9200
- lang: finalLangAst.lang,
9201
- script: finalLangAst.script,
9202
- region: finalLangAst.region,
9203
- variants: []
9204
- })];
9205
- if (replacedLang) {
9206
- const replacedLangAst = parseUnicodeLanguageId(replacedLang.split("-"));
9207
- finalLangAst = {
9208
- lang: replacedLangAst.lang,
9209
- script: replacedLangAst.script,
9210
- region: replacedLangAst.region,
9211
- variants: finalLangAst.variants
9212
- };
9213
- }
9214
- }
9215
- if (finalLangAst.region) {
9216
- const replacedLang = languageAlias[emitUnicodeLanguageId({
9217
- lang: finalLangAst.lang,
9218
- region: finalLangAst.region,
9219
- variants: []
9220
- })];
9221
- if (replacedLang) {
9222
- const replacedLangAst = parseUnicodeLanguageId(replacedLang.split("-"));
9223
- finalLangAst = {
9224
- lang: replacedLangAst.lang,
9225
- script: finalLangAst.script || replacedLangAst.script,
9226
- region: replacedLangAst.region,
9227
- variants: finalLangAst.variants
9228
- };
9229
- }
9230
- }
9231
- const replacedLang = languageAlias[emitUnicodeLanguageId({
9232
- lang: finalLangAst.lang,
9233
- variants: []
9234
- })];
9235
- if (replacedLang) {
9236
- const replacedLangAst = parseUnicodeLanguageId(replacedLang.split("-"));
9467
+ const matches = ({ type }) => (!type.script || type.script === finalLangAst.script) && (!type.region || type.region === finalLangAst.region) && type.variants.every((variant) => finalLangAst.variants.includes(variant));
9468
+ const languageRule = languageAliasRules[finalLangAst.lang]?.find(matches);
9469
+ const undRule = finalLangAst.lang === "und" ? void 0 : languageAliasRules.und?.find(matches);
9470
+ const matched = !languageRule ? undRule : !undRule ? languageRule : compareLanguageAliasRules(languageRule, undRule) <= 0 ? languageRule : undRule;
9471
+ if (matched) {
9472
+ const { type, replacement } = matched;
9237
9473
  finalLangAst = {
9238
- lang: replacedLangAst.lang,
9239
- script: finalLangAst.script || replacedLangAst.script,
9240
- region: finalLangAst.region || replacedLangAst.region,
9241
- variants: finalLangAst.variants
9474
+ lang: type.lang !== "und" || finalLangAst.lang === "und" ? replacement.lang : finalLangAst.lang,
9475
+ script: type.script ? replacement.script : finalLangAst.script || replacement.script,
9476
+ region: type.region ? replacement.region : finalLangAst.region || replacement.region,
9477
+ variants: mergeVariants(finalLangAst.variants.filter((v) => !type.variants.includes(v)), replacement.variants)
9242
9478
  };
9479
+ return canonicalizeUnicodeLanguageId(finalLangAst);
9243
9480
  }
9244
9481
  if (finalLangAst.region) {
9245
- const regionAlias = territoryAlias[finalLangAst.region.toUpperCase()];
9482
+ const region = finalLangAst.region.toUpperCase();
9483
+ const regionAlias = territoryAlias[region];
9246
9484
  let replacedRegion;
9247
9485
  if (regionAlias) {
9248
9486
  const regions = regionAlias.split(" ");
@@ -9275,7 +9513,7 @@ function canonicalizeUnicodeLanguageId(unicodeLanguageId) {
9275
9513
  }
9276
9514
  finalLangAst.variants.sort();
9277
9515
  }
9278
- return finalLangAst;
9516
+ return emitUnicodeLanguageId(finalLangAst) === original ? finalLangAst : canonicalizeUnicodeLanguageId(finalLangAst);
9279
9517
  }
9280
9518
  /**
9281
9519
  * Canonicalize based on
@@ -9289,16 +9527,14 @@ function CanonicalizeUnicodeLocaleId(locale) {
9289
9527
  if (locale.extensions) {
9290
9528
  for (const extension of locale.extensions) switch (extension.type) {
9291
9529
  case "u":
9292
- extension.keywords = canonicalizeKVs(extension.keywords);
9530
+ extension.keywords = canonicalizeKVs(extension.keywords, "u");
9293
9531
  if (extension.attributes) extension.attributes = canonicalizeAttrs(extension.attributes);
9294
9532
  break;
9295
9533
  case "t":
9296
9534
  if (extension.lang) extension.lang = canonicalizeUnicodeLanguageId(extension.lang);
9297
- extension.fields = canonicalizeKVs(extension.fields);
9298
- break;
9299
- default:
9300
- extension.value = extension.value.toLowerCase();
9535
+ extension.fields = canonicalizeKVs(extension.fields, "t");
9301
9536
  break;
9537
+ default: extension.value = extension.value.toLowerCase();
9302
9538
  }
9303
9539
  locale.extensions.sort(compareExtension);
9304
9540
  }
@@ -9306,38 +9542,38 @@ function CanonicalizeUnicodeLocaleId(locale) {
9306
9542
  }
9307
9543
  //#endregion
9308
9544
  //#region packages/intl-getcanonicallocales/index.ts
9309
- /**
9310
- * Check if value is an Intl.Locale object by checking for [[InitializedLocale]] internal slot
9311
- * We detect this by checking if it's an Intl.Locale instance
9312
- *
9313
- * Per ECMA-402 #sec-canonicalizelocalelist step 7.c:
9314
- * "If Type(kValue) is Object and kValue has an [[InitializedLocale]] internal slot, then
9315
- * Let tag be kValue.[[Locale]]"
9316
- *
9317
- * https://tc39.es/ecma402/#sec-canonicalizelocalelist
9318
- */
9319
- function isLocaleObject(value) {
9320
- return typeof value === "object" && value !== null && typeof value.toString === "function" && typeof value.baseName === "string" && typeof value.language === "string";
9545
+ const originalLocaleToString = typeof Intl !== "undefined" ? Intl.Locale?.prototype.toString : void 0;
9546
+ function localeString(value) {
9547
+ if (value === null || typeof value !== "object" && typeof value !== "function") return void 0;
9548
+ const currentLocaleToString = typeof Intl !== "undefined" ? Intl.Locale?.prototype.toString : void 0;
9549
+ for (const method of [originalLocaleToString, currentLocaleToString]) if (method) try {
9550
+ const tag = method.call(value);
9551
+ if (typeof tag === "string") return tag;
9552
+ } catch {}
9321
9553
  }
9322
9554
  /**
9555
+ * ECMA-402 §9.2.1 CanonicalizeLocaleList, steps 3–7.
9323
9556
  * https://tc39.es/ecma402/#sec-canonicalizelocalelist
9324
- * @param locales
9557
+ * https://github.com/tc39/ecma402/blob/b1c961988b9a07894b1dc3dc2b5626ea48387d61/spec/negotiation.html#L51-L70
9325
9558
  */
9326
9559
  function CanonicalizeLocaleList(locales) {
9327
9560
  if (locales === void 0) return [];
9561
+ if (locales === null) throw new TypeError("Cannot convert null to an object");
9562
+ const singleLocale = localeString(locales);
9563
+ const list = typeof locales === "string" ? [locales] : singleLocale !== void 0 ? [singleLocale] : Object(locales);
9564
+ const length = +list.length;
9565
+ const len = isNaN(length) ? 0 : Math.min(Math.max(Math.floor(length), 0), 9007199254740991);
9328
9566
  const seen = [];
9329
- if (typeof locales === "string" || isLocaleObject(locales)) locales = [locales];
9330
- const O = Object(locales);
9331
- const len = typeof O.length === "number" ? O.length : 0;
9332
9567
  for (let k = 0; k < len; k++) {
9333
- if (!(k in O)) continue;
9334
- const kValue = O[k];
9335
- let tag;
9336
- if (typeof kValue === "string") tag = kValue;
9337
- else if (isLocaleObject(kValue)) tag = kValue.toString();
9338
- else throw new TypeError(`Invalid locale type: expected string or Intl.Locale, got ${typeof kValue}`);
9339
- const canonicalizedTag = emitUnicodeLocaleId(CanonicalizeUnicodeLocaleId(parseUnicodeLocaleId(tag)));
9340
- if (seen.indexOf(canonicalizedTag) < 0) seen.push(canonicalizedTag);
9568
+ if (!(k in list)) continue;
9569
+ const value = list[k];
9570
+ if (value === null || ![
9571
+ "string",
9572
+ "object",
9573
+ "function"
9574
+ ].includes(typeof value)) throw new TypeError("Locale list entries must be strings or objects");
9575
+ const canonicalizedTag = emitUnicodeLocaleId(CanonicalizeUnicodeLocaleId(parseUnicodeLocaleId(localeString(value) ?? ToString(value))));
9576
+ if (seen.indexOf(canonicalizedTag) < 0) appendToList(seen, canonicalizedTag);
9341
9577
  }
9342
9578
  return seen;
9343
9579
  }