@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/index.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,19 +9216,32 @@ 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 isStructurallyValidLanguageTag(tag) {
8989
9247
  try {
@@ -8994,13 +9252,13 @@ function isStructurallyValidLanguageTag(tag) {
8994
9252
  return true;
8995
9253
  }
8996
9254
  function isUnicodeRegionSubtag(region) {
8997
- return UNICODE_REGION_SUBTAG_REGEX.test(region);
9255
+ return isSubtag(region, 2, 2) || region.length === 3 && isDigit(region.charCodeAt(0)) && isDigit(region.charCodeAt(1)) && isDigit(region.charCodeAt(2));
8998
9256
  }
8999
9257
  function isUnicodeScriptSubtag(script) {
9000
- return ALPHA_4.test(script);
9258
+ return isSubtag(script, 4, 4);
9001
9259
  }
9002
9260
  function isUnicodeVariantSubtag(variant) {
9003
- return UNICODE_VARIANT_SUBTAG_REGEX.test(variant);
9261
+ return isSubtag(variant, 5, 8, true) || isSubtag(variant, 4, 4, true) && isDigit(variant.charCodeAt(0));
9004
9262
  }
9005
9263
  function parseUnicodeLanguageId(chunks) {
9006
9264
  if (typeof chunks === "string") chunks = chunks.split("-");
@@ -9031,15 +9289,15 @@ function parseUnicodeLanguageId(chunks) {
9031
9289
  function parseUnicodeExtension(chunks) {
9032
9290
  const keywords = [];
9033
9291
  let keyword;
9034
- while (chunks.length && (keyword = parseKeyword(chunks))) keywords.push(keyword);
9292
+ while (chunks.length && (keyword = parseKeyword(chunks))) appendToList(keywords, keyword);
9035
9293
  if (keywords.length) return {
9036
9294
  type: "u",
9037
9295
  keywords,
9038
9296
  attributes: []
9039
9297
  };
9040
9298
  const attributes = [];
9041
- while (chunks.length && ALPHANUM_3_8.test(chunks[0])) attributes.push(chunks.shift());
9042
- while (chunks.length && (keyword = parseKeyword(chunks))) keywords.push(keyword);
9299
+ while (chunks.length && isSubtag(chunks[0], 3, 8, true)) appendToList(attributes, chunks.shift());
9300
+ while (chunks.length && (keyword = parseKeyword(chunks))) appendToList(keywords, keyword);
9043
9301
  if (keywords.length || attributes.length) return {
9044
9302
  type: "u",
9045
9303
  attributes,
@@ -9049,28 +9307,26 @@ function parseUnicodeExtension(chunks) {
9049
9307
  }
9050
9308
  function parseKeyword(chunks) {
9051
9309
  let key;
9052
- if (!KEY_REGEX.test(chunks[0])) return;
9310
+ if (!isUnicodeKey(chunks[0])) return;
9053
9311
  key = chunks.shift();
9054
9312
  const type = [];
9055
- while (chunks.length && TYPE_REGEX.test(chunks[0])) type.push(chunks.shift());
9313
+ while (chunks.length && isSubtag(chunks[0], 3, 8, true)) appendToList(type, chunks.shift());
9056
9314
  let value = "";
9057
9315
  if (type.length) value = type.join("-");
9058
9316
  return [key, value];
9059
9317
  }
9060
9318
  function parseTransformedExtension(chunks) {
9061
9319
  let lang;
9062
- try {
9063
- lang = parseUnicodeLanguageId(chunks);
9064
- } catch {}
9320
+ if (chunks.length && isUnicodeLanguageSubtag(chunks[0])) lang = parseUnicodeLanguageId(chunks);
9065
9321
  const fields = [];
9066
- while (chunks.length && TKEY_REGEX.test(chunks[0])) {
9322
+ while (chunks.length && isTransformedKey(chunks[0])) {
9067
9323
  const key = chunks.shift();
9068
9324
  const value = [];
9069
- while (chunks.length && ALPHANUM_3_8.test(chunks[0])) value.push(chunks.shift());
9325
+ while (chunks.length && isSubtag(chunks[0], 3, 8, true)) appendToList(value, chunks.shift());
9070
9326
  if (!value.length) throw new RangeError(`Missing tvalue for tkey "${key}"`);
9071
- fields.push([key, value.join("-")]);
9327
+ appendToList(fields, [key, value.join("-")]);
9072
9328
  }
9073
- if (fields.length) return {
9329
+ if (lang || fields.length) return {
9074
9330
  type: "t",
9075
9331
  fields,
9076
9332
  lang
@@ -9079,7 +9335,7 @@ function parseTransformedExtension(chunks) {
9079
9335
  }
9080
9336
  function parsePuExtension(chunks) {
9081
9337
  const exts = [];
9082
- while (chunks.length && ALPHANUM_1_8.test(chunks[0])) exts.push(chunks.shift());
9338
+ while (chunks.length && isSubtag(chunks[0], 1, 8, true)) appendToList(exts, chunks.shift());
9083
9339
  if (exts.length) return {
9084
9340
  type: "x",
9085
9341
  value: exts.join("-")
@@ -9088,9 +9344,9 @@ function parsePuExtension(chunks) {
9088
9344
  }
9089
9345
  function parseOtherExtensionValue(chunks) {
9090
9346
  const exts = [];
9091
- while (chunks.length && ALPHANUM_2_8.test(chunks[0])) exts.push(chunks.shift());
9347
+ while (chunks.length && isSubtag(chunks[0], 2, 8, true)) appendToList(exts, chunks.shift());
9092
9348
  if (exts.length) return exts.join("-");
9093
- return "";
9349
+ throw new RangeError("Missing extension value");
9094
9350
  }
9095
9351
  function parseExtensions(chunks) {
9096
9352
  if (!chunks.length) return { extensions: [] };
@@ -9100,36 +9356,35 @@ function parseExtensions(chunks) {
9100
9356
  let puExtension;
9101
9357
  const otherExtensionMap = {};
9102
9358
  do {
9103
- const type = chunks.shift();
9359
+ const type = chunks.shift().toLowerCase();
9104
9360
  switch (type) {
9105
9361
  case "u":
9106
9362
  case "U":
9107
9363
  if (unicodeExtension) throw new RangeError("There can only be 1 -u- extension");
9108
9364
  unicodeExtension = parseUnicodeExtension(chunks);
9109
- extensions.push(unicodeExtension);
9365
+ appendToList(extensions, unicodeExtension);
9110
9366
  break;
9111
9367
  case "t":
9112
9368
  case "T":
9113
9369
  if (transformedExtension) throw new RangeError("There can only be 1 -t- extension");
9114
9370
  transformedExtension = parseTransformedExtension(chunks);
9115
- extensions.push(transformedExtension);
9371
+ appendToList(extensions, transformedExtension);
9116
9372
  break;
9117
9373
  case "x":
9118
9374
  case "X":
9119
9375
  if (puExtension) throw new RangeError("There can only be 1 -x- extension");
9120
9376
  puExtension = parsePuExtension(chunks);
9121
- extensions.push(puExtension);
9377
+ appendToList(extensions, puExtension);
9122
9378
  break;
9123
9379
  default:
9124
- if (!OTHER_EXTENSION_TYPE.test(type)) throw new RangeError("Malformed extension type");
9380
+ if (!isOtherExtensionType(type)) throw new RangeError("Malformed extension type");
9125
9381
  if (type in otherExtensionMap) throw new RangeError(`There can only be 1 -${type}- extension`);
9126
9382
  const extension = {
9127
9383
  type,
9128
9384
  value: parseOtherExtensionValue(chunks)
9129
9385
  };
9130
9386
  otherExtensionMap[extension.type] = extension;
9131
- extensions.push(extension);
9132
- break;
9387
+ appendToList(extensions, extension);
9133
9388
  }
9134
9389
  } while (chunks.length);
9135
9390
  return { extensions };
@@ -9149,14 +9404,17 @@ function canonicalizeAttrs(strs) {
9149
9404
  return all;
9150
9405
  }, {})).sort();
9151
9406
  }
9152
- function canonicalizeKVs(arr) {
9153
- const all = {};
9407
+ function canonicalizeKVs(arr, extension) {
9408
+ const seen = /* @__PURE__ */ new Set();
9154
9409
  const result = [];
9155
- for (const kv of arr) {
9156
- if (kv[0] in all) continue;
9157
- all[kv[0]] = 1;
9158
- if (!kv[1] || kv[1] === "true") result.push([kv[0].toLowerCase()]);
9159
- else result.push([kv[0].toLowerCase(), kv[1].toLowerCase()]);
9410
+ for (const [rawKey, rawValue] of arr) {
9411
+ const key = rawKey.toLowerCase();
9412
+ if (seen.has(key)) continue;
9413
+ seen.add(key);
9414
+ const value = rawValue?.toLowerCase() || "";
9415
+ let canonical = extensionAlias[extension]?.[key]?.[value] || value;
9416
+ if (extension === "u" && (key === "rg" || key === "sd")) canonical = subdivisionAlias[canonical] || canonical;
9417
+ appendToList(result, !canonical || extension === "u" && canonical === "true" ? [key] : [key, canonical]);
9160
9418
  }
9161
9419
  return result.sort(compareKV);
9162
9420
  }
@@ -9168,89 +9426,69 @@ function compareExtension(e1, e2) {
9168
9426
  }
9169
9427
  function mergeVariants(v1, v2) {
9170
9428
  const result = [...v1];
9171
- for (const v of v2) if (v1.indexOf(v) < 0) result.push(v);
9429
+ for (const v of v2) if (v1.indexOf(v) < 0) appendToList(result, v);
9172
9430
  return result;
9173
9431
  }
9174
- /**
9175
- * CAVEAT: We don't do this section in the spec bc they have no JSON data
9176
- * 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,
9177
- Because of the following bcp47 data:
9178
- <key name="ms"…>…<type name="uksystem" … alias="imperial" … />…</key>
9179
- We get the following transformation:
9180
- en-u-ms-imperial ⇒ en-u-ms-uksystem
9181
- * @param lang
9182
- */
9432
+ function compareLanguageAliasRules(a, b) {
9433
+ const fields = (id) => [
9434
+ Number(id.lang !== "und"),
9435
+ Number(!!id.script),
9436
+ Number(!!id.region),
9437
+ id.variants.length
9438
+ ];
9439
+ const left = fields(a.type), right = fields(b.type);
9440
+ const difference = right.reduce((a, b) => a + b, 0) - left.reduce((a, b) => a + b, 0);
9441
+ if (difference) return difference;
9442
+ for (let i = 0; i < left.length; i++) if (!!left[i] !== !!right[i]) return right[i] ? 1 : -1;
9443
+ const leftTag = emitUnicodeLanguageId(a.type), rightTag = emitUnicodeLanguageId(b.type);
9444
+ return leftTag < rightTag ? -1 : leftTag > rightTag ? 1 : 0;
9445
+ }
9446
+ const languageAliasRules = Object.keys(languageAlias).reduce((rules, from) => {
9447
+ const to = languageAlias[from];
9448
+ let type;
9449
+ const source = from.split("-");
9450
+ try {
9451
+ type = parseUnicodeLanguageId(source);
9452
+ } catch {
9453
+ return rules;
9454
+ }
9455
+ if (source.length) return rules;
9456
+ const target = to.split("-");
9457
+ const replacement = parseUnicodeLanguageId(target);
9458
+ if (target.length) throw new Error(`Invalid language alias replacement: ${to}`);
9459
+ appendToList(rules, {
9460
+ type,
9461
+ replacement
9462
+ });
9463
+ return rules;
9464
+ }, []).sort(compareLanguageAliasRules).reduce((groups, rule) => {
9465
+ appendToList(groups[rule.type.lang] ||= [], rule);
9466
+ return groups;
9467
+ }, Object.create(null));
9183
9468
  function canonicalizeUnicodeLanguageId(unicodeLanguageId) {
9184
- /**
9185
- * If the language subtag matches the type attribute of a languageAlias element in Supplemental Data, replace the language subtag with the replacement value.
9186
- * 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.
9187
- * 2. Five special deprecated grandfathered codes (such as i-default) are in type attributes, and are also replaced.
9188
- */
9469
+ unicodeLanguageId.lang = unicodeLanguageId.lang.toLowerCase();
9470
+ if (unicodeLanguageId.script) unicodeLanguageId.script = unicodeLanguageId.script[0].toUpperCase() + unicodeLanguageId.script.slice(1).toLowerCase();
9471
+ if (unicodeLanguageId.region) unicodeLanguageId.region = unicodeLanguageId.region.toUpperCase();
9472
+ unicodeLanguageId.variants = unicodeLanguageId.variants.map((v) => v.toLowerCase());
9473
+ const original = emitUnicodeLanguageId(unicodeLanguageId);
9189
9474
  let finalLangAst = unicodeLanguageId;
9190
- if (unicodeLanguageId.variants.length) {
9191
- let replacedLang = "";
9192
- for (const variant of unicodeLanguageId.variants) if (replacedLang = languageAlias[emitUnicodeLanguageId({
9193
- lang: unicodeLanguageId.lang,
9194
- variants: [variant]
9195
- })]) {
9196
- const replacedLangAst = parseUnicodeLanguageId(replacedLang.split("-"));
9197
- finalLangAst = {
9198
- lang: replacedLangAst.lang,
9199
- script: finalLangAst.script || replacedLangAst.script,
9200
- region: finalLangAst.region || replacedLangAst.region,
9201
- variants: mergeVariants(finalLangAst.variants, replacedLangAst.variants)
9202
- };
9203
- break;
9204
- }
9205
- }
9206
- if (finalLangAst.script && finalLangAst.region) {
9207
- const replacedLang = languageAlias[emitUnicodeLanguageId({
9208
- lang: finalLangAst.lang,
9209
- script: finalLangAst.script,
9210
- region: finalLangAst.region,
9211
- variants: []
9212
- })];
9213
- if (replacedLang) {
9214
- const replacedLangAst = parseUnicodeLanguageId(replacedLang.split("-"));
9215
- finalLangAst = {
9216
- lang: replacedLangAst.lang,
9217
- script: replacedLangAst.script,
9218
- region: replacedLangAst.region,
9219
- variants: finalLangAst.variants
9220
- };
9221
- }
9222
- }
9223
- if (finalLangAst.region) {
9224
- const replacedLang = languageAlias[emitUnicodeLanguageId({
9225
- lang: finalLangAst.lang,
9226
- region: finalLangAst.region,
9227
- variants: []
9228
- })];
9229
- if (replacedLang) {
9230
- const replacedLangAst = parseUnicodeLanguageId(replacedLang.split("-"));
9231
- finalLangAst = {
9232
- lang: replacedLangAst.lang,
9233
- script: finalLangAst.script || replacedLangAst.script,
9234
- region: replacedLangAst.region,
9235
- variants: finalLangAst.variants
9236
- };
9237
- }
9238
- }
9239
- const replacedLang = languageAlias[emitUnicodeLanguageId({
9240
- lang: finalLangAst.lang,
9241
- variants: []
9242
- })];
9243
- if (replacedLang) {
9244
- const replacedLangAst = parseUnicodeLanguageId(replacedLang.split("-"));
9475
+ const matches = ({ type }) => (!type.script || type.script === finalLangAst.script) && (!type.region || type.region === finalLangAst.region) && type.variants.every((variant) => finalLangAst.variants.includes(variant));
9476
+ const languageRule = languageAliasRules[finalLangAst.lang]?.find(matches);
9477
+ const undRule = finalLangAst.lang === "und" ? void 0 : languageAliasRules.und?.find(matches);
9478
+ const matched = !languageRule ? undRule : !undRule ? languageRule : compareLanguageAliasRules(languageRule, undRule) <= 0 ? languageRule : undRule;
9479
+ if (matched) {
9480
+ const { type, replacement } = matched;
9245
9481
  finalLangAst = {
9246
- lang: replacedLangAst.lang,
9247
- script: finalLangAst.script || replacedLangAst.script,
9248
- region: finalLangAst.region || replacedLangAst.region,
9249
- variants: finalLangAst.variants
9482
+ lang: type.lang !== "und" || finalLangAst.lang === "und" ? replacement.lang : finalLangAst.lang,
9483
+ script: type.script ? replacement.script : finalLangAst.script || replacement.script,
9484
+ region: type.region ? replacement.region : finalLangAst.region || replacement.region,
9485
+ variants: mergeVariants(finalLangAst.variants.filter((v) => !type.variants.includes(v)), replacement.variants)
9250
9486
  };
9487
+ return canonicalizeUnicodeLanguageId(finalLangAst);
9251
9488
  }
9252
9489
  if (finalLangAst.region) {
9253
- const regionAlias = territoryAlias[finalLangAst.region.toUpperCase()];
9490
+ const region = finalLangAst.region.toUpperCase();
9491
+ const regionAlias = territoryAlias[region];
9254
9492
  let replacedRegion;
9255
9493
  if (regionAlias) {
9256
9494
  const regions = regionAlias.split(" ");
@@ -9283,7 +9521,7 @@ function canonicalizeUnicodeLanguageId(unicodeLanguageId) {
9283
9521
  }
9284
9522
  finalLangAst.variants.sort();
9285
9523
  }
9286
- return finalLangAst;
9524
+ return emitUnicodeLanguageId(finalLangAst) === original ? finalLangAst : canonicalizeUnicodeLanguageId(finalLangAst);
9287
9525
  }
9288
9526
  /**
9289
9527
  * Canonicalize based on
@@ -9297,16 +9535,14 @@ function CanonicalizeUnicodeLocaleId(locale) {
9297
9535
  if (locale.extensions) {
9298
9536
  for (const extension of locale.extensions) switch (extension.type) {
9299
9537
  case "u":
9300
- extension.keywords = canonicalizeKVs(extension.keywords);
9538
+ extension.keywords = canonicalizeKVs(extension.keywords, "u");
9301
9539
  if (extension.attributes) extension.attributes = canonicalizeAttrs(extension.attributes);
9302
9540
  break;
9303
9541
  case "t":
9304
9542
  if (extension.lang) extension.lang = canonicalizeUnicodeLanguageId(extension.lang);
9305
- extension.fields = canonicalizeKVs(extension.fields);
9306
- break;
9307
- default:
9308
- extension.value = extension.value.toLowerCase();
9543
+ extension.fields = canonicalizeKVs(extension.fields, "t");
9309
9544
  break;
9545
+ default: extension.value = extension.value.toLowerCase();
9310
9546
  }
9311
9547
  locale.extensions.sort(compareExtension);
9312
9548
  }
@@ -9314,38 +9550,38 @@ function CanonicalizeUnicodeLocaleId(locale) {
9314
9550
  }
9315
9551
  //#endregion
9316
9552
  //#region packages/intl-getcanonicallocales/index.ts
9317
- /**
9318
- * Check if value is an Intl.Locale object by checking for [[InitializedLocale]] internal slot
9319
- * We detect this by checking if it's an Intl.Locale instance
9320
- *
9321
- * Per ECMA-402 #sec-canonicalizelocalelist step 7.c:
9322
- * "If Type(kValue) is Object and kValue has an [[InitializedLocale]] internal slot, then
9323
- * Let tag be kValue.[[Locale]]"
9324
- *
9325
- * https://tc39.es/ecma402/#sec-canonicalizelocalelist
9326
- */
9327
- function isLocaleObject(value) {
9328
- return typeof value === "object" && value !== null && typeof value.toString === "function" && typeof value.baseName === "string" && typeof value.language === "string";
9553
+ const originalLocaleToString = typeof Intl !== "undefined" ? Intl.Locale?.prototype.toString : void 0;
9554
+ function localeString(value) {
9555
+ if (value === null || typeof value !== "object" && typeof value !== "function") return void 0;
9556
+ const currentLocaleToString = typeof Intl !== "undefined" ? Intl.Locale?.prototype.toString : void 0;
9557
+ for (const method of [originalLocaleToString, currentLocaleToString]) if (method) try {
9558
+ const tag = method.call(value);
9559
+ if (typeof tag === "string") return tag;
9560
+ } catch {}
9329
9561
  }
9330
9562
  /**
9563
+ * ECMA-402 §9.2.1 CanonicalizeLocaleList, steps 3–7.
9331
9564
  * https://tc39.es/ecma402/#sec-canonicalizelocalelist
9332
- * @param locales
9565
+ * https://github.com/tc39/ecma402/blob/b1c961988b9a07894b1dc3dc2b5626ea48387d61/spec/negotiation.html#L51-L70
9333
9566
  */
9334
9567
  function CanonicalizeLocaleList(locales) {
9335
9568
  if (locales === void 0) return [];
9569
+ if (locales === null) throw new TypeError("Cannot convert null to an object");
9570
+ const singleLocale = localeString(locales);
9571
+ const list = typeof locales === "string" ? [locales] : singleLocale !== void 0 ? [singleLocale] : Object(locales);
9572
+ const length = +list.length;
9573
+ const len = isNaN(length) ? 0 : Math.min(Math.max(Math.floor(length), 0), 9007199254740991);
9336
9574
  const seen = [];
9337
- if (typeof locales === "string" || isLocaleObject(locales)) locales = [locales];
9338
- const O = Object(locales);
9339
- const len = typeof O.length === "number" ? O.length : 0;
9340
9575
  for (let k = 0; k < len; k++) {
9341
- if (!(k in O)) continue;
9342
- const kValue = O[k];
9343
- let tag;
9344
- if (typeof kValue === "string") tag = kValue;
9345
- else if (isLocaleObject(kValue)) tag = kValue.toString();
9346
- else throw new TypeError(`Invalid locale type: expected string or Intl.Locale, got ${typeof kValue}`);
9347
- const canonicalizedTag = emitUnicodeLocaleId(CanonicalizeUnicodeLocaleId(parseUnicodeLocaleId(tag)));
9348
- if (seen.indexOf(canonicalizedTag) < 0) seen.push(canonicalizedTag);
9576
+ if (!(k in list)) continue;
9577
+ const value = list[k];
9578
+ if (value === null || ![
9579
+ "string",
9580
+ "object",
9581
+ "function"
9582
+ ].includes(typeof value)) throw new TypeError("Locale list entries must be strings or objects");
9583
+ const canonicalizedTag = emitUnicodeLocaleId(CanonicalizeUnicodeLocaleId(parseUnicodeLocaleId(localeString(value) ?? ToString(value))));
9584
+ if (seen.indexOf(canonicalizedTag) < 0) appendToList(seen, canonicalizedTag);
9349
9585
  }
9350
9586
  return seen;
9351
9587
  }
@@ -9353,6 +9589,6 @@ function getCanonicalLocales(locales) {
9353
9589
  return CanonicalizeLocaleList(locales);
9354
9590
  }
9355
9591
  //#endregion
9356
- export { emitUnicodeLanguageId, emitUnicodeLocaleId, getCanonicalLocales, isStructurallyValidLanguageTag, isUnicodeLanguageSubtag, isUnicodeRegionSubtag, isUnicodeScriptSubtag, likelySubtags, parseUnicodeLanguageId, parseUnicodeLocaleId };
9592
+ export { emitUnicodeLanguageId, emitUnicodeLocaleId, getCanonicalLocales, isStructurallyValidLanguageTag, isUnicodeLanguageSubtag, isUnicodeRegionSubtag, isUnicodeScriptSubtag, isUnicodeVariantSubtag, likelySubtags, parseUnicodeLanguageId, parseUnicodeLocaleId };
9357
9593
 
9358
9594
  //# sourceMappingURL=index.js.map