@nanahoshi/mona-ui 0.18.6 → 0.20.0

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.
Files changed (116) hide show
  1. package/README.md +71 -13
  2. package/THIRD_PARTY_NOTICES.md +60 -0
  3. package/fesm2022/nanahoshi-mona-ui-auto-complete.mjs +11 -3
  4. package/fesm2022/nanahoshi-mona-ui-breadcrumb.mjs +17 -9
  5. package/fesm2022/nanahoshi-mona-ui-button-group.mjs +16 -7
  6. package/fesm2022/nanahoshi-mona-ui-calendar.mjs +196 -101
  7. package/fesm2022/nanahoshi-mona-ui-card.mjs +22 -14
  8. package/fesm2022/nanahoshi-mona-ui-chart.mjs +78 -18
  9. package/fesm2022/nanahoshi-mona-ui-check-box.mjs +1 -1
  10. package/fesm2022/nanahoshi-mona-ui-chip.mjs +11 -3
  11. package/fesm2022/nanahoshi-mona-ui-circular-progress-bar.mjs +1 -2
  12. package/fesm2022/nanahoshi-mona-ui-color-gradient.mjs +23 -5
  13. package/fesm2022/nanahoshi-mona-ui-color-palette.mjs +49 -28
  14. package/fesm2022/nanahoshi-mona-ui-color-picker.mjs +42 -26
  15. package/fesm2022/nanahoshi-mona-ui-combo-box.mjs +11 -3
  16. package/fesm2022/nanahoshi-mona-ui-date-picker.mjs +39 -21
  17. package/fesm2022/nanahoshi-mona-ui-datetime-picker.mjs +88 -55
  18. package/fesm2022/nanahoshi-mona-ui-dialog.mjs +57 -25
  19. package/fesm2022/nanahoshi-mona-ui-dropdown-list.mjs +13 -5
  20. package/fesm2022/nanahoshi-mona-ui-dropdowns.mjs +17 -6
  21. package/fesm2022/nanahoshi-mona-ui-editor.mjs +178 -59
  22. package/fesm2022/nanahoshi-mona-ui-filter.mjs +137 -54
  23. package/fesm2022/{nanahoshi-mona-ui-grid-grid-footer-cell.component-WEDbZ5vy.mjs → nanahoshi-mona-ui-grid-grid-footer-cell.component-BuybF7tX.mjs} +2 -2
  24. package/fesm2022/{nanahoshi-mona-ui-grid-grid-footer-table-cell.directive-ibH5osCg.mjs → nanahoshi-mona-ui-grid-grid-footer-table-cell.directive-Dj-SaNzk.mjs} +2 -2
  25. package/fesm2022/nanahoshi-mona-ui-grid-grid-list.component-CYAm4l84.mjs +145 -0
  26. package/fesm2022/{nanahoshi-mona-ui-grid-grid-toggle.component-hc-LeIb0.mjs → nanahoshi-mona-ui-grid-grid-toggle.component-B_Gm--X6.mjs} +46 -31
  27. package/fesm2022/{nanahoshi-mona-ui-grid-grid-virtual-list.component-DYajpOb9.mjs → nanahoshi-mona-ui-grid-grid-virtual-list.component-X0X487Rm.mjs} +5 -5
  28. package/fesm2022/{nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-Pm8Fbp6M.mjs → nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-CyzJFQIy.mjs} +99 -42
  29. package/fesm2022/nanahoshi-mona-ui-grid.mjs +1 -1
  30. package/fesm2022/nanahoshi-mona-ui-i18n.mjs +4874 -0
  31. package/fesm2022/nanahoshi-mona-ui-internal-list.mjs +12 -4
  32. package/fesm2022/nanahoshi-mona-ui-internal-tree.mjs +48 -21
  33. package/fesm2022/nanahoshi-mona-ui-list-box.mjs +33 -18
  34. package/fesm2022/nanahoshi-mona-ui-list-view.mjs +10 -10
  35. package/fesm2022/nanahoshi-mona-ui-list.mjs +2 -0
  36. package/fesm2022/nanahoshi-mona-ui-locales.mjs +4973 -0
  37. package/fesm2022/nanahoshi-mona-ui-menubar.mjs +29 -16
  38. package/fesm2022/nanahoshi-mona-ui-multi-select.mjs +12 -3
  39. package/fesm2022/nanahoshi-mona-ui-notification.mjs +23 -18
  40. package/fesm2022/nanahoshi-mona-ui-numeric-text-box.mjs +211 -106
  41. package/fesm2022/nanahoshi-mona-ui-otp-input.mjs +14 -6
  42. package/fesm2022/nanahoshi-mona-ui-pager.mjs +66 -29
  43. package/fesm2022/nanahoshi-mona-ui-popup-menu.mjs +57 -46
  44. package/fesm2022/nanahoshi-mona-ui-popup.mjs +35 -15
  45. package/fesm2022/nanahoshi-mona-ui-progress-bar.mjs +38 -17
  46. package/fesm2022/nanahoshi-mona-ui-rating.mjs +25 -7
  47. package/fesm2022/nanahoshi-mona-ui-scroll-view.mjs +431 -101
  48. package/fesm2022/nanahoshi-mona-ui-segmented.mjs +1 -1
  49. package/fesm2022/nanahoshi-mona-ui-sheet.mjs +26 -8
  50. package/fesm2022/nanahoshi-mona-ui-sidebar.mjs +222 -28
  51. package/fesm2022/nanahoshi-mona-ui-slider.mjs +91 -36
  52. package/fesm2022/nanahoshi-mona-ui-spinner.mjs +34 -15
  53. package/fesm2022/nanahoshi-mona-ui-split-button.mjs +39 -23
  54. package/fesm2022/nanahoshi-mona-ui-splitter.mjs +50 -25
  55. package/fesm2022/nanahoshi-mona-ui-stepper.mjs +41 -14
  56. package/fesm2022/nanahoshi-mona-ui-switch.mjs +9 -9
  57. package/fesm2022/nanahoshi-mona-ui-tabs.mjs +74 -56
  58. package/fesm2022/nanahoshi-mona-ui-text-box.mjs +16 -8
  59. package/fesm2022/nanahoshi-mona-ui-time-picker.mjs +47 -24
  60. package/fesm2022/nanahoshi-mona-ui-time-selector.mjs +66 -27
  61. package/fesm2022/nanahoshi-mona-ui-tree-view.mjs +23 -15
  62. package/fesm2022/nanahoshi-mona-ui-window.mjs +71 -40
  63. package/i18n/package.json +4 -0
  64. package/locales/package.json +4 -0
  65. package/package.json +9 -1
  66. package/types/nanahoshi-mona-ui-auto-complete.d.ts +6 -1
  67. package/types/nanahoshi-mona-ui-breadcrumb.d.ts +9 -3
  68. package/types/nanahoshi-mona-ui-button-group.d.ts +9 -3
  69. package/types/nanahoshi-mona-ui-calendar.d.ts +29 -15
  70. package/types/nanahoshi-mona-ui-card.d.ts +8 -2
  71. package/types/nanahoshi-mona-ui-chart.d.ts +10 -1
  72. package/types/nanahoshi-mona-ui-chip.d.ts +7 -1
  73. package/types/nanahoshi-mona-ui-color-gradient.d.ts +6 -1
  74. package/types/nanahoshi-mona-ui-color-palette.d.ts +21 -10
  75. package/types/nanahoshi-mona-ui-color-picker.d.ts +30 -20
  76. package/types/nanahoshi-mona-ui-combo-box.d.ts +6 -1
  77. package/types/nanahoshi-mona-ui-date-picker.d.ts +14 -6
  78. package/types/nanahoshi-mona-ui-datetime-picker.d.ts +40 -12
  79. package/types/nanahoshi-mona-ui-dialog.d.ts +16 -7
  80. package/types/nanahoshi-mona-ui-dropdown-list.d.ts +6 -1
  81. package/types/nanahoshi-mona-ui-dropdowns.d.ts +4 -1
  82. package/types/nanahoshi-mona-ui-editor.d.ts +6 -1
  83. package/types/nanahoshi-mona-ui-filter.d.ts +16 -10
  84. package/types/nanahoshi-mona-ui-grid.d.ts +50 -2
  85. package/types/nanahoshi-mona-ui-i18n.d.ts +680 -0
  86. package/types/nanahoshi-mona-ui-internal-list.d.ts +7 -2
  87. package/types/nanahoshi-mona-ui-internal-tree.d.ts +7 -3
  88. package/types/nanahoshi-mona-ui-list-box.d.ts +9 -4
  89. package/types/nanahoshi-mona-ui-list-view.d.ts +6 -6
  90. package/types/nanahoshi-mona-ui-list.d.ts +1 -1
  91. package/types/nanahoshi-mona-ui-locales.d.ts +4889 -0
  92. package/types/nanahoshi-mona-ui-menubar.d.ts +59 -58
  93. package/types/nanahoshi-mona-ui-multi-select.d.ts +6 -1
  94. package/types/nanahoshi-mona-ui-notification.d.ts +11 -5
  95. package/types/nanahoshi-mona-ui-numeric-text-box.d.ts +24 -15
  96. package/types/nanahoshi-mona-ui-otp-input.d.ts +9 -3
  97. package/types/nanahoshi-mona-ui-pager.d.ts +20 -6
  98. package/types/nanahoshi-mona-ui-popup.d.ts +2 -1
  99. package/types/nanahoshi-mona-ui-progress-bar.d.ts +9 -7
  100. package/types/nanahoshi-mona-ui-rating.d.ts +19 -12
  101. package/types/nanahoshi-mona-ui-scroll-view.d.ts +34 -28
  102. package/types/nanahoshi-mona-ui-sheet.d.ts +8 -2
  103. package/types/nanahoshi-mona-ui-sidebar.d.ts +3 -0
  104. package/types/nanahoshi-mona-ui-slider.d.ts +44 -26
  105. package/types/nanahoshi-mona-ui-spinner.d.ts +13 -4
  106. package/types/nanahoshi-mona-ui-split-button.d.ts +62 -56
  107. package/types/nanahoshi-mona-ui-splitter.d.ts +9 -6
  108. package/types/nanahoshi-mona-ui-stepper.d.ts +10 -3
  109. package/types/nanahoshi-mona-ui-switch.d.ts +1 -1
  110. package/types/nanahoshi-mona-ui-tabs.d.ts +96 -35
  111. package/types/nanahoshi-mona-ui-text-box.d.ts +11 -5
  112. package/types/nanahoshi-mona-ui-time-picker.d.ts +11 -4
  113. package/types/nanahoshi-mona-ui-time-selector.d.ts +16 -5
  114. package/types/nanahoshi-mona-ui-tree-view.d.ts +15 -10
  115. package/types/nanahoshi-mona-ui-window.d.ts +26 -20
  116. package/fesm2022/nanahoshi-mona-ui-grid-grid-list.component-ZM3CneJ0.mjs +0 -145
@@ -0,0 +1,4874 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, inject, signal, computed, Injectable, ElementRef, DestroyRef, makeEnvironmentProviders } from '@angular/core';
3
+ import { Directionality } from '@angular/cdk/bidi';
4
+ import { DateTime } from 'luxon';
5
+
6
+ const MONA_DEFAULT_LOCALE = {
7
+ direction: "ltr",
8
+ id: "en-US",
9
+ messages: {}
10
+ };
11
+
12
+ const MONA_I18N_CONFIG = new InjectionToken("MONA_I18N_CONFIG", {
13
+ factory: () => ({})
14
+ });
15
+
16
+ function isPlainObject(value) {
17
+ return value !== null && typeof value === "object" && !Array.isArray(value);
18
+ }
19
+ function mergeTwo(base, source) {
20
+ if (!source) {
21
+ return base;
22
+ }
23
+ const result = { ...base };
24
+ const sourceObj = source;
25
+ for (const key of Object.keys(sourceObj)) {
26
+ const sourceVal = sourceObj[key];
27
+ if (sourceVal === undefined) {
28
+ continue;
29
+ }
30
+ const baseVal = result[key];
31
+ if (isPlainObject(baseVal) && isPlainObject(sourceVal)) {
32
+ result[key] = mergeTwo(baseVal, sourceVal);
33
+ }
34
+ else {
35
+ result[key] = sourceVal;
36
+ }
37
+ }
38
+ return result;
39
+ }
40
+ function mergeMessages(fallback, localeMessages, overrideMessages) {
41
+ const withLocale = mergeTwo(fallback, localeMessages);
42
+ return mergeTwo(withLocale, overrideMessages);
43
+ }
44
+
45
+ class MonaI18nService {
46
+ constructor() {
47
+ this.#config = inject(MONA_I18N_CONFIG);
48
+ this.#locale = signal(this.#config.locale ?? MONA_DEFAULT_LOCALE, /* @ts-ignore */
49
+ ...(ngDevMode ? [{ debugName: "#locale" }] : /* istanbul ignore next */ []));
50
+ this.#overrides = signal(this.#config.messages ?? {}, /* @ts-ignore */
51
+ ...(ngDevMode ? [{ debugName: "#overrides" }] : /* istanbul ignore next */ []));
52
+ this.direction = computed(() => this.#locale().direction, /* @ts-ignore */
53
+ ...(ngDevMode ? [{ debugName: "direction" }] : /* istanbul ignore next */ []));
54
+ this.locale = this.#locale.asReadonly();
55
+ this.localeId = computed(() => this.#locale().id, /* @ts-ignore */
56
+ ...(ngDevMode ? [{ debugName: "localeId" }] : /* istanbul ignore next */ []));
57
+ }
58
+ #config;
59
+ #locale;
60
+ #overrides;
61
+ clearMessages() {
62
+ this.#overrides.set({});
63
+ }
64
+ componentMessages(namespace, fallback) {
65
+ return computed(() => {
66
+ const localeMessages = this.#locale().messages[namespace];
67
+ const overrideMessages = this.#overrides()[namespace];
68
+ return mergeMessages(fallback, localeMessages, overrideMessages);
69
+ });
70
+ }
71
+ patchMessages(messages) {
72
+ this.#overrides.update(current => mergeTwo(current, messages));
73
+ }
74
+ setMessages(messages) {
75
+ this.#overrides.set(messages);
76
+ }
77
+ use(locale) {
78
+ this.#locale.set(locale);
79
+ }
80
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: MonaI18nService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
81
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: MonaI18nService, providedIn: "root" }); }
82
+ }
83
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: MonaI18nService, decorators: [{
84
+ type: Injectable,
85
+ args: [{
86
+ providedIn: "root"
87
+ }]
88
+ }] });
89
+
90
+ /**
91
+ * Reads semantic document direction for a connected browser element using `:dir(rtl)` and `:dir(ltr)`.
92
+ *
93
+ * Mona UI direction-sensitive behaviors follow semantic document directionality
94
+ * (`:dir(...)`, `[dir]`, and CDK Directionality), matching Tailwind's `rtl:`/`ltr:`
95
+ * variant matching. Styling-only CSS `direction` property is not treated as the
96
+ * authoritative Mona direction switch.
97
+ */
98
+ function readSemanticDirection(element) {
99
+ if (!element || !element.isConnected) {
100
+ return null;
101
+ }
102
+ try {
103
+ if (element.matches(":dir(rtl)")) {
104
+ return "rtl";
105
+ }
106
+ if (element.matches(":dir(ltr)")) {
107
+ return "ltr";
108
+ }
109
+ }
110
+ catch {
111
+ // selector unsupported / environment limitation
112
+ }
113
+ return null;
114
+ }
115
+ function findNearestValidDirState(element) {
116
+ let current = element;
117
+ while (current) {
118
+ const rawDir = current.getAttribute?.("dir")?.trim().toLowerCase();
119
+ if (rawDir === "rtl" || rawDir === "ltr") {
120
+ return rawDir;
121
+ }
122
+ if (rawDir === "auto") {
123
+ const semanticDir = readSemanticDirection(current) ?? readSemanticDirection(element);
124
+ if (semanticDir) {
125
+ return semanticDir;
126
+ }
127
+ }
128
+ current = current.parentElement;
129
+ }
130
+ return null;
131
+ }
132
+ function resolveComponentDirection(hostElement, directionality) {
133
+ const element = hostElement instanceof ElementRef ? hostElement.nativeElement : hostElement;
134
+ // 1. Connected browser semantic direction (:dir(rtl) / :dir(ltr))
135
+ const semantic = readSemanticDirection(element);
136
+ if (semantic) {
137
+ return semantic;
138
+ }
139
+ // 2. Non-browser / unattached DOM fallback: nearest ancestor explicit dir attribute ("ltr", "rtl", or "auto")
140
+ const explicit = findNearestValidDirState(element);
141
+ if (explicit) {
142
+ return explicit;
143
+ }
144
+ // 3. Angular CDK Directionality fallback
145
+ if (directionality?.value === "rtl" || directionality?.value === "ltr") {
146
+ return directionality.value;
147
+ }
148
+ return "ltr";
149
+ }
150
+ const documentObservers = new WeakMap();
151
+ function observeDocumentDirChanges(doc, callback) {
152
+ let entry = documentObservers.get(doc);
153
+ if (!entry) {
154
+ const callbacks = new Set();
155
+ const observer = new MutationObserver(() => {
156
+ for (const cb of Array.from(callbacks)) {
157
+ cb();
158
+ }
159
+ });
160
+ if (doc.documentElement) {
161
+ observer.observe(doc.documentElement, {
162
+ attributes: true,
163
+ attributeFilter: ["dir"],
164
+ subtree: true
165
+ });
166
+ }
167
+ entry = { refCount: 0, observer, callbacks };
168
+ documentObservers.set(doc, entry);
169
+ }
170
+ entry.refCount++;
171
+ entry.callbacks.add(callback);
172
+ let cleanedUp = false;
173
+ return () => {
174
+ if (cleanedUp || !entry) {
175
+ return;
176
+ }
177
+ cleanedUp = true;
178
+ entry.callbacks.delete(callback);
179
+ entry.refCount--;
180
+ if (entry.refCount <= 0) {
181
+ entry.observer.disconnect();
182
+ documentObservers.delete(doc);
183
+ }
184
+ };
185
+ }
186
+ const autoDirectionObservers = new WeakMap();
187
+ function observeAutoDirectionChanges(autoRoot, callback) {
188
+ let entry = autoDirectionObservers.get(autoRoot);
189
+ if (!entry) {
190
+ const callbacks = new Set();
191
+ const observer = new MutationObserver(() => {
192
+ const currentDir = readSemanticDirection(autoRoot);
193
+ if (entry && (entry.lastDirection === null || currentDir !== entry.lastDirection)) {
194
+ entry.lastDirection = currentDir;
195
+ for (const cb of Array.from(callbacks)) {
196
+ cb();
197
+ }
198
+ }
199
+ });
200
+ observer.observe(autoRoot, {
201
+ childList: true,
202
+ characterData: true,
203
+ subtree: true
204
+ });
205
+ entry = {
206
+ refCount: 0,
207
+ observer,
208
+ callbacks,
209
+ lastDirection: readSemanticDirection(autoRoot)
210
+ };
211
+ autoDirectionObservers.set(autoRoot, entry);
212
+ }
213
+ entry.refCount++;
214
+ entry.callbacks.add(callback);
215
+ let cleanedUp = false;
216
+ return () => {
217
+ if (cleanedUp || !entry) {
218
+ return;
219
+ }
220
+ cleanedUp = true;
221
+ entry.callbacks.delete(callback);
222
+ entry.refCount--;
223
+ if (entry.refCount <= 0) {
224
+ entry.observer.disconnect();
225
+ autoDirectionObservers.delete(autoRoot);
226
+ }
227
+ };
228
+ }
229
+ function observeComponentDirection(hostElement, directionality, onChange) {
230
+ const element = hostElement instanceof ElementRef ? hostElement.nativeElement : hostElement;
231
+ let currentDir = resolveComponentDirection(element, directionality);
232
+ let unobserveAuto = null;
233
+ let observedAutoElement = null;
234
+ const updateAutoContentObserver = () => {
235
+ if (typeof MutationObserver === "undefined" || !element) {
236
+ return;
237
+ }
238
+ let autoRoot = null;
239
+ let current = element;
240
+ while (current) {
241
+ const rawDir = current.getAttribute?.("dir")?.trim().toLowerCase();
242
+ if (rawDir === "auto") {
243
+ autoRoot = current;
244
+ break;
245
+ }
246
+ if (rawDir === "rtl" || rawDir === "ltr") {
247
+ break;
248
+ }
249
+ current = current.parentElement;
250
+ }
251
+ if (autoRoot) {
252
+ if (observedAutoElement !== autoRoot) {
253
+ if (unobserveAuto) {
254
+ unobserveAuto();
255
+ }
256
+ observedAutoElement = autoRoot;
257
+ unobserveAuto = observeAutoDirectionChanges(autoRoot, () => check());
258
+ }
259
+ }
260
+ else {
261
+ if (unobserveAuto) {
262
+ unobserveAuto();
263
+ unobserveAuto = null;
264
+ observedAutoElement = null;
265
+ }
266
+ }
267
+ };
268
+ const check = () => {
269
+ updateAutoContentObserver();
270
+ const nextDir = resolveComponentDirection(element, directionality);
271
+ if (nextDir !== currentDir) {
272
+ currentDir = nextDir;
273
+ onChange(nextDir);
274
+ }
275
+ };
276
+ updateAutoContentObserver();
277
+ const cleanupFns = [];
278
+ if (directionality) {
279
+ const sub = directionality.change.subscribe(dir => {
280
+ if (dir === "rtl" || dir === "ltr") {
281
+ check();
282
+ }
283
+ });
284
+ cleanupFns.push(() => sub.unsubscribe());
285
+ }
286
+ if (typeof MutationObserver !== "undefined") {
287
+ if (element) {
288
+ const elObserver = new MutationObserver(() => check());
289
+ elObserver.observe(element, { attributes: true, attributeFilter: ["dir"] });
290
+ cleanupFns.push(() => elObserver.disconnect());
291
+ const root = element.getRootNode?.();
292
+ if (root && root !== element && root !== element.ownerDocument) {
293
+ const rootObserver = new MutationObserver(() => check());
294
+ rootObserver.observe(root, { attributes: true, attributeFilter: ["dir"], subtree: true });
295
+ cleanupFns.push(() => rootObserver.disconnect());
296
+ }
297
+ if (element.ownerDocument) {
298
+ cleanupFns.push(observeDocumentDirChanges(element.ownerDocument, check));
299
+ }
300
+ }
301
+ }
302
+ cleanupFns.push(() => {
303
+ if (unobserveAuto) {
304
+ unobserveAuto();
305
+ unobserveAuto = null;
306
+ observedAutoElement = null;
307
+ }
308
+ });
309
+ const handle = Object.assign(() => {
310
+ for (const fn of cleanupFns) {
311
+ fn();
312
+ }
313
+ }, {
314
+ check,
315
+ updateAutoObserver: updateAutoContentObserver
316
+ });
317
+ return handle;
318
+ }
319
+ function injectComponentDirection(hostElementRef) {
320
+ const directionality = inject(Directionality, { optional: true });
321
+ const hostRef = hostElementRef ?? inject((ElementRef), { optional: true });
322
+ const destroyRef = inject(DestroyRef, { optional: true });
323
+ const domVersion = signal(0, /* @ts-ignore */
324
+ ...(ngDevMode ? [{ debugName: "domVersion" }] : /* istanbul ignore next */ []));
325
+ let updateAutoObserverFn = () => { };
326
+ if (destroyRef) {
327
+ const cleanup = observeComponentDirection(hostRef, directionality, () => {
328
+ domVersion.update(v => v + 1);
329
+ });
330
+ updateAutoObserverFn = cleanup.updateAutoObserver;
331
+ destroyRef.onDestroy(() => cleanup());
332
+ }
333
+ return computed(() => {
334
+ domVersion();
335
+ updateAutoObserverFn();
336
+ return resolveComponentDirection(hostRef, directionality);
337
+ });
338
+ }
339
+ class MonaDirectionService {
340
+ #directionality = inject(Directionality, { optional: true });
341
+ getDirection(element) {
342
+ return resolveComponentDirection(element, this.#directionality);
343
+ }
344
+ isRtl(element) {
345
+ return this.getDirection(element) === "rtl";
346
+ }
347
+ observeDirection(element, onChange) {
348
+ return observeComponentDirection(element, this.#directionality, onChange);
349
+ }
350
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: MonaDirectionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
351
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: MonaDirectionService, providedIn: "root" }); }
352
+ }
353
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: MonaDirectionService, decorators: [{
354
+ type: Injectable,
355
+ args: [{
356
+ providedIn: "root"
357
+ }]
358
+ }] });
359
+
360
+ function provideMonaI18n(config = {}) {
361
+ return makeEnvironmentProviders([
362
+ {
363
+ provide: MONA_I18N_CONFIG,
364
+ useValue: config
365
+ }
366
+ ]);
367
+ }
368
+
369
+ const numberSymbolsCache = new Map();
370
+ const numberFormatterCache = new Map();
371
+ const numberGroupingCache = new Map();
372
+ function serializeOptions(options) {
373
+ if (!options) {
374
+ return "";
375
+ }
376
+ const keys = Object.keys(options).sort();
377
+ return keys.map(k => `${k}:${String(options[k])}`).join(";");
378
+ }
379
+ function getNumberGroupingPattern(localeId) {
380
+ let pattern = numberGroupingCache.get(localeId);
381
+ if (!pattern) {
382
+ try {
383
+ const formatter = new Intl.NumberFormat(localeId, {
384
+ useGrouping: true,
385
+ maximumFractionDigits: 0
386
+ });
387
+ const parts = formatter.formatToParts(123456789012345);
388
+ const integerParts = parts.filter(p => p.type === "integer");
389
+ const groupParts = parts.filter(p => p.type === "group");
390
+ const groupSeparator = groupParts[0]?.value ?? getNumberSymbols(localeId).group ?? ",";
391
+ let minimumGroupedIntegerDigits = 4;
392
+ try {
393
+ const defaultFormatter = new Intl.NumberFormat(localeId);
394
+ let probe = 1000;
395
+ let digits = 4;
396
+ while (digits <= 8) {
397
+ if (defaultFormatter.formatToParts(probe).some(p => p.type === "group")) {
398
+ minimumGroupedIntegerDigits = digits;
399
+ break;
400
+ }
401
+ probe *= 10;
402
+ digits++;
403
+ }
404
+ }
405
+ catch {
406
+ minimumGroupedIntegerDigits = 4;
407
+ }
408
+ if (integerParts.length >= 2) {
409
+ const primaryStr = integerParts[integerParts.length - 1].value.replace(/[\u061C\u200E\u200F\s]/g, "");
410
+ const secondaryStr = integerParts[integerParts.length - 2].value.replace(/[\u061C\u200E\u200F\s]/g, "");
411
+ const primaryGroupSize = Array.from(primaryStr).length;
412
+ const secondaryGroupSize = Array.from(secondaryStr).length;
413
+ pattern = {
414
+ primaryGroupSize: primaryGroupSize > 0 ? primaryGroupSize : 3,
415
+ secondaryGroupSize: secondaryGroupSize > 0 ? secondaryGroupSize : 3,
416
+ groupSeparator,
417
+ minimumGroupedIntegerDigits
418
+ };
419
+ }
420
+ else {
421
+ pattern = {
422
+ primaryGroupSize: 3,
423
+ secondaryGroupSize: 3,
424
+ groupSeparator,
425
+ minimumGroupedIntegerDigits
426
+ };
427
+ }
428
+ }
429
+ catch {
430
+ const groupSeparator = getNumberSymbols(localeId).group ?? ",";
431
+ pattern = {
432
+ primaryGroupSize: 3,
433
+ secondaryGroupSize: 3,
434
+ groupSeparator,
435
+ minimumGroupedIntegerDigits: 4
436
+ };
437
+ }
438
+ numberGroupingCache.set(localeId, pattern);
439
+ }
440
+ return pattern;
441
+ }
442
+ function getNumberSymbols(localeId) {
443
+ let symbols = numberSymbolsCache.get(localeId);
444
+ if (!symbols) {
445
+ const digitMap = new Map();
446
+ // Seed digit map with common localized scripts as fallback
447
+ for (let i = 0; i <= 9; i++) {
448
+ digitMap.set(String(i), String(i));
449
+ digitMap.set(String.fromCharCode(0x0660 + i), String(i)); // Arabic-Indic
450
+ digitMap.set(String.fromCharCode(0x06f0 + i), String(i)); // Eastern Arabic-Indic / Persian
451
+ digitMap.set(String.fromCharCode(0x09e6 + i), String(i)); // Bengali
452
+ digitMap.set(String.fromCharCode(0x0966 + i), String(i)); // Devanagari
453
+ }
454
+ try {
455
+ const parts = new Intl.NumberFormat(localeId).formatToParts(-12345.6);
456
+ const decimal = parts.find(p => p.type === "decimal")?.value ?? ".";
457
+ const group = parts.find(p => p.type === "group")?.value ?? ",";
458
+ const minus = parts.find(p => p.type === "minusSign")?.value ?? "-";
459
+ // Dynamically query localized digit glyphs for this locale
460
+ try {
461
+ const digitFormatter = new Intl.NumberFormat(localeId, {
462
+ useGrouping: false,
463
+ maximumFractionDigits: 0
464
+ });
465
+ for (let i = 0; i <= 9; i++) {
466
+ const glyph = digitFormatter.format(i).replace(/[\u061C\u200E\u200F\s]/g, "");
467
+ if (glyph) {
468
+ digitMap.set(glyph, String(i));
469
+ }
470
+ }
471
+ }
472
+ catch {
473
+ // Ignore formatter failure
474
+ }
475
+ symbols = { decimal, group, minus, digits: digitMap };
476
+ }
477
+ catch {
478
+ symbols = { decimal: ".", group: ",", minus: "-", digits: digitMap };
479
+ }
480
+ numberSymbolsCache.set(localeId, symbols);
481
+ }
482
+ return symbols;
483
+ }
484
+ function getNumberFormatter(locale, options) {
485
+ const cleanLocale = (locale ?? "").trim() || "en-US";
486
+ const key = `${cleanLocale}:${serializeOptions(options)}`;
487
+ let formatter = numberFormatterCache.get(key);
488
+ if (!formatter) {
489
+ try {
490
+ formatter = new Intl.NumberFormat(cleanLocale, options);
491
+ }
492
+ catch {
493
+ formatter = new Intl.NumberFormat("en-US", options);
494
+ }
495
+ numberFormatterCache.set(key, formatter);
496
+ }
497
+ return formatter;
498
+ }
499
+ function formatNumber(value, locale, options) {
500
+ return getNumberFormatter(locale, options).format(value);
501
+ }
502
+ function normalizeLocalizedDigits(text, localeId) {
503
+ if (!text) {
504
+ return text;
505
+ }
506
+ const symbols = localeId ? getNumberSymbols(localeId) : null;
507
+ let result = "";
508
+ for (const char of text) {
509
+ if (symbols?.digits.has(char)) {
510
+ result += symbols.digits.get(char);
511
+ }
512
+ else {
513
+ const code = char.charCodeAt(0);
514
+ if (code >= 0x0660 && code <= 0x0669) {
515
+ result += String(code - 0x0660);
516
+ }
517
+ else if (code >= 0x06f0 && code <= 0x06f9) {
518
+ result += String(code - 0x06f0);
519
+ }
520
+ else if (code >= 0x09e6 && code <= 0x09ef) {
521
+ result += String(code - 0x09e6);
522
+ }
523
+ else if (code >= 0x0966 && code <= 0x096f) {
524
+ result += String(code - 0x0966);
525
+ }
526
+ else {
527
+ result += char;
528
+ }
529
+ }
530
+ }
531
+ return result;
532
+ }
533
+ function normalizeLocalizedMinus(text, symbols) {
534
+ if (!text) {
535
+ return text;
536
+ }
537
+ let result = text
538
+ .replace(/[\u2212\uFE63\uFF0D]/g, "-")
539
+ .replace(/[\u061C\u200E\u200F]/g, "");
540
+ if (symbols?.minus && symbols.minus !== "-") {
541
+ result = result.replaceAll(symbols.minus, "-");
542
+ }
543
+ return result;
544
+ }
545
+ function normalizeLocalizedInput(text, localeId) {
546
+ const symbols = getNumberSymbols(localeId);
547
+ let cleaned = normalizeLocalizedMinus(text, symbols);
548
+ cleaned = normalizeLocalizedDigits(cleaned, localeId);
549
+ return cleaned;
550
+ }
551
+ function parseLocalizedNumber(text, localeId, options) {
552
+ if (text == null) {
553
+ return null;
554
+ }
555
+ let cleaned = String(text).trim();
556
+ if (cleaned === "") {
557
+ return null;
558
+ }
559
+ const symbols = getNumberSymbols(localeId);
560
+ // Normalize minus signs, bidi controls, and localized digits
561
+ cleaned = normalizeLocalizedMinus(cleaned, symbols);
562
+ cleaned = normalizeLocalizedDigits(cleaned, localeId);
563
+ if (cleaned === "-" || cleaned === "+") {
564
+ return null;
565
+ }
566
+ // Only one leading sign is permitted
567
+ let sign = "";
568
+ if (cleaned.startsWith("-")) {
569
+ sign = "-";
570
+ cleaned = cleaned.slice(1);
571
+ }
572
+ else if (cleaned.startsWith("+")) {
573
+ cleaned = cleaned.slice(1);
574
+ }
575
+ if (cleaned.includes("-") || cleaned.includes("+")) {
576
+ return null;
577
+ }
578
+ const mode = options?.mode ?? (options?.alternateDecimal ? "edit" : "locale");
579
+ if (mode === "locale") {
580
+ const grouping = getNumberGroupingPattern(localeId);
581
+ const groupSep = grouping.groupSeparator;
582
+ const isSpaceGroup = /[ \u00A0\u202F]/.test(groupSep);
583
+ const decimalSep = symbols.decimal;
584
+ // Reject non-accepted control or whitespace characters (tabs, newlines, formfeeds)
585
+ if (/[^\S\u0020\u00A0\u202F]/.test(cleaned)) {
586
+ return null;
587
+ }
588
+ // In strict locale mode, if grouping separator is not space-like, any internal whitespace is invalid
589
+ if (!isSpaceGroup && /[\s\u00A0\u202F]/.test(cleaned)) {
590
+ return null;
591
+ }
592
+ // Split integer and fraction by canonical decimal separator
593
+ let intPart;
594
+ let fracPart = null;
595
+ if (decimalSep && cleaned.includes(decimalSep)) {
596
+ if (cleaned.indexOf(decimalSep) !== cleaned.lastIndexOf(decimalSep)) {
597
+ return null;
598
+ }
599
+ const decimalIdx = cleaned.indexOf(decimalSep);
600
+ intPart = cleaned.slice(0, decimalIdx);
601
+ fracPart = cleaned.slice(decimalIdx + decimalSep.length);
602
+ }
603
+ else {
604
+ // If the string contains an unexpected decimal-like character that is not the group separator, reject
605
+ if (decimalSep === "," && groupSep !== "." && cleaned.includes(".")) {
606
+ return null;
607
+ }
608
+ if (decimalSep === "." && groupSep !== "," && cleaned.includes(",")) {
609
+ return null;
610
+ }
611
+ intPart = cleaned;
612
+ }
613
+ // Fractional part validation
614
+ if (fracPart !== null) {
615
+ // Group separators or whitespace are never permitted in the fractional part
616
+ if (groupSep && fracPart.includes(groupSep)) {
617
+ return null;
618
+ }
619
+ if (/[\s\u00A0\u202F]/.test(fracPart)) {
620
+ return null;
621
+ }
622
+ if (fracPart.length > 0 && !/^\d+$/.test(fracPart)) {
623
+ return null;
624
+ }
625
+ }
626
+ // Integer part validation
627
+ if (intPart.length === 0) {
628
+ if (fracPart === null || fracPart.length === 0) {
629
+ return null;
630
+ }
631
+ intPart = "0";
632
+ }
633
+ else {
634
+ let intGroups;
635
+ let hasGroup = false;
636
+ if (isSpaceGroup) {
637
+ if (/[ \u00A0\u202F]/.test(intPart)) {
638
+ hasGroup = true;
639
+ // Splitting by single accepted space character preserves empty strings for consecutive spaces
640
+ intGroups = intPart.split(/[ \u00A0\u202F]/);
641
+ }
642
+ else {
643
+ intGroups = [intPart];
644
+ }
645
+ }
646
+ else {
647
+ if (groupSep && intPart.includes(groupSep)) {
648
+ hasGroup = true;
649
+ intGroups = intPart.split(groupSep);
650
+ }
651
+ else {
652
+ intGroups = [intPart];
653
+ }
654
+ }
655
+ if (hasGroup) {
656
+ if (intGroups.length < 2) {
657
+ return null;
658
+ }
659
+ // Canonical strict check: must meet locale's minimum grouping threshold
660
+ const totalGroupedDigits = intGroups.join("").length;
661
+ if (totalGroupedDigits < grouping.minimumGroupedIntegerDigits) {
662
+ return null;
663
+ }
664
+ // Last (rightmost) group: must match primaryGroupSize digits
665
+ const lastGroup = intGroups[intGroups.length - 1];
666
+ if (lastGroup.length !== grouping.primaryGroupSize || !/^\d+$/.test(lastGroup)) {
667
+ return null;
668
+ }
669
+ // Intermediate groups: must match secondaryGroupSize digits
670
+ for (let i = 1; i < intGroups.length - 1; i++) {
671
+ const midGroup = intGroups[i];
672
+ if (midGroup.length !== grouping.secondaryGroupSize || !/^\d+$/.test(midGroup)) {
673
+ return null;
674
+ }
675
+ }
676
+ // First group: must have 1..secondaryGroupSize digits
677
+ const firstGroup = intGroups[0];
678
+ if (firstGroup.length < 1 ||
679
+ firstGroup.length > grouping.secondaryGroupSize ||
680
+ !/^\d+$/.test(firstGroup)) {
681
+ return null;
682
+ }
683
+ intPart = intGroups.join("");
684
+ }
685
+ else {
686
+ // Ungrouped integer must consist solely of digits
687
+ if (!/^\d+$/.test(intPart)) {
688
+ return null;
689
+ }
690
+ }
691
+ }
692
+ const normalizedStr = sign + intPart + (fracPart && fracPart.length > 0 ? "." + fracPart : "");
693
+ const num = Number(normalizedStr);
694
+ return Number.isFinite(num) ? num : null;
695
+ }
696
+ else {
697
+ // mode === "edit": editor buffer grammar with exactly one decimal separator (locale primary or alternate)
698
+ // No group separators or internal whitespace permitted in editor buffer
699
+ if (/[\s\u00A0\u202F]/.test(cleaned)) {
700
+ return null;
701
+ }
702
+ const primaryDec = symbols.decimal || ".";
703
+ const candidateSeparators = new Set();
704
+ candidateSeparators.add(primaryDec);
705
+ if (primaryDec === ".") {
706
+ candidateSeparators.add(",");
707
+ }
708
+ else if (primaryDec === ",") {
709
+ candidateSeparators.add(".");
710
+ }
711
+ else {
712
+ candidateSeparators.add(".");
713
+ candidateSeparators.add(",");
714
+ }
715
+ if (primaryDec === "\u066B") {
716
+ candidateSeparators.add(".");
717
+ candidateSeparators.add(",");
718
+ }
719
+ if (primaryDec === "/") {
720
+ candidateSeparators.add(".");
721
+ candidateSeparators.add(",");
722
+ }
723
+ let foundSep = null;
724
+ let sepIndex = -1;
725
+ for (let i = 0; i < cleaned.length; i++) {
726
+ for (const sep of candidateSeparators) {
727
+ if (cleaned.startsWith(sep, i)) {
728
+ if (foundSep !== null) {
729
+ // More than one separator (or repeated alternate separators) is rejected
730
+ return null;
731
+ }
732
+ foundSep = sep;
733
+ sepIndex = i;
734
+ i += sep.length - 1;
735
+ break;
736
+ }
737
+ }
738
+ }
739
+ // Reject if any non-candidate dot or comma remains
740
+ if (cleaned.includes(".") && !candidateSeparators.has(".")) {
741
+ return null;
742
+ }
743
+ if (cleaned.includes(",") && !candidateSeparators.has(",")) {
744
+ return null;
745
+ }
746
+ let intPart;
747
+ let fracPart;
748
+ if (foundSep !== null) {
749
+ intPart = cleaned.slice(0, sepIndex);
750
+ fracPart = cleaned.slice(sepIndex + foundSep.length);
751
+ if (intPart.length > 0 && !/^\d+$/.test(intPart)) {
752
+ return null;
753
+ }
754
+ if (fracPart.length > 0 && !/^\d+$/.test(fracPart)) {
755
+ return null;
756
+ }
757
+ if (intPart.length === 0 && fracPart.length === 0) {
758
+ return null;
759
+ }
760
+ }
761
+ else {
762
+ if (!/^\d+$/.test(cleaned)) {
763
+ return null;
764
+ }
765
+ intPart = cleaned;
766
+ fracPart = "";
767
+ }
768
+ const normalizedStr = sign +
769
+ (intPart.length > 0 ? intPart : "0") +
770
+ (fracPart.length > 0 ? "." + fracPart : cleaned.endsWith(foundSep ?? "") ? "" : "");
771
+ const num = Number(normalizedStr);
772
+ return Number.isFinite(num) ? num : null;
773
+ }
774
+ }
775
+ function validateLocalizedNumber(text, localeId, options) {
776
+ if (text == null) {
777
+ return { value: null, valid: true, fractionDigits: 0 };
778
+ }
779
+ const trimmed = String(text).trim();
780
+ if (trimmed === "" || trimmed === "-" || trimmed === "+") {
781
+ return { value: null, valid: true, fractionDigits: 0 };
782
+ }
783
+ const mode = options?.mode ?? "locale";
784
+ const parsed = parseLocalizedNumber(trimmed, localeId, { mode });
785
+ if (parsed === null || !Number.isFinite(parsed)) {
786
+ return { value: null, valid: false, fractionDigits: 0 };
787
+ }
788
+ // Determine the number of fraction digits from the source string
789
+ const symbols = getNumberSymbols(localeId);
790
+ let normalized = normalizeLocalizedMinus(trimmed, symbols);
791
+ normalized = normalizeLocalizedDigits(normalized, localeId);
792
+ normalized = normalized.replace(/[ \u00A0\u202F]/g, "");
793
+ let fractionDigits = 0;
794
+ if (mode === "locale") {
795
+ if (symbols.decimal && normalized.includes(symbols.decimal)) {
796
+ const fracPart = normalized
797
+ .slice(normalized.lastIndexOf(symbols.decimal) + symbols.decimal.length)
798
+ .replace(/\D/g, "");
799
+ fractionDigits = fracPart.length;
800
+ }
801
+ else if (normalized.includes("\u066B")) {
802
+ const fracPart = normalized.slice(normalized.lastIndexOf("\u066B") + 1).replace(/\D/g, "");
803
+ fractionDigits = fracPart.length;
804
+ }
805
+ }
806
+ else {
807
+ let sep = null;
808
+ if (symbols.decimal === ",") {
809
+ if (normalized.includes(",")) {
810
+ sep = ",";
811
+ }
812
+ else if (normalized.includes(".")) {
813
+ const dotParts = normalized.split(".");
814
+ if (dotParts.length === 2) {
815
+ sep = ".";
816
+ }
817
+ }
818
+ }
819
+ else {
820
+ if (symbols.decimal && symbols.decimal !== "." && symbols.decimal !== "," && normalized.includes(symbols.decimal)) {
821
+ sep = symbols.decimal;
822
+ }
823
+ else if (normalized.includes(".")) {
824
+ sep = ".";
825
+ }
826
+ else if (normalized.includes("\u066B")) {
827
+ sep = "\u066B";
828
+ }
829
+ else if (normalized.includes("/")) {
830
+ sep = "/";
831
+ }
832
+ else if (normalized.includes(",")) {
833
+ const commaParts = normalized.split(",");
834
+ if (commaParts.length === 2) {
835
+ sep = ",";
836
+ }
837
+ }
838
+ }
839
+ if (sep != null) {
840
+ const fracPart = normalized.slice(normalized.lastIndexOf(sep) + sep.length).replace(/\D/g, "");
841
+ fractionDigits = fracPart.length;
842
+ }
843
+ }
844
+ if (options?.decimals !== undefined && fractionDigits > options.decimals) {
845
+ return { value: parsed, valid: false, fractionDigits };
846
+ }
847
+ return { value: parsed, valid: true, fractionDigits };
848
+ }
849
+ function validateLocalizedNumberEdit(text, localeId, options) {
850
+ if (text == null) {
851
+ return { valid: true, complete: false, value: null };
852
+ }
853
+ const raw = String(text);
854
+ if (raw === "") {
855
+ return { valid: true, complete: false, value: null };
856
+ }
857
+ // Reject control or whitespace characters in interactive typing
858
+ if (/[\s\u00A0\u202F]/.test(raw)) {
859
+ return { valid: false, complete: false, value: null };
860
+ }
861
+ const symbols = getNumberSymbols(localeId);
862
+ // Normalize minus signs and bidi controls
863
+ let normalized = normalizeLocalizedMinus(raw, symbols);
864
+ // Normalize localized digits to ASCII
865
+ normalized = normalizeLocalizedDigits(normalized, localeId);
866
+ // Sign handling
867
+ const allowSign = options?.allowSign ?? true;
868
+ if (normalized.startsWith("-") || normalized.startsWith("+")) {
869
+ if (!allowSign) {
870
+ return { valid: false, complete: false, value: null };
871
+ }
872
+ normalized = normalized.slice(1);
873
+ }
874
+ if (normalized.includes("-") || normalized.includes("+")) {
875
+ return { valid: false, complete: false, value: null };
876
+ }
877
+ // If input was just "-" or "+"
878
+ if (normalized === "") {
879
+ return { valid: true, complete: false, value: null };
880
+ }
881
+ // Identify allowed decimal separators
882
+ const primaryDec = symbols.decimal || ".";
883
+ // Candidate separators: primary decimal, plus alternate '.' or ','
884
+ const candidateSeparators = new Set();
885
+ candidateSeparators.add(primaryDec);
886
+ if (primaryDec === ".") {
887
+ candidateSeparators.add(",");
888
+ }
889
+ else if (primaryDec === ",") {
890
+ candidateSeparators.add(".");
891
+ }
892
+ else {
893
+ candidateSeparators.add(".");
894
+ candidateSeparators.add(",");
895
+ }
896
+ if (primaryDec === "\u066B") {
897
+ candidateSeparators.add(".");
898
+ candidateSeparators.add(",");
899
+ }
900
+ // Count how many separators from the candidate set appear
901
+ let foundSep = null;
902
+ let sepIndex = -1;
903
+ for (let i = 0; i < normalized.length; i++) {
904
+ for (const sep of candidateSeparators) {
905
+ if (normalized.startsWith(sep, i)) {
906
+ if (foundSep !== null) {
907
+ // More than one separator is rejected in edit mode
908
+ return { valid: false, complete: false, value: null };
909
+ }
910
+ foundSep = sep;
911
+ sepIndex = i;
912
+ i += sep.length - 1;
913
+ break;
914
+ }
915
+ }
916
+ }
917
+ const decimals = options?.decimals ?? 0;
918
+ if (foundSep !== null) {
919
+ if (decimals === 0) {
920
+ // No decimal point permitted when decimals === 0
921
+ return { valid: false, complete: false, value: null };
922
+ }
923
+ const intPart = normalized.slice(0, sepIndex);
924
+ const fracPart = normalized.slice(sepIndex + foundSep.length);
925
+ // Integer part before separator must consist purely of ASCII digits (or empty, e.g. ".5")
926
+ if (intPart.length > 0 && !/^\d+$/.test(intPart)) {
927
+ return { valid: false, complete: false, value: null };
928
+ }
929
+ // Fractional part after separator must consist purely of ASCII digits (or empty, e.g. "12.")
930
+ if (fracPart.length > 0 && !/^\d+$/.test(fracPart)) {
931
+ return { valid: false, complete: false, value: null };
932
+ }
933
+ // Count fraction digits using normalized ASCII characters (safe against UTF-16 astral splitting)
934
+ if (fracPart.length > decimals) {
935
+ return { valid: false, complete: false, value: null };
936
+ }
937
+ const parsed = parseLocalizedNumber(raw, localeId, { mode: "edit" });
938
+ const complete = fracPart.length > 0 && (intPart.length > 0 || fracPart.length > 0);
939
+ return {
940
+ valid: true,
941
+ complete,
942
+ value: parsed
943
+ };
944
+ }
945
+ // No separator found: must be purely ASCII digits
946
+ if (!/^\d+$/.test(normalized)) {
947
+ return { valid: false, complete: false, value: null };
948
+ }
949
+ const parsed = parseLocalizedNumber(raw, localeId, { mode: "edit" });
950
+ return {
951
+ valid: true,
952
+ complete: true,
953
+ value: parsed
954
+ };
955
+ }
956
+
957
+ /**
958
+ * Normalizes a locale string to ensure it uses the Gregorian calendar system
959
+ * and doesn't contain a conflicting -u-ca-* extension.
960
+ */
961
+ function normalizeGregorianLocale(localeId) {
962
+ const trimmed = (localeId ?? "").trim();
963
+ if (!trimmed) {
964
+ return trimmed;
965
+ }
966
+ try {
967
+ if (typeof Intl !== "undefined" && typeof Intl.Locale === "function") {
968
+ const loc = new Intl.Locale(trimmed, { calendar: "gregory" });
969
+ return loc.toString();
970
+ }
971
+ }
972
+ catch {
973
+ // Fallback safely if localeId is malformed
974
+ }
975
+ return trimmed;
976
+ }
977
+ /**
978
+ * Creates a Luxon DateTime from a Date instance, reconfigured to the specified locale
979
+ * with an explicit Gregorian output calendar.
980
+ */
981
+ function gregorianDateTime(date, localeId) {
982
+ const locale = normalizeGregorianLocale(localeId);
983
+ return DateTime.fromJSDate(date).reconfigure({
984
+ locale,
985
+ outputCalendar: "gregory"
986
+ });
987
+ }
988
+ /**
989
+ * Creates a Luxon DateTime from object components (year, month, etc.), reconfigured to the
990
+ * specified locale with an explicit Gregorian output calendar.
991
+ */
992
+ function gregorianDateTimeFromObject(obj, localeId) {
993
+ const locale = normalizeGregorianLocale(localeId);
994
+ return DateTime.fromObject(obj).reconfigure({
995
+ locale,
996
+ outputCalendar: "gregory"
997
+ });
998
+ }
999
+ /**
1000
+ * Formats a date using locale-native token ordering and explicit Gregorian calendar.
1001
+ */
1002
+ function formatGregorianDateToLocaleString(date, localeId, options) {
1003
+ const locale = normalizeGregorianLocale(localeId);
1004
+ return gregorianDateTime(date, locale).toLocaleString({
1005
+ ...options
1006
+ });
1007
+ }
1008
+ /**
1009
+ * Regular expression matching Unicode bidirectional formatting controls
1010
+ * (such as LRM, RLM, ALM, embeddings, overrides, and isolates).
1011
+ */
1012
+ const BIDI_CONTROL_REGEX = /[\u061C\u200E\u200F\u202A-\u202E\u2066-\u2069]/g;
1013
+ /**
1014
+ * Strips Unicode bidirectional formatting controls from a string.
1015
+ */
1016
+ function stripBidiControls(value) {
1017
+ return value.replace(BIDI_CONTROL_REGEX, "");
1018
+ }
1019
+ /**
1020
+ * Sanitizes date/time text by stripping invisible bidi controls and
1021
+ * normalizing typographic/non-breaking spaces to standard ASCII spaces.
1022
+ */
1023
+ function sanitizeDateText(value) {
1024
+ return stripBidiControls(value).replace(/[\u00A0\u2009\u202F]/g, " ");
1025
+ }
1026
+ /**
1027
+ * Parses a date string using the specified format and locale, forcing Gregorian calendar.
1028
+ * Localized digits are normalized first to support locales that use native numbering systems.
1029
+ */
1030
+ function parseGregorianDate(text, format, localeId) {
1031
+ const locale = normalizeGregorianLocale(localeId);
1032
+ let dt = DateTime.fromFormat(text, format, { locale, outputCalendar: "gregory" });
1033
+ if (!dt.isValid) {
1034
+ const sanitizedText = sanitizeDateText(text);
1035
+ const sanitizedFormat = sanitizeDateText(format);
1036
+ dt = DateTime.fromFormat(sanitizedText, sanitizedFormat, { locale, outputCalendar: "gregory" });
1037
+ if (!dt.isValid) {
1038
+ let normalizedText = normalizeLocalizedDigits(sanitizedText, locale);
1039
+ let latnLocale = locale;
1040
+ try {
1041
+ if (typeof Intl !== "undefined" && typeof Intl.Locale === "function") {
1042
+ latnLocale = new Intl.Locale(locale, { numberingSystem: "latn" }).toString();
1043
+ }
1044
+ }
1045
+ catch {
1046
+ // fallback
1047
+ }
1048
+ dt = DateTime.fromFormat(normalizedText, sanitizedFormat, { locale: latnLocale, outputCalendar: "gregory" });
1049
+ if (!dt.isValid) {
1050
+ dt = DateTime.fromFormat(normalizedText, sanitizedFormat, { locale, outputCalendar: "gregory" });
1051
+ }
1052
+ if (!dt.isValid) {
1053
+ const effectiveLocale = latnLocale !== locale ? latnLocale : locale;
1054
+ if (sanitizedFormat.includes(". ") && !normalizedText.includes(". ")) {
1055
+ const textWithDotSpaces = normalizedText.replace(/\.(?!\s|$)/g, ". ");
1056
+ dt = DateTime.fromFormat(textWithDotSpaces, sanitizedFormat, {
1057
+ locale: effectiveLocale,
1058
+ outputCalendar: "gregory"
1059
+ });
1060
+ if (!dt.isValid && effectiveLocale !== locale) {
1061
+ dt = DateTime.fromFormat(textWithDotSpaces, sanitizedFormat, {
1062
+ locale,
1063
+ outputCalendar: "gregory"
1064
+ });
1065
+ }
1066
+ if (dt.isValid) {
1067
+ return dt;
1068
+ }
1069
+ normalizedText = textWithDotSpaces;
1070
+ }
1071
+ if (sanitizedFormat.includes("dd. ") &&
1072
+ /(\b\d{4}\.\s*\d{1,2}\.\s*\d{1,2})\.?\s+/.test(normalizedText)) {
1073
+ const withDotBeforeTime = normalizedText.replace(/(\b\d{4}\.\s*\d{1,2}\.\s*\d{1,2})\.?\s+/, (_match, datePart) => `${datePart}. `);
1074
+ dt = DateTime.fromFormat(withDotBeforeTime, sanitizedFormat, {
1075
+ locale: effectiveLocale,
1076
+ outputCalendar: "gregory"
1077
+ });
1078
+ if (!dt.isValid && effectiveLocale !== locale) {
1079
+ dt = DateTime.fromFormat(withDotBeforeTime, sanitizedFormat, {
1080
+ locale,
1081
+ outputCalendar: "gregory"
1082
+ });
1083
+ }
1084
+ if (dt.isValid) {
1085
+ return dt;
1086
+ }
1087
+ }
1088
+ const trimmedFormat = sanitizedFormat.trimEnd();
1089
+ const trimmedText = normalizedText.trim();
1090
+ if (trimmedFormat.endsWith(".")) {
1091
+ const textWithDot = trimmedText.endsWith(".") ? trimmedText : trimmedText + ".";
1092
+ dt = DateTime.fromFormat(textWithDot, trimmedFormat, {
1093
+ locale: effectiveLocale,
1094
+ outputCalendar: "gregory"
1095
+ });
1096
+ if (!dt.isValid && effectiveLocale !== locale) {
1097
+ dt = DateTime.fromFormat(textWithDot, trimmedFormat, {
1098
+ locale,
1099
+ outputCalendar: "gregory"
1100
+ });
1101
+ }
1102
+ }
1103
+ }
1104
+ }
1105
+ }
1106
+ return dt;
1107
+ }
1108
+
1109
+ /**
1110
+ * Pinned Unicode CLDR release: 46 / Unicode 16.0
1111
+ * Sources:
1112
+ * - cldr-core/supplemental/weekData.json (weekData/firstDay)
1113
+ * - cldr-core/supplemental/likelySubtags.json
1114
+ * Default territory ("001") is Monday.
1115
+ * Generated by scripts/generate-cldr-week-data.ts from the pinned CLDR dataset.
1116
+ * Update from the pinned CLDR dataset rather than editing ad hoc.
1117
+ */
1118
+ const CLDR_WEEK_DATA_VERSION = "46";
1119
+ const CLDR_LIKELY_SUBTAGS_VERSION = "46";
1120
+ // Territories where firstDay is Friday (CLDR weekData/firstDay day="fri")
1121
+ const FRIDAY_FIRST_REGIONS = new Set([
1122
+ "MV"
1123
+ ]);
1124
+ // Territories where firstDay is Saturday (CLDR weekData/firstDay day="sat")
1125
+ const SATURDAY_FIRST_REGIONS = new Set([
1126
+ "AF",
1127
+ "BH",
1128
+ "DJ",
1129
+ "DZ",
1130
+ "EG",
1131
+ "IQ",
1132
+ "IR",
1133
+ "JO",
1134
+ "KW",
1135
+ "LY",
1136
+ "OM",
1137
+ "QA",
1138
+ "SD",
1139
+ "SY"
1140
+ ]);
1141
+ // Territories where firstDay is Sunday (CLDR weekData/firstDay day="sun")
1142
+ const SUNDAY_FIRST_REGIONS = new Set([
1143
+ "AG",
1144
+ "AS",
1145
+ "BD",
1146
+ "BR",
1147
+ "BS",
1148
+ "BT",
1149
+ "BW",
1150
+ "BZ",
1151
+ "CA",
1152
+ "CO",
1153
+ "DM",
1154
+ "DO",
1155
+ "ET",
1156
+ "GT",
1157
+ "GU",
1158
+ "HK",
1159
+ "HN",
1160
+ "ID",
1161
+ "IL",
1162
+ "IN",
1163
+ "JM",
1164
+ "JP",
1165
+ "KE",
1166
+ "KH",
1167
+ "KR",
1168
+ "LA",
1169
+ "MH",
1170
+ "MM",
1171
+ "MO",
1172
+ "MT",
1173
+ "MX",
1174
+ "MZ",
1175
+ "NI",
1176
+ "NP",
1177
+ "PA",
1178
+ "PE",
1179
+ "PH",
1180
+ "PK",
1181
+ "PR",
1182
+ "PT",
1183
+ "PY",
1184
+ "SA",
1185
+ "SG",
1186
+ "SV",
1187
+ "TH",
1188
+ "TT",
1189
+ "TW",
1190
+ "UM",
1191
+ "US",
1192
+ "VE",
1193
+ "VI",
1194
+ "WS",
1195
+ "YE",
1196
+ "ZA",
1197
+ "ZW"
1198
+ ]);
1199
+ // Base language, undefined-language, and language-script tags whose CLDR likely territory is Friday-first
1200
+ const LIKELY_FRIDAY_FIRST_TAGS = new Set([
1201
+ "dv",
1202
+ "und-Diak",
1203
+ "und-Thaa"
1204
+ ]);
1205
+ // Base language, undefined-language, and language-script tags whose CLDR likely territory is Saturday-first
1206
+ const LIKELY_SATURDAY_FIRST_TAGS = new Set([
1207
+ "aao",
1208
+ "abv",
1209
+ "acm",
1210
+ "acx",
1211
+ "acz",
1212
+ "adf",
1213
+ "ae",
1214
+ "aec",
1215
+ "aee",
1216
+ "afb",
1217
+ "aii",
1218
+ "aiq",
1219
+ "akk",
1220
+ "amw",
1221
+ "apc",
1222
+ "ar",
1223
+ "arc",
1224
+ "arc-Hatr",
1225
+ "arc-Nbat",
1226
+ "arc-Palm",
1227
+ "arq",
1228
+ "arz",
1229
+ "ask",
1230
+ "atn",
1231
+ "auj",
1232
+ "avd",
1233
+ "avl",
1234
+ "ayl",
1235
+ "ayp",
1236
+ "az-Arab",
1237
+ "azb",
1238
+ "bdi",
1239
+ "bej",
1240
+ "bhm",
1241
+ "bjm",
1242
+ "bqi",
1243
+ "brk",
1244
+ "bsh",
1245
+ "ckb",
1246
+ "cop",
1247
+ "daj",
1248
+ "dec",
1249
+ "def",
1250
+ "dgl",
1251
+ "dil",
1252
+ "egy",
1253
+ "esh",
1254
+ "fa",
1255
+ "fay",
1256
+ "faz",
1257
+ "fia",
1258
+ "fvr",
1259
+ "gbz",
1260
+ "gha",
1261
+ "glh",
1262
+ "glk",
1263
+ "gwt",
1264
+ "gza",
1265
+ "gzi",
1266
+ "hac",
1267
+ "haz",
1268
+ "hbn",
1269
+ "hoh",
1270
+ "hrz",
1271
+ "hss",
1272
+ "isk",
1273
+ "jat",
1274
+ "jbn",
1275
+ "jle",
1276
+ "jum",
1277
+ "kab",
1278
+ "kcp",
1279
+ "kcy",
1280
+ "kec",
1281
+ "keg",
1282
+ "kfm",
1283
+ "kgo",
1284
+ "kho",
1285
+ "kib",
1286
+ "kko",
1287
+ "klj",
1288
+ "kmz",
1289
+ "kqd",
1290
+ "ktl",
1291
+ "ku-Arab",
1292
+ "lhs",
1293
+ "liu",
1294
+ "lki",
1295
+ "lmd",
1296
+ "lrc",
1297
+ "lrl",
1298
+ "lro",
1299
+ "lsa",
1300
+ "luv",
1301
+ "luz",
1302
+ "mhj",
1303
+ "mid",
1304
+ "mls",
1305
+ "mnj",
1306
+ "mor",
1307
+ "myz",
1308
+ "mzn",
1309
+ "nli",
1310
+ "ntz",
1311
+ "nyi",
1312
+ "nyq",
1313
+ "oar",
1314
+ "obm",
1315
+ "otr",
1316
+ "pal",
1317
+ "pbt",
1318
+ "peo",
1319
+ "phv",
1320
+ "prc",
1321
+ "prd",
1322
+ "ps",
1323
+ "psh",
1324
+ "psi",
1325
+ "qxq",
1326
+ "rdb",
1327
+ "rmt",
1328
+ "sdb",
1329
+ "sdf",
1330
+ "sdg",
1331
+ "sdh",
1332
+ "sgr",
1333
+ "sgy",
1334
+ "shj",
1335
+ "shm",
1336
+ "shv",
1337
+ "shw",
1338
+ "shy",
1339
+ "siy",
1340
+ "siz",
1341
+ "smy",
1342
+ "sqo",
1343
+ "srz",
1344
+ "sts",
1345
+ "syn",
1346
+ "syr",
1347
+ "tag",
1348
+ "taz",
1349
+ "tbi",
1350
+ "teq",
1351
+ "tey",
1352
+ "thv",
1353
+ "tic",
1354
+ "tjo",
1355
+ "tks",
1356
+ "tov",
1357
+ "tra",
1358
+ "trm",
1359
+ "udu",
1360
+ "uga",
1361
+ "und-Arab",
1362
+ "und-Armi",
1363
+ "und-Avst",
1364
+ "und-Copt",
1365
+ "und-Egyp",
1366
+ "und-Elym",
1367
+ "und-Hatr",
1368
+ "und-Mand",
1369
+ "und-Merc",
1370
+ "und-Mero",
1371
+ "und-Nbat",
1372
+ "und-Palm",
1373
+ "und-Phli",
1374
+ "und-Prti",
1375
+ "und-Syrc",
1376
+ "und-Ugar",
1377
+ "und-Xpeo",
1378
+ "und-Xsux",
1379
+ "uz-Arab",
1380
+ "uzs",
1381
+ "vaf",
1382
+ "vmh",
1383
+ "wbk",
1384
+ "wsv",
1385
+ "xkc",
1386
+ "xkj",
1387
+ "xkp",
1388
+ "xly",
1389
+ "xmr",
1390
+ "xnz",
1391
+ "xom",
1392
+ "xpr",
1393
+ "xtc",
1394
+ "xtq",
1395
+ "xvi",
1396
+ "zag",
1397
+ "zmo",
1398
+ "zum"
1399
+ ]);
1400
+ // Base language, undefined-language, and language-script tags whose CLDR likely territory is Sunday-first
1401
+ const LIKELY_SUNDAY_FIRST_TAGS = new Set([
1402
+ "aa",
1403
+ "aaf",
1404
+ "aan",
1405
+ "aap",
1406
+ "aaq",
1407
+ "aax",
1408
+ "aaz",
1409
+ "abc",
1410
+ "abd",
1411
+ "abe",
1412
+ "abl",
1413
+ "abp",
1414
+ "abs",
1415
+ "abx",
1416
+ "abz",
1417
+ "aca",
1418
+ "ace",
1419
+ "acq",
1420
+ "acr",
1421
+ "acs",
1422
+ "acv",
1423
+ "acw",
1424
+ "adi",
1425
+ "adl",
1426
+ "adn",
1427
+ "adr",
1428
+ "adw",
1429
+ "aeq",
1430
+ "af",
1431
+ "afs",
1432
+ "afz",
1433
+ "aga",
1434
+ "agf",
1435
+ "agi",
1436
+ "agj",
1437
+ "agk",
1438
+ "agn",
1439
+ "agr",
1440
+ "agt",
1441
+ "agu",
1442
+ "agv",
1443
+ "agy",
1444
+ "agz",
1445
+ "ahg",
1446
+ "ahh",
1447
+ "ahk",
1448
+ "aho",
1449
+ "ahr",
1450
+ "aht",
1451
+ "aig",
1452
+ "aij",
1453
+ "aim",
1454
+ "ain",
1455
+ "aio",
1456
+ "aip",
1457
+ "air",
1458
+ "ait",
1459
+ "aiw",
1460
+ "ajz",
1461
+ "akb",
1462
+ "akc",
1463
+ "akg",
1464
+ "akl",
1465
+ "akz",
1466
+ "ale",
1467
+ "alj",
1468
+ "alk",
1469
+ "all",
1470
+ "alo",
1471
+ "alp",
1472
+ "alq",
1473
+ "alw",
1474
+ "am",
1475
+ "ama",
1476
+ "amc",
1477
+ "ame",
1478
+ "amf",
1479
+ "ami",
1480
+ "amk",
1481
+ "amq",
1482
+ "amr",
1483
+ "ams",
1484
+ "amu",
1485
+ "amv",
1486
+ "ana",
1487
+ "anb",
1488
+ "and",
1489
+ "anl",
1490
+ "anm",
1491
+ "ano",
1492
+ "anp",
1493
+ "anq",
1494
+ "anr",
1495
+ "ans",
1496
+ "anu",
1497
+ "aoc",
1498
+ "aol",
1499
+ "aos",
1500
+ "aot",
1501
+ "aoz",
1502
+ "apf",
1503
+ "apg",
1504
+ "aph",
1505
+ "api",
1506
+ "apj",
1507
+ "apk",
1508
+ "apl",
1509
+ "apm",
1510
+ "apn",
1511
+ "apt",
1512
+ "apu",
1513
+ "apv",
1514
+ "apw",
1515
+ "apx",
1516
+ "apy",
1517
+ "aqm",
1518
+ "aqn",
1519
+ "aqt",
1520
+ "aqz",
1521
+ "arh",
1522
+ "ari",
1523
+ "arj",
1524
+ "ark",
1525
+ "arl",
1526
+ "arp",
1527
+ "arr",
1528
+ "ars",
1529
+ "aru",
1530
+ "arx",
1531
+ "as",
1532
+ "asb",
1533
+ "asc",
1534
+ "ase",
1535
+ "ash",
1536
+ "asi",
1537
+ "asl",
1538
+ "asn",
1539
+ "asr",
1540
+ "asu",
1541
+ "asy",
1542
+ "asz",
1543
+ "atc",
1544
+ "atd",
1545
+ "atj",
1546
+ "atk",
1547
+ "atl",
1548
+ "atm",
1549
+ "atp",
1550
+ "atq",
1551
+ "atr",
1552
+ "ats",
1553
+ "att",
1554
+ "atw",
1555
+ "atx",
1556
+ "atz",
1557
+ "auq",
1558
+ "auu",
1559
+ "auw",
1560
+ "avo",
1561
+ "avs",
1562
+ "avv",
1563
+ "awa",
1564
+ "awe",
1565
+ "awh",
1566
+ "awn",
1567
+ "awr",
1568
+ "aws",
1569
+ "awt",
1570
+ "awu",
1571
+ "awv",
1572
+ "awy",
1573
+ "axg",
1574
+ "ayc",
1575
+ "ayh",
1576
+ "ayn",
1577
+ "ayo",
1578
+ "ays",
1579
+ "ayt",
1580
+ "ayz",
1581
+ "azd",
1582
+ "azg",
1583
+ "azm",
1584
+ "azn",
1585
+ "azt",
1586
+ "azz",
1587
+ "bac",
1588
+ "bae",
1589
+ "bah",
1590
+ "baj",
1591
+ "bal",
1592
+ "ban",
1593
+ "bao",
1594
+ "bap",
1595
+ "bap-Krai",
1596
+ "bay",
1597
+ "bbc",
1598
+ "bcd",
1599
+ "bcq",
1600
+ "bcr",
1601
+ "bdb",
1602
+ "bdc",
1603
+ "bdl",
1604
+ "bdv",
1605
+ "bdw",
1606
+ "bdx",
1607
+ "bdz",
1608
+ "bea",
1609
+ "bed",
1610
+ "bee",
1611
+ "bei",
1612
+ "bep",
1613
+ "beu",
1614
+ "bew",
1615
+ "bfb",
1616
+ "bfe",
1617
+ "bfg",
1618
+ "bfq",
1619
+ "bft",
1620
+ "bfu",
1621
+ "bfw",
1622
+ "bfx",
1623
+ "bfy",
1624
+ "bfz",
1625
+ "bgb",
1626
+ "bgc",
1627
+ "bgd",
1628
+ "bgg",
1629
+ "bgi",
1630
+ "bgn",
1631
+ "bgp",
1632
+ "bgq",
1633
+ "bgr",
1634
+ "bgs",
1635
+ "bgv",
1636
+ "bgw",
1637
+ "bgy",
1638
+ "bgz",
1639
+ "bha",
1640
+ "bhb",
1641
+ "bhc",
1642
+ "bhd",
1643
+ "bhe",
1644
+ "bhh",
1645
+ "bhi",
1646
+ "bhj",
1647
+ "bho",
1648
+ "bhp",
1649
+ "bhq",
1650
+ "bht",
1651
+ "bhu",
1652
+ "bhv",
1653
+ "bhw",
1654
+ "bhz",
1655
+ "bik",
1656
+ "biu",
1657
+ "biy",
1658
+ "bjf",
1659
+ "bji",
1660
+ "bjj",
1661
+ "bjn",
1662
+ "bjx",
1663
+ "bkd",
1664
+ "bkk",
1665
+ "bkl",
1666
+ "bkn",
1667
+ "bkq",
1668
+ "bkr",
1669
+ "bks",
1670
+ "bku",
1671
+ "bkz",
1672
+ "bla",
1673
+ "blc",
1674
+ "bld",
1675
+ "blf",
1676
+ "blj",
1677
+ "blk",
1678
+ "bln",
1679
+ "bls",
1680
+ "blw",
1681
+ "blx",
1682
+ "blz",
1683
+ "bmj",
1684
+ "bmr",
1685
+ "bn",
1686
+ "bna",
1687
+ "bnc",
1688
+ "bnd",
1689
+ "bne",
1690
+ "bnf",
1691
+ "bnj",
1692
+ "bnn",
1693
+ "bno",
1694
+ "bnq",
1695
+ "bns",
1696
+ "bnu",
1697
+ "bnv",
1698
+ "boa",
1699
+ "bob",
1700
+ "bor",
1701
+ "bpg",
1702
+ "bpo",
1703
+ "bpp",
1704
+ "bpq",
1705
+ "bpr",
1706
+ "bps",
1707
+ "bpv",
1708
+ "bpx",
1709
+ "bpy",
1710
+ "bpz",
1711
+ "bqb",
1712
+ "bqq",
1713
+ "bqr",
1714
+ "bra",
1715
+ "brb",
1716
+ "brd",
1717
+ "brh",
1718
+ "brl",
1719
+ "bro",
1720
+ "brp",
1721
+ "brs",
1722
+ "brv",
1723
+ "brw",
1724
+ "brx",
1725
+ "bsa",
1726
+ "bsk",
1727
+ "bsm",
1728
+ "bsn",
1729
+ "bst",
1730
+ "bsu",
1731
+ "bsw",
1732
+ "btd",
1733
+ "bti",
1734
+ "btj",
1735
+ "btm",
1736
+ "btn",
1737
+ "bto",
1738
+ "bts",
1739
+ "btv",
1740
+ "btw",
1741
+ "btx",
1742
+ "bty",
1743
+ "btz",
1744
+ "bue",
1745
+ "bug",
1746
+ "bup",
1747
+ "bve",
1748
+ "bvk",
1749
+ "bvt",
1750
+ "bvu",
1751
+ "bvv",
1752
+ "bvy",
1753
+ "bvz",
1754
+ "bwe",
1755
+ "bwg",
1756
+ "bwi",
1757
+ "bwo",
1758
+ "bwp",
1759
+ "bya",
1760
+ "byd",
1761
+ "byh",
1762
+ "byl",
1763
+ "byw",
1764
+ "bzb",
1765
+ "bzi",
1766
+ "bzj",
1767
+ "bzk",
1768
+ "bzl",
1769
+ "bzn",
1770
+ "bzp",
1771
+ "bzq",
1772
+ "bzu",
1773
+ "caa",
1774
+ "cab",
1775
+ "cac",
1776
+ "cad",
1777
+ "caf",
1778
+ "cag",
1779
+ "cah",
1780
+ "cak",
1781
+ "caq",
1782
+ "car",
1783
+ "cay",
1784
+ "cbb",
1785
+ "cbc",
1786
+ "cbd",
1787
+ "cbg",
1788
+ "cbk",
1789
+ "cbl",
1790
+ "cbn",
1791
+ "cbr",
1792
+ "cbs",
1793
+ "cbt",
1794
+ "cbu",
1795
+ "cbv",
1796
+ "cbw",
1797
+ "cby",
1798
+ "ccc",
1799
+ "ccd",
1800
+ "cce",
1801
+ "cco",
1802
+ "ccp",
1803
+ "ccr",
1804
+ "cde",
1805
+ "cdf",
1806
+ "cdh",
1807
+ "cdi",
1808
+ "cdj",
1809
+ "cdm",
1810
+ "cdz",
1811
+ "cea",
1812
+ "ceb",
1813
+ "ceg",
1814
+ "cek",
1815
+ "cey",
1816
+ "cfm",
1817
+ "cgc",
1818
+ "cgk",
1819
+ "ch",
1820
+ "chb",
1821
+ "chd",
1822
+ "chf",
1823
+ "chh",
1824
+ "chj",
1825
+ "chl",
1826
+ "chn",
1827
+ "cho",
1828
+ "chp",
1829
+ "chq",
1830
+ "chr",
1831
+ "cht",
1832
+ "chw",
1833
+ "chx",
1834
+ "chy",
1835
+ "chz",
1836
+ "cia",
1837
+ "cic",
1838
+ "cih",
1839
+ "cin",
1840
+ "cip",
1841
+ "ciw",
1842
+ "ciy",
1843
+ "cja",
1844
+ "cjh",
1845
+ "cjo",
1846
+ "ckn",
1847
+ "cku",
1848
+ "ckv",
1849
+ "ckz",
1850
+ "clc",
1851
+ "cle",
1852
+ "clh",
1853
+ "clj",
1854
+ "clk",
1855
+ "clm",
1856
+ "clo",
1857
+ "clt",
1858
+ "clu",
1859
+ "cly",
1860
+ "cmi",
1861
+ "cml",
1862
+ "cmr",
1863
+ "cmt",
1864
+ "cna",
1865
+ "cnb",
1866
+ "cnh",
1867
+ "cni",
1868
+ "cnk",
1869
+ "cnl",
1870
+ "cns",
1871
+ "cnt",
1872
+ "cnw",
1873
+ "cob",
1874
+ "coc",
1875
+ "cod",
1876
+ "coe",
1877
+ "cog",
1878
+ "coh",
1879
+ "coj",
1880
+ "cok",
1881
+ "col",
1882
+ "com",
1883
+ "coo",
1884
+ "coq",
1885
+ "cot",
1886
+ "cox",
1887
+ "coz",
1888
+ "cpa",
1889
+ "cpb",
1890
+ "cpc",
1891
+ "cps",
1892
+ "cpu",
1893
+ "cpy",
1894
+ "cr",
1895
+ "cra",
1896
+ "crd",
1897
+ "crf",
1898
+ "crg",
1899
+ "crj",
1900
+ "crk",
1901
+ "crl",
1902
+ "crm",
1903
+ "crn",
1904
+ "cro",
1905
+ "crv",
1906
+ "crx",
1907
+ "crz",
1908
+ "csa",
1909
+ "csh",
1910
+ "csj",
1911
+ "csm",
1912
+ "cso",
1913
+ "css",
1914
+ "cst",
1915
+ "csv",
1916
+ "csw",
1917
+ "csy",
1918
+ "csz",
1919
+ "cta",
1920
+ "ctc",
1921
+ "ctd",
1922
+ "cte",
1923
+ "ctg",
1924
+ "cth",
1925
+ "ctl",
1926
+ "ctm",
1927
+ "ctn",
1928
+ "cto",
1929
+ "ctp",
1930
+ "cts",
1931
+ "ctt",
1932
+ "ctu",
1933
+ "cty",
1934
+ "ctz",
1935
+ "cub",
1936
+ "cuc",
1937
+ "cuh",
1938
+ "cui",
1939
+ "cuj",
1940
+ "cuk",
1941
+ "cul",
1942
+ "cuo",
1943
+ "cup",
1944
+ "cut",
1945
+ "cux",
1946
+ "cuy",
1947
+ "cvg",
1948
+ "cvn",
1949
+ "cwb",
1950
+ "cya",
1951
+ "cyo",
1952
+ "czn",
1953
+ "czt",
1954
+ "dak",
1955
+ "dal",
1956
+ "dao",
1957
+ "daq",
1958
+ "dav",
1959
+ "daw",
1960
+ "daz",
1961
+ "dbe",
1962
+ "dbf",
1963
+ "dbn",
1964
+ "dcc",
1965
+ "dcr",
1966
+ "ddw",
1967
+ "deh",
1968
+ "dei",
1969
+ "del",
1970
+ "dem",
1971
+ "den",
1972
+ "der",
1973
+ "des",
1974
+ "dgc",
1975
+ "dgr",
1976
+ "dhi",
1977
+ "dhn",
1978
+ "dho",
1979
+ "dhw",
1980
+ "dig",
1981
+ "dih",
1982
+ "dij",
1983
+ "dis",
1984
+ "diy",
1985
+ "djo",
1986
+ "dka",
1987
+ "dkk",
1988
+ "dln",
1989
+ "dmk",
1990
+ "dml",
1991
+ "dmr",
1992
+ "dms",
1993
+ "dmu",
1994
+ "dmx",
1995
+ "dmy",
1996
+ "dna",
1997
+ "dni",
1998
+ "dnk",
1999
+ "dnt",
2000
+ "dnu",
2001
+ "dnv",
2002
+ "dnw",
2003
+ "dny",
2004
+ "doi",
2005
+ "dok",
2006
+ "dov",
2007
+ "dox",
2008
+ "drc",
2009
+ "dre",
2010
+ "drn",
2011
+ "drq",
2012
+ "drs",
2013
+ "dru",
2014
+ "dry",
2015
+ "dsh",
2016
+ "dsn",
2017
+ "dso",
2018
+ "dtd",
2019
+ "dty",
2020
+ "dub",
2021
+ "due",
2022
+ "dug",
2023
+ "duh",
2024
+ "dul",
2025
+ "dun",
2026
+ "duo",
2027
+ "dup",
2028
+ "duq",
2029
+ "dus",
2030
+ "duv",
2031
+ "duw",
2032
+ "duy",
2033
+ "dwk",
2034
+ "dwr",
2035
+ "dwz",
2036
+ "dyg",
2037
+ "dz",
2038
+ "dzl",
2039
+ "ebc",
2040
+ "ebk",
2041
+ "ebu",
2042
+ "eip",
2043
+ "ekg",
2044
+ "ekl",
2045
+ "eko",
2046
+ "eky",
2047
+ "elo",
2048
+ "emb",
2049
+ "emg",
2050
+ "emm",
2051
+ "emp",
2052
+ "ems",
2053
+ "emu",
2054
+ "emw",
2055
+ "en",
2056
+ "enb",
2057
+ "end",
2058
+ "enl",
2059
+ "eno",
2060
+ "enr",
2061
+ "enx",
2062
+ "era",
2063
+ "ert",
2064
+ "erw",
2065
+ "esg",
2066
+ "esi",
2067
+ "ess",
2068
+ "esu",
2069
+ "esy",
2070
+ "etz",
2071
+ "eud",
2072
+ "eya",
2073
+ "eyo",
2074
+ "fau",
2075
+ "fbl",
2076
+ "fif",
2077
+ "fil",
2078
+ "fla",
2079
+ "flh",
2080
+ "fly",
2081
+ "fmu",
2082
+ "fng",
2083
+ "fos",
2084
+ "frc",
2085
+ "frd",
2086
+ "fun",
2087
+ "gac",
2088
+ "gad",
2089
+ "gae",
2090
+ "gak",
2091
+ "gaq",
2092
+ "gas",
2093
+ "gau",
2094
+ "gax",
2095
+ "gay",
2096
+ "gbi",
2097
+ "gbj",
2098
+ "gbk",
2099
+ "gbl",
2100
+ "gbm",
2101
+ "gct",
2102
+ "gdb",
2103
+ "gdg",
2104
+ "gdl",
2105
+ "gdq",
2106
+ "gdx",
2107
+ "gef",
2108
+ "geh",
2109
+ "gei",
2110
+ "ges",
2111
+ "gez",
2112
+ "ggg",
2113
+ "ghe",
2114
+ "ghk",
2115
+ "ghr",
2116
+ "ght",
2117
+ "gic",
2118
+ "gig",
2119
+ "git",
2120
+ "gjk",
2121
+ "gju",
2122
+ "gku",
2123
+ "gmv",
2124
+ "gn",
2125
+ "gnb",
2126
+ "gnk",
2127
+ "gob",
2128
+ "goe",
2129
+ "gof",
2130
+ "goj",
2131
+ "gok",
2132
+ "gon",
2133
+ "gop",
2134
+ "goq",
2135
+ "gor",
2136
+ "gqn",
2137
+ "gra",
2138
+ "grs",
2139
+ "grt",
2140
+ "gru",
2141
+ "gta",
2142
+ "gu",
2143
+ "gub",
2144
+ "guc",
2145
+ "guh",
2146
+ "guk",
2147
+ "gul",
2148
+ "gum",
2149
+ "gun",
2150
+ "guo",
2151
+ "guq",
2152
+ "guu",
2153
+ "guz",
2154
+ "gva",
2155
+ "gvc",
2156
+ "gvj",
2157
+ "gvo",
2158
+ "gvp",
2159
+ "gvr",
2160
+ "gwc",
2161
+ "gwd",
2162
+ "gwf",
2163
+ "gwi",
2164
+ "gwj",
2165
+ "gyl",
2166
+ "gym",
2167
+ "gyo",
2168
+ "gzn",
2169
+ "haa",
2170
+ "had",
2171
+ "hae",
2172
+ "hai",
2173
+ "haj",
2174
+ "hap",
2175
+ "har",
2176
+ "has",
2177
+ "haw",
2178
+ "hax",
2179
+ "hbo",
2180
+ "hch",
2181
+ "hdy",
2182
+ "he",
2183
+ "heg",
2184
+ "hei",
2185
+ "hi",
2186
+ "hib",
2187
+ "hid",
2188
+ "hii",
2189
+ "hik",
2190
+ "hil",
2191
+ "hio",
2192
+ "hir",
2193
+ "hix",
2194
+ "hji",
2195
+ "hkh",
2196
+ "hlb",
2197
+ "hlt",
2198
+ "hmr",
2199
+ "hmu",
2200
+ "hnd",
2201
+ "hne",
2202
+ "hnh",
2203
+ "hnj",
2204
+ "hnj-Hmng",
2205
+ "hnn",
2206
+ "hno",
2207
+ "hoc",
2208
+ "hoi",
2209
+ "hoj",
2210
+ "hop",
2211
+ "hov",
2212
+ "hoy",
2213
+ "hpo",
2214
+ "hra",
2215
+ "hrk",
2216
+ "hru",
2217
+ "hrx",
2218
+ "hti",
2219
+ "hto",
2220
+ "htu",
2221
+ "hub",
2222
+ "huc",
2223
+ "hud",
2224
+ "hue",
2225
+ "hug",
2226
+ "huk",
2227
+ "hup",
2228
+ "hur",
2229
+ "hus",
2230
+ "hut",
2231
+ "huu",
2232
+ "huv",
2233
+ "huw",
2234
+ "hux",
2235
+ "huy",
2236
+ "hve",
2237
+ "hvn",
2238
+ "hvv",
2239
+ "hwc",
2240
+ "ibg",
2241
+ "ibl",
2242
+ "ibu",
2243
+ "icr",
2244
+ "id",
2245
+ "ida",
2246
+ "idb",
2247
+ "ifa",
2248
+ "ifb",
2249
+ "ifk",
2250
+ "ifu",
2251
+ "ify",
2252
+ "ihb",
2253
+ "ihp",
2254
+ "ik",
2255
+ "ikt",
2256
+ "ila",
2257
+ "ilk",
2258
+ "ilo",
2259
+ "ilp",
2260
+ "ilu",
2261
+ "iml",
2262
+ "imr",
2263
+ "in",
2264
+ "inb",
2265
+ "ing",
2266
+ "inj",
2267
+ "inn",
2268
+ "inp",
2269
+ "int",
2270
+ "ior",
2271
+ "iow",
2272
+ "iqu",
2273
+ "ire",
2274
+ "irh",
2275
+ "irn",
2276
+ "iru",
2277
+ "irx",
2278
+ "iry",
2279
+ "isc",
2280
+ "isd",
2281
+ "ism",
2282
+ "itb",
2283
+ "itd",
2284
+ "iti",
2285
+ "itt",
2286
+ "itv",
2287
+ "itx",
2288
+ "ity",
2289
+ "itz",
2290
+ "iu",
2291
+ "ivb",
2292
+ "ivv",
2293
+ "iw",
2294
+ "iwk",
2295
+ "iwo",
2296
+ "ixc",
2297
+ "ixl",
2298
+ "ja",
2299
+ "jaa",
2300
+ "jac",
2301
+ "jal",
2302
+ "jam",
2303
+ "jaq",
2304
+ "jau",
2305
+ "jax",
2306
+ "jbe",
2307
+ "jbj",
2308
+ "jbr",
2309
+ "jbt",
2310
+ "jda",
2311
+ "jdg",
2312
+ "jeb",
2313
+ "jee",
2314
+ "jei",
2315
+ "jel",
2316
+ "jic",
2317
+ "jje",
2318
+ "jka",
2319
+ "jkm",
2320
+ "jmd",
2321
+ "jml",
2322
+ "jmn",
2323
+ "jmx",
2324
+ "jna",
2325
+ "jnd",
2326
+ "jnj",
2327
+ "jnl",
2328
+ "jns",
2329
+ "jog",
2330
+ "jpr",
2331
+ "jqr",
2332
+ "jrb",
2333
+ "jru",
2334
+ "jua",
2335
+ "jul",
2336
+ "jun",
2337
+ "jup",
2338
+ "jur",
2339
+ "juy",
2340
+ "jv",
2341
+ "jvd",
2342
+ "jw",
2343
+ "jye",
2344
+ "kac",
2345
+ "kak",
2346
+ "kam",
2347
+ "kaq",
2348
+ "kav",
2349
+ "kaw",
2350
+ "kax",
2351
+ "kay",
2352
+ "kbb",
2353
+ "kbc",
2354
+ "kbg",
2355
+ "kbh",
2356
+ "kbi",
2357
+ "kbr",
2358
+ "kbu",
2359
+ "kbv",
2360
+ "kcd",
2361
+ "kck",
2362
+ "kdn",
2363
+ "kdq",
2364
+ "kdt",
2365
+ "kdw",
2366
+ "kdy",
2367
+ "kee",
2368
+ "kei",
2369
+ "kek",
2370
+ "kev",
2371
+ "kex",
2372
+ "key",
2373
+ "kfa",
2374
+ "kfb",
2375
+ "kfc",
2376
+ "kfd",
2377
+ "kfe",
2378
+ "kff",
2379
+ "kfg",
2380
+ "kfh",
2381
+ "kfi",
2382
+ "kfk",
2383
+ "kfp",
2384
+ "kfq",
2385
+ "kfr",
2386
+ "kfs",
2387
+ "kfu",
2388
+ "kfv",
2389
+ "kfw",
2390
+ "kfx",
2391
+ "kfy",
2392
+ "kgb",
2393
+ "kge",
2394
+ "kgj",
2395
+ "kgk",
2396
+ "kgp",
2397
+ "kgq",
2398
+ "kgr",
2399
+ "kgv",
2400
+ "kgw",
2401
+ "kgx",
2402
+ "kgy",
2403
+ "kha",
2404
+ "khc",
2405
+ "khd",
2406
+ "khe",
2407
+ "khf",
2408
+ "khh",
2409
+ "khn",
2410
+ "khp",
2411
+ "khr",
2412
+ "kht",
2413
+ "khw",
2414
+ "ki",
2415
+ "kic",
2416
+ "kif",
2417
+ "kig",
2418
+ "kio",
2419
+ "kip",
2420
+ "kiq",
2421
+ "kix",
2422
+ "kiy",
2423
+ "kja",
2424
+ "kjb",
2425
+ "kjc",
2426
+ "kje",
2427
+ "kjg",
2428
+ "kjk",
2429
+ "kjl",
2430
+ "kjo",
2431
+ "kjp",
2432
+ "kjq",
2433
+ "kjr",
2434
+ "kjt",
2435
+ "kju",
2436
+ "kjz",
2437
+ "kkb",
2438
+ "kkf",
2439
+ "kkg",
2440
+ "kkh",
2441
+ "kkl",
2442
+ "kkt",
2443
+ "kkv",
2444
+ "kkx",
2445
+ "kkz",
2446
+ "kla",
2447
+ "klb",
2448
+ "kle",
2449
+ "klg",
2450
+ "kli",
2451
+ "kll",
2452
+ "kln",
2453
+ "klr",
2454
+ "kls",
2455
+ "klw",
2456
+ "kly",
2457
+ "klz",
2458
+ "km",
2459
+ "kmd",
2460
+ "kmj",
2461
+ "kmk",
2462
+ "kml",
2463
+ "kmm",
2464
+ "kmq",
2465
+ "kmt",
2466
+ "kmv",
2467
+ "kn",
2468
+ "knb",
2469
+ "knd",
2470
+ "kne",
2471
+ "knj",
2472
+ "knl",
2473
+ "knm",
2474
+ "knn",
2475
+ "knt",
2476
+ "knx",
2477
+ "ko",
2478
+ "kod",
2479
+ "kog",
2480
+ "kok",
2481
+ "koy",
2482
+ "kpc",
2483
+ "kpd",
2484
+ "kpi",
2485
+ "kpj",
2486
+ "kpn",
2487
+ "kpq",
2488
+ "kps",
2489
+ "kpu",
2490
+ "kqe",
2491
+ "kqq",
2492
+ "kqu",
2493
+ "kqv",
2494
+ "kqy",
2495
+ "kqz",
2496
+ "kra",
2497
+ "krb",
2498
+ "kre",
2499
+ "krj",
2500
+ "krr",
2501
+ "kru",
2502
+ "krv",
2503
+ "krz",
2504
+ "ks",
2505
+ "ksc",
2506
+ "ksk",
2507
+ "ksn",
2508
+ "ksu",
2509
+ "ksw",
2510
+ "ksx",
2511
+ "ksz",
2512
+ "ktb",
2513
+ "kte",
2514
+ "kti",
2515
+ "ktn",
2516
+ "ktq",
2517
+ "kts",
2518
+ "ktt",
2519
+ "ktw",
2520
+ "ktx",
2521
+ "kuc",
2522
+ "kuf",
2523
+ "kui",
2524
+ "kuk",
2525
+ "kuq",
2526
+ "kut",
2527
+ "kuu",
2528
+ "kuv",
2529
+ "kvb",
2530
+ "kvd",
2531
+ "kvh",
2532
+ "kvl",
2533
+ "kvn",
2534
+ "kvo",
2535
+ "kvp",
2536
+ "kvq",
2537
+ "kvr",
2538
+ "kvt",
2539
+ "kvv",
2540
+ "kvw",
2541
+ "kvx",
2542
+ "kvy",
2543
+ "kvz",
2544
+ "kwa",
2545
+ "kwe",
2546
+ "kwh",
2547
+ "kwi",
2548
+ "kwk",
2549
+ "kwr",
2550
+ "kwt",
2551
+ "kxc",
2552
+ "kxf",
2553
+ "kxk",
2554
+ "kxm",
2555
+ "kxo",
2556
+ "kxp",
2557
+ "kxq",
2558
+ "kxv",
2559
+ "kyb",
2560
+ "kyd",
2561
+ "kyh",
2562
+ "kyj",
2563
+ "kyk",
2564
+ "kyl",
2565
+ "kyn",
2566
+ "kyo",
2567
+ "kyr",
2568
+ "kyt",
2569
+ "kyu",
2570
+ "kyv",
2571
+ "kyw",
2572
+ "kyz",
2573
+ "kzb",
2574
+ "kzd",
2575
+ "kzf",
2576
+ "kzl",
2577
+ "kzm",
2578
+ "kzp",
2579
+ "kzu",
2580
+ "kzv",
2581
+ "kzw",
2582
+ "kzx",
2583
+ "kzz",
2584
+ "laa",
2585
+ "lac",
2586
+ "lad",
2587
+ "lae",
2588
+ "lah",
2589
+ "lau",
2590
+ "law",
2591
+ "lax",
2592
+ "lbf",
2593
+ "lbj",
2594
+ "lbl",
2595
+ "lbm",
2596
+ "lbn",
2597
+ "lbo",
2598
+ "lbr",
2599
+ "lbw",
2600
+ "lbx",
2601
+ "lcc",
2602
+ "lcd",
2603
+ "lce",
2604
+ "lcf",
2605
+ "lcl",
2606
+ "lcq",
2607
+ "lcs",
2608
+ "len",
2609
+ "lep",
2610
+ "lev",
2611
+ "lew",
2612
+ "lex",
2613
+ "ley",
2614
+ "lgi",
2615
+ "lgn",
2616
+ "lhh",
2617
+ "lhm",
2618
+ "lif",
2619
+ "lif-Limb",
2620
+ "lil",
2621
+ "lio",
2622
+ "liq",
2623
+ "liw",
2624
+ "lix",
2625
+ "lje",
2626
+ "lji",
2627
+ "ljl",
2628
+ "ljp",
2629
+ "lkb",
2630
+ "lkd",
2631
+ "lkh",
2632
+ "lko",
2633
+ "lks",
2634
+ "lkt",
2635
+ "llb",
2636
+ "llg",
2637
+ "llm",
2638
+ "llq",
2639
+ "lmf",
2640
+ "lmh",
2641
+ "lmj",
2642
+ "lmk",
2643
+ "lmn",
2644
+ "lmq",
2645
+ "lmr",
2646
+ "lmw",
2647
+ "lmy",
2648
+ "lnd",
2649
+ "lo",
2650
+ "loa",
2651
+ "loc",
2652
+ "loe",
2653
+ "lou",
2654
+ "lox",
2655
+ "loy",
2656
+ "lpe",
2657
+ "lpn",
2658
+ "lri",
2659
+ "lrk",
2660
+ "lrm",
2661
+ "lrn",
2662
+ "lrt",
2663
+ "lsd",
2664
+ "lsi",
2665
+ "lss",
2666
+ "lti",
2667
+ "ltn",
2668
+ "lto",
2669
+ "lts",
2670
+ "ltu",
2671
+ "lui",
2672
+ "luk",
2673
+ "luo",
2674
+ "lur",
2675
+ "lus",
2676
+ "lut",
2677
+ "luu",
2678
+ "luy",
2679
+ "lvi",
2680
+ "lvu",
2681
+ "lwe",
2682
+ "lwg",
2683
+ "lwl",
2684
+ "lwt",
2685
+ "lya",
2686
+ "lzn",
2687
+ "maa",
2688
+ "mab",
2689
+ "mad",
2690
+ "mag",
2691
+ "mai",
2692
+ "maj",
2693
+ "mak",
2694
+ "mam",
2695
+ "maq",
2696
+ "mas",
2697
+ "mat",
2698
+ "mau",
2699
+ "mav",
2700
+ "max",
2701
+ "maz",
2702
+ "mba",
2703
+ "mbb",
2704
+ "mbc",
2705
+ "mbd",
2706
+ "mbf",
2707
+ "mbi",
2708
+ "mbj",
2709
+ "mbl",
2710
+ "mbn",
2711
+ "mbp",
2712
+ "mbr",
2713
+ "mbs",
2714
+ "mbt",
2715
+ "mby",
2716
+ "mbz",
2717
+ "mca",
2718
+ "mcb",
2719
+ "mcd",
2720
+ "mce",
2721
+ "mcf",
2722
+ "mcg",
2723
+ "mch",
2724
+ "mcl",
2725
+ "mco",
2726
+ "mdh",
2727
+ "mdr",
2728
+ "mdv",
2729
+ "mdx",
2730
+ "mdy",
2731
+ "mdz",
2732
+ "meh",
2733
+ "mej",
2734
+ "mer",
2735
+ "mez",
2736
+ "mfa",
2737
+ "mfb",
2738
+ "mfp",
2739
+ "mfx",
2740
+ "mfy",
2741
+ "mgf",
2742
+ "mgh",
2743
+ "mgk",
2744
+ "mgp",
2745
+ "mh",
2746
+ "mhc",
2747
+ "mhm",
2748
+ "mhp",
2749
+ "mhq",
2750
+ "mhs",
2751
+ "mht",
2752
+ "mhu",
2753
+ "mhw",
2754
+ "mhx",
2755
+ "mhy",
2756
+ "mhz",
2757
+ "mia",
2758
+ "mib",
2759
+ "mic",
2760
+ "mie",
2761
+ "mig",
2762
+ "mih",
2763
+ "mii",
2764
+ "mik",
2765
+ "mil",
2766
+ "mim",
2767
+ "min",
2768
+ "mio",
2769
+ "mip",
2770
+ "miq",
2771
+ "mir",
2772
+ "mit",
2773
+ "miu",
2774
+ "mix",
2775
+ "miy",
2776
+ "miz",
2777
+ "mjc",
2778
+ "mjd",
2779
+ "mjl",
2780
+ "mjq",
2781
+ "mjr",
2782
+ "mjt",
2783
+ "mju",
2784
+ "mjv",
2785
+ "mjw",
2786
+ "mjx",
2787
+ "mjy",
2788
+ "mjz",
2789
+ "mkb",
2790
+ "mke",
2791
+ "mki",
2792
+ "mkm",
2793
+ "mkn",
2794
+ "mks",
2795
+ "mkx",
2796
+ "mky",
2797
+ "ml",
2798
+ "mlf",
2799
+ "mli",
2800
+ "mlk",
2801
+ "mlz",
2802
+ "mmb",
2803
+ "mmc",
2804
+ "mmh",
2805
+ "mmn",
2806
+ "mmv",
2807
+ "mnb",
2808
+ "mnd",
2809
+ "mni",
2810
+ "mnr",
2811
+ "mnu",
2812
+ "mnw",
2813
+ "mnx",
2814
+ "mny",
2815
+ "mnz",
2816
+ "mod",
2817
+ "moe",
2818
+ "mog",
2819
+ "moh",
2820
+ "mok",
2821
+ "mom",
2822
+ "mop",
2823
+ "moq",
2824
+ "mot",
2825
+ "mov",
2826
+ "moy",
2827
+ "mpd",
2828
+ "mpe",
2829
+ "mpm",
2830
+ "mpq",
2831
+ "mpu",
2832
+ "mpw",
2833
+ "mpy",
2834
+ "mpz",
2835
+ "mqa",
2836
+ "mqc",
2837
+ "mqf",
2838
+ "mqg",
2839
+ "mqh",
2840
+ "mqi",
2841
+ "mqj",
2842
+ "mqk",
2843
+ "mqn",
2844
+ "mqo",
2845
+ "mqp",
2846
+ "mqr",
2847
+ "mqs",
2848
+ "mqx",
2849
+ "mqy",
2850
+ "mr",
2851
+ "mra",
2852
+ "mrc",
2853
+ "mrd",
2854
+ "mrf",
2855
+ "mrg",
2856
+ "mrh",
2857
+ "mro",
2858
+ "mrr",
2859
+ "mrw",
2860
+ "mrx",
2861
+ "mry",
2862
+ "mrz",
2863
+ "msb",
2864
+ "msf",
2865
+ "msg",
2866
+ "msk",
2867
+ "msl",
2868
+ "msm",
2869
+ "mso",
2870
+ "msp",
2871
+ "mss",
2872
+ "mt",
2873
+ "mta",
2874
+ "mtd",
2875
+ "mtg",
2876
+ "mth",
2877
+ "mtj",
2878
+ "mtn",
2879
+ "mto",
2880
+ "mtr",
2881
+ "mts",
2882
+ "mtu",
2883
+ "mtw",
2884
+ "mtx",
2885
+ "mui",
2886
+ "muk",
2887
+ "mus",
2888
+ "mut",
2889
+ "muu",
2890
+ "muv",
2891
+ "muz",
2892
+ "mvd",
2893
+ "mve",
2894
+ "mvg",
2895
+ "mvp",
2896
+ "mvr",
2897
+ "mvs",
2898
+ "mvx",
2899
+ "mvy",
2900
+ "mvz",
2901
+ "mwl",
2902
+ "mwq",
2903
+ "mwr",
2904
+ "mws",
2905
+ "mwt",
2906
+ "mwv",
2907
+ "mww",
2908
+ "mxa",
2909
+ "mxb",
2910
+ "mxc",
2911
+ "mxd",
2912
+ "mxj",
2913
+ "mxn",
2914
+ "mxp",
2915
+ "mxq",
2916
+ "mxs",
2917
+ "mxt",
2918
+ "mxv",
2919
+ "mxy",
2920
+ "mxz",
2921
+ "my",
2922
+ "myf",
2923
+ "myh",
2924
+ "myl",
2925
+ "mym",
2926
+ "myp",
2927
+ "myr",
2928
+ "myu",
2929
+ "myy",
2930
+ "mza",
2931
+ "mzi",
2932
+ "mzl",
2933
+ "mzo",
2934
+ "mzq",
2935
+ "mzr",
2936
+ "naa",
2937
+ "nab",
2938
+ "nae",
2939
+ "nag",
2940
+ "nao",
2941
+ "naz",
2942
+ "nbc",
2943
+ "nbe",
2944
+ "nbi",
2945
+ "nbn",
2946
+ "nbq",
2947
+ "nbt",
2948
+ "nbu",
2949
+ "ncb",
2950
+ "ncd",
2951
+ "ncg",
2952
+ "nch",
2953
+ "nci",
2954
+ "ncj",
2955
+ "ncl",
2956
+ "ncq",
2957
+ "nct",
2958
+ "ncx",
2959
+ "ncz",
2960
+ "nd",
2961
+ "ndc",
2962
+ "ndx",
2963
+ "ne",
2964
+ "nea",
2965
+ "nec",
2966
+ "neh",
2967
+ "neq",
2968
+ "ner",
2969
+ "new",
2970
+ "nez",
2971
+ "nfa",
2972
+ "ngh",
2973
+ "ngl",
2974
+ "ngt",
2975
+ "ngu",
2976
+ "nhc",
2977
+ "nhd",
2978
+ "nhe",
2979
+ "nhg",
2980
+ "nhi",
2981
+ "nhk",
2982
+ "nhm",
2983
+ "nhn",
2984
+ "nhp",
2985
+ "nhq",
2986
+ "nhr",
2987
+ "nht",
2988
+ "nhv",
2989
+ "nhw",
2990
+ "nhx",
2991
+ "nhy",
2992
+ "nhz",
2993
+ "nia",
2994
+ "nij",
2995
+ "nil",
2996
+ "niq",
2997
+ "nir",
2998
+ "nit",
2999
+ "njb",
3000
+ "njh",
3001
+ "njm",
3002
+ "njn",
3003
+ "njo",
3004
+ "njs",
3005
+ "njz",
3006
+ "nkb",
3007
+ "nkd",
3008
+ "nkf",
3009
+ "nkh",
3010
+ "nki",
3011
+ "nkj",
3012
+ "nks",
3013
+ "nlc",
3014
+ "nle",
3015
+ "nlk",
3016
+ "nlm",
3017
+ "nlq",
3018
+ "nlv",
3019
+ "nlx",
3020
+ "nma",
3021
+ "nme",
3022
+ "nmf",
3023
+ "nmh",
3024
+ "nmm",
3025
+ "nmn",
3026
+ "nmo",
3027
+ "nmq",
3028
+ "nmu",
3029
+ "nng",
3030
+ "nni",
3031
+ "nnj",
3032
+ "nnl",
3033
+ "nnp",
3034
+ "nnt",
3035
+ "noa",
3036
+ "nod",
3037
+ "noe",
3038
+ "noi",
3039
+ "noj",
3040
+ "nok",
3041
+ "not",
3042
+ "npb",
3043
+ "npg",
3044
+ "nph",
3045
+ "npl",
3046
+ "npo",
3047
+ "nps",
3048
+ "npu",
3049
+ "npy",
3050
+ "nqm",
3051
+ "nqq",
3052
+ "nqy",
3053
+ "nr",
3054
+ "nre",
3055
+ "nri",
3056
+ "nsa",
3057
+ "nsb",
3058
+ "nsk",
3059
+ "nsm",
3060
+ "nso",
3061
+ "nsq",
3062
+ "nst",
3063
+ "nsu",
3064
+ "nsy",
3065
+ "nsz",
3066
+ "nte",
3067
+ "ntp",
3068
+ "ntx",
3069
+ "nuc",
3070
+ "nuk",
3071
+ "nun",
3072
+ "nuz",
3073
+ "nv",
3074
+ "nwc",
3075
+ "nwx",
3076
+ "nxe",
3077
+ "nxg",
3078
+ "nxl",
3079
+ "nxx",
3080
+ "nyd",
3081
+ "nyf",
3082
+ "nyl",
3083
+ "nyu",
3084
+ "nyw",
3085
+ "nzm",
3086
+ "obi",
3087
+ "obk",
3088
+ "obo",
3089
+ "obr",
3090
+ "oca",
3091
+ "ocu",
3092
+ "odk",
3093
+ "oia",
3094
+ "oj",
3095
+ "ojb",
3096
+ "ojc",
3097
+ "ojs",
3098
+ "ojw",
3099
+ "oka",
3100
+ "oki",
3101
+ "okm",
3102
+ "oko",
3103
+ "okz",
3104
+ "ola",
3105
+ "ole",
3106
+ "om",
3107
+ "oma",
3108
+ "omc",
3109
+ "omg",
3110
+ "omp",
3111
+ "omr",
3112
+ "omt",
3113
+ "omu",
3114
+ "omx",
3115
+ "one",
3116
+ "oni",
3117
+ "ono",
3118
+ "onp",
3119
+ "onx",
3120
+ "ood",
3121
+ "oon",
3122
+ "oor",
3123
+ "opk",
3124
+ "opt",
3125
+ "opy",
3126
+ "or",
3127
+ "orc",
3128
+ "ore",
3129
+ "ort",
3130
+ "oru",
3131
+ "orw",
3132
+ "orz",
3133
+ "osa",
3134
+ "osi",
3135
+ "otd",
3136
+ "ote",
3137
+ "oti",
3138
+ "otl",
3139
+ "otm",
3140
+ "otn",
3141
+ "otq",
3142
+ "ots",
3143
+ "ott",
3144
+ "otu",
3145
+ "otw",
3146
+ "otx",
3147
+ "oty",
3148
+ "otz",
3149
+ "oyd",
3150
+ "oym",
3151
+ "pa",
3152
+ "pa-Arab",
3153
+ "pab",
3154
+ "pad",
3155
+ "paf",
3156
+ "pag",
3157
+ "pah",
3158
+ "pak",
3159
+ "pam",
3160
+ "pao",
3161
+ "par",
3162
+ "pas",
3163
+ "pav",
3164
+ "paw",
3165
+ "pax",
3166
+ "pay",
3167
+ "paz",
3168
+ "pbb",
3169
+ "pbe",
3170
+ "pbf",
3171
+ "pbg",
3172
+ "pbh",
3173
+ "pbm",
3174
+ "pbs",
3175
+ "pbv",
3176
+ "pca",
3177
+ "pcb",
3178
+ "pce",
3179
+ "pcf",
3180
+ "pcg",
3181
+ "pch",
3182
+ "pci",
3183
+ "pcj",
3184
+ "pck",
3185
+ "pdc",
3186
+ "pdn",
3187
+ "pdo",
3188
+ "pdt",
3189
+ "pdu",
3190
+ "pea",
3191
+ "peb",
3192
+ "pee",
3193
+ "peg",
3194
+ "pei",
3195
+ "pel",
3196
+ "peq",
3197
+ "pev",
3198
+ "pey",
3199
+ "pgd",
3200
+ "pgg",
3201
+ "pgu",
3202
+ "phd",
3203
+ "phk",
3204
+ "phl",
3205
+ "phm",
3206
+ "pho",
3207
+ "phr",
3208
+ "pht",
3209
+ "phu",
3210
+ "phw",
3211
+ "pi",
3212
+ "pia",
3213
+ "pib",
3214
+ "pid",
3215
+ "pig",
3216
+ "pij",
3217
+ "pim",
3218
+ "pio",
3219
+ "pir",
3220
+ "pka",
3221
+ "pkb",
3222
+ "pkh",
3223
+ "pko",
3224
+ "pkr",
3225
+ "pku",
3226
+ "plc",
3227
+ "ple",
3228
+ "plh",
3229
+ "plk",
3230
+ "pll",
3231
+ "pln",
3232
+ "plo",
3233
+ "pls",
3234
+ "plu",
3235
+ "plv",
3236
+ "plw",
3237
+ "pmf",
3238
+ "pmh",
3239
+ "pmo",
3240
+ "pmq",
3241
+ "pmw",
3242
+ "pmx",
3243
+ "pmy",
3244
+ "pmz",
3245
+ "pnc",
3246
+ "pni",
3247
+ "pno",
3248
+ "pnp",
3249
+ "pns",
3250
+ "poc",
3251
+ "poe",
3252
+ "pog",
3253
+ "poh",
3254
+ "poi",
3255
+ "pok",
3256
+ "pom",
3257
+ "poo",
3258
+ "poq",
3259
+ "pos",
3260
+ "pot",
3261
+ "pow",
3262
+ "ppi",
3263
+ "ppk",
3264
+ "ppl",
3265
+ "ppm",
3266
+ "pps",
3267
+ "pqm",
3268
+ "pra",
3269
+ "prf",
3270
+ "prh",
3271
+ "prk",
3272
+ "prq",
3273
+ "prr",
3274
+ "prt",
3275
+ "pru",
3276
+ "prx",
3277
+ "psa",
3278
+ "pse",
3279
+ "psn",
3280
+ "pst",
3281
+ "psu",
3282
+ "pt",
3283
+ "pta",
3284
+ "pth",
3285
+ "ptn",
3286
+ "pto",
3287
+ "ptt",
3288
+ "ptu",
3289
+ "pua",
3290
+ "pub",
3291
+ "puc",
3292
+ "pud",
3293
+ "puf",
3294
+ "pui",
3295
+ "puj",
3296
+ "pum",
3297
+ "pur",
3298
+ "put",
3299
+ "puy",
3300
+ "pwm",
3301
+ "pwn",
3302
+ "pwo",
3303
+ "pwr",
3304
+ "pww",
3305
+ "pxm",
3306
+ "pyn",
3307
+ "pyu",
3308
+ "pyx",
3309
+ "pyy",
3310
+ "pzh",
3311
+ "pzn",
3312
+ "qu",
3313
+ "qua",
3314
+ "qub",
3315
+ "quc",
3316
+ "quf",
3317
+ "qui",
3318
+ "quk",
3319
+ "qum",
3320
+ "qun",
3321
+ "qup",
3322
+ "qur",
3323
+ "quv",
3324
+ "qux",
3325
+ "quy",
3326
+ "qva",
3327
+ "qvc",
3328
+ "qve",
3329
+ "qvh",
3330
+ "qvl",
3331
+ "qvm",
3332
+ "qvn",
3333
+ "qvo",
3334
+ "qvp",
3335
+ "qvs",
3336
+ "qvw",
3337
+ "qwa",
3338
+ "qwc",
3339
+ "qwh",
3340
+ "qws",
3341
+ "qwt",
3342
+ "qxa",
3343
+ "qxc",
3344
+ "qxh",
3345
+ "qxn",
3346
+ "qxo",
3347
+ "qxp",
3348
+ "qxt",
3349
+ "qxu",
3350
+ "qxw",
3351
+ "qyp",
3352
+ "raa",
3353
+ "rab",
3354
+ "rac",
3355
+ "raf",
3356
+ "rag",
3357
+ "rah",
3358
+ "raj",
3359
+ "ram",
3360
+ "ran",
3361
+ "rav",
3362
+ "raw",
3363
+ "raz",
3364
+ "rbb",
3365
+ "rbk",
3366
+ "rbl",
3367
+ "reb",
3368
+ "rei",
3369
+ "rej",
3370
+ "rel",
3371
+ "rem",
3372
+ "ret",
3373
+ "rgr",
3374
+ "rgu",
3375
+ "rhg",
3376
+ "ria",
3377
+ "ril",
3378
+ "rir",
3379
+ "riu",
3380
+ "rjg",
3381
+ "rji",
3382
+ "rjs",
3383
+ "rka",
3384
+ "rkb",
3385
+ "rki",
3386
+ "rkt",
3387
+ "rma",
3388
+ "rmh",
3389
+ "rmm",
3390
+ "rmz",
3391
+ "rng",
3392
+ "rnl",
3393
+ "rnn",
3394
+ "rob",
3395
+ "rol",
3396
+ "ror",
3397
+ "row",
3398
+ "rtc",
3399
+ "rth",
3400
+ "rtw",
3401
+ "rwr",
3402
+ "ryu",
3403
+ "sa",
3404
+ "sab",
3405
+ "sac",
3406
+ "sae",
3407
+ "saj",
3408
+ "sao",
3409
+ "saq",
3410
+ "sas",
3411
+ "sat",
3412
+ "sau",
3413
+ "saw",
3414
+ "saz",
3415
+ "sbg",
3416
+ "sbl",
3417
+ "sbn",
3418
+ "sbr",
3419
+ "sbt",
3420
+ "sbu",
3421
+ "sbx",
3422
+ "scf",
3423
+ "scg",
3424
+ "sch",
3425
+ "sck",
3426
+ "scl",
3427
+ "scp",
3428
+ "scs",
3429
+ "sct",
3430
+ "scu",
3431
+ "sd",
3432
+ "sd-Deva",
3433
+ "sd-Khoj",
3434
+ "sd-Sind",
3435
+ "sda",
3436
+ "sdq",
3437
+ "sdr",
3438
+ "sdu",
3439
+ "sec",
3440
+ "see",
3441
+ "seh",
3442
+ "sei",
3443
+ "sek",
3444
+ "ser",
3445
+ "set",
3446
+ "seu",
3447
+ "sez",
3448
+ "sfe",
3449
+ "sgb",
3450
+ "sgc",
3451
+ "sgd",
3452
+ "sge",
3453
+ "sgj",
3454
+ "sgm",
3455
+ "sgp",
3456
+ "sgt",
3457
+ "sgu",
3458
+ "sgw",
3459
+ "shb",
3460
+ "shd",
3461
+ "she",
3462
+ "shg",
3463
+ "shh",
3464
+ "shn",
3465
+ "shp",
3466
+ "shs",
3467
+ "sht",
3468
+ "sid",
3469
+ "sii",
3470
+ "sik",
3471
+ "sip",
3472
+ "sis",
3473
+ "sja",
3474
+ "sjb",
3475
+ "sjl",
3476
+ "sjm",
3477
+ "sjp",
3478
+ "sjw",
3479
+ "ska",
3480
+ "skb",
3481
+ "skd",
3482
+ "skf",
3483
+ "skh",
3484
+ "ski",
3485
+ "skj",
3486
+ "skn",
3487
+ "sko",
3488
+ "skr",
3489
+ "skv",
3490
+ "skx",
3491
+ "skz",
3492
+ "slc",
3493
+ "slg",
3494
+ "slh",
3495
+ "slj",
3496
+ "slm",
3497
+ "sln",
3498
+ "slp",
3499
+ "slu",
3500
+ "sly",
3501
+ "slz",
3502
+ "sm",
3503
+ "smk",
3504
+ "sml",
3505
+ "smp",
3506
+ "smr",
3507
+ "smt",
3508
+ "smu",
3509
+ "smw",
3510
+ "sn",
3511
+ "sni",
3512
+ "snl",
3513
+ "snn",
3514
+ "sno",
3515
+ "snu",
3516
+ "soa",
3517
+ "sob",
3518
+ "soi",
3519
+ "sou",
3520
+ "spb",
3521
+ "spc",
3522
+ "spi",
3523
+ "spn",
3524
+ "spo",
3525
+ "spq",
3526
+ "spr",
3527
+ "spt",
3528
+ "spv",
3529
+ "sqq",
3530
+ "sqt",
3531
+ "squ",
3532
+ "srb",
3533
+ "sre",
3534
+ "srg",
3535
+ "sri",
3536
+ "srl",
3537
+ "srs",
3538
+ "srt",
3539
+ "sru",
3540
+ "srv",
3541
+ "srw",
3542
+ "srx",
3543
+ "ss",
3544
+ "ssb",
3545
+ "sse",
3546
+ "ssf",
3547
+ "ssn",
3548
+ "ssq",
3549
+ "sss",
3550
+ "st",
3551
+ "stb",
3552
+ "ste",
3553
+ "sto",
3554
+ "stp",
3555
+ "str",
3556
+ "stv",
3557
+ "su",
3558
+ "suc",
3559
+ "suq",
3560
+ "sut",
3561
+ "suv",
3562
+ "suy",
3563
+ "suz",
3564
+ "sve",
3565
+ "swo",
3566
+ "swr",
3567
+ "sws",
3568
+ "swt",
3569
+ "swu",
3570
+ "swv",
3571
+ "swx",
3572
+ "sxb",
3573
+ "sxn",
3574
+ "sxr",
3575
+ "sya",
3576
+ "syb",
3577
+ "syl",
3578
+ "syo",
3579
+ "syw",
3580
+ "szb",
3581
+ "szn",
3582
+ "szp",
3583
+ "szw",
3584
+ "szy",
3585
+ "ta",
3586
+ "taa",
3587
+ "tac",
3588
+ "tad",
3589
+ "tae",
3590
+ "taf",
3591
+ "taj",
3592
+ "tao",
3593
+ "tar",
3594
+ "tau",
3595
+ "tav",
3596
+ "tay",
3597
+ "tba",
3598
+ "tbk",
3599
+ "tbl",
3600
+ "tbn",
3601
+ "tbp",
3602
+ "tbu",
3603
+ "tbw",
3604
+ "tby",
3605
+ "tca",
3606
+ "tcb",
3607
+ "tce",
3608
+ "tcf",
3609
+ "tcg",
3610
+ "tcm",
3611
+ "tcn",
3612
+ "tco",
3613
+ "tcp",
3614
+ "tcq",
3615
+ "tcu",
3616
+ "tcw",
3617
+ "tcx",
3618
+ "tcy",
3619
+ "tcz",
3620
+ "tdb",
3621
+ "tdc",
3622
+ "tdg",
3623
+ "tdh",
3624
+ "tdi",
3625
+ "tdj",
3626
+ "tdn",
3627
+ "tds",
3628
+ "tdy",
3629
+ "te",
3630
+ "tec",
3631
+ "tee",
3632
+ "ten",
3633
+ "tep",
3634
+ "ter",
3635
+ "tes",
3636
+ "tev",
3637
+ "tew",
3638
+ "tfn",
3639
+ "tfo",
3640
+ "tfr",
3641
+ "tft",
3642
+ "tg-Arab",
3643
+ "tga",
3644
+ "tge",
3645
+ "tgf",
3646
+ "tgh",
3647
+ "tgj",
3648
+ "tgn",
3649
+ "tgt",
3650
+ "tgv",
3651
+ "tgx",
3652
+ "th",
3653
+ "the",
3654
+ "thf",
3655
+ "thh",
3656
+ "thi",
3657
+ "thk",
3658
+ "thl",
3659
+ "thm",
3660
+ "thp",
3661
+ "thq",
3662
+ "thr",
3663
+ "ths",
3664
+ "tht",
3665
+ "ti",
3666
+ "tij",
3667
+ "til",
3668
+ "tip",
3669
+ "tis",
3670
+ "tit",
3671
+ "tiu",
3672
+ "tix",
3673
+ "tiy",
3674
+ "tjg",
3675
+ "tjl",
3676
+ "tka",
3677
+ "tkb",
3678
+ "tke",
3679
+ "tkf",
3680
+ "tkt",
3681
+ "tku",
3682
+ "tkx",
3683
+ "tl",
3684
+ "tla",
3685
+ "tlb",
3686
+ "tlc",
3687
+ "tld",
3688
+ "tlg",
3689
+ "tli",
3690
+ "tlk",
3691
+ "tln",
3692
+ "tlp",
3693
+ "tlq",
3694
+ "tlt",
3695
+ "tlu",
3696
+ "tlv",
3697
+ "tme",
3698
+ "tmf",
3699
+ "tmg",
3700
+ "tmj",
3701
+ "tml",
3702
+ "tmn",
3703
+ "tmr",
3704
+ "tmu",
3705
+ "tmz",
3706
+ "tn",
3707
+ "tnb",
3708
+ "tnc",
3709
+ "tnd",
3710
+ "tni",
3711
+ "tnm",
3712
+ "tnq",
3713
+ "tnt",
3714
+ "tnv",
3715
+ "tnw",
3716
+ "toc",
3717
+ "toh",
3718
+ "toj",
3719
+ "tol",
3720
+ "tom",
3721
+ "too",
3722
+ "top",
3723
+ "tos",
3724
+ "tow",
3725
+ "toy",
3726
+ "tpc",
3727
+ "tpe",
3728
+ "tpf",
3729
+ "tpg",
3730
+ "tpj",
3731
+ "tpk",
3732
+ "tpl",
3733
+ "tpn",
3734
+ "tpp",
3735
+ "tpr",
3736
+ "tpt",
3737
+ "tpu",
3738
+ "tpx",
3739
+ "tpy",
3740
+ "tqb",
3741
+ "tqn",
3742
+ "tqt",
3743
+ "tqw",
3744
+ "trc",
3745
+ "tre",
3746
+ "trf",
3747
+ "trg",
3748
+ "tro",
3749
+ "trp",
3750
+ "trq",
3751
+ "trr",
3752
+ "trs",
3753
+ "trt",
3754
+ "trv",
3755
+ "trw",
3756
+ "try",
3757
+ "trz",
3758
+ "ts",
3759
+ "tsb",
3760
+ "tsc",
3761
+ "tsg",
3762
+ "tsi",
3763
+ "tsj",
3764
+ "tsu",
3765
+ "tsz",
3766
+ "ttc",
3767
+ "tth",
3768
+ "tti",
3769
+ "ttk",
3770
+ "ttm",
3771
+ "ttn",
3772
+ "tto",
3773
+ "ttp",
3774
+ "tts",
3775
+ "tty",
3776
+ "ttz",
3777
+ "tub",
3778
+ "tud",
3779
+ "tue",
3780
+ "tuf",
3781
+ "tuj",
3782
+ "tun",
3783
+ "tuo",
3784
+ "tus",
3785
+ "tuu",
3786
+ "tuv",
3787
+ "tux",
3788
+ "tuy",
3789
+ "tve",
3790
+ "tvm",
3791
+ "tvn",
3792
+ "tvo",
3793
+ "tvs",
3794
+ "tvt",
3795
+ "tvw",
3796
+ "tvx",
3797
+ "twa",
3798
+ "twb",
3799
+ "twe",
3800
+ "twf",
3801
+ "twg",
3802
+ "twl",
3803
+ "twm",
3804
+ "two",
3805
+ "twr",
3806
+ "twt",
3807
+ "twu",
3808
+ "twx",
3809
+ "twy",
3810
+ "txe",
3811
+ "txi",
3812
+ "txm",
3813
+ "txn",
3814
+ "txo",
3815
+ "txq",
3816
+ "txs",
3817
+ "txt",
3818
+ "txu",
3819
+ "tyn",
3820
+ "tyu",
3821
+ "tzh",
3822
+ "tzj",
3823
+ "tzn",
3824
+ "tzo",
3825
+ "uam",
3826
+ "ubl",
3827
+ "udg",
3828
+ "udj",
3829
+ "ues",
3830
+ "ugo",
3831
+ "uhn",
3832
+ "uka",
3833
+ "uki",
3834
+ "ukk",
3835
+ "ulf",
3836
+ "ulm",
3837
+ "ulu",
3838
+ "ulw",
3839
+ "uma",
3840
+ "umn",
3841
+ "umo",
3842
+ "ums",
3843
+ "und",
3844
+ "und-Ahom",
3845
+ "und-Bali",
3846
+ "und-Batk",
3847
+ "und-Beng",
3848
+ "und-Bhks",
3849
+ "und-Bopo",
3850
+ "und-Brah",
3851
+ "und-Bugi",
3852
+ "und-Buhd",
3853
+ "und-Cakm",
3854
+ "und-Cans",
3855
+ "und-Cher",
3856
+ "und-Deva",
3857
+ "und-Dogr",
3858
+ "und-Ethi",
3859
+ "und-Gong",
3860
+ "und-Gonm",
3861
+ "und-Gran",
3862
+ "und-Gujr",
3863
+ "und-Gukh",
3864
+ "und-Guru",
3865
+ "und-Hanb",
3866
+ "und-Hang",
3867
+ "und-Hano",
3868
+ "und-Hant",
3869
+ "und-Hebr",
3870
+ "und-Hira",
3871
+ "und-Hmng",
3872
+ "und-Hmnp",
3873
+ "und-Jamo",
3874
+ "und-Java",
3875
+ "und-Jpan",
3876
+ "und-Kali",
3877
+ "und-Kana",
3878
+ "und-Kawi",
3879
+ "und-Khar",
3880
+ "und-Khmr",
3881
+ "und-Khoj",
3882
+ "und-Knda",
3883
+ "und-Kore",
3884
+ "und-Krai",
3885
+ "und-Kthi",
3886
+ "und-Lana",
3887
+ "und-Laoo",
3888
+ "und-Latf",
3889
+ "und-Latg",
3890
+ "und-Latn",
3891
+ "und-Lepc",
3892
+ "und-Limb",
3893
+ "und-Mahj",
3894
+ "und-Maka",
3895
+ "und-Mlym",
3896
+ "und-Modi",
3897
+ "und-Mroo",
3898
+ "und-Mtei",
3899
+ "und-Mult",
3900
+ "und-Mymr",
3901
+ "und-Nagm",
3902
+ "und-Nand",
3903
+ "und-Narb",
3904
+ "und-Newa",
3905
+ "und-Olck",
3906
+ "und-Onao",
3907
+ "und-Orya",
3908
+ "und-Osge",
3909
+ "und-Pauc",
3910
+ "und-Rjng",
3911
+ "und-Rohg",
3912
+ "und-Samr",
3913
+ "und-Sarb",
3914
+ "und-Saur",
3915
+ "und-Sgnw",
3916
+ "und-Shrd",
3917
+ "und-Sidd",
3918
+ "und-Sind",
3919
+ "und-Sora",
3920
+ "und-Sund",
3921
+ "und-Sunu",
3922
+ "und-Sylo",
3923
+ "und-Tagb",
3924
+ "und-Takr",
3925
+ "und-Taml",
3926
+ "und-Telu",
3927
+ "und-Tglg",
3928
+ "und-Thai",
3929
+ "und-Tirh",
3930
+ "und-Tnsa",
3931
+ "und-Toto",
3932
+ "und-Tutg",
3933
+ "und-Wara",
3934
+ "und-Wcho",
3935
+ "unk",
3936
+ "unm",
3937
+ "unr",
3938
+ "unr-Deva",
3939
+ "unx",
3940
+ "unz",
3941
+ "uon",
3942
+ "ur",
3943
+ "ura",
3944
+ "urb",
3945
+ "urk",
3946
+ "urn",
3947
+ "urp",
3948
+ "uru",
3949
+ "ury",
3950
+ "urz",
3951
+ "ush",
3952
+ "usi",
3953
+ "usp",
3954
+ "ute",
3955
+ "vaa",
3956
+ "vah",
3957
+ "vap",
3958
+ "var",
3959
+ "vas",
3960
+ "vav",
3961
+ "vay",
3962
+ "vbb",
3963
+ "vbk",
3964
+ "ve",
3965
+ "veo",
3966
+ "vgr",
3967
+ "vjk",
3968
+ "vkk",
3969
+ "vkl",
3970
+ "vkm",
3971
+ "vko",
3972
+ "vkp",
3973
+ "vkt",
3974
+ "vmc",
3975
+ "vmd",
3976
+ "vme",
3977
+ "vmj",
3978
+ "vmk",
3979
+ "vmm",
3980
+ "vmp",
3981
+ "vmq",
3982
+ "vmr",
3983
+ "vms",
3984
+ "vmw",
3985
+ "vmx",
3986
+ "vmy",
3987
+ "vmz",
3988
+ "vto",
3989
+ "waa",
3990
+ "wac",
3991
+ "wad",
3992
+ "waf",
3993
+ "wah",
3994
+ "wai",
3995
+ "wal",
3996
+ "wam",
3997
+ "war",
3998
+ "was",
3999
+ "wau",
4000
+ "waw",
4001
+ "wba",
4002
+ "wbb",
4003
+ "wbe",
4004
+ "wbl",
4005
+ "wbq",
4006
+ "wbr",
4007
+ "wbw",
4008
+ "wca",
4009
+ "wdt",
4010
+ "weo",
4011
+ "wet",
4012
+ "weu",
4013
+ "wew",
4014
+ "wfg",
4015
+ "wgo",
4016
+ "wha",
4017
+ "whk",
4018
+ "whu",
4019
+ "wic",
4020
+ "win",
4021
+ "wir",
4022
+ "wiy",
4023
+ "wkd",
4024
+ "wle",
4025
+ "wli",
4026
+ "wlo",
4027
+ "wlw",
4028
+ "wmd",
4029
+ "wme",
4030
+ "wmm",
4031
+ "wms",
4032
+ "wmw",
4033
+ "wne",
4034
+ "wng",
4035
+ "wnk",
4036
+ "wno",
4037
+ "wnw",
4038
+ "wod",
4039
+ "woi",
4040
+ "woo",
4041
+ "wor",
4042
+ "wow",
4043
+ "wpc",
4044
+ "wrp",
4045
+ "wru",
4046
+ "wrx",
4047
+ "wsa",
4048
+ "wsg",
4049
+ "wsu",
4050
+ "wti",
4051
+ "wtm",
4052
+ "wtw",
4053
+ "wul",
4054
+ "wuy",
4055
+ "wyn",
4056
+ "wyr",
4057
+ "xai",
4058
+ "xaj",
4059
+ "xak",
4060
+ "xam",
4061
+ "xan",
4062
+ "xat",
4063
+ "xau",
4064
+ "xav",
4065
+ "xaw",
4066
+ "xay",
4067
+ "xbr",
4068
+ "xbw",
4069
+ "xch",
4070
+ "xdy",
4071
+ "xeg",
4072
+ "xem",
4073
+ "xer",
4074
+ "xet",
4075
+ "xh",
4076
+ "xhe",
4077
+ "xhm",
4078
+ "xii",
4079
+ "xin",
4080
+ "xir",
4081
+ "xis",
4082
+ "xiy",
4083
+ "xka",
4084
+ "xkd",
4085
+ "xke",
4086
+ "xkf",
4087
+ "xkl",
4088
+ "xkn",
4089
+ "xkq",
4090
+ "xkr",
4091
+ "xks",
4092
+ "xkv",
4093
+ "xkw",
4094
+ "xkz",
4095
+ "xmc",
4096
+ "xmm",
4097
+ "xmo",
4098
+ "xmt",
4099
+ "xmx",
4100
+ "xmz",
4101
+ "xna",
4102
+ "xnb",
4103
+ "xnn",
4104
+ "xnq",
4105
+ "xnr",
4106
+ "xnt",
4107
+ "xod",
4108
+ "xok",
4109
+ "xoo",
4110
+ "xor",
4111
+ "xpk",
4112
+ "xpn",
4113
+ "xpo",
4114
+ "xpq",
4115
+ "xra",
4116
+ "xre",
4117
+ "xri",
4118
+ "xsa",
4119
+ "xsb",
4120
+ "xse",
4121
+ "xsq",
4122
+ "xsr",
4123
+ "xsu",
4124
+ "xsy",
4125
+ "xta",
4126
+ "xtb",
4127
+ "xtd",
4128
+ "xte",
4129
+ "xti",
4130
+ "xtj",
4131
+ "xtl",
4132
+ "xtm",
4133
+ "xtn",
4134
+ "xtp",
4135
+ "xts",
4136
+ "xtt",
4137
+ "xtu",
4138
+ "xtw",
4139
+ "xty",
4140
+ "xub",
4141
+ "xuj",
4142
+ "xwa",
4143
+ "xwr",
4144
+ "xxk",
4145
+ "xxr",
4146
+ "xxt",
4147
+ "xyl",
4148
+ "xzp",
4149
+ "yaa",
4150
+ "yab",
4151
+ "yac",
4152
+ "yad",
4153
+ "yae",
4154
+ "yak",
4155
+ "yan",
4156
+ "yao",
4157
+ "yaq",
4158
+ "yar",
4159
+ "yau",
4160
+ "yaw",
4161
+ "ybh",
4162
+ "ybi",
4163
+ "ybn",
4164
+ "ycn",
4165
+ "ycr",
4166
+ "ydg",
4167
+ "yea",
4168
+ "yet",
4169
+ "yeu",
4170
+ "yey",
4171
+ "yhd",
4172
+ "yim",
4173
+ "yir",
4174
+ "yka",
4175
+ "yki",
4176
+ "yli",
4177
+ "yme",
4178
+ "ymk",
4179
+ "ymn",
4180
+ "ynu",
4181
+ "yog",
4182
+ "yoi",
4183
+ "yok",
4184
+ "yoy",
4185
+ "yrl",
4186
+ "yro",
4187
+ "yrs",
4188
+ "yua",
4189
+ "yuc",
4190
+ "yud",
4191
+ "yue",
4192
+ "yuf",
4193
+ "yui",
4194
+ "yum",
4195
+ "yup",
4196
+ "yur",
4197
+ "yva",
4198
+ "yvt",
4199
+ "ywn",
4200
+ "zaa",
4201
+ "zab",
4202
+ "zac",
4203
+ "zad",
4204
+ "zae",
4205
+ "zaf",
4206
+ "zam",
4207
+ "zao",
4208
+ "zap",
4209
+ "zaq",
4210
+ "zar",
4211
+ "zas",
4212
+ "zat",
4213
+ "zau",
4214
+ "zav",
4215
+ "zaw",
4216
+ "zax",
4217
+ "zay",
4218
+ "zbt",
4219
+ "zca",
4220
+ "zh-Bopo",
4221
+ "zh-Hanb",
4222
+ "zh-Hant",
4223
+ "zka",
4224
+ "zkd",
4225
+ "zkp",
4226
+ "zoc",
4227
+ "zoh",
4228
+ "zom",
4229
+ "zoo",
4230
+ "zoq",
4231
+ "zor",
4232
+ "zos",
4233
+ "zpa",
4234
+ "zpb",
4235
+ "zpc",
4236
+ "zpd",
4237
+ "zpe",
4238
+ "zpf",
4239
+ "zpg",
4240
+ "zph",
4241
+ "zpi",
4242
+ "zpj",
4243
+ "zpk",
4244
+ "zpl",
4245
+ "zpm",
4246
+ "zpn",
4247
+ "zpo",
4248
+ "zpp",
4249
+ "zpq",
4250
+ "zpr",
4251
+ "zps",
4252
+ "zpt",
4253
+ "zpu",
4254
+ "zpv",
4255
+ "zpw",
4256
+ "zpx",
4257
+ "zpy",
4258
+ "zpz",
4259
+ "zrg",
4260
+ "zrs",
4261
+ "zsr",
4262
+ "zte",
4263
+ "ztg",
4264
+ "ztl",
4265
+ "ztm",
4266
+ "ztn",
4267
+ "ztp",
4268
+ "ztq",
4269
+ "zts",
4270
+ "ztt",
4271
+ "ztu",
4272
+ "ztx",
4273
+ "zty",
4274
+ "zu",
4275
+ "zun",
4276
+ "zwa",
4277
+ "zyp"
4278
+ ]);
4279
+ // Specific language-script combinations that resolve to Monday in CLDR despite their base language resolving to non-Monday
4280
+ const LIKELY_MONDAY_SCRIPT_OVERRIDES = new Set([
4281
+ "en-Shaw",
4282
+ "pal-Phlp",
4283
+ "und-Adlm",
4284
+ "und-Aghb",
4285
+ "und-Armn",
4286
+ "und-Bamu",
4287
+ "und-Bass",
4288
+ "und-Brai",
4289
+ "und-Cari",
4290
+ "und-Cham",
4291
+ "und-Chrs",
4292
+ "und-Cpmn",
4293
+ "und-Cprt",
4294
+ "und-Cyrl",
4295
+ "und-Dupl",
4296
+ "und-Elba",
4297
+ "und-Gara",
4298
+ "und-Geor",
4299
+ "und-Glag",
4300
+ "und-Goth",
4301
+ "und-Grek",
4302
+ "und-Hani",
4303
+ "und-Hans",
4304
+ "und-Hluw",
4305
+ "und-Hung",
4306
+ "und-Ital",
4307
+ "und-Kits",
4308
+ "und-Lina",
4309
+ "und-Linb",
4310
+ "und-Lisu",
4311
+ "und-Lyci",
4312
+ "und-Lydi",
4313
+ "und-Mani",
4314
+ "und-Marc",
4315
+ "und-Medf",
4316
+ "und-Mend",
4317
+ "und-Mong",
4318
+ "und-Nkoo",
4319
+ "und-Nshu",
4320
+ "und-Ogam",
4321
+ "und-Orkh",
4322
+ "und-Osma",
4323
+ "und-Ougr",
4324
+ "und-Perm",
4325
+ "und-Phag",
4326
+ "und-Phlp",
4327
+ "und-Phnx",
4328
+ "und-Plrd",
4329
+ "und-Runr",
4330
+ "und-Shaw",
4331
+ "und-Sinh",
4332
+ "und-Sogd",
4333
+ "und-Sogo",
4334
+ "und-Soyo",
4335
+ "und-Tale",
4336
+ "und-Talu",
4337
+ "und-Tang",
4338
+ "und-Tavt",
4339
+ "und-Tfng",
4340
+ "und-Tibt",
4341
+ "und-Todr",
4342
+ "und-Vaii",
4343
+ "und-Vith",
4344
+ "und-Yezi",
4345
+ "und-Yiii",
4346
+ "und-Zanb",
4347
+ "yue-Hans"
4348
+ ]);
4349
+ /**
4350
+ * Resolves the likely first day of week for a base language tag, undefined-language tag,
4351
+ * or language-script tag when native Intl.Locale.maximize() is unavailable.
4352
+ */
4353
+ function resolveLikelyFirstDayOfWeek(baseTag) {
4354
+ if (LIKELY_MONDAY_SCRIPT_OVERRIDES.has(baseTag)) {
4355
+ return "monday";
4356
+ }
4357
+ if (LIKELY_FRIDAY_FIRST_TAGS.has(baseTag)) {
4358
+ return "friday";
4359
+ }
4360
+ if (LIKELY_SATURDAY_FIRST_TAGS.has(baseTag)) {
4361
+ return "saturday";
4362
+ }
4363
+ if (LIKELY_SUNDAY_FIRST_TAGS.has(baseTag)) {
4364
+ return "sunday";
4365
+ }
4366
+ return null;
4367
+ }
4368
+
4369
+ const FW_TO_FIRST_DAY = {
4370
+ mon: "monday",
4371
+ tue: "tuesday",
4372
+ wed: "wednesday",
4373
+ thu: "thursday",
4374
+ fri: "friday",
4375
+ sat: "saturday",
4376
+ sun: "sunday"
4377
+ };
4378
+ const ISO_DAY_MAP = {
4379
+ 1: "monday",
4380
+ 2: "tuesday",
4381
+ 3: "wednesday",
4382
+ 4: "thursday",
4383
+ 5: "friday",
4384
+ 6: "saturday",
4385
+ 7: "sunday"
4386
+ };
4387
+ /**
4388
+ * Extracts explicit Unicode extension 'fw' (first day of week) subtag if present.
4389
+ * Example: 'en-US-u-fw-mon' -> 'monday'.
4390
+ */
4391
+ function resolveExplicitFirstDayOverride(localeId) {
4392
+ if (!localeId) {
4393
+ return null;
4394
+ }
4395
+ const normalized = localeId.trim().replace(/_/g, "-");
4396
+ const subtags = normalized.split("-");
4397
+ let inUExtension = false;
4398
+ for (let i = 0; i < subtags.length; i++) {
4399
+ const subtag = subtags[i].toLowerCase();
4400
+ if (subtag.length === 1) {
4401
+ if (subtag === "x") {
4402
+ break;
4403
+ }
4404
+ inUExtension = subtag === "u";
4405
+ continue;
4406
+ }
4407
+ if (inUExtension && subtag === "fw") {
4408
+ const nextSubtag = subtags[i + 1]?.toLowerCase();
4409
+ if (nextSubtag && nextSubtag in FW_TO_FIRST_DAY) {
4410
+ return FW_TO_FIRST_DAY[nextSubtag];
4411
+ }
4412
+ }
4413
+ }
4414
+ return null;
4415
+ }
4416
+ /**
4417
+ * Resolves the 2-letter ISO region code from a locale tag.
4418
+ * 1. Uses Intl.Locale.region, then Intl.Locale.maximize().region.
4419
+ * 2. If Intl.Locale is unavailable or fails, canonicalizes via Intl.getCanonicalLocales() to map numeric M49 region codes to alpha-2.
4420
+ * 3. Falls back to manual base language tag parsing (safely stripping extension singletons like -u- or -x-) for 2-letter alpha territory subtags.
4421
+ * Private-use tags (e.g. 'x-US') without a standard language tag are ignored.
4422
+ */
4423
+ function resolveLikelyRegion(localeId) {
4424
+ if (!localeId) {
4425
+ return null;
4426
+ }
4427
+ const normalized = localeId.trim().replace(/_/g, "-");
4428
+ if (!normalized || /^[xX](?:-|$)/.test(normalized)) {
4429
+ return null;
4430
+ }
4431
+ try {
4432
+ if (typeof Intl !== "undefined" && typeof Intl.Locale === "function") {
4433
+ const loc = new Intl.Locale(normalized);
4434
+ if (loc.region) {
4435
+ return loc.region.toUpperCase();
4436
+ }
4437
+ if (typeof loc.maximize === "function") {
4438
+ const maximized = loc.maximize();
4439
+ if (maximized.region) {
4440
+ return maximized.region.toUpperCase();
4441
+ }
4442
+ }
4443
+ }
4444
+ }
4445
+ catch {
4446
+ // Fallback safely to canonicalization / manual base tag parser
4447
+ }
4448
+ let tagToParse = normalized;
4449
+ try {
4450
+ if (typeof Intl !== "undefined" && typeof Intl.getCanonicalLocales === "function") {
4451
+ const canonical = Intl.getCanonicalLocales(normalized)[0];
4452
+ if (canonical) {
4453
+ tagToParse = canonical;
4454
+ }
4455
+ }
4456
+ }
4457
+ catch {
4458
+ // Continue with normalized tag
4459
+ }
4460
+ // Manual BCP-47 fallback: strip singleton extensions (-u-, -x-, -t-, etc.) and everything following
4461
+ const basePart = tagToParse.split(/-[a-zA-Z0-9]-/)[0];
4462
+ const subtags = basePart.split("-");
4463
+ if (!subtags[0] || subtags[0].length <= 1) {
4464
+ return null;
4465
+ }
4466
+ for (let i = 1; i < subtags.length; i++) {
4467
+ const subtag = subtags[i];
4468
+ if (/^[a-zA-Z]{2}$/.test(subtag)) {
4469
+ return subtag.toUpperCase();
4470
+ }
4471
+ }
4472
+ return null;
4473
+ }
4474
+ /**
4475
+ * Pure fallback resolver when Intl.Locale.weekInfo / getWeekInfo() is unavailable.
4476
+ */
4477
+ function resolveFallbackFirstDayOfWeek(localeId) {
4478
+ const normalized = (localeId ?? "").trim();
4479
+ if (!normalized) {
4480
+ return "monday";
4481
+ }
4482
+ const explicitOverride = resolveExplicitFirstDayOverride(normalized);
4483
+ if (explicitOverride) {
4484
+ return explicitOverride;
4485
+ }
4486
+ const region = resolveLikelyRegion(normalized);
4487
+ if (region) {
4488
+ if (FRIDAY_FIRST_REGIONS.has(region)) {
4489
+ return "friday";
4490
+ }
4491
+ if (SATURDAY_FIRST_REGIONS.has(region)) {
4492
+ return "saturday";
4493
+ }
4494
+ if (SUNDAY_FIRST_REGIONS.has(region)) {
4495
+ return "sunday";
4496
+ }
4497
+ return "monday";
4498
+ }
4499
+ // Base tag fallback for primitive environments where maximize() was unavailable
4500
+ const tag = normalized.replace(/_/g, "-");
4501
+ if (/^[xX](?:-|$)/.test(tag)) {
4502
+ return "monday";
4503
+ }
4504
+ const basePart = tag.split(/-[a-zA-Z0-9]-/)[0];
4505
+ const subtags = basePart.split("-");
4506
+ if (!subtags[0] || subtags[0].length <= 1) {
4507
+ return "monday";
4508
+ }
4509
+ // If an explicit region subtag was present (alpha-2 or 3-digit numeric) but could not be mapped,
4510
+ // do not fall back to language-only likely subtags; use deterministic default (Monday).
4511
+ const hasRegion = subtags.slice(1).some(s => /^[a-zA-Z]{2}$|^\d{3}$/.test(s));
4512
+ if (hasRegion) {
4513
+ return "monday";
4514
+ }
4515
+ const baseLang = subtags[0].toLowerCase();
4516
+ if (subtags.length > 1 && /^[a-zA-Z]{4}$/.test(subtags[1])) {
4517
+ const script = subtags[1].charAt(0).toUpperCase() + subtags[1].slice(1).toLowerCase();
4518
+ const langScript = `${baseLang}-${script}`;
4519
+ const scriptFirstDay = resolveLikelyFirstDayOfWeek(langScript);
4520
+ if (scriptFirstDay) {
4521
+ return scriptFirstDay;
4522
+ }
4523
+ }
4524
+ const langFirstDay = resolveLikelyFirstDayOfWeek(baseLang);
4525
+ if (langFirstDay) {
4526
+ return langFirstDay;
4527
+ }
4528
+ return "monday";
4529
+ }
4530
+ /**
4531
+ * Pure, uncached resolver for locale first day of week.
4532
+ * 1. Checks Intl.Locale.weekInfo / getWeekInfo()
4533
+ * 2. Falls back to deterministic CLDR fallback
4534
+ */
4535
+ function resolveLocaleFirstDayOfWeek(localeId) {
4536
+ const normalized = (localeId ?? "").trim();
4537
+ if (!normalized) {
4538
+ return "monday";
4539
+ }
4540
+ try {
4541
+ if (typeof Intl !== "undefined" && typeof Intl.Locale === "function") {
4542
+ const loc = new Intl.Locale(normalized);
4543
+ const weekInfo = loc.weekInfo ?? loc.getWeekInfo?.();
4544
+ if (weekInfo && typeof weekInfo.firstDay === "number") {
4545
+ const dayNum = weekInfo.firstDay === 0 ? 7 : weekInfo.firstDay;
4546
+ const mapped = ISO_DAY_MAP[dayNum];
4547
+ if (mapped) {
4548
+ return mapped;
4549
+ }
4550
+ }
4551
+ }
4552
+ }
4553
+ catch {
4554
+ // fallback
4555
+ }
4556
+ return resolveFallbackFirstDayOfWeek(normalized);
4557
+ }
4558
+
4559
+ const dateFormatCache = new Map();
4560
+ const timeFormatCache = new Map();
4561
+ const dateTimeFormatCache = new Map();
4562
+ const firstDayCache = new Map();
4563
+ function normalizeEditableLiteral(value) {
4564
+ return sanitizeDateText(value);
4565
+ }
4566
+ /**
4567
+ * Derives a localized numeric date format (e.g. "yyyy/MM/dd" or "dd/MM/yyyy") for the given locale.
4568
+ */
4569
+ function getLocaleDateInputFormat(localeId) {
4570
+ const locale = normalizeGregorianLocale(localeId);
4571
+ let format = dateFormatCache.get(locale);
4572
+ if (!format) {
4573
+ try {
4574
+ const dtf = new Intl.DateTimeFormat(locale, {
4575
+ calendar: "gregory",
4576
+ year: "numeric",
4577
+ month: "2-digit",
4578
+ day: "2-digit"
4579
+ });
4580
+ const parts = dtf.formatToParts(new Date(2026, 8, 15));
4581
+ let derived = "";
4582
+ for (const part of parts) {
4583
+ if (part.type === "year") {
4584
+ derived += "yyyy";
4585
+ }
4586
+ else if (part.type === "month") {
4587
+ derived += "MM";
4588
+ }
4589
+ else if (part.type === "day") {
4590
+ derived += "dd";
4591
+ }
4592
+ else if (part.type === "literal") {
4593
+ derived += normalizeEditableLiteral(part.value);
4594
+ }
4595
+ }
4596
+ format = derived || "dd/MM/yyyy";
4597
+ }
4598
+ catch {
4599
+ format = "dd/MM/yyyy";
4600
+ }
4601
+ dateFormatCache.set(locale, format);
4602
+ }
4603
+ return format;
4604
+ }
4605
+ /**
4606
+ * Derives a localized time format (e.g. "HH:mm", "ahh:mm", "hh:mm a") for the given locale.
4607
+ */
4608
+ function getLocaleTimeInputFormat(localeId, options) {
4609
+ const locale = normalizeGregorianLocale(localeId);
4610
+ const hourFormat = options?.hourFormat ?? "24";
4611
+ const showSeconds = options?.showSeconds ?? false;
4612
+ const cacheKey = `${locale}|${hourFormat}|${showSeconds}`;
4613
+ let format = timeFormatCache.get(cacheKey);
4614
+ if (!format) {
4615
+ const is12 = hourFormat === "12";
4616
+ try {
4617
+ const dtfOptions = {
4618
+ calendar: "gregory",
4619
+ hour: "2-digit",
4620
+ minute: "2-digit",
4621
+ hour12: is12
4622
+ };
4623
+ if (showSeconds) {
4624
+ dtfOptions.second = "2-digit";
4625
+ }
4626
+ const dtf = new Intl.DateTimeFormat(locale, dtfOptions);
4627
+ const parts = dtf.formatToParts(new Date(2026, 8, 15, 21, 30, 45));
4628
+ let derived = "";
4629
+ for (const part of parts) {
4630
+ if (part.type === "hour") {
4631
+ derived += is12 ? "hh" : "HH";
4632
+ }
4633
+ else if (part.type === "minute") {
4634
+ derived += "mm";
4635
+ }
4636
+ else if (part.type === "second") {
4637
+ derived += "ss";
4638
+ }
4639
+ else if (part.type === "dayPeriod") {
4640
+ derived += "a";
4641
+ }
4642
+ else if (part.type === "literal") {
4643
+ derived += normalizeEditableLiteral(part.value);
4644
+ }
4645
+ }
4646
+ format =
4647
+ derived ||
4648
+ (is12 ? (showSeconds ? "hh:mm:ss a" : "hh:mm a") : showSeconds ? "HH:mm:ss" : "HH:mm");
4649
+ }
4650
+ catch {
4651
+ format = is12 ? (showSeconds ? "hh:mm:ss a" : "hh:mm a") : showSeconds ? "HH:mm:ss" : "HH:mm";
4652
+ }
4653
+ timeFormatCache.set(cacheKey, format);
4654
+ }
4655
+ return format;
4656
+ }
4657
+ /**
4658
+ * Derives a localized date-time format for the given locale.
4659
+ */
4660
+ function getLocaleDateTimeInputFormat(localeId, options) {
4661
+ const locale = normalizeGregorianLocale(localeId);
4662
+ const hourFormat = options?.hourFormat ?? "24";
4663
+ const showSeconds = options?.showSeconds ?? false;
4664
+ const cacheKey = `${locale}|${hourFormat}|${showSeconds}`;
4665
+ let format = dateTimeFormatCache.get(cacheKey);
4666
+ if (!format) {
4667
+ const is12 = hourFormat === "12";
4668
+ try {
4669
+ const dtfOptions = {
4670
+ calendar: "gregory",
4671
+ year: "numeric",
4672
+ month: "2-digit",
4673
+ day: "2-digit",
4674
+ hour: "2-digit",
4675
+ minute: "2-digit",
4676
+ hour12: is12
4677
+ };
4678
+ if (showSeconds) {
4679
+ dtfOptions.second = "2-digit";
4680
+ }
4681
+ const dtf = new Intl.DateTimeFormat(locale, dtfOptions);
4682
+ const parts = dtf.formatToParts(new Date(2026, 8, 15, 21, 30, 45));
4683
+ let derived = "";
4684
+ for (const part of parts) {
4685
+ if (part.type === "year") {
4686
+ derived += "yyyy";
4687
+ }
4688
+ else if (part.type === "month") {
4689
+ derived += "MM";
4690
+ }
4691
+ else if (part.type === "day") {
4692
+ derived += "dd";
4693
+ }
4694
+ else if (part.type === "hour") {
4695
+ derived += is12 ? "hh" : "HH";
4696
+ }
4697
+ else if (part.type === "minute") {
4698
+ derived += "mm";
4699
+ }
4700
+ else if (part.type === "second") {
4701
+ derived += "ss";
4702
+ }
4703
+ else if (part.type === "dayPeriod") {
4704
+ derived += "a";
4705
+ }
4706
+ else if (part.type === "literal") {
4707
+ derived += normalizeEditableLiteral(part.value);
4708
+ }
4709
+ }
4710
+ format = derived || `${getLocaleDateInputFormat(localeId)} ${getLocaleTimeInputFormat(localeId, options)}`;
4711
+ }
4712
+ catch {
4713
+ format = `${getLocaleDateInputFormat(localeId)} ${getLocaleTimeInputFormat(localeId, options)}`;
4714
+ }
4715
+ dateTimeFormatCache.set(cacheKey, format);
4716
+ }
4717
+ return format;
4718
+ }
4719
+ /**
4720
+ * Resolves the first day of the week for the given locale using Intl.Locale.weekInfo,
4721
+ * Intl.Locale.getWeekInfo(), or CLDR fallbacks.
4722
+ */
4723
+ function getLocaleFirstDayOfWeek(localeId) {
4724
+ const normalizedLocaleId = (localeId ?? "").trim();
4725
+ let firstDay = firstDayCache.get(normalizedLocaleId);
4726
+ if (!firstDay) {
4727
+ firstDay = resolveLocaleFirstDayOfWeek(normalizedLocaleId);
4728
+ firstDayCache.set(normalizedLocaleId, firstDay);
4729
+ }
4730
+ return firstDay;
4731
+ }
4732
+
4733
+ const PSEUDO_MAP = {
4734
+ a: "å",
4735
+ b: "ƀ",
4736
+ c: "ç",
4737
+ d: "đ",
4738
+ e: "é",
4739
+ f: "ƒ",
4740
+ g: "ĝ",
4741
+ h: "ĥ",
4742
+ i: "î",
4743
+ j: "ĵ",
4744
+ k: "ķ",
4745
+ l: "ļ",
4746
+ m: "m",
4747
+ n: "ñ",
4748
+ o: "ö",
4749
+ p: "þ",
4750
+ q: "q",
4751
+ r: "ř",
4752
+ s: "š",
4753
+ t: "ţ",
4754
+ u: "û",
4755
+ v: "ṽ",
4756
+ w: "ŵ",
4757
+ x: "x",
4758
+ y: "ŷ",
4759
+ z: "ž",
4760
+ A: "Å",
4761
+ B: "Ɓ",
4762
+ C: "Ç",
4763
+ D: "Đ",
4764
+ E: "É",
4765
+ F: "Ƒ",
4766
+ G: "Ĝ",
4767
+ H: "Ĥ",
4768
+ I: "Î",
4769
+ J: "Ĵ",
4770
+ K: "Ķ",
4771
+ L: "Ļ",
4772
+ M: "M",
4773
+ N: "Ñ",
4774
+ O: "Ö",
4775
+ P: "Þ",
4776
+ Q: "Q",
4777
+ R: "Ř",
4778
+ S: "Š",
4779
+ T: "Ţ",
4780
+ U: "Û",
4781
+ V: "Ṽ",
4782
+ W: "Ŵ",
4783
+ X: "X",
4784
+ Y: "Ŷ",
4785
+ Z: "Ž"
4786
+ };
4787
+ /**
4788
+ * Transforms a text string into pseudo-localized text (e.g. "Apply" -> "[!! Åþþļÿ~~ !!]").
4789
+ * Tokens enclosed in single braces {placeholder}, double braces {{placeholder}}, or HTML tags <tag>
4790
+ * are preserved verbatim so formatting / parameter substitution continues to function.
4791
+ */
4792
+ function pseudoLocalize(text, options = {}) {
4793
+ if (!text || typeof text !== "string") {
4794
+ return text;
4795
+ }
4796
+ const { prefix = "[!! ", suffix = " !!]", expand = true, expansionFactor = 0.3 } = options;
4797
+ if (text.startsWith(prefix) && text.endsWith(suffix)) {
4798
+ return text;
4799
+ }
4800
+ // Preserve tokens like {0}, {name}, {{val}}, <span ...>, </b>
4801
+ const tokens = text.split(/(\{[^{}]+\}|\{\{[^{}]+\}|<[^>]+>)/g);
4802
+ const convertedTokens = tokens.map((segment, index) => {
4803
+ // Odd indices match the split token regex
4804
+ if (index % 2 === 1) {
4805
+ return segment;
4806
+ }
4807
+ return segment
4808
+ .split("")
4809
+ .map(char => PSEUDO_MAP[char] ?? char)
4810
+ .join("");
4811
+ });
4812
+ let transformed = convertedTokens.join("");
4813
+ if (expand) {
4814
+ const expansionLen = Math.max(1, Math.round(text.length * expansionFactor));
4815
+ transformed += "~".repeat(expansionLen);
4816
+ }
4817
+ return `${prefix}${transformed}${suffix}`;
4818
+ }
4819
+ /**
4820
+ * Recursively pseudo-localizes a message catalog or nested object of message catalogs.
4821
+ * Plain strings are pseudo-localized, and message functions (e.g. (page: number) => string)
4822
+ * are wrapped so their string outputs are pseudo-localized when invoked.
4823
+ */
4824
+ function pseudoLocalizeCatalog(catalog, options) {
4825
+ const result = {};
4826
+ for (const [key, value] of Object.entries(catalog)) {
4827
+ if (typeof value === "string") {
4828
+ result[key] = pseudoLocalize(value, options);
4829
+ }
4830
+ else if (typeof value === "function") {
4831
+ result[key] = (...args) => {
4832
+ const out = value(...args);
4833
+ return typeof out === "string" ? pseudoLocalize(out, options) : out;
4834
+ };
4835
+ }
4836
+ else if (value && typeof value === "object" && !Array.isArray(value)) {
4837
+ result[key] = pseudoLocalizeCatalog(value, options);
4838
+ }
4839
+ else {
4840
+ result[key] = value;
4841
+ }
4842
+ }
4843
+ return result;
4844
+ }
4845
+ /**
4846
+ * Generates a full pseudo-localized MonaLocale (e.g. en-XA) from a dictionary of message catalogs.
4847
+ */
4848
+ function generatePseudoLocale(catalogs, options) {
4849
+ const id = options?.id ?? "en-XA";
4850
+ const direction = options?.direction ?? "ltr";
4851
+ const pseudoOptions = options?.pseudoOptions;
4852
+ const messages = {};
4853
+ for (const [namespace, catalog] of Object.entries(catalogs)) {
4854
+ if (catalog && typeof catalog === "object") {
4855
+ messages[namespace] = pseudoLocalizeCatalog(catalog, pseudoOptions);
4856
+ }
4857
+ }
4858
+ return {
4859
+ direction,
4860
+ id,
4861
+ messages: messages
4862
+ };
4863
+ }
4864
+
4865
+ /*
4866
+ * Public API Surface of @nanahoshi/mona-ui/i18n
4867
+ */
4868
+
4869
+ /**
4870
+ * Generated bundle index. Do not edit.
4871
+ */
4872
+
4873
+ export { BIDI_CONTROL_REGEX, MONA_DEFAULT_LOCALE, MONA_I18N_CONFIG, MonaDirectionService, MonaI18nService, formatGregorianDateToLocaleString, formatNumber, generatePseudoLocale, getLocaleDateInputFormat, getLocaleDateTimeInputFormat, getLocaleFirstDayOfWeek, getLocaleTimeInputFormat, getNumberFormatter, getNumberGroupingPattern, getNumberSymbols, gregorianDateTime, gregorianDateTimeFromObject, injectComponentDirection, mergeMessages, mergeTwo, normalizeGregorianLocale, normalizeLocalizedDigits, normalizeLocalizedInput, normalizeLocalizedMinus, observeComponentDirection, parseGregorianDate, parseLocalizedNumber, provideMonaI18n, pseudoLocalize, pseudoLocalizeCatalog, resolveComponentDirection, sanitizeDateText, stripBidiControls, validateLocalizedNumber, validateLocalizedNumberEdit };
4874
+ //# sourceMappingURL=nanahoshi-mona-ui-i18n.mjs.map