@digitaldefiance/i18n-lib 1.0.33 β 1.1.1
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 +477 -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 +41 -0
- package/dist/core-i18n.js +436 -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/strict-types.d.ts +18 -0
- package/dist/strict-types.js +17 -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,326 @@ 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
|
+
#### Compile-Time Completeness Enforcement (Strict Mode)
|
|
235
|
+
|
|
236
|
+
By default the plugin engine performs runtime validation and provides fallbacks. If you want **compile-time** enforcement that every language mapping contains every string key, use the helper in `strict-types`:
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
import { createCompleteComponentStrings } from '@digitaldefiance/i18n-lib';
|
|
240
|
+
|
|
241
|
+
enum MyStrings {
|
|
242
|
+
Welcome = 'welcome',
|
|
243
|
+
Farewell = 'farewell'
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
type AppLang = 'en' | 'fr';
|
|
247
|
+
|
|
248
|
+
// This will only compile if BOTH languages contain BOTH keys.
|
|
249
|
+
const myStrictStrings = createCompleteComponentStrings<MyStrings, AppLang>({
|
|
250
|
+
en: {
|
|
251
|
+
[MyStrings.Welcome]: 'Welcome',
|
|
252
|
+
[MyStrings.Farewell]: 'Goodbye'
|
|
253
|
+
},
|
|
254
|
+
fr: {
|
|
255
|
+
[MyStrings.Welcome]: 'Bienvenue',
|
|
256
|
+
[MyStrings.Farewell]: 'Au revoir'
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// If any key is missing, TypeScript reports an error before runtime.
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
The core library itself uses this helper for the core component (`createCoreComponentStrings`) to guarantee internal completeness. For partial / iterative authoring you can still start with normal objects and later switch to the strict helper when translations stabilize.
|
|
264
|
+
|
|
265
|
+
#### Adding New Languages
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
import { createLanguageDefinition } from '@digitaldefiance/i18n-lib';
|
|
269
|
+
|
|
270
|
+
// Add Italian support
|
|
271
|
+
const italian = createLanguageDefinition('it', 'Italiano', 'it');
|
|
272
|
+
i18n.registerLanguage(italian);
|
|
273
|
+
|
|
274
|
+
// Update existing components with Italian translations
|
|
275
|
+
i18n.updateComponentStrings('my-component', {
|
|
276
|
+
it: {
|
|
277
|
+
[MyComponentStringKey.Welcome]: 'Benvenuto nel mio componente!',
|
|
278
|
+
[MyComponentStringKey.Goodbye]: 'Arrivederci dal mio componente!',
|
|
279
|
+
[MyComponentStringKey.UserGreetingTemplate]: 'Ciao, {name}!'
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
#### Component Registration Validation
|
|
285
|
+
|
|
286
|
+
The plugin engine provides comprehensive validation to ensure translation completeness:
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
// Each component is validated against ALL system languages
|
|
290
|
+
enum MyStrings {
|
|
291
|
+
Welcome = 'welcome',
|
|
292
|
+
Goodbye = 'goodbye'
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const myComponent: ComponentDefinition<MyStrings> = {
|
|
296
|
+
id: 'my-component',
|
|
297
|
+
name: 'My Component',
|
|
298
|
+
stringKeys: Object.values(MyStrings)
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
// System has EN, FR, ES languages - component must provide translations for all three
|
|
302
|
+
const registration: ComponentRegistration<MyStrings, CoreLanguage> = {
|
|
303
|
+
component: myComponent,
|
|
304
|
+
strings: {
|
|
305
|
+
[CoreLanguage.EnglishUS]: {
|
|
306
|
+
[MyStrings.Welcome]: 'Welcome',
|
|
307
|
+
[MyStrings.Goodbye]: 'Goodbye'
|
|
308
|
+
},
|
|
309
|
+
[CoreLanguage.French]: {
|
|
310
|
+
[MyStrings.Welcome]: 'Bienvenue',
|
|
311
|
+
[MyStrings.Goodbye]: 'Au revoir'
|
|
312
|
+
},
|
|
313
|
+
[CoreLanguage.Spanish]: {
|
|
314
|
+
[MyStrings.Welcome]: 'Bienvenido',
|
|
315
|
+
[MyStrings.Goodbye]: 'AdiΓ³s'
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
const result = i18n.registerComponent(registration);
|
|
321
|
+
if (!result.isValid) {
|
|
322
|
+
console.log('Missing translations:', result.missingKeys);
|
|
323
|
+
// Shows exactly which string keys are missing for which languages
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
#### Flexible Language Support
|
|
328
|
+
|
|
329
|
+
Components can support different subsets of system languages:
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
// Component A supports EN, FR, ES
|
|
333
|
+
const componentA = {
|
|
334
|
+
component: { id: 'comp-a', name: 'Component A', stringKeys: ['hello'] },
|
|
335
|
+
strings: {
|
|
336
|
+
en: { hello: 'Hello' },
|
|
337
|
+
fr: { hello: 'Bonjour' },
|
|
338
|
+
es: { hello: 'Hola' }
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
// Component B only supports EN and DE (added later)
|
|
343
|
+
const componentB = {
|
|
344
|
+
component: { id: 'comp-b', name: 'Component B', stringKeys: ['save'] },
|
|
345
|
+
strings: {
|
|
346
|
+
en: { save: 'Save' },
|
|
347
|
+
de: { save: 'Speichern' }
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
// Both components can coexist - missing translations use fallback
|
|
352
|
+
i18n.registerComponent(componentA); // β Complete
|
|
353
|
+
i18n.registerComponent(componentB); // β Missing FR, ES - uses fallback
|
|
354
|
+
|
|
355
|
+
// Usage automatically handles fallbacks
|
|
356
|
+
i18n.translate('comp-b', 'save', {}, 'fr'); // Returns 'Save' (EN fallback)
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
#### Dynamic Language Addition
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
// Add new language to system
|
|
363
|
+
const germanLang = { id: 'de', name: 'German', code: 'de' };
|
|
364
|
+
i18n.registerLanguage(germanLang);
|
|
365
|
+
|
|
366
|
+
// New component registrations now require German translations
|
|
367
|
+
const newRegistration = {
|
|
368
|
+
component: { id: 'new-comp', name: 'New Component', stringKeys: ['test'] },
|
|
369
|
+
strings: {
|
|
370
|
+
en: { test: 'Test' },
|
|
371
|
+
fr: { test: 'Test' },
|
|
372
|
+
es: { test: 'Prueba' }
|
|
373
|
+
// Missing 'de' - validation will flag this
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
const result = i18n.registerComponent(newRegistration);
|
|
378
|
+
console.log(result.missingKeys); // Shows missing German translations
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
#### Validation and Error Handling
|
|
382
|
+
|
|
383
|
+
```typescript
|
|
384
|
+
// Comprehensive validation
|
|
385
|
+
const globalValidation = i18n.validateAllComponents();
|
|
386
|
+
if (!globalValidation.isValid) {
|
|
387
|
+
console.error('Validation errors:', globalValidation.errors);
|
|
388
|
+
console.warn('Warnings:', globalValidation.warnings);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Handle registration errors
|
|
392
|
+
try {
|
|
393
|
+
i18n.registerComponent(incompleteRegistration);
|
|
394
|
+
} catch (error) {
|
|
395
|
+
if (error instanceof RegistryError) {
|
|
396
|
+
console.error(`Registry error: ${error.type}`, error.metadata);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Strict validation mode (rejects incomplete registrations)
|
|
401
|
+
const strictEngine = new PluginI18nEngine(languages, {
|
|
402
|
+
validation: {
|
|
403
|
+
requireCompleteStrings: true,
|
|
404
|
+
allowPartialRegistration: false,
|
|
405
|
+
fallbackLanguageId: 'en'
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
#### Multi-Instance Support
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
// Create separate instances for different contexts
|
|
414
|
+
const adminI18n = PluginI18nEngine.createInstance('admin', languages);
|
|
415
|
+
const userI18n = PluginI18nEngine.createInstance('user', languages);
|
|
416
|
+
|
|
417
|
+
// Register different components for each
|
|
418
|
+
adminI18n.registerComponent(adminComponentRegistration);
|
|
419
|
+
userI18n.registerComponent(userComponentRegistration);
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
For complete documentation on the plugin architecture, see [PLUGIN_ARCHITECTURE.md](./PLUGIN_ARCHITECTURE.md).
|
|
423
|
+
|
|
82
424
|
## Advanced Features
|
|
83
425
|
|
|
84
426
|
### Enum Translation Registry
|
|
@@ -214,20 +556,90 @@ I18nEngine.removeInstance('main');
|
|
|
214
556
|
|
|
215
557
|
## API Reference
|
|
216
558
|
|
|
217
|
-
###
|
|
559
|
+
### Plugin Architecture API
|
|
560
|
+
|
|
561
|
+
#### PluginI18nEngine
|
|
562
|
+
|
|
563
|
+
**Constructor**
|
|
564
|
+
|
|
565
|
+
- `new PluginI18nEngine<TLanguages>(languages, config?)` - Create new plugin engine
|
|
566
|
+
- `PluginI18nEngine.createInstance<TLanguages>(key, languages, config?)` - Create named instance
|
|
567
|
+
- `PluginI18nEngine.getInstance<TLanguages>(key?)` - Get existing instance
|
|
568
|
+
|
|
569
|
+
**Component Management**
|
|
570
|
+
|
|
571
|
+
- `registerComponent<TStringKeys>(registration)` - Register component with translations
|
|
572
|
+
- `updateComponentStrings<TStringKeys>(componentId, strings)` - Update existing component strings
|
|
573
|
+
- `getComponents()` - Get all registered components
|
|
574
|
+
- `hasComponent(componentId)` - Check if component exists
|
|
575
|
+
|
|
576
|
+
**Translation Methods**
|
|
577
|
+
|
|
578
|
+
- `translate<TStringKeys>(componentId, stringKey, variables?, language?)` - Translate component string
|
|
579
|
+
- `safeTranslate(componentId, stringKey, variables?, language?)` - Safe translate with fallback
|
|
580
|
+
- `getTranslationDetails<TStringKeys>(componentId, stringKey, variables?, language?)` - Get detailed translation response
|
|
581
|
+
|
|
582
|
+
**Language Management**
|
|
583
|
+
|
|
584
|
+
- `registerLanguage(language)` - Register new language
|
|
585
|
+
- `registerLanguages(languages)` - Register multiple languages
|
|
586
|
+
- `getLanguages()` - Get all registered languages
|
|
587
|
+
- `hasLanguage(language)` - Check if language exists
|
|
588
|
+
- `setLanguage(language)` - Set current language
|
|
589
|
+
- `getLanguageByCode(code)` - Get language by ISO code
|
|
590
|
+
|
|
591
|
+
**Validation**
|
|
592
|
+
|
|
593
|
+
- `validateAllComponents()` - Validate all registered components
|
|
594
|
+
- `getLanguageRegistry()` - Access language registry directly
|
|
595
|
+
- `getComponentRegistry()` - Access component registry directly
|
|
596
|
+
|
|
597
|
+
#### Core I18n Functions
|
|
598
|
+
|
|
599
|
+
- `createCoreI18nEngine(instanceKey?)` - Create engine with core components
|
|
600
|
+
- `getCoreTranslation(stringKey, variables?, language?, instanceKey?)` - Get core translation
|
|
601
|
+
- `safeCoreTranslation(stringKey, variables?, language?, instanceKey?)` - Safe core translation
|
|
602
|
+
|
|
603
|
+
#### Component Registration Types
|
|
604
|
+
|
|
605
|
+
```typescript
|
|
606
|
+
interface ComponentDefinition<TStringKeys extends string> {
|
|
607
|
+
readonly id: string;
|
|
608
|
+
readonly name: string;
|
|
609
|
+
readonly stringKeys: readonly TStringKeys[];
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
interface ComponentRegistration<TStringKeys extends string, TLanguages extends string> {
|
|
613
|
+
readonly component: ComponentDefinition<TStringKeys>;
|
|
614
|
+
readonly strings: PartialComponentLanguageStrings<TStringKeys, TLanguages>;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
interface LanguageDefinition {
|
|
618
|
+
readonly id: string;
|
|
619
|
+
readonly name: string;
|
|
620
|
+
readonly code: string;
|
|
621
|
+
readonly isDefault?: boolean;
|
|
622
|
+
}
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
### Legacy I18nEngine (Still Supported)
|
|
218
626
|
|
|
219
627
|
#### Constructor
|
|
628
|
+
|
|
220
629
|
- `new I18nEngine<TStringKey, TLanguage>(config, key?)` - Create new engine instance
|
|
221
630
|
|
|
222
631
|
#### Translation Methods
|
|
632
|
+
|
|
223
633
|
- `translate(key, vars?, language?, fallbackLanguage?)` - Translate string with optional variables
|
|
224
634
|
- `translateEnum(enumObj, value, language)` - Translate enum value
|
|
225
635
|
- `t(templateString, language?, ...vars)` - Process template string with `{{EnumName.EnumKey}}` patterns
|
|
226
636
|
|
|
227
637
|
#### Registration
|
|
638
|
+
|
|
228
639
|
- `registerEnum(enumObj, translations, enumName)` - Register enum translations
|
|
229
640
|
|
|
230
641
|
#### Language Management
|
|
642
|
+
|
|
231
643
|
- `getLanguageCode(language)` - Get language code for language
|
|
232
644
|
- `getLanguageFromCode(code)` - Get language from code
|
|
233
645
|
- `getAllLanguageCodes()` - Get all language codes
|
|
@@ -235,34 +647,41 @@ I18nEngine.removeInstance('main');
|
|
|
235
647
|
- `isLanguageAvailable(language)` - Check if language is available
|
|
236
648
|
|
|
237
649
|
#### Context Management
|
|
650
|
+
|
|
238
651
|
- `get context()` - Get current context
|
|
239
652
|
- `set context(context)` - Set context properties
|
|
240
653
|
|
|
241
654
|
#### Static Methods
|
|
655
|
+
|
|
242
656
|
- `getInstance(key?)` - Get instance by key
|
|
243
657
|
- `clearInstances()` - Clear all instances
|
|
244
658
|
- `removeInstance(key?)` - Remove specific instance
|
|
245
659
|
|
|
246
660
|
### Context Utilities
|
|
661
|
+
|
|
247
662
|
- `createContext(defaultLanguage, defaultContext)` - Create new context
|
|
248
663
|
- `setLanguage(context, language)` - Set user language
|
|
249
664
|
- `setAdminLanguage(context, language)` - Set admin language
|
|
250
665
|
- `setContext(context, contextType)` - Set context type
|
|
251
666
|
|
|
252
667
|
### ContextManager
|
|
668
|
+
|
|
253
669
|
- `addListener(listener)` - Add change listener
|
|
254
670
|
- `removeListener(listener)` - Remove change listener
|
|
255
671
|
- `createProxy(context)` - Create reactive context proxy
|
|
256
672
|
|
|
257
673
|
### Currency Utilities
|
|
674
|
+
|
|
258
675
|
- `getCurrencyFormat(locale, currencyCode)` - Get currency formatting info
|
|
259
676
|
|
|
260
677
|
### Type Utilities
|
|
678
|
+
|
|
261
679
|
- `createTranslations(translations)` - Helper for creating typed translations
|
|
262
680
|
|
|
263
681
|
## Type Definitions
|
|
264
682
|
|
|
265
683
|
### Core Types
|
|
684
|
+
|
|
266
685
|
```typescript
|
|
267
686
|
type EnumTranslation<T extends string | number> = {
|
|
268
687
|
[K in T]: string;
|
|
@@ -422,6 +841,20 @@ If localized error messages aren't provided, the engine falls back to English te
|
|
|
422
841
|
|
|
423
842
|
## Best Practices
|
|
424
843
|
|
|
844
|
+
### Plugin Architecture (Recommended for New Projects)
|
|
845
|
+
|
|
846
|
+
1. **Use Component Registration**: Organize translations into logical components with `PluginI18nEngine`
|
|
847
|
+
2. **Define String Key Enums**: Always use TypeScript enums for string keys to ensure compile-time type safety
|
|
848
|
+
3. **Complete Component Translations**: Provide translations for all supported languages in each component
|
|
849
|
+
4. **Validate Registrations**: Check validation results and handle missing translations appropriately
|
|
850
|
+
5. **Use Core Components**: Start with `createCoreI18nEngine()` for built-in system strings
|
|
851
|
+
6. **Fallback Strategy**: Configure appropriate fallback languages for missing translations
|
|
852
|
+
7. **Component Isolation**: Keep related strings together in the same component
|
|
853
|
+
8. **Template Variables**: Use template strings with variables for dynamic content
|
|
854
|
+
9. **Multi-Instance Architecture**: Use named instances for different application contexts (admin, user, etc.)
|
|
855
|
+
|
|
856
|
+
### Legacy System (Still Supported)
|
|
857
|
+
|
|
425
858
|
1. **Complete Translations**: EnumTranslation requires all enum values to be translated
|
|
426
859
|
2. **Type Safety**: Use TypeScript enums for string keys and languages
|
|
427
860
|
3. **Context Separation**: Use different contexts for admin and user interfaces
|
|
@@ -430,10 +863,50 @@ If localized error messages aren't provided, the engine falls back to English te
|
|
|
430
863
|
6. **Layered Extension**: Use union types when extending configurations across libraries
|
|
431
864
|
7. **Default Configuration**: Use `getDefaultI18nEngine()` for standard setups
|
|
432
865
|
|
|
866
|
+
### Migration Strategy
|
|
867
|
+
|
|
868
|
+
When migrating from legacy to plugin architecture:
|
|
869
|
+
|
|
870
|
+
```typescript
|
|
871
|
+
// Legacy approach
|
|
872
|
+
const legacy = new I18nEngine(config);
|
|
873
|
+
const text = legacy.translate(MyStrings.Welcome);
|
|
874
|
+
|
|
875
|
+
// New plugin approach
|
|
876
|
+
const modern = createCoreI18nEngine();
|
|
877
|
+
modern.registerComponent(myComponentRegistration);
|
|
878
|
+
const text = modern.translate('my-component', MyStrings.Welcome);
|
|
879
|
+
```
|
|
880
|
+
|
|
881
|
+
Both systems can coexist in the same application during migration.
|
|
882
|
+
|
|
433
883
|
## License
|
|
434
884
|
|
|
435
885
|
MIT
|
|
436
886
|
|
|
437
887
|
## Repository
|
|
438
888
|
|
|
439
|
-
Part of the DigitalBurnbag project - a secure file sharing and automated protocol system.
|
|
889
|
+
Part of the DigitalBurnbag project - a secure file sharing and automated protocol system.
|
|
890
|
+
|
|
891
|
+
## ChangeLog
|
|
892
|
+
|
|
893
|
+
### Version 1.1.1
|
|
894
|
+
|
|
895
|
+
- Sat Oct 11 2025 17:47:00 GMT-0700 (Pacific Daylight Time)
|
|
896
|
+
- Improved type checking for completeness of component translations during registration
|
|
897
|
+
- Updated README/Migration guide for clarity.
|
|
898
|
+
|
|
899
|
+
### Version 1.1.0
|
|
900
|
+
|
|
901
|
+
- Sat Oct 11 2025 16:49:00 GMT-0700 (Pacific Daylight Time)
|
|
902
|
+
- Introduced plugin-based architecture with component registration and compile-time type safety
|
|
903
|
+
- Added `PluginI18nEngine` with comprehensive validation and fallback system
|
|
904
|
+
- Maintained full support for legacy `I18nEngine`
|
|
905
|
+
- Added pre-built core and user system components
|
|
906
|
+
- Enhanced template processing and context management features
|
|
907
|
+
- Improved documentation and examples for both architectures
|
|
908
|
+
|
|
909
|
+
### Version 1.0.33
|
|
910
|
+
|
|
911
|
+
- Wed Sep 24 2025 15:20:07 GMT-0700 (Pacific Daylight Time)
|
|
912
|
+
- 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
|
+
}
|