@digitaldefiance/i18n-lib 1.3.13 → 1.3.14
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 +4 -0
- package/package.json +4 -3
- package/src/active-context.d.ts +30 -0
- package/src/active-context.d.ts.map +1 -0
- package/src/active-context.js +3 -0
- package/src/active-context.js.map +1 -0
- package/src/component-definition.d.ts +12 -0
- package/src/component-definition.d.ts.map +1 -0
- package/src/component-definition.js +3 -0
- package/src/component-definition.js.map +1 -0
- package/src/component-registration.d.ts +10 -0
- package/src/component-registration.d.ts.map +1 -0
- package/src/component-registration.js +3 -0
- package/src/component-registration.js.map +1 -0
- package/src/component-registry.d.ts +69 -0
- package/src/component-registry.d.ts.map +1 -0
- package/src/component-registry.js +248 -0
- package/src/component-registry.js.map +1 -0
- package/src/context-error-type.d.ts +4 -0
- package/src/context-error-type.d.ts.map +1 -0
- package/src/context-error-type.js +8 -0
- package/src/context-error-type.js.map +1 -0
- package/src/context-error.d.ts +7 -0
- package/src/context-error.d.ts.map +1 -0
- package/src/context-error.js +18 -0
- package/src/context-error.js.map +1 -0
- package/src/context-manager.d.ts +34 -0
- package/src/context-manager.d.ts.map +1 -0
- package/src/context-manager.js +60 -0
- package/src/context-manager.js.map +1 -0
- package/src/context.d.ts +45 -0
- package/src/context.d.ts.map +1 -0
- package/src/context.js +70 -0
- package/src/context.js.map +1 -0
- package/src/core-i18n.d.ts +63 -0
- package/src/core-i18n.d.ts.map +1 -0
- package/src/core-i18n.js +478 -0
- package/src/core-i18n.js.map +1 -0
- package/src/core-string-key.d.ts +43 -0
- package/src/core-string-key.d.ts.map +1 -0
- package/src/core-string-key.js +51 -0
- package/src/core-string-key.js.map +1 -0
- package/src/create-translation-adapter.d.ts +21 -0
- package/src/create-translation-adapter.d.ts.map +1 -0
- package/src/create-translation-adapter.js +37 -0
- package/src/create-translation-adapter.js.map +1 -0
- package/src/currency-code.d.ts +20 -0
- package/src/currency-code.d.ts.map +1 -0
- package/src/currency-code.js +37 -0
- package/src/currency-code.js.map +1 -0
- package/src/{currency-format.ts → currency-format.d.ts} +5 -5
- package/src/currency-format.d.ts.map +1 -0
- package/src/currency-format.js +3 -0
- package/src/currency-format.js.map +1 -0
- package/src/currency.d.ts +12 -0
- package/src/currency.d.ts.map +1 -0
- package/src/currency.js +49 -0
- package/src/currency.js.map +1 -0
- package/src/default-config.d.ts +33 -0
- package/src/default-config.d.ts.map +1 -0
- package/src/default-config.js +102 -0
- package/src/default-config.js.map +1 -0
- package/src/enum-registry.d.ts +45 -0
- package/src/enum-registry.d.ts.map +1 -0
- package/src/enum-registry.js +103 -0
- package/src/enum-registry.js.map +1 -0
- package/src/global-active-context.d.ts +51 -0
- package/src/global-active-context.d.ts.map +1 -0
- package/src/global-active-context.js +179 -0
- package/src/global-active-context.js.map +1 -0
- package/src/handleable.d.ts +14 -0
- package/src/handleable.d.ts.map +1 -0
- package/src/handleable.js +66 -0
- package/src/handleable.js.map +1 -0
- package/src/i-global-active-context.d.ts +23 -0
- package/src/i-global-active-context.d.ts.map +1 -0
- package/src/i-global-active-context.js +3 -0
- package/src/i-global-active-context.js.map +1 -0
- package/src/i-handleable-error-options.d.ts +7 -0
- package/src/i-handleable-error-options.d.ts.map +1 -0
- package/src/i-handleable-error-options.js +3 -0
- package/src/i-handleable-error-options.js.map +1 -0
- package/src/i-handleable.d.ts +6 -0
- package/src/i-handleable.d.ts.map +1 -0
- package/src/i-handleable.js +3 -0
- package/src/i-handleable.js.map +1 -0
- package/src/i18n-config.d.ts +21 -0
- package/src/i18n-config.d.ts.map +1 -0
- package/src/i18n-config.js +3 -0
- package/src/i18n-config.js.map +1 -0
- package/src/{i18n-context.ts → i18n-context.d.ts} +7 -7
- package/src/i18n-context.d.ts.map +1 -0
- package/src/i18n-context.js +3 -0
- package/src/i18n-context.js.map +1 -0
- package/src/i18n-engine.d.ts +179 -0
- package/src/i18n-engine.d.ts.map +1 -0
- package/src/i18n-engine.js +355 -0
- package/src/i18n-engine.js.map +1 -0
- package/src/{index.ts → index.d.ts} +2 -10
- package/src/index.d.ts.map +1 -0
- package/src/index.js +71 -0
- package/src/index.js.map +1 -0
- package/src/{language-codes.ts → language-codes.d.ts} +12 -23
- package/src/language-codes.d.ts.map +1 -0
- package/src/language-codes.js +32 -0
- package/src/language-codes.js.map +1 -0
- package/src/language-definition.d.ts +14 -0
- package/src/language-definition.d.ts.map +1 -0
- package/src/language-definition.js +3 -0
- package/src/language-definition.js.map +1 -0
- package/src/language-registry.d.ts +114 -0
- package/src/language-registry.d.ts.map +1 -0
- package/src/language-registry.js +217 -0
- package/src/language-registry.js.map +1 -0
- package/src/plugin-i18n-engine.d.ts +147 -0
- package/src/plugin-i18n-engine.d.ts.map +1 -0
- package/src/plugin-i18n-engine.js +369 -0
- package/src/plugin-i18n-engine.js.map +1 -0
- package/src/plugin-translatable-generic-error.d.ts +30 -0
- package/src/plugin-translatable-generic-error.d.ts.map +1 -0
- package/src/plugin-translatable-generic-error.js +72 -0
- package/src/plugin-translatable-generic-error.js.map +1 -0
- package/src/plugin-translatable-handleable-generic.d.ts +29 -0
- package/src/plugin-translatable-handleable-generic.d.ts.map +1 -0
- package/src/plugin-translatable-handleable-generic.js +44 -0
- package/src/plugin-translatable-handleable-generic.js.map +1 -0
- package/src/plugin-typed-handleable.d.ts +15 -0
- package/src/plugin-typed-handleable.d.ts.map +1 -0
- package/src/plugin-typed-handleable.js +51 -0
- package/src/plugin-typed-handleable.js.map +1 -0
- package/src/registry-config.d.ts +15 -0
- package/src/registry-config.d.ts.map +1 -0
- package/src/registry-config.js +3 -0
- package/src/registry-config.js.map +1 -0
- package/src/registry-error-type.d.ts +13 -0
- package/src/registry-error-type.d.ts.map +1 -0
- package/src/registry-error-type.js +17 -0
- package/src/registry-error-type.js.map +1 -0
- package/src/registry-error.d.ts +19 -0
- package/src/registry-error.d.ts.map +1 -0
- package/src/registry-error.js +48 -0
- package/src/registry-error.js.map +1 -0
- package/src/strict-types.d.ts +19 -0
- package/src/strict-types.d.ts.map +1 -0
- package/src/strict-types.js +18 -0
- package/src/strict-types.js.map +1 -0
- package/src/template.d.ts +13 -0
- package/src/template.d.ts.map +1 -0
- package/src/template.js +31 -0
- package/src/template.js.map +1 -0
- package/src/timezone.d.ts +12 -0
- package/src/timezone.d.ts.map +1 -0
- package/src/timezone.js +24 -0
- package/src/timezone.js.map +1 -0
- package/src/translatable.d.ts +6 -0
- package/src/translatable.d.ts.map +1 -0
- package/src/translatable.js +12 -0
- package/src/translatable.js.map +1 -0
- package/src/translation-engine.d.ts +9 -0
- package/src/translation-engine.d.ts.map +1 -0
- package/src/translation-engine.js +3 -0
- package/src/translation-engine.js.map +1 -0
- package/src/translation-request.d.ts +10 -0
- package/src/translation-request.d.ts.map +1 -0
- package/src/translation-request.js +3 -0
- package/src/translation-request.js.map +1 -0
- package/src/translation-response.d.ts +9 -0
- package/src/translation-response.d.ts.map +1 -0
- package/src/translation-response.js +3 -0
- package/src/translation-response.js.map +1 -0
- package/src/typed-error.d.ts +73 -0
- package/src/typed-error.d.ts.map +1 -0
- package/src/typed-error.js +267 -0
- package/src/typed-error.js.map +1 -0
- package/src/typed-handleable.d.ts +15 -0
- package/src/typed-handleable.d.ts.map +1 -0
- package/src/typed-handleable.js +46 -0
- package/src/typed-handleable.js.map +1 -0
- package/src/{types.ts → types.d.ts} +21 -75
- package/src/types.d.ts.map +1 -0
- package/src/types.js +19 -0
- package/src/types.js.map +1 -0
- package/src/unified-translator.d.ts +31 -0
- package/src/unified-translator.d.ts.map +1 -0
- package/src/unified-translator.js +71 -0
- package/src/unified-translator.js.map +1 -0
- package/src/utils.d.ts +65 -0
- package/src/utils.d.ts.map +1 -0
- package/src/utils.js +129 -0
- package/src/utils.js.map +1 -0
- package/src/validation-config.d.ts +12 -0
- package/src/validation-config.d.ts.map +1 -0
- package/src/validation-config.js +3 -0
- package/src/validation-config.js.map +1 -0
- package/src/validation-result.d.ts +13 -0
- package/src/validation-result.d.ts.map +1 -0
- package/src/validation-result.js +3 -0
- package/src/validation-result.js.map +1 -0
- package/LICENSE +0 -21
- package/src/active-context.ts +0 -30
- package/src/component-definition.ts +0 -11
- package/src/component-registration.ts +0 -13
- package/src/component-registry.ts +0 -392
- package/src/context-error-type.ts +0 -3
- package/src/context-error.ts +0 -16
- package/src/context-manager.ts +0 -71
- package/src/context.ts +0 -90
- package/src/core-i18n.ts +0 -609
- package/src/core-string-key.ts +0 -49
- package/src/create-translation-adapter.ts +0 -47
- package/src/currency-code.ts +0 -35
- package/src/currency.ts +0 -52
- package/src/default-config.ts +0 -199
- package/src/enum-registry.ts +0 -138
- package/src/global-active-context.ts +0 -255
- package/src/handleable.ts +0 -79
- package/src/i-global-active-context.ts +0 -59
- package/src/i-handleable-error-options.ts +0 -6
- package/src/i-handleable.ts +0 -5
- package/src/i18n-config.ts +0 -29
- package/src/i18n-engine.ts +0 -491
- package/src/language-definition.ts +0 -13
- package/src/language-registry.ts +0 -292
- package/src/plugin-i18n-engine.ts +0 -520
- package/src/plugin-translatable-generic-error.ts +0 -106
- package/src/plugin-translatable-handleable-generic.ts +0 -60
- package/src/plugin-typed-handleable.ts +0 -77
- package/src/registry-config.ts +0 -15
- package/src/registry-error-type.ts +0 -12
- package/src/registry-error.ts +0 -74
- package/src/strict-types.ts +0 -35
- package/src/template.ts +0 -63
- package/src/timezone.ts +0 -20
- package/src/translatable.ts +0 -15
- package/src/translation-engine.ts +0 -8
- package/src/translation-request.ts +0 -12
- package/src/translation-response.ts +0 -8
- package/src/typed-error.ts +0 -384
- package/src/typed-handleable.ts +0 -70
- package/src/unified-translator.ts +0 -96
- package/src/utils.ts +0 -213
- package/src/validation-config.ts +0 -11
- package/src/validation-result.ts +0 -12
|
@@ -1,520 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Plugin-based internationalization engine with component and language registration
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { ComponentDefinition } from './component-definition';
|
|
6
|
-
import { ComponentRegistration } from './component-registration';
|
|
7
|
-
import { ComponentRegistry } from './component-registry';
|
|
8
|
-
import { CurrencyCode } from './currency-code';
|
|
9
|
-
import { EnumTranslationRegistry } from './enum-registry';
|
|
10
|
-
import { GlobalActiveContext } from './global-active-context';
|
|
11
|
-
import { IActiveContext } from './active-context';
|
|
12
|
-
import { LanguageDefinition } from './language-definition';
|
|
13
|
-
import { LanguageRegistry } from './language-registry';
|
|
14
|
-
import { RegistryConfig } from './registry-config';
|
|
15
|
-
import { RegistryError } from './registry-error';
|
|
16
|
-
import { RegistryErrorType } from './registry-error-type';
|
|
17
|
-
import { Timezone } from './timezone';
|
|
18
|
-
import { TranslationRequest } from './translation-request';
|
|
19
|
-
import { TranslationResponse } from './translation-response';
|
|
20
|
-
import { EnumLanguageTranslation } from './types';
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Plugin-based I18n Engine with registration capabilities
|
|
24
|
-
*/
|
|
25
|
-
export class PluginI18nEngine<TLanguages extends string> {
|
|
26
|
-
private readonly componentRegistry: ComponentRegistry<TLanguages>;
|
|
27
|
-
private readonly enumRegistry: EnumTranslationRegistry<string, TLanguages>;
|
|
28
|
-
private readonly config: RegistryConfig<TLanguages>;
|
|
29
|
-
private contextKey: string;
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Default template processor instance
|
|
33
|
-
*/
|
|
34
|
-
public readonly t: (
|
|
35
|
-
str: string,
|
|
36
|
-
language?: TLanguages,
|
|
37
|
-
...otherVars: Record<string, string | number>[]
|
|
38
|
-
) => string;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Static instances for semi-singleton pattern
|
|
44
|
-
*/
|
|
45
|
-
private static _instances = new Map<string, PluginI18nEngine<any>>();
|
|
46
|
-
private static _defaultKey: string | null = null;
|
|
47
|
-
protected static readonly DefaultInstanceKey = 'default';
|
|
48
|
-
|
|
49
|
-
constructor(
|
|
50
|
-
initialLanguages: readonly LanguageDefinition[],
|
|
51
|
-
config: Partial<RegistryConfig<TLanguages>> = {},
|
|
52
|
-
) {
|
|
53
|
-
// Find default language from initialLanguages or use the first one
|
|
54
|
-
const defaultLang =
|
|
55
|
-
initialLanguages.find((l) => l.isDefault) || initialLanguages[0];
|
|
56
|
-
if (!defaultLang) {
|
|
57
|
-
throw new Error('At least one language must be provided');
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Set up configuration with defaults
|
|
61
|
-
this.config = {
|
|
62
|
-
defaultLanguage: defaultLang.id as TLanguages,
|
|
63
|
-
fallbackLanguage: defaultLang.id as TLanguages,
|
|
64
|
-
defaultCurrencyCode: new CurrencyCode('USD'),
|
|
65
|
-
timezone: new Timezone('UTC'),
|
|
66
|
-
adminTimezone: new Timezone('UTC'),
|
|
67
|
-
validation: {
|
|
68
|
-
requireCompleteStrings: false,
|
|
69
|
-
allowPartialRegistration: true,
|
|
70
|
-
fallbackLanguageId: defaultLang.id,
|
|
71
|
-
},
|
|
72
|
-
...config,
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
// Register initial languages in static registry (skip if already registered)
|
|
76
|
-
for (const lang of initialLanguages) {
|
|
77
|
-
if (!LanguageRegistry.hasLanguage(lang.id)) {
|
|
78
|
-
LanguageRegistry.registerLanguage(lang);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Initialize component registry (per-instance)
|
|
83
|
-
this.componentRegistry = new ComponentRegistry<TLanguages>(
|
|
84
|
-
initialLanguages.map((l) => l.id as TLanguages),
|
|
85
|
-
this.config.validation,
|
|
86
|
-
);
|
|
87
|
-
this.enumRegistry = new EnumTranslationRegistry<string, TLanguages>(
|
|
88
|
-
initialLanguages.map((l) => l.id as TLanguages),
|
|
89
|
-
(key: string, vars?: Record<string, any>) =>
|
|
90
|
-
this.safeTranslate('core', key, vars),
|
|
91
|
-
);
|
|
92
|
-
|
|
93
|
-
// Initialize context key for this engine instance
|
|
94
|
-
this.contextKey = PluginI18nEngine.DefaultInstanceKey;
|
|
95
|
-
|
|
96
|
-
// Create or get the global context for this engine
|
|
97
|
-
const globalContext = GlobalActiveContext.getInstance<TLanguages, IActiveContext<TLanguages>>();
|
|
98
|
-
|
|
99
|
-
// Always create/update the context for this engine
|
|
100
|
-
globalContext.createContext(
|
|
101
|
-
this.config.defaultLanguage,
|
|
102
|
-
this.config.defaultLanguage,
|
|
103
|
-
this.contextKey
|
|
104
|
-
);
|
|
105
|
-
globalContext.setCurrencyCode(this.config.defaultCurrencyCode, this.contextKey);
|
|
106
|
-
globalContext.setUserTimezone(this.config.timezone, this.contextKey);
|
|
107
|
-
globalContext.setAdminTimezone(this.config.adminTimezone, this.contextKey);
|
|
108
|
-
|
|
109
|
-
// Initialize the default template processor for component-based patterns
|
|
110
|
-
this.t = (str: string, language?: TLanguages, ...otherVars: Record<string, string | number>[]) => {
|
|
111
|
-
// Step 1: Replace component-based patterns like {{componentId.stringKey}}
|
|
112
|
-
let result = str.replace(/\{\{([^}]+)\}\}/g, (match, pattern) => {
|
|
113
|
-
const parts = pattern.split('.');
|
|
114
|
-
if (parts.length === 2) {
|
|
115
|
-
const [componentId, stringKey] = parts;
|
|
116
|
-
// For template strings, use the first variable object if available
|
|
117
|
-
const isTemplate = stringKey.toLowerCase().endsWith('template');
|
|
118
|
-
const vars = isTemplate && otherVars.length > 0 ? otherVars[0] : {};
|
|
119
|
-
return this.safeTranslate(componentId.trim(), stringKey.trim(), vars, language);
|
|
120
|
-
}
|
|
121
|
-
return match; // Return original if pattern doesn't match expected format
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
// Step 2: Replace remaining variable patterns like {varName} with merged variables
|
|
125
|
-
const allVars = otherVars.reduce((acc, vars) => ({ ...acc, ...vars }), {});
|
|
126
|
-
result = result.replace(/\{(\w+)\}/g, (match, varName) => {
|
|
127
|
-
return allVars[varName] !== undefined ? String(allVars[varName]) : match;
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
return result;
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
// Auto-register as default instance if none exists
|
|
134
|
-
if (!PluginI18nEngine._defaultKey) {
|
|
135
|
-
PluginI18nEngine._instances.set(
|
|
136
|
-
PluginI18nEngine.DefaultInstanceKey,
|
|
137
|
-
this,
|
|
138
|
-
);
|
|
139
|
-
PluginI18nEngine._defaultKey = PluginI18nEngine.DefaultInstanceKey;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Create a new instance with a specific key
|
|
145
|
-
*/
|
|
146
|
-
public static createInstance<TLangs extends string>(
|
|
147
|
-
key: string,
|
|
148
|
-
initialLanguages: readonly LanguageDefinition[],
|
|
149
|
-
config?: Partial<RegistryConfig<TLangs>>,
|
|
150
|
-
): PluginI18nEngine<TLangs> {
|
|
151
|
-
if (PluginI18nEngine._instances.has(key)) {
|
|
152
|
-
throw RegistryError.createSimple(
|
|
153
|
-
RegistryErrorType.DuplicateComponent,
|
|
154
|
-
`I18n instance with key '${key}' already exists`,
|
|
155
|
-
{ key },
|
|
156
|
-
);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const instance = new PluginI18nEngine<TLangs>(initialLanguages, config);
|
|
160
|
-
instance.contextKey = key;
|
|
161
|
-
|
|
162
|
-
// Create context for this specific instance
|
|
163
|
-
const globalContext = GlobalActiveContext.getInstance();
|
|
164
|
-
globalContext.createContext(
|
|
165
|
-
instance.config.defaultLanguage,
|
|
166
|
-
instance.config.defaultLanguage,
|
|
167
|
-
key
|
|
168
|
-
);
|
|
169
|
-
globalContext.setCurrencyCode(instance.config.defaultCurrencyCode, key);
|
|
170
|
-
globalContext.setUserTimezone(instance.config.timezone, key);
|
|
171
|
-
globalContext.setAdminTimezone(instance.config.adminTimezone, key);
|
|
172
|
-
|
|
173
|
-
PluginI18nEngine._instances.set(key, instance);
|
|
174
|
-
|
|
175
|
-
if (!PluginI18nEngine._defaultKey) {
|
|
176
|
-
PluginI18nEngine._defaultKey = key;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
return instance;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Get an existing instance by key
|
|
184
|
-
*/
|
|
185
|
-
public static getInstance<TLangs extends string>(
|
|
186
|
-
key?: string,
|
|
187
|
-
): PluginI18nEngine<TLangs> {
|
|
188
|
-
const instanceKey =
|
|
189
|
-
key ||
|
|
190
|
-
PluginI18nEngine._defaultKey ||
|
|
191
|
-
PluginI18nEngine.DefaultInstanceKey;
|
|
192
|
-
const instance = PluginI18nEngine._instances.get(instanceKey);
|
|
193
|
-
|
|
194
|
-
if (!instance) {
|
|
195
|
-
throw RegistryError.createSimple(
|
|
196
|
-
RegistryErrorType.ComponentNotFound,
|
|
197
|
-
`I18n instance with key '${instanceKey}' not found`,
|
|
198
|
-
{ key: instanceKey },
|
|
199
|
-
);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
return instance as PluginI18nEngine<TLangs>;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Register a new language (updates static registry)
|
|
207
|
-
*/
|
|
208
|
-
public registerLanguage(language: LanguageDefinition): void {
|
|
209
|
-
LanguageRegistry.registerLanguage(language);
|
|
210
|
-
|
|
211
|
-
// Update component registry with new language
|
|
212
|
-
const newLanguages = LanguageRegistry.getLanguageIds();
|
|
213
|
-
this.componentRegistry.updateRegisteredLanguages(
|
|
214
|
-
newLanguages as TLanguages[],
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Register multiple languages (updates static registry)
|
|
220
|
-
*/
|
|
221
|
-
public registerLanguages(languages: readonly LanguageDefinition[]): void {
|
|
222
|
-
for (const language of languages) {
|
|
223
|
-
this.registerLanguage(language);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Register a component with its translations
|
|
229
|
-
*/
|
|
230
|
-
public registerComponent<TStringKeys extends string>(
|
|
231
|
-
registration: ComponentRegistration<TStringKeys, TLanguages>,
|
|
232
|
-
) {
|
|
233
|
-
return this.componentRegistry.registerComponent(registration);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* Update strings for an existing component
|
|
238
|
-
*/
|
|
239
|
-
public updateComponentStrings<TStringKeys extends string>(
|
|
240
|
-
componentId: string,
|
|
241
|
-
strings: Parameters<
|
|
242
|
-
ComponentRegistry<TLanguages>['updateComponentStrings']
|
|
243
|
-
>[1],
|
|
244
|
-
) {
|
|
245
|
-
return this.componentRegistry.updateComponentStrings(componentId, strings);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Register an enum with translations
|
|
250
|
-
*/
|
|
251
|
-
public registerEnum<TEnum extends string | number>(
|
|
252
|
-
enumObj: Record<string, TEnum>,
|
|
253
|
-
translations: EnumLanguageTranslation<TEnum, TLanguages>,
|
|
254
|
-
enumName: string,
|
|
255
|
-
): void {
|
|
256
|
-
this.enumRegistry.register(enumObj, translations, enumName);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* Translate a string for a component
|
|
261
|
-
*/
|
|
262
|
-
public translate<TStringKeys extends string>(
|
|
263
|
-
componentId: string,
|
|
264
|
-
stringKey: TStringKeys,
|
|
265
|
-
variables?: Record<string, string | number>,
|
|
266
|
-
language?: TLanguages,
|
|
267
|
-
): string {
|
|
268
|
-
const request: TranslationRequest<TStringKeys, TLanguages> = {
|
|
269
|
-
componentId,
|
|
270
|
-
stringKey,
|
|
271
|
-
language: language || this.getCurrentLanguage(),
|
|
272
|
-
variables,
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
const response = this.componentRegistry.getTranslation(request);
|
|
276
|
-
return response.translation;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* Safe translate that returns a placeholder if translation fails
|
|
281
|
-
*/
|
|
282
|
-
public safeTranslate(
|
|
283
|
-
componentId: string,
|
|
284
|
-
stringKey: string,
|
|
285
|
-
variables?: Record<string, string | number>,
|
|
286
|
-
language?: TLanguages,
|
|
287
|
-
): string {
|
|
288
|
-
try {
|
|
289
|
-
return this.translate(componentId, stringKey, variables, language);
|
|
290
|
-
} catch (error) {
|
|
291
|
-
// Return a placeholder if translation fails
|
|
292
|
-
return `[${componentId}.${stringKey}]`;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
/**
|
|
297
|
-
* Translate an enum value
|
|
298
|
-
*/
|
|
299
|
-
public translateEnum<TEnum extends string | number>(
|
|
300
|
-
enumObj: Record<string, TEnum>,
|
|
301
|
-
value: TEnum,
|
|
302
|
-
language?: TLanguages,
|
|
303
|
-
): string {
|
|
304
|
-
return this.enumRegistry.translate(
|
|
305
|
-
enumObj,
|
|
306
|
-
value,
|
|
307
|
-
language || this.getCurrentLanguage(),
|
|
308
|
-
);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* Get detailed translation response
|
|
313
|
-
*/
|
|
314
|
-
public getTranslationDetails<TStringKeys extends string>(
|
|
315
|
-
componentId: string,
|
|
316
|
-
stringKey: TStringKeys,
|
|
317
|
-
variables?: Record<string, string | number>,
|
|
318
|
-
language?: TLanguages,
|
|
319
|
-
): TranslationResponse {
|
|
320
|
-
const request: TranslationRequest<TStringKeys, TLanguages> = {
|
|
321
|
-
componentId,
|
|
322
|
-
stringKey,
|
|
323
|
-
language: language || this.getCurrentLanguage(),
|
|
324
|
-
variables,
|
|
325
|
-
};
|
|
326
|
-
|
|
327
|
-
return this.componentRegistry.getTranslation(request);
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
/**
|
|
331
|
-
* Get current context
|
|
332
|
-
*/
|
|
333
|
-
public getContext(): IActiveContext<TLanguages> {
|
|
334
|
-
const globalContext = GlobalActiveContext.getInstance<TLanguages, IActiveContext<TLanguages>>();
|
|
335
|
-
return globalContext.getContext(this.contextKey);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* Update context
|
|
340
|
-
*/
|
|
341
|
-
public updateContext(updates: Partial<IActiveContext<TLanguages>>): void {
|
|
342
|
-
const globalContext = GlobalActiveContext.getInstance<TLanguages, IActiveContext<TLanguages>>();
|
|
343
|
-
|
|
344
|
-
if (updates.language) globalContext.setUserLanguage(updates.language, this.contextKey);
|
|
345
|
-
if (updates.adminLanguage) globalContext.setAdminLanguage(updates.adminLanguage, this.contextKey);
|
|
346
|
-
if (updates.currencyCode) globalContext.setCurrencyCode(updates.currencyCode, this.contextKey);
|
|
347
|
-
if (updates.currentContext) globalContext.setLanguageContextSpace(updates.currentContext, this.contextKey);
|
|
348
|
-
if (updates.timezone) globalContext.setUserTimezone(updates.timezone, this.contextKey);
|
|
349
|
-
if (updates.adminTimezone) globalContext.setAdminTimezone(updates.adminTimezone, this.contextKey);
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
* Get current language from global context
|
|
354
|
-
* Respects language context space (admin vs user)
|
|
355
|
-
*/
|
|
356
|
-
private getCurrentLanguage(): TLanguages {
|
|
357
|
-
const globalContext = GlobalActiveContext.getInstance<TLanguages, IActiveContext<TLanguages>>();
|
|
358
|
-
const context = globalContext.getContext(this.contextKey);
|
|
359
|
-
return context.currentContext === 'admin' ? context.adminLanguage : context.language;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
/**
|
|
363
|
-
* Set current language
|
|
364
|
-
*/
|
|
365
|
-
public setLanguage(language: TLanguages): void {
|
|
366
|
-
if (!LanguageRegistry.hasLanguage(language)) {
|
|
367
|
-
throw RegistryError.createSimple(
|
|
368
|
-
RegistryErrorType.LanguageNotFound,
|
|
369
|
-
`Language '${language}' is not registered`,
|
|
370
|
-
{ language },
|
|
371
|
-
);
|
|
372
|
-
}
|
|
373
|
-
const globalContext = GlobalActiveContext.getInstance<TLanguages, IActiveContext<TLanguages>>();
|
|
374
|
-
globalContext.setUserLanguage(language, this.contextKey);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
/**
|
|
378
|
-
* Get available languages from static registry
|
|
379
|
-
*/
|
|
380
|
-
public getLanguages(): readonly LanguageDefinition[] {
|
|
381
|
-
return LanguageRegistry.getAllLanguages();
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
/**
|
|
385
|
-
* Get registered components
|
|
386
|
-
*/
|
|
387
|
-
public getComponents(): ReadonlyArray<ComponentDefinition<any>> {
|
|
388
|
-
return this.componentRegistry.getComponents();
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
/**
|
|
392
|
-
* Check if a component is registered
|
|
393
|
-
*/
|
|
394
|
-
public hasComponent(componentId: string): boolean {
|
|
395
|
-
return this.componentRegistry.hasComponent(componentId);
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
/**
|
|
399
|
-
* Check if a language is registered in static registry
|
|
400
|
-
*/
|
|
401
|
-
public hasLanguage(language: TLanguages): boolean {
|
|
402
|
-
return LanguageRegistry.hasLanguage(language);
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
/**
|
|
406
|
-
* Get language by code from static registry
|
|
407
|
-
*/
|
|
408
|
-
public getLanguageByCode(code: string): LanguageDefinition | undefined {
|
|
409
|
-
return LanguageRegistry.getLanguageByCode(code);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
/**
|
|
413
|
-
* Get component registry for direct access
|
|
414
|
-
*/
|
|
415
|
-
public getComponentRegistry(): ComponentRegistry<TLanguages> {
|
|
416
|
-
return this.componentRegistry;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
/**
|
|
420
|
-
* Get enum registry for direct access
|
|
421
|
-
*/
|
|
422
|
-
public getEnumRegistry(): EnumTranslationRegistry<string, TLanguages> {
|
|
423
|
-
return this.enumRegistry;
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
/**
|
|
427
|
-
* Validate that all components have complete translations
|
|
428
|
-
*/
|
|
429
|
-
public validateAllComponents(): {
|
|
430
|
-
isValid: boolean;
|
|
431
|
-
errors: string[];
|
|
432
|
-
warnings: string[];
|
|
433
|
-
} {
|
|
434
|
-
const errors: string[] = [];
|
|
435
|
-
const warnings: string[] = [];
|
|
436
|
-
let isValid = true;
|
|
437
|
-
|
|
438
|
-
const components = this.getComponents();
|
|
439
|
-
const languages = LanguageRegistry.getLanguageIds();
|
|
440
|
-
|
|
441
|
-
for (const component of components) {
|
|
442
|
-
const componentStrings = this.componentRegistry.getComponentStrings(
|
|
443
|
-
component.id,
|
|
444
|
-
);
|
|
445
|
-
|
|
446
|
-
if (!componentStrings) {
|
|
447
|
-
errors.push(`Component '${component.id}' has no registered strings`);
|
|
448
|
-
isValid = false;
|
|
449
|
-
continue;
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
for (const language of languages) {
|
|
453
|
-
const languageStrings = componentStrings[language as TLanguages];
|
|
454
|
-
|
|
455
|
-
if (!languageStrings) {
|
|
456
|
-
errors.push(
|
|
457
|
-
`Component '${component.id}' missing strings for language '${language}'`,
|
|
458
|
-
);
|
|
459
|
-
isValid = false;
|
|
460
|
-
continue;
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
for (const stringKey of component.stringKeys) {
|
|
464
|
-
if (!languageStrings[stringKey]) {
|
|
465
|
-
warnings.push(
|
|
466
|
-
`Component '${component.id}' missing key '${stringKey}' for language '${language}'`,
|
|
467
|
-
);
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
return { isValid, errors, warnings };
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
/**
|
|
477
|
-
* Clear all component registrations for this instance (useful for testing)
|
|
478
|
-
*/
|
|
479
|
-
public clearAllComponents(): void {
|
|
480
|
-
this.componentRegistry.clearAllComponents();
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
/**
|
|
484
|
-
* Remove a specific named instance
|
|
485
|
-
*/
|
|
486
|
-
public static removeInstance(key?: string): boolean {
|
|
487
|
-
const instanceKey = key || PluginI18nEngine.DefaultInstanceKey;
|
|
488
|
-
const removed = PluginI18nEngine._instances.delete(instanceKey);
|
|
489
|
-
|
|
490
|
-
// If we removed the default instance, clear the default key
|
|
491
|
-
if (removed && PluginI18nEngine._defaultKey === instanceKey) {
|
|
492
|
-
PluginI18nEngine._defaultKey = null;
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
return removed;
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
/**
|
|
499
|
-
* Check if an instance exists
|
|
500
|
-
*/
|
|
501
|
-
public static hasInstance(key?: string): boolean {
|
|
502
|
-
const instanceKey = key || PluginI18nEngine.DefaultInstanceKey;
|
|
503
|
-
return PluginI18nEngine._instances.has(instanceKey);
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
/**
|
|
507
|
-
* Reset all plugin engines and clear component registrations
|
|
508
|
-
* Useful for test cleanup
|
|
509
|
-
*/
|
|
510
|
-
public static resetAll(): void {
|
|
511
|
-
// Clear component registrations for each engine BEFORE clearing instances
|
|
512
|
-
for (const engine of PluginI18nEngine._instances.values()) {
|
|
513
|
-
engine.clearAllComponents();
|
|
514
|
-
}
|
|
515
|
-
PluginI18nEngine._instances.clear();
|
|
516
|
-
PluginI18nEngine._defaultKey = null;
|
|
517
|
-
LanguageRegistry.clear();
|
|
518
|
-
GlobalActiveContext.clearAll();
|
|
519
|
-
}
|
|
520
|
-
}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { PluginI18nEngine } from './plugin-i18n-engine';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Generic translatable error that works with any plugin engine and component
|
|
5
|
-
*/
|
|
6
|
-
export class PluginTranslatableGenericError<
|
|
7
|
-
TStringKey extends string = string,
|
|
8
|
-
TLanguage extends string = string,
|
|
9
|
-
> extends Error {
|
|
10
|
-
public readonly stringKey: TStringKey;
|
|
11
|
-
public readonly componentId: string;
|
|
12
|
-
public readonly language?: TLanguage;
|
|
13
|
-
public readonly variables?: Record<string, string | number>;
|
|
14
|
-
public readonly metadata?: Record<string, any>;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Create a translatable error
|
|
18
|
-
* @param componentId - The component ID to translate from
|
|
19
|
-
* @param stringKey - The translation key
|
|
20
|
-
* @param variables - Variables for interpolation
|
|
21
|
-
* @param language - Optional language override
|
|
22
|
-
* @param metadata - Additional error metadata
|
|
23
|
-
* @param instanceKey - Optional engine instance key
|
|
24
|
-
*/
|
|
25
|
-
constructor(
|
|
26
|
-
componentId: string,
|
|
27
|
-
stringKey: TStringKey,
|
|
28
|
-
variables?: Record<string, string | number>,
|
|
29
|
-
language?: TLanguage,
|
|
30
|
-
metadata?: Record<string, any>,
|
|
31
|
-
instanceKey?: string,
|
|
32
|
-
) {
|
|
33
|
-
let translatedMessage: string;
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
const engine = PluginI18nEngine.getInstance<TLanguage>(instanceKey);
|
|
37
|
-
translatedMessage = engine.safeTranslate(
|
|
38
|
-
componentId,
|
|
39
|
-
stringKey,
|
|
40
|
-
variables,
|
|
41
|
-
language,
|
|
42
|
-
);
|
|
43
|
-
} catch (error) {
|
|
44
|
-
// If engine not found or translation fails, use fallback format
|
|
45
|
-
translatedMessage = `[${componentId}.${stringKey}]`;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
super(translatedMessage);
|
|
49
|
-
this.name = 'TranslatableGenericError';
|
|
50
|
-
this.stringKey = stringKey;
|
|
51
|
-
this.componentId = componentId;
|
|
52
|
-
this.language = language;
|
|
53
|
-
this.variables = variables;
|
|
54
|
-
this.metadata = metadata;
|
|
55
|
-
|
|
56
|
-
// Ensure proper prototype chain for instanceof checks across transpiled targets
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Create error with explicit engine instance
|
|
61
|
-
*/
|
|
62
|
-
static withEngine<TStringKey extends string, TLanguage extends string>(
|
|
63
|
-
engine: PluginI18nEngine<TLanguage>,
|
|
64
|
-
componentId: string,
|
|
65
|
-
stringKey: TStringKey,
|
|
66
|
-
variables?: Record<string, string | number>,
|
|
67
|
-
language?: TLanguage,
|
|
68
|
-
metadata?: Record<string, any>,
|
|
69
|
-
): PluginTranslatableGenericError<TStringKey, TLanguage> {
|
|
70
|
-
const translatedMessage = engine.safeTranslate(
|
|
71
|
-
componentId,
|
|
72
|
-
stringKey,
|
|
73
|
-
variables,
|
|
74
|
-
language,
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
const error = Object.create(PluginTranslatableGenericError.prototype);
|
|
78
|
-
Error.call(error, translatedMessage);
|
|
79
|
-
error.name = 'TranslatableGenericError';
|
|
80
|
-
error.stringKey = stringKey;
|
|
81
|
-
error.componentId = componentId;
|
|
82
|
-
error.language = language;
|
|
83
|
-
error.variables = variables;
|
|
84
|
-
error.metadata = metadata;
|
|
85
|
-
error.message = translatedMessage;
|
|
86
|
-
|
|
87
|
-
return error;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Retranslate the error message in a different language
|
|
92
|
-
*/
|
|
93
|
-
retranslate(language: TLanguage, instanceKey?: string): string {
|
|
94
|
-
try {
|
|
95
|
-
const engine = PluginI18nEngine.getInstance<TLanguage>(instanceKey);
|
|
96
|
-
return engine.safeTranslate(
|
|
97
|
-
this.componentId,
|
|
98
|
-
this.stringKey,
|
|
99
|
-
this.variables,
|
|
100
|
-
language,
|
|
101
|
-
);
|
|
102
|
-
} catch (error) {
|
|
103
|
-
return `[${this.componentId}.${this.stringKey}]`;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { IHandleable } from './i-handleable';
|
|
2
|
-
import { PluginTranslatableGenericError } from './plugin-translatable-generic-error';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Generic translatable error that works with any plugin engine and component
|
|
6
|
-
*/
|
|
7
|
-
export class PluginTranslatableHandleableGenericError<
|
|
8
|
-
TStringKey extends string = string,
|
|
9
|
-
TLanguage extends string = string,
|
|
10
|
-
>
|
|
11
|
-
extends PluginTranslatableGenericError<TStringKey, TLanguage>
|
|
12
|
-
implements IHandleable
|
|
13
|
-
{
|
|
14
|
-
private _handled = false;
|
|
15
|
-
public override readonly cause?: Error;
|
|
16
|
-
public readonly statusCode: number;
|
|
17
|
-
public readonly sourceData?: unknown;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Create a translatable error
|
|
21
|
-
* @param componentId - The component ID to translate from
|
|
22
|
-
* @param stringKey - The translation key
|
|
23
|
-
* @param variables - Variables for interpolation
|
|
24
|
-
* @param language - Optional language override
|
|
25
|
-
* @param metadata - Additional error metadata
|
|
26
|
-
* @param instanceKey - Optional engine instance key
|
|
27
|
-
*/
|
|
28
|
-
constructor(
|
|
29
|
-
componentId: string,
|
|
30
|
-
stringKey: TStringKey,
|
|
31
|
-
variables?: Record<string, string | number>,
|
|
32
|
-
language?: TLanguage,
|
|
33
|
-
metadata?: Record<string, any>,
|
|
34
|
-
instanceKey?: string,
|
|
35
|
-
handleableOptions?: {
|
|
36
|
-
statusCode?: number;
|
|
37
|
-
cause?: Error;
|
|
38
|
-
sourceData?: unknown;
|
|
39
|
-
},
|
|
40
|
-
) {
|
|
41
|
-
super(componentId, stringKey, variables, language, metadata, instanceKey);
|
|
42
|
-
this.statusCode = handleableOptions?.statusCode ?? 500;
|
|
43
|
-
this.cause = handleableOptions?.cause;
|
|
44
|
-
this.sourceData = handleableOptions?.sourceData;
|
|
45
|
-
}
|
|
46
|
-
public get handled(): boolean {
|
|
47
|
-
return this._handled;
|
|
48
|
-
}
|
|
49
|
-
public set handled(value: boolean) {
|
|
50
|
-
this._handled = value;
|
|
51
|
-
}
|
|
52
|
-
toJSON(): Record<string, unknown> {
|
|
53
|
-
return {
|
|
54
|
-
statusCode: this.statusCode,
|
|
55
|
-
message: this.message,
|
|
56
|
-
cause: this.cause,
|
|
57
|
-
sourceData: this.sourceData,
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
}
|