@digitaldefiance/i18n-lib 1.3.0 → 1.3.2
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 +70 -7
- package/dist/core-i18n.d.ts +15 -8
- package/dist/core-i18n.js +1 -0
- package/dist/language-registry.d.ts +7 -0
- package/dist/language-registry.js +22 -0
- package/dist/registry-error.d.ts +1 -2
- package/dist/registry-error.js +1 -0
- package/dist/typed-error.d.ts +3 -4
- package/dist/typed-error.js +7 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -234,6 +234,17 @@ const displayNames = registry.getLanguageDisplayNames();
|
|
|
234
234
|
// Get language codes for Mongoose enum
|
|
235
235
|
const languageCodes = registry.getLanguageIds(); // ['en-US', 'fr', 'es']
|
|
236
236
|
const isoCodes = registry.getLanguageCodes(); // ['en-US', 'fr', 'es']
|
|
237
|
+
|
|
238
|
+
// Get matching language code with fallback logic
|
|
239
|
+
const matchedCode = registry.getMatchingLanguageCode(
|
|
240
|
+
'de-DE', // Requested code (not registered)
|
|
241
|
+
'fr', // User default (registered)
|
|
242
|
+
// Falls back to site default if neither match
|
|
243
|
+
);
|
|
244
|
+
// Returns: 'fr' (user default)
|
|
245
|
+
|
|
246
|
+
const defaultCode = registry.getMatchingLanguageCode();
|
|
247
|
+
// Returns: 'en-US' (site default)
|
|
237
248
|
```
|
|
238
249
|
|
|
239
250
|
**Key Features:**
|
|
@@ -243,6 +254,53 @@ const isoCodes = registry.getLanguageCodes(); // ['en-US', 'fr', 'es']
|
|
|
243
254
|
- Default language management
|
|
244
255
|
- Duplicate detection and validation
|
|
245
256
|
- Extract language codes for schema definitions
|
|
257
|
+
- Intelligent language code matching with fallback chain
|
|
258
|
+
|
|
259
|
+
### Language Code Resolution
|
|
260
|
+
|
|
261
|
+
The Language Registry provides intelligent language code matching with a fallback chain for handling user preferences and browser language headers:
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
import { LanguageRegistry } from '@digitaldefiance/i18n-lib';
|
|
265
|
+
|
|
266
|
+
const registry = new LanguageRegistry<'en-US' | 'fr' | 'es'>();
|
|
267
|
+
registry.registerLanguages([
|
|
268
|
+
createLanguageDefinition('en-US', 'English (US)', 'en-US', true),
|
|
269
|
+
createLanguageDefinition('fr', 'Français', 'fr'),
|
|
270
|
+
createLanguageDefinition('es', 'Español', 'es'),
|
|
271
|
+
]);
|
|
272
|
+
|
|
273
|
+
// Fallback chain: requested → user default → site default
|
|
274
|
+
const languageCode = registry.getMatchingLanguageCode(
|
|
275
|
+
req.headers['accept-language'], // 1. Try requested code first
|
|
276
|
+
req.user?.siteLanguage, // 2. Fall back to user default
|
|
277
|
+
// 3. Falls back to site default if neither match
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
// Example scenarios:
|
|
281
|
+
registry.getMatchingLanguageCode('fr', 'es'); // Returns: 'fr' (requested exists)
|
|
282
|
+
registry.getMatchingLanguageCode('de', 'es'); // Returns: 'es' (user default exists)
|
|
283
|
+
registry.getMatchingLanguageCode('de', 'it'); // Returns: 'en-US' (site default)
|
|
284
|
+
registry.getMatchingLanguageCode(); // Returns: 'en-US' (site default)
|
|
285
|
+
registry.getMatchingLanguageCode('', ''); // Returns: 'en-US' (empty strings ignored)
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**Use Cases:**
|
|
289
|
+
- HTTP Accept-Language header processing
|
|
290
|
+
- User preference resolution
|
|
291
|
+
- Browser language detection with fallback
|
|
292
|
+
- Multi-tenant applications with per-user defaults
|
|
293
|
+
|
|
294
|
+
**Error Handling:**
|
|
295
|
+
```typescript
|
|
296
|
+
try {
|
|
297
|
+
const emptyRegistry = new LanguageRegistry();
|
|
298
|
+
emptyRegistry.getMatchingLanguageCode('en-US');
|
|
299
|
+
} catch (error) {
|
|
300
|
+
// Throws RegistryError if no default language configured
|
|
301
|
+
console.error('No default language configured');
|
|
302
|
+
}
|
|
303
|
+
```
|
|
246
304
|
|
|
247
305
|
### Enum Translation Registry
|
|
248
306
|
|
|
@@ -1391,6 +1449,7 @@ The core component provides 40+ system strings organized by category:
|
|
|
1391
1449
|
- `hasLanguage(language)` - Check if language exists
|
|
1392
1450
|
- `setLanguage(language)` - Set current language
|
|
1393
1451
|
- `getLanguageByCode(code)` - Get language by ISO code
|
|
1452
|
+
- `getMatchingLanguageCode(requestedCode?, userDefaultCode?)` - Get matching language code with fallback logic
|
|
1394
1453
|
|
|
1395
1454
|
**Validation**
|
|
1396
1455
|
|
|
@@ -2215,16 +2274,20 @@ For issues, questions, or contributions:
|
|
|
2215
2274
|
|
|
2216
2275
|
## ChangeLog
|
|
2217
2276
|
|
|
2218
|
-
### Version 1.3.
|
|
2277
|
+
### Version 1.3.2
|
|
2278
|
+
|
|
2279
|
+
- Add functionality to Language Registry for getMatchingLanguageCode
|
|
2280
|
+
|
|
2281
|
+
### Version 1.3.1
|
|
2219
2282
|
|
|
2220
|
-
- **Changed**: `CoreLanguageCode` now
|
|
2221
|
-
-
|
|
2222
|
-
-
|
|
2223
|
-
-
|
|
2283
|
+
- **Changed**: `CoreLanguageCode` is now `string` - Language Registry is single source of truth
|
|
2284
|
+
- Use `engine.getLanguageRegistry().getLanguageIds()` for runtime validation
|
|
2285
|
+
- Use `getCoreLanguageCodes()` for static arrays (Mongoose schemas, etc.)
|
|
2286
|
+
- Runtime validation via registry, not compile-time types
|
|
2224
2287
|
- **Added**: `getCoreLanguageCodes()` - Get core language codes as runtime array
|
|
2225
2288
|
- **Added**: `getCoreLanguageDefinitions()` - Get core language definitions
|
|
2226
|
-
- **
|
|
2227
|
-
- **Benefit**:
|
|
2289
|
+
- **Philosophy**: Registry-based validation over hardcoded types
|
|
2290
|
+
- **Benefit**: Maximum flexibility - add languages without code changes
|
|
2228
2291
|
|
|
2229
2292
|
### Version 1.2.5
|
|
2230
2293
|
|
package/dist/core-i18n.d.ts
CHANGED
|
@@ -8,10 +8,16 @@ import { LanguageCodes } from './language-codes';
|
|
|
8
8
|
import { LanguageDefinition } from './language-definition';
|
|
9
9
|
import { PluginI18nEngine } from './plugin-i18n-engine';
|
|
10
10
|
/**
|
|
11
|
-
* Core language code type -
|
|
12
|
-
*
|
|
11
|
+
* Core language code type - union of supported language codes
|
|
12
|
+
* Provides compile-time type safety for core languages
|
|
13
|
+
* For custom languages, extend this type or use string
|
|
13
14
|
*/
|
|
14
15
|
export type CoreLanguageCode = typeof LanguageCodes[keyof typeof LanguageCodes];
|
|
16
|
+
/**
|
|
17
|
+
* Flexible language code type - use when you want runtime-only validation
|
|
18
|
+
* Alias for string to indicate it's a language code
|
|
19
|
+
*/
|
|
20
|
+
export type FlexibleLanguageCode = string;
|
|
15
21
|
/**
|
|
16
22
|
* Create default language definitions
|
|
17
23
|
*/
|
|
@@ -24,11 +30,11 @@ export declare const CoreComponentDefinition: ComponentDefinition<CoreStringKey>
|
|
|
24
30
|
/**
|
|
25
31
|
* Core component strings for all default languages
|
|
26
32
|
*/
|
|
27
|
-
export declare function createCoreComponentStrings(): import("./strict-types").CompleteComponentLanguageStrings<CoreStringKey,
|
|
33
|
+
export declare function createCoreComponentStrings(): import("./strict-types").CompleteComponentLanguageStrings<CoreStringKey, string>;
|
|
28
34
|
/**
|
|
29
35
|
* Create core component registration
|
|
30
36
|
*/
|
|
31
|
-
export declare function createCoreComponentRegistration(): ComponentRegistration<CoreStringKey,
|
|
37
|
+
export declare function createCoreComponentRegistration(): ComponentRegistration<CoreStringKey, string>;
|
|
32
38
|
/**
|
|
33
39
|
* Get core language codes as array (for Mongoose enums, etc.)
|
|
34
40
|
*/
|
|
@@ -39,17 +45,18 @@ export declare function getCoreLanguageCodes(): string[];
|
|
|
39
45
|
export declare function getCoreLanguageDefinitions(): LanguageDefinition[];
|
|
40
46
|
/**
|
|
41
47
|
* Create a pre-configured I18n engine with core components
|
|
48
|
+
* Returns engine with string type - use registry for language validation
|
|
42
49
|
*/
|
|
43
|
-
export declare function createCoreI18nEngine(instanceKey?: string): PluginI18nEngine<
|
|
50
|
+
export declare function createCoreI18nEngine(instanceKey?: string): PluginI18nEngine<string>;
|
|
44
51
|
/**
|
|
45
52
|
* Type alias for easier usage
|
|
46
53
|
*/
|
|
47
|
-
export type CoreI18nEngine = PluginI18nEngine<
|
|
54
|
+
export type CoreI18nEngine = PluginI18nEngine<string>;
|
|
48
55
|
/**
|
|
49
56
|
* Helper function to get core translation
|
|
50
57
|
*/
|
|
51
|
-
export declare function getCoreTranslation(stringKey: CoreStringKey, variables?: Record<string, string | number>, language?:
|
|
58
|
+
export declare function getCoreTranslation(stringKey: CoreStringKey, variables?: Record<string, string | number>, language?: string, instanceKey?: string): string;
|
|
52
59
|
/**
|
|
53
60
|
* Helper function to safely get core translation with fallback
|
|
54
61
|
*/
|
|
55
|
-
export declare function safeCoreTranslation(stringKey: CoreStringKey, variables?: Record<string, string | number>, language?:
|
|
62
|
+
export declare function safeCoreTranslation(stringKey: CoreStringKey, variables?: Record<string, string | number>, language?: string, instanceKey?: string): string;
|
package/dist/core-i18n.js
CHANGED
|
@@ -449,6 +449,7 @@ function getCoreLanguageDefinitions() {
|
|
|
449
449
|
}
|
|
450
450
|
/**
|
|
451
451
|
* Create a pre-configured I18n engine with core components
|
|
452
|
+
* Returns engine with string type - use registry for language validation
|
|
452
453
|
*/
|
|
453
454
|
function createCoreI18nEngine(instanceKey = DefaultInstanceKey) {
|
|
454
455
|
const languages = createDefaultLanguages();
|
|
@@ -54,6 +54,13 @@ export declare class LanguageRegistry<TLanguages extends string> {
|
|
|
54
54
|
* Get the default language ID
|
|
55
55
|
*/
|
|
56
56
|
getDefaultLanguageId(): TLanguages | null;
|
|
57
|
+
/**
|
|
58
|
+
* Get matching language code with fallback logic:
|
|
59
|
+
* 1. Try requested code
|
|
60
|
+
* 2. Fall back to user default
|
|
61
|
+
* 3. Fall back to site default
|
|
62
|
+
*/
|
|
63
|
+
getMatchingLanguageCode(requestedCode?: string, userDefaultCode?: string): string;
|
|
57
64
|
/**
|
|
58
65
|
* Set the default language
|
|
59
66
|
*/
|
|
@@ -105,6 +105,28 @@ class LanguageRegistry {
|
|
|
105
105
|
getDefaultLanguageId() {
|
|
106
106
|
return this.defaultLanguageId;
|
|
107
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Get matching language code with fallback logic:
|
|
110
|
+
* 1. Try requested code
|
|
111
|
+
* 2. Fall back to user default
|
|
112
|
+
* 3. Fall back to site default
|
|
113
|
+
*/
|
|
114
|
+
getMatchingLanguageCode(requestedCode, userDefaultCode) {
|
|
115
|
+
// Try requested code first
|
|
116
|
+
if (requestedCode && this.hasLanguageCode(requestedCode)) {
|
|
117
|
+
return requestedCode;
|
|
118
|
+
}
|
|
119
|
+
// Try user default
|
|
120
|
+
if (userDefaultCode && this.hasLanguageCode(userDefaultCode)) {
|
|
121
|
+
return userDefaultCode;
|
|
122
|
+
}
|
|
123
|
+
// Fall back to site default
|
|
124
|
+
const defaultLanguage = this.getDefaultLanguage();
|
|
125
|
+
if (!defaultLanguage) {
|
|
126
|
+
throw registry_error_1.RegistryError.createSimple(registry_error_type_1.RegistryErrorType.LanguageNotFound, 'No default language configured', {});
|
|
127
|
+
}
|
|
128
|
+
return defaultLanguage.code;
|
|
129
|
+
}
|
|
108
130
|
/**
|
|
109
131
|
* Set the default language
|
|
110
132
|
*/
|
package/dist/registry-error.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { CoreLanguageCode } from './core-i18n';
|
|
2
1
|
import { RegistryErrorType } from './registry-error-type';
|
|
3
2
|
import { TranslationEngine } from './typed-error';
|
|
4
3
|
/**
|
|
@@ -11,7 +10,7 @@ export declare class RegistryError extends Error {
|
|
|
11
10
|
/**
|
|
12
11
|
* Create a registry error with translation support
|
|
13
12
|
*/
|
|
14
|
-
static createWithEngine(engine: TranslationEngine, type: RegistryErrorType, variables?: Record<string, string | number>, language?:
|
|
13
|
+
static createWithEngine(engine: TranslationEngine, type: RegistryErrorType, variables?: Record<string, string | number>, language?: string, metadata?: Record<string, any>): RegistryError;
|
|
15
14
|
/**
|
|
16
15
|
* Create a simple RegistryError without engine dependency
|
|
17
16
|
*/
|
package/dist/registry-error.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RegistryError = void 0;
|
|
4
|
+
// CoreLanguageCode is deprecated - using string
|
|
4
5
|
const core_string_key_1 = require("./core-string-key");
|
|
5
6
|
const registry_error_type_1 = require("./registry-error-type");
|
|
6
7
|
const typed_error_1 = require("./typed-error");
|
package/dist/typed-error.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Language, StringKey } from './default-config';
|
|
2
2
|
import { I18nEngine } from './i18n-engine';
|
|
3
|
-
import { CoreLanguageCode } from './core-i18n';
|
|
4
3
|
import { CoreStringKey } from './core-string-key';
|
|
5
4
|
import { PluginI18nEngine } from './plugin-i18n-engine';
|
|
6
5
|
import { TranslationEngine } from './translation-engine';
|
|
@@ -52,9 +51,9 @@ export declare abstract class PluginTypedError<TEnum extends Record<string, stri
|
|
|
52
51
|
export declare abstract class CoreTypedError<TEnum extends Record<string, string>> extends Error {
|
|
53
52
|
readonly type: TEnum[keyof TEnum];
|
|
54
53
|
readonly reasonMap: CompleteReasonMap<TEnum, CoreStringKey>;
|
|
55
|
-
readonly language?:
|
|
54
|
+
readonly language?: string | undefined;
|
|
56
55
|
readonly otherVars?: Record<string, string | number> | undefined;
|
|
57
|
-
constructor(engine: PluginI18nEngine<
|
|
56
|
+
constructor(engine: PluginI18nEngine<string>, type: TEnum[keyof TEnum], reasonMap: CompleteReasonMap<TEnum, CoreStringKey>, language?: string | undefined, otherVars?: Record<string, string | number> | undefined);
|
|
58
57
|
}
|
|
59
58
|
/**
|
|
60
59
|
* Helper function to create a plugin-based TypedError with automatic engine detection
|
|
@@ -63,7 +62,7 @@ export declare function createPluginTypedError<TEnum extends Record<string, stri
|
|
|
63
62
|
/**
|
|
64
63
|
* Helper function to create a core system TypedError with automatic engine detection
|
|
65
64
|
*/
|
|
66
|
-
export declare function createCoreTypedError<TEnum extends Record<string, string>>(type: TEnum[keyof TEnum], reasonMap: CompleteReasonMap<TEnum, CoreStringKey>, otherVars?: Record<string, string | number>, language?:
|
|
65
|
+
export declare function createCoreTypedError<TEnum extends Record<string, string>>(type: TEnum[keyof TEnum], reasonMap: CompleteReasonMap<TEnum, CoreStringKey>, otherVars?: Record<string, string | number>, language?: string, instanceKey?: string): Error;
|
|
67
66
|
/**
|
|
68
67
|
* Create a simple error with translation support (generalized pattern from RegistryError)
|
|
69
68
|
*/
|
package/dist/typed-error.js
CHANGED
|
@@ -6,6 +6,8 @@ exports.createCoreTypedError = createCoreTypedError;
|
|
|
6
6
|
exports.createTranslatedError = createTranslatedError;
|
|
7
7
|
// Legacy imports (for backward compatibility)
|
|
8
8
|
const default_config_1 = require("./default-config");
|
|
9
|
+
// New plugin architecture imports
|
|
10
|
+
// CoreLanguageCode is deprecated - using string for flexibility
|
|
9
11
|
const core_string_key_1 = require("./core-string-key");
|
|
10
12
|
const plugin_i18n_engine_1 = require("./plugin-i18n-engine");
|
|
11
13
|
/**
|
|
@@ -187,7 +189,7 @@ class DatabaseError extends CoreTypedError<typeof DatabaseErrorType> {
|
|
|
187
189
|
}
|
|
188
190
|
|
|
189
191
|
// Usage:
|
|
190
|
-
// const engine = PluginI18nEngine.getInstance<
|
|
192
|
+
// const engine = PluginI18nEngine.getInstance<string>();
|
|
191
193
|
// throw new DatabaseError(engine, DatabaseErrorType.ConnectionFailed);
|
|
192
194
|
*/
|
|
193
195
|
// Example 2: Custom component error with custom strings
|
|
@@ -210,19 +212,19 @@ const userErrorReasonMap: CompleteReasonMap<typeof UserErrorType, UserErrorStrin
|
|
|
210
212
|
[UserErrorType.AccountLocked]: UserErrorStringKey.AccountLockedMessage
|
|
211
213
|
};
|
|
212
214
|
|
|
213
|
-
class UserError extends PluginTypedError<typeof UserErrorType, UserErrorStringKey,
|
|
215
|
+
class UserError extends PluginTypedError<typeof UserErrorType, UserErrorStringKey, string> {
|
|
214
216
|
constructor(
|
|
215
|
-
engine: PluginI18nEngine<
|
|
217
|
+
engine: PluginI18nEngine<string>,
|
|
216
218
|
type: UserErrorType,
|
|
217
219
|
otherVars?: Record<string, string | number>,
|
|
218
|
-
language?:
|
|
220
|
+
language?: string
|
|
219
221
|
) {
|
|
220
222
|
super(engine, 'user-system', type, userErrorReasonMap, language, otherVars);
|
|
221
223
|
}
|
|
222
224
|
}
|
|
223
225
|
|
|
224
226
|
// Usage:
|
|
225
|
-
// const engine = PluginI18nEngine.getInstance<
|
|
227
|
+
// const engine = PluginI18nEngine.getInstance<string>();
|
|
226
228
|
// throw new UserError(engine, UserErrorType.UserNotFound, { username: 'john_doe' });
|
|
227
229
|
*/
|
|
228
230
|
// Example 3: Using helper functions for simpler error creation
|