@gears-frontx/i18n 0.1.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.
package/dist/index.js ADDED
@@ -0,0 +1,850 @@
1
+ // src/types.ts
2
+ var TextDirection = /* @__PURE__ */ ((TextDirection2) => {
3
+ TextDirection2["LeftToRight"] = "ltr";
4
+ TextDirection2["RightToLeft"] = "rtl";
5
+ return TextDirection2;
6
+ })(TextDirection || {});
7
+ var Language = /* @__PURE__ */ ((Language2) => {
8
+ Language2["English"] = "en";
9
+ Language2["Spanish"] = "es";
10
+ Language2["French"] = "fr";
11
+ Language2["German"] = "de";
12
+ Language2["Italian"] = "it";
13
+ Language2["Portuguese"] = "pt";
14
+ Language2["Dutch"] = "nl";
15
+ Language2["Russian"] = "ru";
16
+ Language2["Polish"] = "pl";
17
+ Language2["Ukrainian"] = "uk";
18
+ Language2["Czech"] = "cs";
19
+ Language2["Arabic"] = "ar";
20
+ Language2["Hebrew"] = "he";
21
+ Language2["Persian"] = "fa";
22
+ Language2["Urdu"] = "ur";
23
+ Language2["Turkish"] = "tr";
24
+ Language2["ChineseSimplified"] = "zh";
25
+ Language2["ChineseTraditional"] = "zh-TW";
26
+ Language2["Japanese"] = "ja";
27
+ Language2["Korean"] = "ko";
28
+ Language2["Vietnamese"] = "vi";
29
+ Language2["Thai"] = "th";
30
+ Language2["Indonesian"] = "id";
31
+ Language2["Hindi"] = "hi";
32
+ Language2["Bengali"] = "bn";
33
+ Language2["Swedish"] = "sv";
34
+ Language2["Danish"] = "da";
35
+ Language2["Norwegian"] = "no";
36
+ Language2["Finnish"] = "fi";
37
+ Language2["Greek"] = "el";
38
+ Language2["Romanian"] = "ro";
39
+ Language2["Hungarian"] = "hu";
40
+ Language2["Malay"] = "ms";
41
+ Language2["Tagalog"] = "tl";
42
+ Language2["Tamil"] = "ta";
43
+ Language2["Swahili"] = "sw";
44
+ return Language2;
45
+ })(Language || {});
46
+ var LanguageDisplayMode = /* @__PURE__ */ ((LanguageDisplayMode2) => {
47
+ LanguageDisplayMode2["Native"] = "native";
48
+ LanguageDisplayMode2["English"] = "english";
49
+ return LanguageDisplayMode2;
50
+ })(LanguageDisplayMode || {});
51
+ var I18N_NAMESPACE_SEPARATOR = ":";
52
+ var I18N_PATH_SEPARATOR = ".";
53
+ var I18N_DEFAULT_NAMESPACE = "app";
54
+ var HTML_LANG_ATTRIBUTE = "lang";
55
+ var HTML_DIR_ATTRIBUTE = "dir";
56
+
57
+ // src/languages.ts
58
+ var SUPPORTED_LANGUAGES = [
59
+ // Western European
60
+ {
61
+ code: "en" /* English */,
62
+ name: "English",
63
+ englishName: "English",
64
+ direction: "ltr" /* LeftToRight */
65
+ },
66
+ {
67
+ code: "es" /* Spanish */,
68
+ name: "Espa\xF1ol",
69
+ englishName: "Spanish",
70
+ direction: "ltr" /* LeftToRight */
71
+ },
72
+ {
73
+ code: "fr" /* French */,
74
+ name: "Fran\xE7ais",
75
+ englishName: "French",
76
+ direction: "ltr" /* LeftToRight */
77
+ },
78
+ {
79
+ code: "de" /* German */,
80
+ name: "Deutsch",
81
+ englishName: "German",
82
+ direction: "ltr" /* LeftToRight */
83
+ },
84
+ {
85
+ code: "it" /* Italian */,
86
+ name: "Italiano",
87
+ englishName: "Italian",
88
+ direction: "ltr" /* LeftToRight */
89
+ },
90
+ {
91
+ code: "pt" /* Portuguese */,
92
+ name: "Portugu\xEAs",
93
+ englishName: "Portuguese",
94
+ direction: "ltr" /* LeftToRight */
95
+ },
96
+ {
97
+ code: "nl" /* Dutch */,
98
+ name: "Nederlands",
99
+ englishName: "Dutch",
100
+ direction: "ltr" /* LeftToRight */
101
+ },
102
+ // Eastern European
103
+ {
104
+ code: "ru" /* Russian */,
105
+ name: "\u0420\u0443\u0441\u0441\u043A\u0438\u0439",
106
+ englishName: "Russian",
107
+ direction: "ltr" /* LeftToRight */
108
+ },
109
+ {
110
+ code: "pl" /* Polish */,
111
+ name: "Polski",
112
+ englishName: "Polish",
113
+ direction: "ltr" /* LeftToRight */
114
+ },
115
+ {
116
+ code: "uk" /* Ukrainian */,
117
+ name: "\u0423\u043A\u0440\u0430\u0457\u043D\u0441\u044C\u043A\u0430",
118
+ englishName: "Ukrainian",
119
+ direction: "ltr" /* LeftToRight */
120
+ },
121
+ {
122
+ code: "cs" /* Czech */,
123
+ name: "\u010Ce\u0161tina",
124
+ englishName: "Czech",
125
+ direction: "ltr" /* LeftToRight */
126
+ },
127
+ // Middle East & North Africa (RTL)
128
+ {
129
+ code: "ar" /* Arabic */,
130
+ name: "\u0627\u0644\u0639\u0631\u0628\u064A\u0629",
131
+ englishName: "Arabic",
132
+ direction: "rtl" /* RightToLeft */
133
+ },
134
+ {
135
+ code: "he" /* Hebrew */,
136
+ name: "\u05E2\u05D1\u05E8\u05D9\u05EA",
137
+ englishName: "Hebrew",
138
+ direction: "rtl" /* RightToLeft */
139
+ },
140
+ {
141
+ code: "fa" /* Persian */,
142
+ name: "\u0641\u0627\u0631\u0633\u06CC",
143
+ englishName: "Persian",
144
+ direction: "rtl" /* RightToLeft */
145
+ },
146
+ {
147
+ code: "ur" /* Urdu */,
148
+ name: "\u0627\u0631\u062F\u0648",
149
+ englishName: "Urdu",
150
+ direction: "rtl" /* RightToLeft */
151
+ },
152
+ {
153
+ code: "tr" /* Turkish */,
154
+ name: "T\xFCrk\xE7e",
155
+ englishName: "Turkish",
156
+ direction: "ltr" /* LeftToRight */
157
+ },
158
+ // Asian
159
+ {
160
+ code: "zh" /* ChineseSimplified */,
161
+ name: "\u7B80\u4F53\u4E2D\u6587",
162
+ englishName: "Chinese (Simplified)",
163
+ direction: "ltr" /* LeftToRight */
164
+ },
165
+ {
166
+ code: "zh-TW" /* ChineseTraditional */,
167
+ name: "\u7E41\u9AD4\u4E2D\u6587",
168
+ englishName: "Chinese (Traditional)",
169
+ direction: "ltr" /* LeftToRight */,
170
+ region: "TW"
171
+ },
172
+ {
173
+ code: "ja" /* Japanese */,
174
+ name: "\u65E5\u672C\u8A9E",
175
+ englishName: "Japanese",
176
+ direction: "ltr" /* LeftToRight */
177
+ },
178
+ {
179
+ code: "ko" /* Korean */,
180
+ name: "\uD55C\uAD6D\uC5B4",
181
+ englishName: "Korean",
182
+ direction: "ltr" /* LeftToRight */
183
+ },
184
+ {
185
+ code: "vi" /* Vietnamese */,
186
+ name: "Ti\u1EBFng Vi\u1EC7t",
187
+ englishName: "Vietnamese",
188
+ direction: "ltr" /* LeftToRight */
189
+ },
190
+ {
191
+ code: "th" /* Thai */,
192
+ name: "\u0E44\u0E17\u0E22",
193
+ englishName: "Thai",
194
+ direction: "ltr" /* LeftToRight */
195
+ },
196
+ {
197
+ code: "id" /* Indonesian */,
198
+ name: "Bahasa Indonesia",
199
+ englishName: "Indonesian",
200
+ direction: "ltr" /* LeftToRight */
201
+ },
202
+ {
203
+ code: "hi" /* Hindi */,
204
+ name: "\u0939\u093F\u0928\u094D\u0926\u0940",
205
+ englishName: "Hindi",
206
+ direction: "ltr" /* LeftToRight */
207
+ },
208
+ {
209
+ code: "bn" /* Bengali */,
210
+ name: "\u09AC\u09BE\u0982\u09B2\u09BE",
211
+ englishName: "Bengali",
212
+ direction: "ltr" /* LeftToRight */
213
+ },
214
+ // Nordic
215
+ {
216
+ code: "sv" /* Swedish */,
217
+ name: "Svenska",
218
+ englishName: "Swedish",
219
+ direction: "ltr" /* LeftToRight */
220
+ },
221
+ {
222
+ code: "da" /* Danish */,
223
+ name: "Dansk",
224
+ englishName: "Danish",
225
+ direction: "ltr" /* LeftToRight */
226
+ },
227
+ {
228
+ code: "no" /* Norwegian */,
229
+ name: "Norsk",
230
+ englishName: "Norwegian",
231
+ direction: "ltr" /* LeftToRight */
232
+ },
233
+ {
234
+ code: "fi" /* Finnish */,
235
+ name: "Suomi",
236
+ englishName: "Finnish",
237
+ direction: "ltr" /* LeftToRight */
238
+ },
239
+ // Other
240
+ {
241
+ code: "el" /* Greek */,
242
+ name: "\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC",
243
+ englishName: "Greek",
244
+ direction: "ltr" /* LeftToRight */
245
+ },
246
+ {
247
+ code: "ro" /* Romanian */,
248
+ name: "Rom\xE2n\u0103",
249
+ englishName: "Romanian",
250
+ direction: "ltr" /* LeftToRight */
251
+ },
252
+ {
253
+ code: "hu" /* Hungarian */,
254
+ name: "Magyar",
255
+ englishName: "Hungarian",
256
+ direction: "ltr" /* LeftToRight */
257
+ },
258
+ // Additional major languages
259
+ {
260
+ code: "ms" /* Malay */,
261
+ name: "Bahasa Melayu",
262
+ englishName: "Malay",
263
+ direction: "ltr" /* LeftToRight */
264
+ },
265
+ {
266
+ code: "tl" /* Tagalog */,
267
+ name: "Tagalog",
268
+ englishName: "Tagalog",
269
+ direction: "ltr" /* LeftToRight */
270
+ },
271
+ {
272
+ code: "ta" /* Tamil */,
273
+ name: "\u0BA4\u0BAE\u0BBF\u0BB4\u0BCD",
274
+ englishName: "Tamil",
275
+ direction: "ltr" /* LeftToRight */
276
+ },
277
+ {
278
+ code: "sw" /* Swahili */,
279
+ name: "Kiswahili",
280
+ englishName: "Swahili",
281
+ direction: "ltr" /* LeftToRight */
282
+ }
283
+ ];
284
+ function getLanguageMetadata(code) {
285
+ return SUPPORTED_LANGUAGES.find((lang) => lang.code === code);
286
+ }
287
+ function getRTLLanguages() {
288
+ return SUPPORTED_LANGUAGES.filter((lang) => lang.direction === "rtl" /* RightToLeft */).map((lang) => lang.code);
289
+ }
290
+ function isValidLanguage(code) {
291
+ return SUPPORTED_LANGUAGES.some((lang) => lang.code === code);
292
+ }
293
+
294
+ // src/I18nRegistry.ts
295
+ var I18nRegistryImpl = class _I18nRegistryImpl {
296
+ /** Configuration */
297
+ config;
298
+ /** Current language */
299
+ currentLanguage = null;
300
+ /** Translation dictionaries: namespace -> language -> dictionary */
301
+ dictionaries = /* @__PURE__ */ new Map();
302
+ /** Translation loaders: namespace -> loader function */
303
+ loaders = /* @__PURE__ */ new Map();
304
+ /** Subscribers for translation changes */
305
+ subscribers = /* @__PURE__ */ new Set();
306
+ /** Version counter for React re-rendering */
307
+ version = 0;
308
+ // @cpt-begin:cpt-hai3-algo-i18n-infrastructure-language-file-map:p1:inst-1
309
+ /** Language file mapping */
310
+ static LANGUAGE_FILE_MAP = {
311
+ ["en" /* English */]: "en.json",
312
+ ["es" /* Spanish */]: "es.json",
313
+ ["fr" /* French */]: "fr.json",
314
+ ["de" /* German */]: "de.json",
315
+ ["it" /* Italian */]: "it.json",
316
+ ["pt" /* Portuguese */]: "pt.json",
317
+ ["nl" /* Dutch */]: "nl.json",
318
+ ["ru" /* Russian */]: "ru.json",
319
+ ["pl" /* Polish */]: "pl.json",
320
+ ["uk" /* Ukrainian */]: "uk.json",
321
+ ["cs" /* Czech */]: "cs.json",
322
+ ["ar" /* Arabic */]: "ar.json",
323
+ ["he" /* Hebrew */]: "he.json",
324
+ ["fa" /* Persian */]: "fa.json",
325
+ ["ur" /* Urdu */]: "ur.json",
326
+ ["tr" /* Turkish */]: "tr.json",
327
+ ["zh" /* ChineseSimplified */]: "zh.json",
328
+ ["zh-TW" /* ChineseTraditional */]: "zh-TW.json",
329
+ ["ja" /* Japanese */]: "ja.json",
330
+ ["ko" /* Korean */]: "ko.json",
331
+ ["vi" /* Vietnamese */]: "vi.json",
332
+ ["th" /* Thai */]: "th.json",
333
+ ["id" /* Indonesian */]: "id.json",
334
+ ["hi" /* Hindi */]: "hi.json",
335
+ ["bn" /* Bengali */]: "bn.json",
336
+ ["sv" /* Swedish */]: "sv.json",
337
+ ["da" /* Danish */]: "da.json",
338
+ ["no" /* Norwegian */]: "no.json",
339
+ ["fi" /* Finnish */]: "fi.json",
340
+ ["el" /* Greek */]: "el.json",
341
+ ["ro" /* Romanian */]: "ro.json",
342
+ ["hu" /* Hungarian */]: "hu.json",
343
+ ["ms" /* Malay */]: "ms.json",
344
+ ["tl" /* Tagalog */]: "tl.json",
345
+ ["ta" /* Tamil */]: "ta.json",
346
+ ["sw" /* Swahili */]: "sw.json"
347
+ };
348
+ // @cpt-end:cpt-hai3-algo-i18n-infrastructure-language-file-map:p1:inst-1
349
+ constructor(config) {
350
+ this.config = config;
351
+ }
352
+ // ============================================================================
353
+ // Registration
354
+ // ============================================================================
355
+ // @cpt-begin:cpt-hai3-state-i18n-infrastructure-namespace-cache:p1:inst-1
356
+ /**
357
+ * Register translations for a namespace.
358
+ */
359
+ register(namespace, language, translations) {
360
+ if (!this.dictionaries.has(namespace)) {
361
+ this.dictionaries.set(namespace, /* @__PURE__ */ new Map());
362
+ }
363
+ this.dictionaries.get(namespace).set(language, translations);
364
+ this.notifySubscribers();
365
+ }
366
+ // @cpt-end:cpt-hai3-state-i18n-infrastructure-namespace-cache:p1:inst-1
367
+ /**
368
+ * Subscribe to translation changes.
369
+ * Returns an unsubscribe function.
370
+ */
371
+ subscribe(callback) {
372
+ this.subscribers.add(callback);
373
+ return () => {
374
+ this.subscribers.delete(callback);
375
+ };
376
+ }
377
+ /**
378
+ * Notify all subscribers of a change.
379
+ */
380
+ notifySubscribers() {
381
+ this.version++;
382
+ this.subscribers.forEach((callback) => callback());
383
+ }
384
+ /**
385
+ * Get the current version number.
386
+ * Used by React to detect changes.
387
+ */
388
+ getVersion() {
389
+ return this.version;
390
+ }
391
+ // @cpt-begin:cpt-hai3-flow-i18n-infrastructure-screenset-registration:p1:inst-1
392
+ // @cpt-begin:cpt-hai3-flow-i18n-infrastructure-screen-lazy-load:p1:inst-1
393
+ /**
394
+ * Register a translation loader for a namespace.
395
+ */
396
+ registerLoader(namespace, loader) {
397
+ this.loaders.set(namespace, loader);
398
+ }
399
+ // @cpt-end:cpt-hai3-flow-i18n-infrastructure-screenset-registration:p1:inst-1
400
+ // @cpt-end:cpt-hai3-flow-i18n-infrastructure-screen-lazy-load:p1:inst-1
401
+ /**
402
+ * Check if namespace is registered.
403
+ */
404
+ hasNamespace(namespace) {
405
+ return this.dictionaries.has(namespace) || this.loaders.has(namespace);
406
+ }
407
+ /**
408
+ * Get all registered namespaces.
409
+ */
410
+ getNamespaces() {
411
+ const namespaces = /* @__PURE__ */ new Set();
412
+ this.dictionaries.forEach((_, key) => namespaces.add(key));
413
+ this.loaders.forEach((_, key) => namespaces.add(key));
414
+ return Array.from(namespaces);
415
+ }
416
+ // ============================================================================
417
+ // Translation
418
+ // ============================================================================
419
+ // @cpt-begin:cpt-hai3-flow-i18n-infrastructure-key-resolution:p1:inst-1
420
+ /**
421
+ * Translate a key.
422
+ * Format: 'namespace:key.subkey' or just 'key' for default namespace
423
+ */
424
+ t(key, params) {
425
+ const { namespace, path } = this.parseKey(key);
426
+ const translation = this.getTranslation(namespace, path);
427
+ if (translation === void 0) {
428
+ return key;
429
+ }
430
+ return this.interpolate(translation, params);
431
+ }
432
+ // @cpt-end:cpt-hai3-flow-i18n-infrastructure-key-resolution:p1:inst-1
433
+ // @cpt-begin:cpt-hai3-flow-i18n-infrastructure-key-resolution:p1:inst-2
434
+ /**
435
+ * Parse a translation key into namespace and path.
436
+ */
437
+ parseKey(key) {
438
+ const separatorIndex = key.indexOf(I18N_NAMESPACE_SEPARATOR);
439
+ if (separatorIndex === -1) {
440
+ return {
441
+ namespace: I18N_DEFAULT_NAMESPACE,
442
+ path: key
443
+ };
444
+ }
445
+ return {
446
+ namespace: key.slice(0, separatorIndex),
447
+ path: key.slice(separatorIndex + 1)
448
+ };
449
+ }
450
+ // @cpt-end:cpt-hai3-flow-i18n-infrastructure-key-resolution:p1:inst-2
451
+ // @cpt-begin:cpt-hai3-flow-i18n-infrastructure-key-resolution:p1:inst-3
452
+ /**
453
+ * Get a translation from the dictionary.
454
+ */
455
+ getTranslation(namespace, path) {
456
+ const language = this.currentLanguage ?? this.config.defaultLanguage;
457
+ const fallback = this.config.fallbackLanguage;
458
+ let translation = this.findTranslation(namespace, language, path);
459
+ if (translation !== void 0) {
460
+ return translation;
461
+ }
462
+ if (language !== fallback) {
463
+ translation = this.findTranslation(namespace, fallback, path);
464
+ if (translation !== void 0) {
465
+ return translation;
466
+ }
467
+ }
468
+ return void 0;
469
+ }
470
+ // @cpt-end:cpt-hai3-flow-i18n-infrastructure-key-resolution:p1:inst-3
471
+ // @cpt-begin:cpt-hai3-flow-i18n-infrastructure-key-resolution:p1:inst-4
472
+ // @cpt-begin:cpt-hai3-algo-i18n-infrastructure-path-traversal:p1:inst-1
473
+ /**
474
+ * Find a translation in the dictionary.
475
+ */
476
+ findTranslation(namespace, language, path) {
477
+ const namespaceDicts = this.dictionaries.get(namespace);
478
+ if (!namespaceDicts) {
479
+ return void 0;
480
+ }
481
+ const dict = namespaceDicts.get(language);
482
+ if (!dict) {
483
+ return void 0;
484
+ }
485
+ const parts = path.split(I18N_PATH_SEPARATOR);
486
+ let current = dict;
487
+ for (const part of parts) {
488
+ if (typeof current !== "object" || current === null) {
489
+ return void 0;
490
+ }
491
+ current = current[part];
492
+ if (current === void 0) {
493
+ return void 0;
494
+ }
495
+ }
496
+ return typeof current === "string" ? current : void 0;
497
+ }
498
+ // @cpt-end:cpt-hai3-flow-i18n-infrastructure-key-resolution:p1:inst-4
499
+ // @cpt-end:cpt-hai3-algo-i18n-infrastructure-path-traversal:p1:inst-1
500
+ // @cpt-begin:cpt-hai3-flow-i18n-infrastructure-key-resolution:p1:inst-5
501
+ /**
502
+ * Interpolate parameters into a translation string.
503
+ */
504
+ interpolate(text, params) {
505
+ if (!params) {
506
+ return text;
507
+ }
508
+ return text.replace(/\{(\w+)\}/g, (match, key) => {
509
+ const value = params[key];
510
+ return value !== void 0 ? String(value) : match;
511
+ });
512
+ }
513
+ // @cpt-end:cpt-hai3-flow-i18n-infrastructure-key-resolution:p1:inst-5
514
+ // ============================================================================
515
+ // Language Management
516
+ // ============================================================================
517
+ // @cpt-begin:cpt-hai3-flow-i18n-infrastructure-language-activation:p1:inst-1
518
+ // @cpt-begin:cpt-hai3-state-i18n-infrastructure-registry:p1:inst-1
519
+ /**
520
+ * Set current language and load translations.
521
+ */
522
+ async setLanguage(language) {
523
+ this.currentLanguage = language;
524
+ this.updateHtmlAttributes(language);
525
+ await this.loadLanguage(language);
526
+ }
527
+ // @cpt-end:cpt-hai3-flow-i18n-infrastructure-language-activation:p1:inst-1
528
+ // @cpt-end:cpt-hai3-state-i18n-infrastructure-registry:p1:inst-1
529
+ /**
530
+ * Get current language.
531
+ */
532
+ getLanguage() {
533
+ return this.currentLanguage;
534
+ }
535
+ // @cpt-begin:cpt-hai3-algo-i18n-infrastructure-html-attrs:p1:inst-1
536
+ /**
537
+ * Update HTML lang and dir attributes.
538
+ */
539
+ updateHtmlAttributes(language) {
540
+ if (typeof document === "undefined") {
541
+ return;
542
+ }
543
+ const htmlElement = document.documentElement;
544
+ htmlElement.setAttribute(HTML_LANG_ATTRIBUTE, language);
545
+ htmlElement.setAttribute(
546
+ HTML_DIR_ATTRIBUTE,
547
+ this.isRTL(language) ? "rtl" /* RightToLeft */ : "ltr" /* LeftToRight */
548
+ );
549
+ }
550
+ // @cpt-end:cpt-hai3-algo-i18n-infrastructure-html-attrs:p1:inst-1
551
+ // ============================================================================
552
+ // Language Metadata
553
+ // ============================================================================
554
+ /**
555
+ * Get language metadata.
556
+ */
557
+ getLanguageMetadata(code) {
558
+ const targetCode = code ?? this.currentLanguage;
559
+ if (!targetCode) {
560
+ return void 0;
561
+ }
562
+ return SUPPORTED_LANGUAGES.find((lang) => lang.code === targetCode);
563
+ }
564
+ /**
565
+ * Get all supported languages.
566
+ */
567
+ getSupportedLanguages() {
568
+ return [...SUPPORTED_LANGUAGES];
569
+ }
570
+ /**
571
+ * Check if a language is RTL.
572
+ */
573
+ isRTL(code) {
574
+ const targetCode = code ?? this.currentLanguage;
575
+ if (!targetCode) {
576
+ return false;
577
+ }
578
+ const metadata = this.getLanguageMetadata(targetCode);
579
+ return metadata?.direction === "rtl" /* RightToLeft */;
580
+ }
581
+ // ============================================================================
582
+ // Translation Loading
583
+ // ============================================================================
584
+ // @cpt-begin:cpt-hai3-algo-i18n-infrastructure-lazy-exclusion:p1:inst-1
585
+ // @cpt-begin:cpt-hai3-flow-i18n-infrastructure-language-activation:p1:inst-2
586
+ /**
587
+ * Load translations for a language.
588
+ * Excludes screen.* and screenset.* namespaces which are lazy-loaded:
589
+ * - screen.* namespaces: loaded when screen mounts
590
+ * - screenset.* namespaces: loaded when screenset is activated
591
+ */
592
+ async loadLanguage(language) {
593
+ const loadPromises = [];
594
+ this.loaders.forEach((_loader, namespace) => {
595
+ if (namespace.startsWith("screen.") || namespace.startsWith("screenset.")) {
596
+ return;
597
+ }
598
+ loadPromises.push(this.loadNamespace(namespace, language));
599
+ });
600
+ await Promise.all(loadPromises);
601
+ }
602
+ // @cpt-end:cpt-hai3-algo-i18n-infrastructure-lazy-exclusion:p1:inst-1
603
+ // @cpt-end:cpt-hai3-flow-i18n-infrastructure-language-activation:p1:inst-2
604
+ // @cpt-begin:cpt-hai3-flow-i18n-infrastructure-screen-lazy-load:p1:inst-2
605
+ /**
606
+ * Load translations for a specific namespace.
607
+ */
608
+ async loadNamespace(namespace, language) {
609
+ const loader = this.loaders.get(namespace);
610
+ if (!loader) {
611
+ return;
612
+ }
613
+ try {
614
+ const translations = await loader(language);
615
+ this.register(namespace, language, translations);
616
+ } catch (error) {
617
+ console.warn(`Failed to load translations for ${namespace}/${language}:`, error);
618
+ }
619
+ }
620
+ // @cpt-end:cpt-hai3-flow-i18n-infrastructure-screen-lazy-load:p1:inst-2
621
+ // @cpt-begin:cpt-hai3-flow-i18n-infrastructure-screenset-registration:p1:inst-2
622
+ /**
623
+ * Load translations for a specific screenset.
624
+ */
625
+ async loadScreensetTranslations(screensetId, language) {
626
+ const targetLanguage = language ?? this.currentLanguage ?? this.config.defaultLanguage;
627
+ const namespace = `screenset.${screensetId}`;
628
+ await this.loadNamespace(namespace, targetLanguage);
629
+ }
630
+ // @cpt-end:cpt-hai3-flow-i18n-infrastructure-screenset-registration:p1:inst-2
631
+ /**
632
+ * Preload translations for multiple languages.
633
+ */
634
+ async preloadLanguages(languages) {
635
+ const loadPromises = languages.map((language) => this.loadLanguage(language));
636
+ await Promise.all(loadPromises);
637
+ }
638
+ // ============================================================================
639
+ // Static Helpers
640
+ // ============================================================================
641
+ /**
642
+ * Create a translation loader from a translation map.
643
+ *
644
+ * @example
645
+ * ```typescript
646
+ * const loader = I18nRegistry.createLoader({
647
+ * [Language.English]: () => import('./i18n/en.json'),
648
+ * [Language.Spanish]: () => import('./i18n/es.json'),
649
+ * });
650
+ * ```
651
+ */
652
+ // @cpt-begin:cpt-hai3-algo-i18n-infrastructure-create-loader:p1:inst-1
653
+ // @cpt-begin:cpt-hai3-dod-i18n-infrastructure-lazy-chunks:p1:inst-1
654
+ static createLoader(translationMap) {
655
+ return async (language) => {
656
+ const importFn = translationMap[language];
657
+ if (!importFn) {
658
+ throw new Error(`No translation found for language: ${language}`);
659
+ }
660
+ const module = await importFn();
661
+ return module.default;
662
+ };
663
+ }
664
+ // @cpt-end:cpt-hai3-algo-i18n-infrastructure-create-loader:p1:inst-1
665
+ // @cpt-end:cpt-hai3-dod-i18n-infrastructure-lazy-chunks:p1:inst-1
666
+ /**
667
+ * Create a translation loader from a directory.
668
+ * Maps Language enum values to file names automatically.
669
+ *
670
+ * @param basePath - Base path for translation files
671
+ * @param importFn - Dynamic import function
672
+ */
673
+ static createLoaderFromDirectory(importFn) {
674
+ return async (language) => {
675
+ const filename = _I18nRegistryImpl.LANGUAGE_FILE_MAP[language];
676
+ const module = await importFn(filename);
677
+ return module.default;
678
+ };
679
+ }
680
+ };
681
+ var i18nRegistry = new I18nRegistryImpl({
682
+ defaultLanguage: "en" /* English */,
683
+ fallbackLanguage: "en" /* English */
684
+ });
685
+ function createI18nRegistry(config) {
686
+ return new I18nRegistryImpl(config);
687
+ }
688
+
689
+ // src/formatters/utils.ts
690
+ function getLocale() {
691
+ return i18nRegistry.getLanguage() ?? "en" /* English */;
692
+ }
693
+ function toNumber(value) {
694
+ if (value === null || value === void 0) return null;
695
+ const n = Number(value);
696
+ return Number.isNaN(n) ? null : n;
697
+ }
698
+
699
+ // src/formatters/dateFormatter.ts
700
+ function toDate(value) {
701
+ if (value === null || value === void 0) return null;
702
+ const d = new Date(value);
703
+ return Number.isNaN(d.getTime()) ? null : d;
704
+ }
705
+ function formatDate(date, format) {
706
+ const d = toDate(date);
707
+ if (!d) return "";
708
+ const locale = getLocale();
709
+ return new Intl.DateTimeFormat(locale, { dateStyle: format }).format(d);
710
+ }
711
+ function formatTime(date, format) {
712
+ const d = toDate(date);
713
+ if (!d) return "";
714
+ const locale = getLocale();
715
+ return new Intl.DateTimeFormat(locale, { timeStyle: format }).format(d);
716
+ }
717
+ function formatDateTime(date, dateFormat, timeFormat) {
718
+ const d = toDate(date);
719
+ if (!d) return "";
720
+ const locale = getLocale();
721
+ return new Intl.DateTimeFormat(locale, {
722
+ dateStyle: dateFormat,
723
+ timeStyle: timeFormat
724
+ }).format(d);
725
+ }
726
+ var MS_PER_SECOND = 1e3;
727
+ var MS_PER_MINUTE = 60 * MS_PER_SECOND;
728
+ var MS_PER_HOUR = 60 * MS_PER_MINUTE;
729
+ var MS_PER_DAY = 24 * MS_PER_HOUR;
730
+ function getRelativeUnit(date, base) {
731
+ const diffMs = date.getTime() - base.getTime();
732
+ const absMs = Math.abs(diffMs);
733
+ const sign = diffMs < 0 ? -1 : 1;
734
+ if (absMs < 60 * MS_PER_SECOND) {
735
+ const value = Math.round(diffMs / MS_PER_SECOND);
736
+ return { value: value === 0 ? 0 : value, unit: "second" };
737
+ }
738
+ if (absMs < 60 * MS_PER_MINUTE) {
739
+ return { value: sign * Math.round(absMs / MS_PER_MINUTE), unit: "minute" };
740
+ }
741
+ if (absMs < MS_PER_DAY) {
742
+ return { value: sign * Math.round(absMs / MS_PER_HOUR), unit: "hour" };
743
+ }
744
+ const baseY = base.getUTCFullYear();
745
+ const baseM = base.getUTCMonth();
746
+ const baseD = base.getUTCDate();
747
+ const dateY = date.getUTCFullYear();
748
+ const dateM = date.getUTCMonth();
749
+ const dateD = date.getUTCDate();
750
+ const totalMonths = (dateY - baseY) * 12 + (dateM - baseM);
751
+ const baseUTC = Date.UTC(baseY, baseM, baseD);
752
+ const dateUTC = Date.UTC(dateY, dateM, dateD);
753
+ const diffDays = Math.round((dateUTC - baseUTC) / MS_PER_DAY);
754
+ if (Math.abs(totalMonths) >= 12) {
755
+ const value = Math.round(totalMonths / 12);
756
+ return { value, unit: "year" };
757
+ }
758
+ if (Math.abs(totalMonths) >= 1) {
759
+ return { value: totalMonths, unit: "month" };
760
+ }
761
+ return { value: diffDays === 0 ? sign * 1 : diffDays, unit: "day" };
762
+ }
763
+ function formatRelative(date, base) {
764
+ const d = toDate(date);
765
+ if (!d) return "";
766
+ const baseDate = base !== void 0 ? toDate(base) : /* @__PURE__ */ new Date();
767
+ if (!baseDate) return "";
768
+ const locale = getLocale();
769
+ const rtf = new Intl.RelativeTimeFormat(locale, { numeric: "auto" });
770
+ const { value, unit } = getRelativeUnit(d, baseDate);
771
+ return rtf.format(value, unit);
772
+ }
773
+
774
+ // src/formatters/numberFormatter.ts
775
+ function formatNumber(value, options) {
776
+ const n = toNumber(value);
777
+ if (n === null) return "";
778
+ const locale = getLocale();
779
+ return new Intl.NumberFormat(locale, options).format(n);
780
+ }
781
+ function formatPercent(value, decimals) {
782
+ const n = toNumber(value);
783
+ if (n === null) return "";
784
+ const locale = getLocale();
785
+ const opts = {
786
+ style: "percent",
787
+ ...decimals !== void 0 && { minimumFractionDigits: decimals, maximumFractionDigits: decimals }
788
+ };
789
+ return new Intl.NumberFormat(locale, opts).format(n);
790
+ }
791
+ function formatCompact(value) {
792
+ const n = toNumber(value);
793
+ if (n === null) return "";
794
+ const locale = getLocale();
795
+ return new Intl.NumberFormat(locale, { notation: "compact" }).format(n);
796
+ }
797
+
798
+ // src/formatters/currencyFormatter.ts
799
+ function formatCurrency(value, currencyCode) {
800
+ const n = toNumber(value);
801
+ if (n === null) return "";
802
+ if (!currencyCode || typeof currencyCode !== "string") return "";
803
+ const locale = getLocale();
804
+ try {
805
+ return new Intl.NumberFormat(locale, {
806
+ style: "currency",
807
+ currency: currencyCode
808
+ }).format(n);
809
+ } catch {
810
+ return "";
811
+ }
812
+ }
813
+
814
+ // src/formatters/sortUtils.ts
815
+ function compareStrings(a, b, options) {
816
+ const locale = getLocale();
817
+ return new Intl.Collator(locale, options).compare(a, b);
818
+ }
819
+ function createCollator(options) {
820
+ const locale = getLocale();
821
+ return new Intl.Collator(locale, options);
822
+ }
823
+ export {
824
+ HTML_DIR_ATTRIBUTE,
825
+ HTML_LANG_ATTRIBUTE,
826
+ I18N_DEFAULT_NAMESPACE,
827
+ I18N_NAMESPACE_SEPARATOR,
828
+ I18N_PATH_SEPARATOR,
829
+ I18nRegistryImpl,
830
+ Language,
831
+ LanguageDisplayMode,
832
+ SUPPORTED_LANGUAGES,
833
+ TextDirection,
834
+ compareStrings,
835
+ createCollator,
836
+ createI18nRegistry,
837
+ formatCompact,
838
+ formatCurrency,
839
+ formatDate,
840
+ formatDateTime,
841
+ formatNumber,
842
+ formatPercent,
843
+ formatRelative,
844
+ formatTime,
845
+ getLanguageMetadata,
846
+ getRTLLanguages,
847
+ i18nRegistry,
848
+ isValidLanguage
849
+ };
850
+ //# sourceMappingURL=index.js.map