@digitaldefiance/i18n-lib 1.0.33 β 1.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/README.md +440 -4
- package/dist/component-definition.d.ts +11 -0
- package/dist/component-definition.js +2 -0
- package/dist/component-registration.d.ts +9 -0
- package/dist/component-registration.js +2 -0
- package/dist/component-registry.d.ts +64 -0
- package/dist/component-registry.js +238 -0
- package/dist/context.d.ts +2 -1
- package/dist/core-i18n.d.ts +330 -0
- package/dist/core-i18n.js +435 -0
- package/dist/core-language.d.ts +13 -0
- package/dist/core-language.js +17 -0
- package/dist/core-string-key.d.ts +39 -0
- package/dist/core-string-key.js +47 -0
- package/dist/default-config.d.ts +2 -1
- package/dist/default-config.js +24 -24
- package/dist/i18n-config.d.ts +20 -0
- package/dist/i18n-config.js +2 -0
- package/dist/i18n-context.d.ts +14 -0
- package/dist/i18n-context.js +2 -0
- package/dist/i18n-engine.d.ts +3 -1
- package/dist/index.d.ts +21 -1
- package/dist/index.js +25 -2
- package/dist/language-definition.d.ts +13 -0
- package/dist/language-definition.js +2 -0
- package/dist/language-registry.d.ts +106 -0
- package/dist/language-registry.js +194 -0
- package/dist/plugin-i18n-engine.d.ts +126 -0
- package/dist/plugin-i18n-engine.js +266 -0
- package/dist/registry-config.d.ts +14 -0
- package/dist/registry-config.js +2 -0
- package/dist/registry-context.d.ts +12 -0
- package/dist/registry-context.js +2 -0
- package/dist/registry-error-type.d.ts +12 -0
- package/dist/registry-error-type.js +16 -0
- package/dist/registry-error.d.ts +19 -0
- package/dist/registry-error.js +44 -0
- package/dist/translation-request.d.ts +9 -0
- package/dist/translation-request.js +2 -0
- package/dist/translation-response.d.ts +8 -0
- package/dist/translation-response.js +2 -0
- package/dist/typed-error.d.ts +63 -3
- package/dist/typed-error.js +230 -2
- package/dist/types.d.ts +42 -29
- package/dist/validation-config.d.ts +11 -0
- package/dist/validation-config.js +2 -0
- package/dist/validation-result.d.ts +12 -0
- package/dist/validation-result.js +2 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
# @digitaldefiance/i18n-lib
|
|
2
2
|
|
|
3
|
-
A comprehensive TypeScript internationalization library with enum translation support, template processing, and context management.
|
|
3
|
+
A comprehensive TypeScript internationalization library with plugin-based component registration, enum translation support, template processing, and context management.
|
|
4
|
+
|
|
5
|
+
## π New Plugin-Based Architecture
|
|
6
|
+
|
|
7
|
+
**Version 1.1.0** introduces a revolutionary plugin-based architecture with component registration and rigid compile-time type safety:
|
|
8
|
+
|
|
9
|
+
- **Component Registration System**: Register translation components with their own string keys
|
|
10
|
+
- **Language Plugin Support**: Add new languages dynamically with validation
|
|
11
|
+
- **Compile-Time Type Safety**: TypeScript ensures all strings are complete for all languages
|
|
12
|
+
- **Automatic Validation**: Comprehensive validation with detailed error reporting
|
|
13
|
+
- **Fallback System**: Intelligent fallback to default languages with missing translation detection
|
|
14
|
+
- **Multi-Instance Support**: Named instances for different application contexts
|
|
4
15
|
|
|
5
16
|
## Features
|
|
6
17
|
|
|
18
|
+
### Core Features
|
|
19
|
+
|
|
7
20
|
- **Type-Safe Translations**: Full TypeScript support with generic types for strings and languages
|
|
21
|
+
- **Plugin Architecture**: Register components and languages dynamically with full type safety
|
|
8
22
|
- **Configuration Validation**: Automatic validation ensures all languages have complete string collections
|
|
9
23
|
- **Localized Error Messages**: Error messages can be translated using the engine's own translation system
|
|
10
24
|
- **Enum Translation Registry**: Translate enum values with complete type safety
|
|
@@ -14,7 +28,15 @@ A comprehensive TypeScript internationalization library with enum translation su
|
|
|
14
28
|
- **Currency Formatting**: Built-in currency formatting utilities with locale support
|
|
15
29
|
- **Fallback System**: Graceful degradation when translations are missing
|
|
16
30
|
- **Extensible Configuration**: Module augmentation support for layered library extension
|
|
17
|
-
- **
|
|
31
|
+
- **Backward Compatibility**: Legacy I18nEngine remains fully supported
|
|
32
|
+
|
|
33
|
+
### New Plugin Features
|
|
34
|
+
|
|
35
|
+
- **Component Registry**: Manage translation components with validation
|
|
36
|
+
- **Language Registry**: Dynamic language registration with metadata
|
|
37
|
+
- **Type-Safe Registration**: Compile-time guarantees for translation completeness
|
|
38
|
+
- **Validation Reporting**: Detailed missing translation reports
|
|
39
|
+
- **Plugin System**: Modular component architecture
|
|
18
40
|
|
|
19
41
|
## Installation
|
|
20
42
|
|
|
@@ -79,6 +101,295 @@ const spanishGreeting = i18n.translate(MyStrings.UserGreetingTemplate, { name: '
|
|
|
79
101
|
// "Β‘Hola, Juan!"
|
|
80
102
|
```
|
|
81
103
|
|
|
104
|
+
## π Plugin-Based Architecture (New in v1.1.0)
|
|
105
|
+
|
|
106
|
+
The new plugin-based architecture provides a component registration system with rigid compile-time type safety.
|
|
107
|
+
|
|
108
|
+
### Quick Start with Plugin Architecture
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
import {
|
|
112
|
+
createCoreI18nEngine,
|
|
113
|
+
CoreStringKey,
|
|
114
|
+
CoreLanguage,
|
|
115
|
+
ComponentDefinition,
|
|
116
|
+
ComponentRegistration
|
|
117
|
+
} from '@digitaldefiance/i18n-lib';
|
|
118
|
+
|
|
119
|
+
// Create engine with default languages and core strings
|
|
120
|
+
const i18n = createCoreI18nEngine('myapp');
|
|
121
|
+
|
|
122
|
+
// Use core translations
|
|
123
|
+
const welcomeMessage = i18n.translate('core', CoreStringKey.System_Welcome);
|
|
124
|
+
const errorMessage = i18n.translate('core', CoreStringKey.Error_ValidationFailed);
|
|
125
|
+
|
|
126
|
+
// Define your own component with type safety
|
|
127
|
+
enum MyComponentStringKey {
|
|
128
|
+
Welcome = 'welcome',
|
|
129
|
+
Goodbye = 'goodbye',
|
|
130
|
+
UserGreetingTemplate = 'userGreetingTemplate'
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const MyComponent: ComponentDefinition<MyComponentStringKey> = {
|
|
134
|
+
id: 'my-component',
|
|
135
|
+
name: 'My Custom Component',
|
|
136
|
+
stringKeys: Object.values(MyComponentStringKey)
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// Define translations for all supported languages
|
|
140
|
+
const myComponentStrings = {
|
|
141
|
+
[CoreLanguage.EnglishUS]: {
|
|
142
|
+
[MyComponentStringKey.Welcome]: 'Welcome to my component!',
|
|
143
|
+
[MyComponentStringKey.Goodbye]: 'Goodbye from my component!',
|
|
144
|
+
[MyComponentStringKey.UserGreetingTemplate]: 'Hello, {name}!'
|
|
145
|
+
},
|
|
146
|
+
[CoreLanguage.French]: {
|
|
147
|
+
[MyComponentStringKey.Welcome]: 'Bienvenue dans mon composant !',
|
|
148
|
+
[MyComponentStringKey.Goodbye]: 'Au revoir de mon composant !',
|
|
149
|
+
[MyComponentStringKey.UserGreetingTemplate]: 'Bonjour, {name} !'
|
|
150
|
+
},
|
|
151
|
+
[CoreLanguage.Spanish]: {
|
|
152
|
+
[MyComponentStringKey.Welcome]: 'Β‘Bienvenido a mi componente!',
|
|
153
|
+
[MyComponentStringKey.Goodbye]: 'Β‘AdiΓ³s desde mi componente!',
|
|
154
|
+
[MyComponentStringKey.UserGreetingTemplate]: 'Β‘Hola, {name}!'
|
|
155
|
+
}
|
|
156
|
+
// TypeScript ensures all CoreLanguages are handled
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
// Register component (with validation)
|
|
160
|
+
const registration: ComponentRegistration<MyComponentStringKey, CoreLanguage> = {
|
|
161
|
+
component: MyComponent,
|
|
162
|
+
strings: myComponentStrings
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const validationResult = i18n.registerComponent(registration);
|
|
166
|
+
if (!validationResult.isValid) {
|
|
167
|
+
console.warn('Missing translations:', validationResult.missingKeys);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Use your component's translations
|
|
171
|
+
const welcome = i18n.translate('my-component', MyComponentStringKey.Welcome);
|
|
172
|
+
const greeting = i18n.translate('my-component', MyComponentStringKey.UserGreetingTemplate, {
|
|
173
|
+
name: 'John'
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// Change language - affects all components
|
|
177
|
+
i18n.setLanguage(CoreLanguage.French);
|
|
178
|
+
const frenchWelcome = i18n.translate('my-component', MyComponentStringKey.Welcome);
|
|
179
|
+
// "Bienvenue dans mon composant !"
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Key Plugin Architecture Benefits
|
|
183
|
+
|
|
184
|
+
1. **Compile-Time Type Safety**: TypeScript ensures all string keys exist for all languages
|
|
185
|
+
2. **Component Isolation**: Each component manages its own strings independently
|
|
186
|
+
3. **Flexible Language Support**: Components can support different subsets of system languages
|
|
187
|
+
4. **Comprehensive Validation**: Automatic detection of missing translations with detailed reporting
|
|
188
|
+
5. **Fallback System**: Intelligent fallback to default language when translations are missing
|
|
189
|
+
6. **Dynamic Language Addition**: Add new languages at runtime with automatic validation updates
|
|
190
|
+
7. **Extensibility**: Easy to add new languages and components dynamically
|
|
191
|
+
|
|
192
|
+
### Pre-built Components
|
|
193
|
+
|
|
194
|
+
The library includes several pre-built components:
|
|
195
|
+
|
|
196
|
+
#### Core I18n Component
|
|
197
|
+
|
|
198
|
+
Provides essential system strings in 8 languages:
|
|
199
|
+
|
|
200
|
+
- English (US/UK), French, Spanish, German, Chinese (Simplified), Japanese, Ukrainian
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
import { createCoreI18nEngine, CoreStringKey } from '@digitaldefiance/i18n-lib';
|
|
204
|
+
|
|
205
|
+
const i18n = createCoreI18nEngine();
|
|
206
|
+
const saveText = i18n.translate('core', CoreStringKey.Common_Save);
|
|
207
|
+
const errorMsg = i18n.translate('core', CoreStringKey.Error_ValidationFailed);
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
#### User System Component (Example)
|
|
211
|
+
|
|
212
|
+
Demonstrates user management strings:
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
import {
|
|
216
|
+
registerUserSystemComponent,
|
|
217
|
+
getUserTranslation,
|
|
218
|
+
UserStringKey
|
|
219
|
+
} from '@digitaldefiance/i18n-lib';
|
|
220
|
+
|
|
221
|
+
// Register user system with existing engine
|
|
222
|
+
registerUserSystemComponent(i18n);
|
|
223
|
+
|
|
224
|
+
// Use user system translations
|
|
225
|
+
const loginText = getUserTranslation(UserStringKey.Auth_Login);
|
|
226
|
+
const userNotFound = getUserTranslation(
|
|
227
|
+
UserStringKey.Error_UserNotFoundTemplate,
|
|
228
|
+
{ username: 'john_doe' }
|
|
229
|
+
);
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Advanced Plugin Usage
|
|
233
|
+
|
|
234
|
+
#### Adding New Languages
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
import { createLanguageDefinition } from '@digitaldefiance/i18n-lib';
|
|
238
|
+
|
|
239
|
+
// Add Italian support
|
|
240
|
+
const italian = createLanguageDefinition('it', 'Italiano', 'it');
|
|
241
|
+
i18n.registerLanguage(italian);
|
|
242
|
+
|
|
243
|
+
// Update existing components with Italian translations
|
|
244
|
+
i18n.updateComponentStrings('my-component', {
|
|
245
|
+
it: {
|
|
246
|
+
[MyComponentStringKey.Welcome]: 'Benvenuto nel mio componente!',
|
|
247
|
+
[MyComponentStringKey.Goodbye]: 'Arrivederci dal mio componente!',
|
|
248
|
+
[MyComponentStringKey.UserGreetingTemplate]: 'Ciao, {name}!'
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
#### Component Registration Validation
|
|
254
|
+
|
|
255
|
+
The plugin engine provides comprehensive validation to ensure translation completeness:
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
// Each component is validated against ALL system languages
|
|
259
|
+
enum MyStrings {
|
|
260
|
+
Welcome = 'welcome',
|
|
261
|
+
Goodbye = 'goodbye'
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const myComponent: ComponentDefinition<MyStrings> = {
|
|
265
|
+
id: 'my-component',
|
|
266
|
+
name: 'My Component',
|
|
267
|
+
stringKeys: Object.values(MyStrings)
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
// System has EN, FR, ES languages - component must provide translations for all three
|
|
271
|
+
const registration: ComponentRegistration<MyStrings, CoreLanguage> = {
|
|
272
|
+
component: myComponent,
|
|
273
|
+
strings: {
|
|
274
|
+
[CoreLanguage.EnglishUS]: {
|
|
275
|
+
[MyStrings.Welcome]: 'Welcome',
|
|
276
|
+
[MyStrings.Goodbye]: 'Goodbye'
|
|
277
|
+
},
|
|
278
|
+
[CoreLanguage.French]: {
|
|
279
|
+
[MyStrings.Welcome]: 'Bienvenue',
|
|
280
|
+
[MyStrings.Goodbye]: 'Au revoir'
|
|
281
|
+
},
|
|
282
|
+
[CoreLanguage.Spanish]: {
|
|
283
|
+
[MyStrings.Welcome]: 'Bienvenido',
|
|
284
|
+
[MyStrings.Goodbye]: 'AdiΓ³s'
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
const result = i18n.registerComponent(registration);
|
|
290
|
+
if (!result.isValid) {
|
|
291
|
+
console.log('Missing translations:', result.missingKeys);
|
|
292
|
+
// Shows exactly which string keys are missing for which languages
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
#### Flexible Language Support
|
|
297
|
+
|
|
298
|
+
Components can support different subsets of system languages:
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
// Component A supports EN, FR, ES
|
|
302
|
+
const componentA = {
|
|
303
|
+
component: { id: 'comp-a', name: 'Component A', stringKeys: ['hello'] },
|
|
304
|
+
strings: {
|
|
305
|
+
en: { hello: 'Hello' },
|
|
306
|
+
fr: { hello: 'Bonjour' },
|
|
307
|
+
es: { hello: 'Hola' }
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
// Component B only supports EN and DE (added later)
|
|
312
|
+
const componentB = {
|
|
313
|
+
component: { id: 'comp-b', name: 'Component B', stringKeys: ['save'] },
|
|
314
|
+
strings: {
|
|
315
|
+
en: { save: 'Save' },
|
|
316
|
+
de: { save: 'Speichern' }
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
// Both components can coexist - missing translations use fallback
|
|
321
|
+
i18n.registerComponent(componentA); // β Complete
|
|
322
|
+
i18n.registerComponent(componentB); // β Missing FR, ES - uses fallback
|
|
323
|
+
|
|
324
|
+
// Usage automatically handles fallbacks
|
|
325
|
+
i18n.translate('comp-b', 'save', {}, 'fr'); // Returns 'Save' (EN fallback)
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
#### Dynamic Language Addition
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
// Add new language to system
|
|
332
|
+
const germanLang = { id: 'de', name: 'German', code: 'de' };
|
|
333
|
+
i18n.registerLanguage(germanLang);
|
|
334
|
+
|
|
335
|
+
// New component registrations now require German translations
|
|
336
|
+
const newRegistration = {
|
|
337
|
+
component: { id: 'new-comp', name: 'New Component', stringKeys: ['test'] },
|
|
338
|
+
strings: {
|
|
339
|
+
en: { test: 'Test' },
|
|
340
|
+
fr: { test: 'Test' },
|
|
341
|
+
es: { test: 'Prueba' }
|
|
342
|
+
// Missing 'de' - validation will flag this
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
const result = i18n.registerComponent(newRegistration);
|
|
347
|
+
console.log(result.missingKeys); // Shows missing German translations
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
#### Validation and Error Handling
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
// Comprehensive validation
|
|
354
|
+
const globalValidation = i18n.validateAllComponents();
|
|
355
|
+
if (!globalValidation.isValid) {
|
|
356
|
+
console.error('Validation errors:', globalValidation.errors);
|
|
357
|
+
console.warn('Warnings:', globalValidation.warnings);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Handle registration errors
|
|
361
|
+
try {
|
|
362
|
+
i18n.registerComponent(incompleteRegistration);
|
|
363
|
+
} catch (error) {
|
|
364
|
+
if (error instanceof RegistryError) {
|
|
365
|
+
console.error(`Registry error: ${error.type}`, error.metadata);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// Strict validation mode (rejects incomplete registrations)
|
|
370
|
+
const strictEngine = new PluginI18nEngine(languages, {
|
|
371
|
+
validation: {
|
|
372
|
+
requireCompleteStrings: true,
|
|
373
|
+
allowPartialRegistration: false,
|
|
374
|
+
fallbackLanguageId: 'en'
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
#### Multi-Instance Support
|
|
380
|
+
|
|
381
|
+
```typescript
|
|
382
|
+
// Create separate instances for different contexts
|
|
383
|
+
const adminI18n = PluginI18nEngine.createInstance('admin', languages);
|
|
384
|
+
const userI18n = PluginI18nEngine.createInstance('user', languages);
|
|
385
|
+
|
|
386
|
+
// Register different components for each
|
|
387
|
+
adminI18n.registerComponent(adminComponentRegistration);
|
|
388
|
+
userI18n.registerComponent(userComponentRegistration);
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
For complete documentation on the plugin architecture, see [PLUGIN_ARCHITECTURE.md](./PLUGIN_ARCHITECTURE.md).
|
|
392
|
+
|
|
82
393
|
## Advanced Features
|
|
83
394
|
|
|
84
395
|
### Enum Translation Registry
|
|
@@ -214,20 +525,90 @@ I18nEngine.removeInstance('main');
|
|
|
214
525
|
|
|
215
526
|
## API Reference
|
|
216
527
|
|
|
217
|
-
###
|
|
528
|
+
### Plugin Architecture API
|
|
529
|
+
|
|
530
|
+
#### PluginI18nEngine
|
|
531
|
+
|
|
532
|
+
**Constructor**
|
|
533
|
+
|
|
534
|
+
- `new PluginI18nEngine<TLanguages>(languages, config?)` - Create new plugin engine
|
|
535
|
+
- `PluginI18nEngine.createInstance<TLanguages>(key, languages, config?)` - Create named instance
|
|
536
|
+
- `PluginI18nEngine.getInstance<TLanguages>(key?)` - Get existing instance
|
|
537
|
+
|
|
538
|
+
**Component Management**
|
|
539
|
+
|
|
540
|
+
- `registerComponent<TStringKeys>(registration)` - Register component with translations
|
|
541
|
+
- `updateComponentStrings<TStringKeys>(componentId, strings)` - Update existing component strings
|
|
542
|
+
- `getComponents()` - Get all registered components
|
|
543
|
+
- `hasComponent(componentId)` - Check if component exists
|
|
544
|
+
|
|
545
|
+
**Translation Methods**
|
|
546
|
+
|
|
547
|
+
- `translate<TStringKeys>(componentId, stringKey, variables?, language?)` - Translate component string
|
|
548
|
+
- `safeTranslate(componentId, stringKey, variables?, language?)` - Safe translate with fallback
|
|
549
|
+
- `getTranslationDetails<TStringKeys>(componentId, stringKey, variables?, language?)` - Get detailed translation response
|
|
550
|
+
|
|
551
|
+
**Language Management**
|
|
552
|
+
|
|
553
|
+
- `registerLanguage(language)` - Register new language
|
|
554
|
+
- `registerLanguages(languages)` - Register multiple languages
|
|
555
|
+
- `getLanguages()` - Get all registered languages
|
|
556
|
+
- `hasLanguage(language)` - Check if language exists
|
|
557
|
+
- `setLanguage(language)` - Set current language
|
|
558
|
+
- `getLanguageByCode(code)` - Get language by ISO code
|
|
559
|
+
|
|
560
|
+
**Validation**
|
|
561
|
+
|
|
562
|
+
- `validateAllComponents()` - Validate all registered components
|
|
563
|
+
- `getLanguageRegistry()` - Access language registry directly
|
|
564
|
+
- `getComponentRegistry()` - Access component registry directly
|
|
565
|
+
|
|
566
|
+
#### Core I18n Functions
|
|
567
|
+
|
|
568
|
+
- `createCoreI18nEngine(instanceKey?)` - Create engine with core components
|
|
569
|
+
- `getCoreTranslation(stringKey, variables?, language?, instanceKey?)` - Get core translation
|
|
570
|
+
- `safeCoreTranslation(stringKey, variables?, language?, instanceKey?)` - Safe core translation
|
|
571
|
+
|
|
572
|
+
#### Component Registration Types
|
|
573
|
+
|
|
574
|
+
```typescript
|
|
575
|
+
interface ComponentDefinition<TStringKeys extends string> {
|
|
576
|
+
readonly id: string;
|
|
577
|
+
readonly name: string;
|
|
578
|
+
readonly stringKeys: readonly TStringKeys[];
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
interface ComponentRegistration<TStringKeys extends string, TLanguages extends string> {
|
|
582
|
+
readonly component: ComponentDefinition<TStringKeys>;
|
|
583
|
+
readonly strings: PartialComponentLanguageStrings<TStringKeys, TLanguages>;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
interface LanguageDefinition {
|
|
587
|
+
readonly id: string;
|
|
588
|
+
readonly name: string;
|
|
589
|
+
readonly code: string;
|
|
590
|
+
readonly isDefault?: boolean;
|
|
591
|
+
}
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
### Legacy I18nEngine (Still Supported)
|
|
218
595
|
|
|
219
596
|
#### Constructor
|
|
597
|
+
|
|
220
598
|
- `new I18nEngine<TStringKey, TLanguage>(config, key?)` - Create new engine instance
|
|
221
599
|
|
|
222
600
|
#### Translation Methods
|
|
601
|
+
|
|
223
602
|
- `translate(key, vars?, language?, fallbackLanguage?)` - Translate string with optional variables
|
|
224
603
|
- `translateEnum(enumObj, value, language)` - Translate enum value
|
|
225
604
|
- `t(templateString, language?, ...vars)` - Process template string with `{{EnumName.EnumKey}}` patterns
|
|
226
605
|
|
|
227
606
|
#### Registration
|
|
607
|
+
|
|
228
608
|
- `registerEnum(enumObj, translations, enumName)` - Register enum translations
|
|
229
609
|
|
|
230
610
|
#### Language Management
|
|
611
|
+
|
|
231
612
|
- `getLanguageCode(language)` - Get language code for language
|
|
232
613
|
- `getLanguageFromCode(code)` - Get language from code
|
|
233
614
|
- `getAllLanguageCodes()` - Get all language codes
|
|
@@ -235,34 +616,41 @@ I18nEngine.removeInstance('main');
|
|
|
235
616
|
- `isLanguageAvailable(language)` - Check if language is available
|
|
236
617
|
|
|
237
618
|
#### Context Management
|
|
619
|
+
|
|
238
620
|
- `get context()` - Get current context
|
|
239
621
|
- `set context(context)` - Set context properties
|
|
240
622
|
|
|
241
623
|
#### Static Methods
|
|
624
|
+
|
|
242
625
|
- `getInstance(key?)` - Get instance by key
|
|
243
626
|
- `clearInstances()` - Clear all instances
|
|
244
627
|
- `removeInstance(key?)` - Remove specific instance
|
|
245
628
|
|
|
246
629
|
### Context Utilities
|
|
630
|
+
|
|
247
631
|
- `createContext(defaultLanguage, defaultContext)` - Create new context
|
|
248
632
|
- `setLanguage(context, language)` - Set user language
|
|
249
633
|
- `setAdminLanguage(context, language)` - Set admin language
|
|
250
634
|
- `setContext(context, contextType)` - Set context type
|
|
251
635
|
|
|
252
636
|
### ContextManager
|
|
637
|
+
|
|
253
638
|
- `addListener(listener)` - Add change listener
|
|
254
639
|
- `removeListener(listener)` - Remove change listener
|
|
255
640
|
- `createProxy(context)` - Create reactive context proxy
|
|
256
641
|
|
|
257
642
|
### Currency Utilities
|
|
643
|
+
|
|
258
644
|
- `getCurrencyFormat(locale, currencyCode)` - Get currency formatting info
|
|
259
645
|
|
|
260
646
|
### Type Utilities
|
|
647
|
+
|
|
261
648
|
- `createTranslations(translations)` - Helper for creating typed translations
|
|
262
649
|
|
|
263
650
|
## Type Definitions
|
|
264
651
|
|
|
265
652
|
### Core Types
|
|
653
|
+
|
|
266
654
|
```typescript
|
|
267
655
|
type EnumTranslation<T extends string | number> = {
|
|
268
656
|
[K in T]: string;
|
|
@@ -422,6 +810,20 @@ If localized error messages aren't provided, the engine falls back to English te
|
|
|
422
810
|
|
|
423
811
|
## Best Practices
|
|
424
812
|
|
|
813
|
+
### Plugin Architecture (Recommended for New Projects)
|
|
814
|
+
|
|
815
|
+
1. **Use Component Registration**: Organize translations into logical components with `PluginI18nEngine`
|
|
816
|
+
2. **Define String Key Enums**: Always use TypeScript enums for string keys to ensure compile-time type safety
|
|
817
|
+
3. **Complete Component Translations**: Provide translations for all supported languages in each component
|
|
818
|
+
4. **Validate Registrations**: Check validation results and handle missing translations appropriately
|
|
819
|
+
5. **Use Core Components**: Start with `createCoreI18nEngine()` for built-in system strings
|
|
820
|
+
6. **Fallback Strategy**: Configure appropriate fallback languages for missing translations
|
|
821
|
+
7. **Component Isolation**: Keep related strings together in the same component
|
|
822
|
+
8. **Template Variables**: Use template strings with variables for dynamic content
|
|
823
|
+
9. **Multi-Instance Architecture**: Use named instances for different application contexts (admin, user, etc.)
|
|
824
|
+
|
|
825
|
+
### Legacy System (Still Supported)
|
|
826
|
+
|
|
425
827
|
1. **Complete Translations**: EnumTranslation requires all enum values to be translated
|
|
426
828
|
2. **Type Safety**: Use TypeScript enums for string keys and languages
|
|
427
829
|
3. **Context Separation**: Use different contexts for admin and user interfaces
|
|
@@ -430,10 +832,44 @@ If localized error messages aren't provided, the engine falls back to English te
|
|
|
430
832
|
6. **Layered Extension**: Use union types when extending configurations across libraries
|
|
431
833
|
7. **Default Configuration**: Use `getDefaultI18nEngine()` for standard setups
|
|
432
834
|
|
|
835
|
+
### Migration Strategy
|
|
836
|
+
|
|
837
|
+
When migrating from legacy to plugin architecture:
|
|
838
|
+
|
|
839
|
+
```typescript
|
|
840
|
+
// Legacy approach
|
|
841
|
+
const legacy = new I18nEngine(config);
|
|
842
|
+
const text = legacy.translate(MyStrings.Welcome);
|
|
843
|
+
|
|
844
|
+
// New plugin approach
|
|
845
|
+
const modern = createCoreI18nEngine();
|
|
846
|
+
modern.registerComponent(myComponentRegistration);
|
|
847
|
+
const text = modern.translate('my-component', MyStrings.Welcome);
|
|
848
|
+
```
|
|
849
|
+
|
|
850
|
+
Both systems can coexist in the same application during migration.
|
|
851
|
+
|
|
433
852
|
## License
|
|
434
853
|
|
|
435
854
|
MIT
|
|
436
855
|
|
|
437
856
|
## Repository
|
|
438
857
|
|
|
439
|
-
Part of the DigitalBurnbag project - a secure file sharing and automated protocol system.
|
|
858
|
+
Part of the DigitalBurnbag project - a secure file sharing and automated protocol system.
|
|
859
|
+
|
|
860
|
+
## ChangeLog
|
|
861
|
+
|
|
862
|
+
### Version 1.1.0
|
|
863
|
+
|
|
864
|
+
- Sat Oct 11 2025 16:49:00 GMT-0700 (Pacific Daylight Time)
|
|
865
|
+
- Introduced plugin-based architecture with component registration and compile-time type safety
|
|
866
|
+
- Added `PluginI18nEngine` with comprehensive validation and fallback system
|
|
867
|
+
- Maintained full support for legacy `I18nEngine`
|
|
868
|
+
- Added pre-built core and user system components
|
|
869
|
+
- Enhanced template processing and context management features
|
|
870
|
+
- Improved documentation and examples for both architectures
|
|
871
|
+
|
|
872
|
+
### Version 1.0.33
|
|
873
|
+
|
|
874
|
+
- Wed Sep 24 2025 15:20:07 GMT-0700 (Pacific Daylight Time)
|
|
875
|
+
- Initial release of the TypeScript internationalization library with enum translation, template processing, context management, and currency formatting.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component definition with its string keys
|
|
3
|
+
*/
|
|
4
|
+
export interface ComponentDefinition<TStringKeys extends string> {
|
|
5
|
+
/** Unique identifier for the component */
|
|
6
|
+
readonly id: string;
|
|
7
|
+
/** Human-readable name for the component */
|
|
8
|
+
readonly name: string;
|
|
9
|
+
/** Array of all string keys this component requires */
|
|
10
|
+
readonly stringKeys: readonly TStringKeys[];
|
|
11
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ComponentDefinition } from './component-definition';
|
|
2
|
+
import { PartialComponentLanguageStrings } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Registration payload for a component with its strings
|
|
5
|
+
*/
|
|
6
|
+
export interface ComponentRegistration<TStringKeys extends string, TLanguages extends string> {
|
|
7
|
+
readonly component: ComponentDefinition<TStringKeys>;
|
|
8
|
+
readonly strings: PartialComponentLanguageStrings<TStringKeys, TLanguages>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component registry for managing internationalization components and their string translations
|
|
3
|
+
*/
|
|
4
|
+
import { ComponentDefinition } from './component-definition';
|
|
5
|
+
import { ComponentRegistration } from './component-registration';
|
|
6
|
+
import { TranslationRequest } from './translation-request';
|
|
7
|
+
import { TranslationResponse } from './translation-response';
|
|
8
|
+
import { ComponentLanguageStrings, PartialComponentLanguageStrings } from './types';
|
|
9
|
+
import { ValidationConfig } from './validation-config';
|
|
10
|
+
import { ValidationResult } from './validation-result';
|
|
11
|
+
/**
|
|
12
|
+
* Registry for managing components and their translations
|
|
13
|
+
*/
|
|
14
|
+
export declare class ComponentRegistry<TLanguages extends string> {
|
|
15
|
+
private readonly components;
|
|
16
|
+
private readonly componentStrings;
|
|
17
|
+
private readonly validationConfig;
|
|
18
|
+
private readonly registeredLanguages;
|
|
19
|
+
constructor(languages: readonly TLanguages[], validationConfig: ValidationConfig);
|
|
20
|
+
/**
|
|
21
|
+
* Update the set of registered languages (for dynamic language addition)
|
|
22
|
+
*/
|
|
23
|
+
updateRegisteredLanguages(languages: readonly TLanguages[]): void;
|
|
24
|
+
/**
|
|
25
|
+
* Register a new component with its translations
|
|
26
|
+
*/
|
|
27
|
+
registerComponent<TStringKeys extends string>(registration: ComponentRegistration<TStringKeys, TLanguages>): ValidationResult;
|
|
28
|
+
/**
|
|
29
|
+
* Update strings for an existing component
|
|
30
|
+
*/
|
|
31
|
+
updateComponentStrings<TStringKeys extends string>(componentId: string, strings: PartialComponentLanguageStrings<TStringKeys, TLanguages>): ValidationResult;
|
|
32
|
+
/**
|
|
33
|
+
* Get a translation for a specific component, string key, and language
|
|
34
|
+
*/
|
|
35
|
+
getTranslation<TStringKeys extends string>(request: TranslationRequest<TStringKeys, TLanguages>): TranslationResponse;
|
|
36
|
+
/**
|
|
37
|
+
* Get all registered components
|
|
38
|
+
*/
|
|
39
|
+
getComponents(): ReadonlyArray<ComponentDefinition<any>>;
|
|
40
|
+
/**
|
|
41
|
+
* Get a specific component by ID
|
|
42
|
+
*/
|
|
43
|
+
getComponent<TStringKeys extends string>(componentId: string): ComponentDefinition<TStringKeys> | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Check if a component is registered
|
|
46
|
+
*/
|
|
47
|
+
hasComponent(componentId: string): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Get all strings for a component in all languages
|
|
50
|
+
*/
|
|
51
|
+
getComponentStrings<TStringKeys extends string>(componentId: string): ComponentLanguageStrings<TStringKeys, TLanguages> | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* Validate a component registration
|
|
54
|
+
*/
|
|
55
|
+
private validateComponentRegistration;
|
|
56
|
+
/**
|
|
57
|
+
* Complete missing strings with fallbacks
|
|
58
|
+
*/
|
|
59
|
+
private completeStringsWithFallbacks;
|
|
60
|
+
/**
|
|
61
|
+
* Merge existing strings with new strings
|
|
62
|
+
*/
|
|
63
|
+
private mergeStrings;
|
|
64
|
+
}
|