@digitaldefiance/i18n-lib 1.3.2 → 1.3.3

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/README.md CHANGED
@@ -2274,6 +2274,10 @@ For issues, questions, or contributions:
2274
2274
 
2275
2275
  ## ChangeLog
2276
2276
 
2277
+ ### Version 1.3.3
2278
+
2279
+ - Make LanguageRegistry static
2280
+
2277
2281
  ### Version 1.3.2
2278
2282
 
2279
2283
  - Add functionality to Language Registry for getMatchingLanguageCode
@@ -3,92 +3,92 @@
3
3
  */
4
4
  import { LanguageDefinition } from './language-definition';
5
5
  /**
6
- * Registry for managing supported languages
6
+ * Static singleton registry for managing supported languages globally
7
7
  */
8
- export declare class LanguageRegistry<TLanguages extends string> {
9
- private readonly languages;
10
- private readonly languagesByCodes;
11
- private defaultLanguageId;
12
- constructor();
8
+ export declare class LanguageRegistry {
9
+ private static languages;
10
+ private static languagesByCodes;
11
+ private static defaultLanguageId;
12
+ private constructor();
13
13
  /**
14
14
  * Register a new language
15
15
  */
16
- registerLanguage(language: LanguageDefinition): void;
16
+ static registerLanguage(language: LanguageDefinition): void;
17
17
  /**
18
18
  * Register multiple languages at once
19
19
  */
20
- registerLanguages(languages: readonly LanguageDefinition[]): void;
20
+ static registerLanguages(languages: readonly LanguageDefinition[]): void;
21
21
  /**
22
22
  * Get a language by its ID
23
23
  */
24
- getLanguage(languageId: TLanguages): LanguageDefinition | undefined;
24
+ static getLanguage(languageId: string): LanguageDefinition | undefined;
25
25
  /**
26
26
  * Get a language by its code
27
27
  */
28
- getLanguageByCode(code: string): LanguageDefinition | undefined;
28
+ static getLanguageByCode(code: string): LanguageDefinition | undefined;
29
29
  /**
30
30
  * Get all registered languages
31
31
  */
32
- getAllLanguages(): ReadonlyArray<LanguageDefinition>;
32
+ static getAllLanguages(): ReadonlyArray<LanguageDefinition>;
33
33
  /**
34
34
  * Get all language IDs
35
35
  */
36
- getLanguageIds(): readonly TLanguages[];
36
+ static getLanguageIds(): readonly string[];
37
37
  /**
38
38
  * Get all language codes
39
39
  */
40
- getLanguageCodes(): readonly string[];
40
+ static getLanguageCodes(): readonly string[];
41
41
  /**
42
42
  * Check if a language is registered
43
43
  */
44
- hasLanguage(languageId: TLanguages): boolean;
44
+ static hasLanguage(languageId: string): boolean;
45
45
  /**
46
46
  * Check if a language code is registered
47
47
  */
48
- hasLanguageCode(code: string): boolean;
48
+ static hasLanguageCode(code: string): boolean;
49
49
  /**
50
50
  * Get the default language
51
51
  */
52
- getDefaultLanguage(): LanguageDefinition | null;
52
+ static getDefaultLanguage(): LanguageDefinition | null;
53
53
  /**
54
54
  * Get the default language ID
55
55
  */
56
- getDefaultLanguageId(): TLanguages | null;
56
+ static getDefaultLanguageId(): string | null;
57
57
  /**
58
58
  * Get matching language code with fallback logic:
59
59
  * 1. Try requested code
60
60
  * 2. Fall back to user default
61
61
  * 3. Fall back to site default
62
62
  */
63
- getMatchingLanguageCode(requestedCode?: string, userDefaultCode?: string): string;
63
+ static getMatchingLanguageCode(requestedCode?: string, userDefaultCode?: string): string;
64
64
  /**
65
65
  * Set the default language
66
66
  */
67
- setDefaultLanguage(languageId: TLanguages): void;
67
+ static setDefaultLanguage(languageId: string): void;
68
68
  /**
69
69
  * Get the number of registered languages
70
70
  */
71
- getLanguageCount(): number;
71
+ static getLanguageCount(): number;
72
72
  /**
73
73
  * Validate that all required languages are present
74
74
  */
75
- validateRequiredLanguages(requiredLanguages: readonly TLanguages[]): LanguageValidationResult;
75
+ static validateRequiredLanguages(requiredLanguages: readonly string[]): LanguageValidationResult;
76
76
  /**
77
77
  * Create a mapping of language IDs to their display names
78
78
  */
79
- getLanguageDisplayNames(): Record<TLanguages, string>;
79
+ static getLanguageDisplayNames(): Record<string, string>;
80
80
  /**
81
81
  * Create a mapping of language IDs to their codes
82
82
  */
83
- getLanguageCodeMapping(): Record<TLanguages, string>;
83
+ static getLanguageCodeMapping(): Record<string, string>;
84
84
  /**
85
85
  * Find languages by partial name match (case-insensitive)
86
86
  */
87
- findLanguagesByName(partialName: string): readonly LanguageDefinition[];
87
+ static findLanguagesByName(partialName: string): readonly LanguageDefinition[];
88
88
  /**
89
- * Clear all registered languages
89
+ * Clear all registered languages (useful for testing)
90
90
  */
91
- clear(): void;
91
+ static clear(): void;
92
92
  }
93
93
  /**
94
94
  * Validation result for language operations
@@ -9,101 +9,98 @@ exports.createLanguageDefinitions = createLanguageDefinitions;
9
9
  const registry_error_1 = require("./registry-error");
10
10
  const registry_error_type_1 = require("./registry-error-type");
11
11
  /**
12
- * Registry for managing supported languages
12
+ * Static singleton registry for managing supported languages globally
13
13
  */
14
14
  class LanguageRegistry {
15
15
  constructor() {
16
- this.languages = new Map();
17
- this.languagesByCodes = new Map();
18
- this.defaultLanguageId = null;
19
- // Empty constructor - languages are registered via registerLanguage method
16
+ // Private constructor - use static methods
20
17
  }
21
18
  /**
22
19
  * Register a new language
23
20
  */
24
- registerLanguage(language) {
21
+ static registerLanguage(language) {
25
22
  const languageId = language.id;
26
23
  // Check for duplicate language ID
27
- if (this.languages.has(languageId)) {
24
+ if (LanguageRegistry.languages.has(languageId)) {
28
25
  throw registry_error_1.RegistryError.createSimple(registry_error_type_1.RegistryErrorType.DuplicateLanguage, `Language '${languageId}' is already registered`, { languageId });
29
26
  }
30
27
  // Check for duplicate language code
31
- if (this.languagesByCodes.has(language.code)) {
32
- const existingLanguageId = this.languagesByCodes.get(language.code);
28
+ if (LanguageRegistry.languagesByCodes.has(language.code)) {
29
+ const existingLanguageId = LanguageRegistry.languagesByCodes.get(language.code);
33
30
  throw registry_error_1.RegistryError.createSimple(registry_error_type_1.RegistryErrorType.DuplicateLanguage, `Language code '${language.code}' is already used by language '${existingLanguageId}'`, { languageId, code: language.code, existingLanguageId });
34
31
  }
35
32
  // Register the language
36
- this.languages.set(languageId, language);
37
- this.languagesByCodes.set(language.code, languageId);
33
+ LanguageRegistry.languages.set(languageId, language);
34
+ LanguageRegistry.languagesByCodes.set(language.code, languageId);
38
35
  // Set as default if specified or if it's the first language
39
- if (language.isDefault || this.defaultLanguageId === null) {
40
- this.defaultLanguageId = languageId;
36
+ if (language.isDefault || LanguageRegistry.defaultLanguageId === null) {
37
+ LanguageRegistry.defaultLanguageId = languageId;
41
38
  }
42
39
  }
43
40
  /**
44
41
  * Register multiple languages at once
45
42
  */
46
- registerLanguages(languages) {
43
+ static registerLanguages(languages) {
47
44
  for (const language of languages) {
48
- this.registerLanguage(language);
45
+ LanguageRegistry.registerLanguage(language);
49
46
  }
50
47
  }
51
48
  /**
52
49
  * Get a language by its ID
53
50
  */
54
- getLanguage(languageId) {
55
- return this.languages.get(languageId);
51
+ static getLanguage(languageId) {
52
+ return LanguageRegistry.languages.get(languageId);
56
53
  }
57
54
  /**
58
55
  * Get a language by its code
59
56
  */
60
- getLanguageByCode(code) {
61
- const languageId = this.languagesByCodes.get(code);
62
- return languageId ? this.languages.get(languageId) : undefined;
57
+ static getLanguageByCode(code) {
58
+ const languageId = LanguageRegistry.languagesByCodes.get(code);
59
+ return languageId ? LanguageRegistry.languages.get(languageId) : undefined;
63
60
  }
64
61
  /**
65
62
  * Get all registered languages
66
63
  */
67
- getAllLanguages() {
68
- return Array.from(this.languages.values());
64
+ static getAllLanguages() {
65
+ return Array.from(LanguageRegistry.languages.values());
69
66
  }
70
67
  /**
71
68
  * Get all language IDs
72
69
  */
73
- getLanguageIds() {
74
- return Array.from(this.languages.keys());
70
+ static getLanguageIds() {
71
+ return Array.from(LanguageRegistry.languages.keys());
75
72
  }
76
73
  /**
77
74
  * Get all language codes
78
75
  */
79
- getLanguageCodes() {
80
- return Array.from(this.languagesByCodes.keys());
76
+ static getLanguageCodes() {
77
+ return Array.from(LanguageRegistry.languagesByCodes.keys());
81
78
  }
82
79
  /**
83
80
  * Check if a language is registered
84
81
  */
85
- hasLanguage(languageId) {
86
- return this.languages.has(languageId);
82
+ static hasLanguage(languageId) {
83
+ return LanguageRegistry.languages.has(languageId);
87
84
  }
88
85
  /**
89
86
  * Check if a language code is registered
90
87
  */
91
- hasLanguageCode(code) {
92
- return this.languagesByCodes.has(code);
88
+ static hasLanguageCode(code) {
89
+ return LanguageRegistry.languagesByCodes.has(code);
93
90
  }
94
91
  /**
95
92
  * Get the default language
96
93
  */
97
- getDefaultLanguage() {
98
- return this.defaultLanguageId
99
- ? this.languages.get(this.defaultLanguageId) || null
94
+ static getDefaultLanguage() {
95
+ return LanguageRegistry.defaultLanguageId
96
+ ? LanguageRegistry.languages.get(LanguageRegistry.defaultLanguageId) || null
100
97
  : null;
101
98
  }
102
99
  /**
103
100
  * Get the default language ID
104
101
  */
105
- getDefaultLanguageId() {
106
- return this.defaultLanguageId;
102
+ static getDefaultLanguageId() {
103
+ return LanguageRegistry.defaultLanguageId;
107
104
  }
108
105
  /**
109
106
  * Get matching language code with fallback logic:
@@ -111,17 +108,17 @@ class LanguageRegistry {
111
108
  * 2. Fall back to user default
112
109
  * 3. Fall back to site default
113
110
  */
114
- getMatchingLanguageCode(requestedCode, userDefaultCode) {
111
+ static getMatchingLanguageCode(requestedCode, userDefaultCode) {
115
112
  // Try requested code first
116
- if (requestedCode && this.hasLanguageCode(requestedCode)) {
113
+ if (requestedCode && LanguageRegistry.hasLanguageCode(requestedCode)) {
117
114
  return requestedCode;
118
115
  }
119
116
  // Try user default
120
- if (userDefaultCode && this.hasLanguageCode(userDefaultCode)) {
117
+ if (userDefaultCode && LanguageRegistry.hasLanguageCode(userDefaultCode)) {
121
118
  return userDefaultCode;
122
119
  }
123
120
  // Fall back to site default
124
- const defaultLanguage = this.getDefaultLanguage();
121
+ const defaultLanguage = LanguageRegistry.getDefaultLanguage();
125
122
  if (!defaultLanguage) {
126
123
  throw registry_error_1.RegistryError.createSimple(registry_error_type_1.RegistryErrorType.LanguageNotFound, 'No default language configured', {});
127
124
  }
@@ -130,26 +127,26 @@ class LanguageRegistry {
130
127
  /**
131
128
  * Set the default language
132
129
  */
133
- setDefaultLanguage(languageId) {
134
- if (!this.languages.has(languageId)) {
130
+ static setDefaultLanguage(languageId) {
131
+ if (!LanguageRegistry.languages.has(languageId)) {
135
132
  throw registry_error_1.RegistryError.createSimple(registry_error_type_1.RegistryErrorType.LanguageNotFound, `Language '${languageId}' not found`, { languageId });
136
133
  }
137
- this.defaultLanguageId = languageId;
134
+ LanguageRegistry.defaultLanguageId = languageId;
138
135
  }
139
136
  /**
140
137
  * Get the number of registered languages
141
138
  */
142
- getLanguageCount() {
143
- return this.languages.size;
139
+ static getLanguageCount() {
140
+ return LanguageRegistry.languages.size;
144
141
  }
145
142
  /**
146
143
  * Validate that all required languages are present
147
144
  */
148
- validateRequiredLanguages(requiredLanguages) {
145
+ static validateRequiredLanguages(requiredLanguages) {
149
146
  const missingLanguages = [];
150
147
  const errors = [];
151
148
  for (const languageId of requiredLanguages) {
152
- if (!this.languages.has(languageId)) {
149
+ if (!LanguageRegistry.languages.has(languageId)) {
153
150
  missingLanguages.push(languageId);
154
151
  errors.push(`Required language '${languageId}' is not registered`);
155
152
  }
@@ -163,9 +160,9 @@ class LanguageRegistry {
163
160
  /**
164
161
  * Create a mapping of language IDs to their display names
165
162
  */
166
- getLanguageDisplayNames() {
163
+ static getLanguageDisplayNames() {
167
164
  const result = {};
168
- for (const [languageId, language] of this.languages) {
165
+ for (const [languageId, language] of LanguageRegistry.languages) {
169
166
  result[languageId] = language.name;
170
167
  }
171
168
  return result;
@@ -173,9 +170,9 @@ class LanguageRegistry {
173
170
  /**
174
171
  * Create a mapping of language IDs to their codes
175
172
  */
176
- getLanguageCodeMapping() {
173
+ static getLanguageCodeMapping() {
177
174
  const result = {};
178
- for (const [languageId, language] of this.languages) {
175
+ for (const [languageId, language] of LanguageRegistry.languages) {
179
176
  result[languageId] = language.code;
180
177
  }
181
178
  return result;
@@ -183,20 +180,23 @@ class LanguageRegistry {
183
180
  /**
184
181
  * Find languages by partial name match (case-insensitive)
185
182
  */
186
- findLanguagesByName(partialName) {
183
+ static findLanguagesByName(partialName) {
187
184
  const searchTerm = partialName.toLowerCase();
188
- return Array.from(this.languages.values()).filter((language) => language.name.toLowerCase().includes(searchTerm));
185
+ return Array.from(LanguageRegistry.languages.values()).filter((language) => language.name.toLowerCase().includes(searchTerm));
189
186
  }
190
187
  /**
191
- * Clear all registered languages
188
+ * Clear all registered languages (useful for testing)
192
189
  */
193
- clear() {
194
- this.languages.clear();
195
- this.languagesByCodes.clear();
196
- this.defaultLanguageId = null;
190
+ static clear() {
191
+ LanguageRegistry.languages.clear();
192
+ LanguageRegistry.languagesByCodes.clear();
193
+ LanguageRegistry.defaultLanguageId = null;
197
194
  }
198
195
  }
199
196
  exports.LanguageRegistry = LanguageRegistry;
197
+ LanguageRegistry.languages = new Map();
198
+ LanguageRegistry.languagesByCodes = new Map();
199
+ LanguageRegistry.defaultLanguageId = null;
200
200
  /**
201
201
  * Helper function to create language definitions with type safety
202
202
  */
@@ -7,7 +7,6 @@ import { ComponentRegistry } from './component-registry';
7
7
  import { EnumTranslationRegistry } from './enum-registry';
8
8
  import { IActiveContext } from './active-context';
9
9
  import { LanguageDefinition } from './language-definition';
10
- import { LanguageRegistry } from './language-registry';
11
10
  import { RegistryConfig } from './registry-config';
12
11
  import { TranslationResponse } from './translation-response';
13
12
  import { EnumLanguageTranslation } from './types';
@@ -15,7 +14,6 @@ import { EnumLanguageTranslation } from './types';
15
14
  * Plugin-based I18n Engine with registration capabilities
16
15
  */
17
16
  export declare class PluginI18nEngine<TLanguages extends string> {
18
- private readonly languageRegistry;
19
17
  private readonly componentRegistry;
20
18
  private readonly enumRegistry;
21
19
  private readonly config;
@@ -40,11 +38,11 @@ export declare class PluginI18nEngine<TLanguages extends string> {
40
38
  */
41
39
  static getInstance<TLangs extends string>(key?: string): PluginI18nEngine<TLangs>;
42
40
  /**
43
- * Register a new language
41
+ * Register a new language (updates static registry)
44
42
  */
45
43
  registerLanguage(language: LanguageDefinition): void;
46
44
  /**
47
- * Register multiple languages
45
+ * Register multiple languages (updates static registry)
48
46
  */
49
47
  registerLanguages(languages: readonly LanguageDefinition[]): void;
50
48
  /**
@@ -92,7 +90,7 @@ export declare class PluginI18nEngine<TLanguages extends string> {
92
90
  */
93
91
  setLanguage(language: TLanguages): void;
94
92
  /**
95
- * Get available languages
93
+ * Get available languages from static registry
96
94
  */
97
95
  getLanguages(): readonly LanguageDefinition[];
98
96
  /**
@@ -104,17 +102,13 @@ export declare class PluginI18nEngine<TLanguages extends string> {
104
102
  */
105
103
  hasComponent(componentId: string): boolean;
106
104
  /**
107
- * Check if a language is registered
105
+ * Check if a language is registered in static registry
108
106
  */
109
107
  hasLanguage(language: TLanguages): boolean;
110
108
  /**
111
- * Get language by code
109
+ * Get language by code from static registry
112
110
  */
113
111
  getLanguageByCode(code: string): LanguageDefinition | undefined;
114
- /**
115
- * Get language registry for direct access
116
- */
117
- getLanguageRegistry(): LanguageRegistry<TLanguages>;
118
112
  /**
119
113
  * Get component registry for direct access
120
114
  */
@@ -36,12 +36,15 @@ class PluginI18nEngine {
36
36
  },
37
37
  ...config,
38
38
  };
39
- // Initialize registries
40
- this.languageRegistry = new language_registry_1.LanguageRegistry();
39
+ // Register initial languages in static registry (skip if already registered)
40
+ for (const lang of initialLanguages) {
41
+ if (!language_registry_1.LanguageRegistry.hasLanguage(lang.id)) {
42
+ language_registry_1.LanguageRegistry.registerLanguage(lang);
43
+ }
44
+ }
45
+ // Initialize component registry (per-instance)
41
46
  this.componentRegistry = new component_registry_1.ComponentRegistry(initialLanguages.map((l) => l.id), this.config.validation);
42
47
  this.enumRegistry = new enum_registry_1.EnumTranslationRegistry(initialLanguages.map((l) => l.id), (key, vars) => this.safeTranslate('core', key, vars));
43
- // Register initial languages
44
- this.languageRegistry.registerLanguages(initialLanguages);
45
48
  // Initialize context key for this engine instance
46
49
  this.contextKey = PluginI18nEngine.DefaultInstanceKey;
47
50
  // Create or get the global context for this engine
@@ -113,16 +116,16 @@ class PluginI18nEngine {
113
116
  return instance;
114
117
  }
115
118
  /**
116
- * Register a new language
119
+ * Register a new language (updates static registry)
117
120
  */
118
121
  registerLanguage(language) {
119
- this.languageRegistry.registerLanguage(language);
122
+ language_registry_1.LanguageRegistry.registerLanguage(language);
120
123
  // Update component registry with new language
121
- const newLanguages = this.languageRegistry.getLanguageIds();
124
+ const newLanguages = language_registry_1.LanguageRegistry.getLanguageIds();
122
125
  this.componentRegistry.updateRegisteredLanguages(newLanguages);
123
126
  }
124
127
  /**
125
- * Register multiple languages
128
+ * Register multiple languages (updates static registry)
126
129
  */
127
130
  registerLanguages(languages) {
128
131
  for (const language of languages) {
@@ -226,17 +229,17 @@ class PluginI18nEngine {
226
229
  * Set current language
227
230
  */
228
231
  setLanguage(language) {
229
- if (!this.languageRegistry.hasLanguage(language)) {
232
+ if (!language_registry_1.LanguageRegistry.hasLanguage(language)) {
230
233
  throw registry_error_1.RegistryError.createSimple(registry_error_type_1.RegistryErrorType.LanguageNotFound, `Language '${language}' is not registered`, { language });
231
234
  }
232
235
  const globalContext = global_active_context_1.GlobalActiveContext.getInstance();
233
236
  globalContext.setUserLanguage(language, this.contextKey);
234
237
  }
235
238
  /**
236
- * Get available languages
239
+ * Get available languages from static registry
237
240
  */
238
241
  getLanguages() {
239
- return this.languageRegistry.getAllLanguages();
242
+ return language_registry_1.LanguageRegistry.getAllLanguages();
240
243
  }
241
244
  /**
242
245
  * Get registered components
@@ -251,22 +254,16 @@ class PluginI18nEngine {
251
254
  return this.componentRegistry.hasComponent(componentId);
252
255
  }
253
256
  /**
254
- * Check if a language is registered
257
+ * Check if a language is registered in static registry
255
258
  */
256
259
  hasLanguage(language) {
257
- return this.languageRegistry.hasLanguage(language);
260
+ return language_registry_1.LanguageRegistry.hasLanguage(language);
258
261
  }
259
262
  /**
260
- * Get language by code
263
+ * Get language by code from static registry
261
264
  */
262
265
  getLanguageByCode(code) {
263
- return this.languageRegistry.getLanguageByCode(code);
264
- }
265
- /**
266
- * Get language registry for direct access
267
- */
268
- getLanguageRegistry() {
269
- return this.languageRegistry;
266
+ return language_registry_1.LanguageRegistry.getLanguageByCode(code);
270
267
  }
271
268
  /**
272
269
  * Get component registry for direct access
@@ -288,7 +285,7 @@ class PluginI18nEngine {
288
285
  const warnings = [];
289
286
  let isValid = true;
290
287
  const components = this.getComponents();
291
- const languages = this.languageRegistry.getLanguageIds();
288
+ const languages = language_registry_1.LanguageRegistry.getLanguageIds();
292
289
  for (const component of components) {
293
290
  const componentStrings = this.componentRegistry.getComponentStrings(component.id);
294
291
  if (!componentStrings) {
@@ -355,6 +352,7 @@ class PluginI18nEngine {
355
352
  }
356
353
  PluginI18nEngine._instances.clear();
357
354
  PluginI18nEngine._defaultKey = null;
355
+ language_registry_1.LanguageRegistry.clear();
358
356
  }
359
357
  }
360
358
  exports.PluginI18nEngine = PluginI18nEngine;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digitaldefiance/i18n-lib",
3
- "version": "1.3.2",
3
+ "version": "1.3.3",
4
4
  "description": "Generic i18n library with enum translation support",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",