@digitaldefiance/i18n-lib 1.3.12 → 1.3.13

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 (148) hide show
  1. package/README.md +4 -0
  2. package/package.json +12 -27
  3. package/src/active-context.ts +30 -0
  4. package/src/component-definition.ts +11 -0
  5. package/src/component-registration.ts +13 -0
  6. package/src/component-registry.ts +392 -0
  7. package/src/context-error-type.ts +3 -0
  8. package/src/context-error.ts +16 -0
  9. package/src/context-manager.ts +71 -0
  10. package/src/context.ts +90 -0
  11. package/src/core-i18n.ts +609 -0
  12. package/src/core-string-key.ts +49 -0
  13. package/src/create-translation-adapter.ts +47 -0
  14. package/src/currency-code.ts +35 -0
  15. package/{dist/currency-format.d.ts → src/currency-format.ts} +5 -4
  16. package/src/currency.ts +52 -0
  17. package/src/default-config.ts +199 -0
  18. package/src/enum-registry.ts +138 -0
  19. package/src/global-active-context.ts +255 -0
  20. package/src/handleable.ts +79 -0
  21. package/src/i-global-active-context.ts +59 -0
  22. package/src/i-handleable-error-options.ts +6 -0
  23. package/src/i-handleable.ts +5 -0
  24. package/src/i18n-config.ts +29 -0
  25. package/{dist/i18n-context.d.ts → src/i18n-context.ts} +7 -6
  26. package/src/i18n-engine.ts +491 -0
  27. package/{dist/index.d.ts → src/index.ts} +10 -1
  28. package/{dist/language-codes.d.ts → src/language-codes.ts} +23 -11
  29. package/src/language-definition.ts +13 -0
  30. package/src/language-registry.ts +292 -0
  31. package/src/plugin-i18n-engine.ts +520 -0
  32. package/src/plugin-translatable-generic-error.ts +106 -0
  33. package/src/plugin-translatable-handleable-generic.ts +60 -0
  34. package/src/plugin-typed-handleable.ts +77 -0
  35. package/src/registry-config.ts +15 -0
  36. package/src/registry-error-type.ts +12 -0
  37. package/src/registry-error.ts +74 -0
  38. package/src/strict-types.ts +35 -0
  39. package/src/template.ts +63 -0
  40. package/src/timezone.ts +20 -0
  41. package/src/translatable.ts +15 -0
  42. package/src/translation-engine.ts +8 -0
  43. package/src/translation-request.ts +12 -0
  44. package/src/translation-response.ts +8 -0
  45. package/src/typed-error.ts +384 -0
  46. package/src/typed-handleable.ts +70 -0
  47. package/{dist/types.d.ts → src/types.ts} +75 -20
  48. package/src/unified-translator.ts +96 -0
  49. package/src/utils.ts +213 -0
  50. package/src/validation-config.ts +11 -0
  51. package/src/validation-result.ts +12 -0
  52. package/dist/active-context.d.ts +0 -29
  53. package/dist/active-context.js +0 -2
  54. package/dist/component-definition.d.ts +0 -11
  55. package/dist/component-definition.js +0 -2
  56. package/dist/component-registration.d.ts +0 -9
  57. package/dist/component-registration.js +0 -2
  58. package/dist/component-registry.d.ts +0 -68
  59. package/dist/component-registry.js +0 -245
  60. package/dist/context-error-type.d.ts +0 -3
  61. package/dist/context-error-type.js +0 -7
  62. package/dist/context-error.d.ts +0 -6
  63. package/dist/context-error.js +0 -15
  64. package/dist/context-manager.d.ts +0 -33
  65. package/dist/context-manager.js +0 -61
  66. package/dist/context.d.ts +0 -44
  67. package/dist/context.js +0 -69
  68. package/dist/core-i18n.d.ts +0 -62
  69. package/dist/core-i18n.js +0 -477
  70. package/dist/core-string-key.d.ts +0 -42
  71. package/dist/core-string-key.js +0 -50
  72. package/dist/create-translation-adapter.d.ts +0 -20
  73. package/dist/create-translation-adapter.js +0 -36
  74. package/dist/currency-code.d.ts +0 -19
  75. package/dist/currency-code.js +0 -36
  76. package/dist/currency-format.js +0 -2
  77. package/dist/currency.d.ts +0 -11
  78. package/dist/currency.js +0 -48
  79. package/dist/default-config.d.ts +0 -32
  80. package/dist/default-config.js +0 -101
  81. package/dist/enum-registry.d.ts +0 -44
  82. package/dist/enum-registry.js +0 -100
  83. package/dist/global-active-context.d.ts +0 -50
  84. package/dist/global-active-context.js +0 -177
  85. package/dist/handleable.d.ts +0 -13
  86. package/dist/handleable.js +0 -56
  87. package/dist/i-global-active-context.d.ts +0 -22
  88. package/dist/i-global-active-context.js +0 -2
  89. package/dist/i-handleable-error-options.d.ts +0 -6
  90. package/dist/i-handleable-error-options.js +0 -2
  91. package/dist/i-handleable.d.ts +0 -5
  92. package/dist/i-handleable.js +0 -2
  93. package/dist/i18n-config.d.ts +0 -20
  94. package/dist/i18n-config.js +0 -2
  95. package/dist/i18n-context.js +0 -2
  96. package/dist/i18n-engine.d.ts +0 -178
  97. package/dist/i18n-engine.js +0 -338
  98. package/dist/index.js +0 -83
  99. package/dist/language-codes.js +0 -31
  100. package/dist/language-definition.d.ts +0 -13
  101. package/dist/language-definition.js +0 -2
  102. package/dist/language-registry.d.ts +0 -113
  103. package/dist/language-registry.js +0 -216
  104. package/dist/plugin-i18n-engine.d.ts +0 -146
  105. package/dist/plugin-i18n-engine.js +0 -360
  106. package/dist/plugin-translatable-generic-error.d.ts +0 -29
  107. package/dist/plugin-translatable-generic-error.js +0 -66
  108. package/dist/plugin-translatable-handleable-generic.d.ts +0 -28
  109. package/dist/plugin-translatable-handleable-generic.js +0 -40
  110. package/dist/plugin-typed-handleable.d.ts +0 -14
  111. package/dist/plugin-typed-handleable.js +0 -45
  112. package/dist/registry-config.d.ts +0 -14
  113. package/dist/registry-config.js +0 -2
  114. package/dist/registry-error-type.d.ts +0 -12
  115. package/dist/registry-error-type.js +0 -16
  116. package/dist/registry-error.d.ts +0 -18
  117. package/dist/registry-error.js +0 -45
  118. package/dist/strict-types.d.ts +0 -18
  119. package/dist/strict-types.js +0 -17
  120. package/dist/template.d.ts +0 -12
  121. package/dist/template.js +0 -30
  122. package/dist/timezone.d.ts +0 -11
  123. package/dist/timezone.js +0 -22
  124. package/dist/translatable-generic-error.d.ts +0 -29
  125. package/dist/translatable-generic-error.js +0 -66
  126. package/dist/translatable-handleable-generic.d.ts +0 -28
  127. package/dist/translatable-handleable-generic.js +0 -40
  128. package/dist/translatable.d.ts +0 -5
  129. package/dist/translatable.js +0 -11
  130. package/dist/translation-engine.d.ts +0 -8
  131. package/dist/translation-engine.js +0 -2
  132. package/dist/translation-request.d.ts +0 -9
  133. package/dist/translation-request.js +0 -2
  134. package/dist/translation-response.d.ts +0 -8
  135. package/dist/translation-response.js +0 -2
  136. package/dist/typed-error.d.ts +0 -72
  137. package/dist/typed-error.js +0 -251
  138. package/dist/typed-handleable.d.ts +0 -14
  139. package/dist/typed-handleable.js +0 -40
  140. package/dist/types.js +0 -18
  141. package/dist/unified-translator.d.ts +0 -30
  142. package/dist/unified-translator.js +0 -68
  143. package/dist/utils.d.ts +0 -64
  144. package/dist/utils.js +0 -130
  145. package/dist/validation-config.d.ts +0 -11
  146. package/dist/validation-config.js +0 -2
  147. package/dist/validation-result.d.ts +0 -12
  148. package/dist/validation-result.js +0 -2
@@ -0,0 +1,292 @@
1
+ /**
2
+ * Language registry for managing supported languages and their properties
3
+ */
4
+
5
+ import { LanguageDefinition } from './language-definition';
6
+ import { RegistryError } from './registry-error';
7
+ import { RegistryErrorType } from './registry-error-type';
8
+
9
+ /**
10
+ * Static singleton registry for managing supported languages globally
11
+ */
12
+ export class LanguageRegistry {
13
+ private static languages = new Map<string, LanguageDefinition>();
14
+ private static languagesByCodes = new Map<string, string>();
15
+ private static defaultLanguageId: string | null = null;
16
+
17
+ private constructor() {
18
+ // Private constructor - use static methods
19
+ }
20
+
21
+ /**
22
+ * Register a new language
23
+ */
24
+ public static registerLanguage(language: LanguageDefinition): void {
25
+ const languageId = language.id;
26
+
27
+ // Check for duplicate language ID
28
+ if (LanguageRegistry.languages.has(languageId)) {
29
+ throw RegistryError.createSimple(
30
+ RegistryErrorType.DuplicateLanguage,
31
+ `Language '${languageId}' is already registered`,
32
+ { languageId },
33
+ );
34
+ }
35
+
36
+ // Check for duplicate language code
37
+ if (LanguageRegistry.languagesByCodes.has(language.code)) {
38
+ const existingLanguageId = LanguageRegistry.languagesByCodes.get(language.code)!;
39
+ throw RegistryError.createSimple(
40
+ RegistryErrorType.DuplicateLanguage,
41
+ `Language code '${language.code}' is already used by language '${existingLanguageId}'`,
42
+ { languageId, code: language.code, existingLanguageId },
43
+ );
44
+ }
45
+
46
+ // Register the language
47
+ LanguageRegistry.languages.set(languageId, language);
48
+ LanguageRegistry.languagesByCodes.set(language.code, languageId);
49
+
50
+ // Set as default if specified or if it's the first language
51
+ if (language.isDefault || LanguageRegistry.defaultLanguageId === null) {
52
+ LanguageRegistry.defaultLanguageId = languageId;
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Register multiple languages at once
58
+ */
59
+ public static registerLanguages(languages: readonly LanguageDefinition[]): void {
60
+ for (const language of languages) {
61
+ LanguageRegistry.registerLanguage(language);
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Get a language by its ID
67
+ */
68
+ public static getLanguage(languageId: string): LanguageDefinition | undefined {
69
+ return LanguageRegistry.languages.get(languageId);
70
+ }
71
+
72
+ /**
73
+ * Get a language by its code
74
+ */
75
+ public static getLanguageByCode(code: string): LanguageDefinition | undefined {
76
+ const languageId = LanguageRegistry.languagesByCodes.get(code);
77
+ return languageId ? LanguageRegistry.languages.get(languageId) : undefined;
78
+ }
79
+
80
+ /**
81
+ * Get all registered languages
82
+ */
83
+ public static getAllLanguages(): ReadonlyArray<LanguageDefinition> {
84
+ return Array.from(LanguageRegistry.languages.values());
85
+ }
86
+
87
+ /**
88
+ * Get all language IDs
89
+ */
90
+ public static getLanguageIds(): readonly string[] {
91
+ return Array.from(LanguageRegistry.languages.keys());
92
+ }
93
+
94
+ /**
95
+ * Get all language codes
96
+ */
97
+ public static getLanguageCodes(): readonly string[] {
98
+ return Array.from(LanguageRegistry.languagesByCodes.keys());
99
+ }
100
+
101
+ /**
102
+ * Check if a language is registered
103
+ */
104
+ public static hasLanguage(languageId: string): boolean {
105
+ return LanguageRegistry.languages.has(languageId);
106
+ }
107
+
108
+ /**
109
+ * Check if a language code is registered
110
+ */
111
+ public static hasLanguageCode(code: string): boolean {
112
+ return LanguageRegistry.languagesByCodes.has(code);
113
+ }
114
+
115
+ /**
116
+ * Get the default language
117
+ */
118
+ public static getDefaultLanguage(): LanguageDefinition | null {
119
+ return LanguageRegistry.defaultLanguageId
120
+ ? LanguageRegistry.languages.get(LanguageRegistry.defaultLanguageId) || null
121
+ : null;
122
+ }
123
+
124
+ /**
125
+ * Get the default language ID
126
+ */
127
+ public static getDefaultLanguageId(): string | null {
128
+ return LanguageRegistry.defaultLanguageId;
129
+ }
130
+
131
+ /**
132
+ * Get matching language code with fallback logic:
133
+ * 1. Try requested code
134
+ * 2. Fall back to user default
135
+ * 3. Fall back to site default
136
+ */
137
+ public static getMatchingLanguageCode(
138
+ requestedCode?: string,
139
+ userDefaultCode?: string,
140
+ ): string {
141
+ // Try requested code first
142
+ if (requestedCode && LanguageRegistry.hasLanguageCode(requestedCode)) {
143
+ return requestedCode;
144
+ }
145
+
146
+ // Try user default
147
+ if (userDefaultCode && LanguageRegistry.hasLanguageCode(userDefaultCode)) {
148
+ return userDefaultCode;
149
+ }
150
+
151
+ // Fall back to site default
152
+ const defaultLanguage = LanguageRegistry.getDefaultLanguage();
153
+ if (!defaultLanguage) {
154
+ throw RegistryError.createSimple(
155
+ RegistryErrorType.LanguageNotFound,
156
+ 'No default language configured',
157
+ {},
158
+ );
159
+ }
160
+
161
+ return defaultLanguage.code;
162
+ }
163
+
164
+ /**
165
+ * Set the default language
166
+ */
167
+ public static setDefaultLanguage(languageId: string): void {
168
+ if (!LanguageRegistry.languages.has(languageId)) {
169
+ throw RegistryError.createSimple(
170
+ RegistryErrorType.LanguageNotFound,
171
+ `Language '${languageId}' not found`,
172
+ { languageId },
173
+ );
174
+ }
175
+ LanguageRegistry.defaultLanguageId = languageId;
176
+ }
177
+
178
+ /**
179
+ * Get the number of registered languages
180
+ */
181
+ public static getLanguageCount(): number {
182
+ return LanguageRegistry.languages.size;
183
+ }
184
+
185
+ /**
186
+ * Validate that all required languages are present
187
+ */
188
+ public static validateRequiredLanguages(
189
+ requiredLanguages: readonly string[],
190
+ ): LanguageValidationResult {
191
+ const missingLanguages: string[] = [];
192
+ const errors: string[] = [];
193
+
194
+ for (const languageId of requiredLanguages) {
195
+ if (!LanguageRegistry.languages.has(languageId)) {
196
+ missingLanguages.push(languageId);
197
+ errors.push(`Required language '${languageId}' is not registered`);
198
+ }
199
+ }
200
+
201
+ return {
202
+ isValid: missingLanguages.length === 0,
203
+ missingLanguages,
204
+ errors,
205
+ };
206
+ }
207
+
208
+ /**
209
+ * Create a mapping of language IDs to their display names
210
+ */
211
+ public static getLanguageDisplayNames(): Record<string, string> {
212
+ const result: Record<string, string> = {};
213
+ for (const [languageId, language] of LanguageRegistry.languages) {
214
+ result[languageId] = language.name;
215
+ }
216
+ return result;
217
+ }
218
+
219
+ /**
220
+ * Create a mapping of language IDs to their codes
221
+ */
222
+ public static getLanguageCodeMapping(): Record<string, string> {
223
+ const result: Record<string, string> = {};
224
+ for (const [languageId, language] of LanguageRegistry.languages) {
225
+ result[languageId] = language.code;
226
+ }
227
+ return result;
228
+ }
229
+
230
+ /**
231
+ * Find languages by partial name match (case-insensitive)
232
+ */
233
+ public static findLanguagesByName(
234
+ partialName: string,
235
+ ): readonly LanguageDefinition[] {
236
+ const searchTerm = partialName.toLowerCase();
237
+ return Array.from(LanguageRegistry.languages.values()).filter((language) =>
238
+ language.name.toLowerCase().includes(searchTerm),
239
+ );
240
+ }
241
+
242
+ /**
243
+ * Clear all registered languages (useful for testing)
244
+ */
245
+ public static clear(): void {
246
+ LanguageRegistry.languages.clear();
247
+ LanguageRegistry.languagesByCodes.clear();
248
+ LanguageRegistry.defaultLanguageId = null;
249
+ }
250
+ }
251
+
252
+ /**
253
+ * Validation result for language operations
254
+ */
255
+ export interface LanguageValidationResult {
256
+ readonly isValid: boolean;
257
+ readonly missingLanguages: readonly string[];
258
+ readonly errors: readonly string[];
259
+ }
260
+
261
+ /**
262
+ * Helper function to create language definitions with type safety
263
+ */
264
+ export function createLanguageDefinition(
265
+ id: string,
266
+ name: string,
267
+ code: string,
268
+ isDefault?: boolean,
269
+ ): LanguageDefinition {
270
+ return {
271
+ id,
272
+ name,
273
+ code,
274
+ isDefault: isDefault || false,
275
+ };
276
+ }
277
+
278
+ /**
279
+ * Helper function to create multiple language definitions
280
+ */
281
+ export function createLanguageDefinitions(
282
+ languages: Array<{
283
+ id: string;
284
+ name: string;
285
+ code: string;
286
+ isDefault?: boolean;
287
+ }>,
288
+ ): LanguageDefinition[] {
289
+ return languages.map((lang) =>
290
+ createLanguageDefinition(lang.id, lang.name, lang.code, lang.isDefault),
291
+ );
292
+ }