@digitaldefiance/i18n-lib 1.0.22 → 1.0.24
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 +135 -6
- package/dist/context.d.ts +1 -1
- package/dist/default-config.d.ts +31 -0
- package/dist/default-config.js +67 -0
- package/dist/i18n-engine.d.ts +20 -5
- package/dist/i18n-engine.js +55 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/package.json +52 -0
- package/dist/src/active-context.d.ts +29 -0
- package/dist/src/active-context.js +2 -0
- package/dist/src/context-manager.d.ts +33 -0
- package/dist/src/context-manager.js +61 -0
- package/dist/src/context.d.ts +43 -0
- package/dist/src/context.js +69 -0
- package/dist/src/currency-code.d.ts +19 -0
- package/dist/src/currency-code.js +36 -0
- package/dist/src/currency-format.d.ts +10 -0
- package/dist/src/currency-format.js +2 -0
- package/dist/src/currency.d.ts +11 -0
- package/dist/src/currency.js +48 -0
- package/dist/src/enum-registry.d.ts +35 -0
- package/dist/src/enum-registry.js +67 -0
- package/dist/src/i18n-engine.d.ts +156 -0
- package/dist/src/i18n-engine.js +267 -0
- package/dist/src/index.d.ts +13 -0
- package/dist/src/index.js +32 -0
- package/dist/src/template.d.ts +12 -0
- package/dist/src/template.js +30 -0
- package/dist/src/timezone.d.ts +11 -0
- package/dist/src/timezone.js +22 -0
- package/dist/src/types.d.ts +78 -0
- package/dist/src/types.js +14 -0
- package/dist/src/utils.d.ts +41 -0
- package/dist/src/utils.js +85 -0
- package/package.json +2 -2
- package/dist/global-active-context.d.ts +0 -22
- package/dist/global-active-context.js +0 -73
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.I18nEngine = void 0;
|
|
4
|
+
const context_1 = require("./context");
|
|
5
|
+
const enum_registry_1 = require("./enum-registry");
|
|
6
|
+
const template_1 = require("./template");
|
|
7
|
+
const utils_1 = require("./utils");
|
|
8
|
+
/**
|
|
9
|
+
* Internationalization engine class
|
|
10
|
+
*/
|
|
11
|
+
class I18nEngine {
|
|
12
|
+
/**
|
|
13
|
+
* Creates a new I18nEngine instance
|
|
14
|
+
* @param config The i18n configuration
|
|
15
|
+
* @param key Optional instance key for the semi-singleton pattern
|
|
16
|
+
* @throws Error if an instance with the same key already exists
|
|
17
|
+
*/
|
|
18
|
+
constructor(config, key, newContext = () => (0, context_1.createContext)(config.defaultLanguage, config.defaultTranslationContext, config.defaultCurrencyCode, config.timezone, config.adminTimezone)) {
|
|
19
|
+
this.config = config;
|
|
20
|
+
this.enumRegistry = new enum_registry_1.EnumTranslationRegistry();
|
|
21
|
+
this._context = newContext();
|
|
22
|
+
const instanceKey = key || I18nEngine.DefaultInstanceKey;
|
|
23
|
+
if (I18nEngine._instances.has(instanceKey)) {
|
|
24
|
+
const existing = I18nEngine._instances.get(instanceKey);
|
|
25
|
+
throw new Error(existing.translate('Error_InstanceAlreadyExistsTemplate', {
|
|
26
|
+
key: instanceKey,
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
I18nEngine._instances.set(instanceKey, this);
|
|
30
|
+
if (!I18nEngine._defaultKey) {
|
|
31
|
+
I18nEngine._defaultKey = instanceKey;
|
|
32
|
+
}
|
|
33
|
+
// Initialize the default template processor
|
|
34
|
+
this.t = (0, template_1.createTemplateProcessor)(this.config.enumObj || {}, (key, vars, language) => this.translate(key, vars, language), this.config.enumName || 'StringKey');
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Gets an instance of the I18nEngine by key. If no key is provided, the default instance is returned.
|
|
38
|
+
* @param key The key of the instance to retrieve
|
|
39
|
+
* @returns The I18nEngine instance
|
|
40
|
+
* @throws Error if the instance with the provided key does not exist
|
|
41
|
+
*/
|
|
42
|
+
static getInstance(key) {
|
|
43
|
+
const instanceKey = key || I18nEngine._defaultKey || I18nEngine.DefaultInstanceKey;
|
|
44
|
+
if (!instanceKey || !I18nEngine._instances.has(instanceKey)) {
|
|
45
|
+
throw new Error(I18nEngine.getErrorMessage('Error_InstanceNotFoundTemplate', {
|
|
46
|
+
key: instanceKey,
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
return I18nEngine._instances.get(instanceKey);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Gets a translation for the provided error key using the specified instance (or default instance if none is provided).
|
|
53
|
+
* @param errorKey The error key to translate
|
|
54
|
+
* @param vars Variables to replace in the translation string
|
|
55
|
+
* @param instanceKey The key of the I18nEngine instance to use
|
|
56
|
+
* @param language The language to translate to
|
|
57
|
+
* @param fallbackLanguage The fallback language if the translation is not found
|
|
58
|
+
* @returns The translated error message
|
|
59
|
+
*/
|
|
60
|
+
static getErrorMessage(errorKey, vars, instanceKey, language, fallbackLanguage) {
|
|
61
|
+
try {
|
|
62
|
+
const instance = I18nEngine.getInstance(instanceKey);
|
|
63
|
+
return instance.translate(errorKey, vars, language, fallbackLanguage);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return `${errorKey}: ${JSON.stringify(vars || {})}`;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Throws an error with a translated message using the specified instance (or default instance if none is provided).
|
|
71
|
+
* @param errorKey The error key to translate
|
|
72
|
+
* @param vars Variables to replace in the translation string
|
|
73
|
+
* @param instanceKey The key of the I18nEngine instance to use
|
|
74
|
+
* @throws Error with translated message
|
|
75
|
+
*/
|
|
76
|
+
static throwError(errorKey, vars, instanceKey) {
|
|
77
|
+
throw new Error(I18nEngine.getErrorMessage(errorKey, vars, instanceKey));
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Gets the global context for translations
|
|
81
|
+
* @returns The global context object
|
|
82
|
+
*/
|
|
83
|
+
get context() {
|
|
84
|
+
return this._context;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Sets the global context for translations (used if no context is provided) for this instance
|
|
88
|
+
* @param context The context to set
|
|
89
|
+
*/
|
|
90
|
+
set context(context) {
|
|
91
|
+
this._context = { ...this._context, ...context };
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Translates a string key into the specified language, replacing any variables as needed.
|
|
95
|
+
* @param key The string key to translate
|
|
96
|
+
* @param vars Variables to replace in the translation string
|
|
97
|
+
* @param language The language to translate to
|
|
98
|
+
* @param fallbackLanguage The fallback language if the translation is not found
|
|
99
|
+
* @returns The translated string
|
|
100
|
+
*/
|
|
101
|
+
translate(key, vars, language, fallbackLanguage) {
|
|
102
|
+
const lang = language ??
|
|
103
|
+
(this._context.currentContext === 'admin'
|
|
104
|
+
? this._context.adminLanguage
|
|
105
|
+
: this._context.language);
|
|
106
|
+
const fallback = fallbackLanguage ?? this.config.defaultLanguage;
|
|
107
|
+
try {
|
|
108
|
+
const stringValue = this.getString(lang, key);
|
|
109
|
+
return (0, utils_1.isTemplate)(key)
|
|
110
|
+
? (0, utils_1.replaceVariables)(stringValue, vars, this.config.constants)
|
|
111
|
+
: stringValue;
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
if (lang !== fallback) {
|
|
115
|
+
try {
|
|
116
|
+
const stringValue = this.getString(fallback, key);
|
|
117
|
+
return (0, utils_1.isTemplate)(key)
|
|
118
|
+
? (0, utils_1.replaceVariables)(stringValue, vars, this.config.constants)
|
|
119
|
+
: stringValue;
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return key;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return key;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Translates an enumeration value into the specified language.
|
|
130
|
+
* @param enumObj The enumeration object
|
|
131
|
+
* @param value The enumeration value to translate
|
|
132
|
+
* @param language The language to translate to
|
|
133
|
+
* @returns The translated enumeration value
|
|
134
|
+
*/
|
|
135
|
+
translateEnum(enumObj, value, language) {
|
|
136
|
+
return this.enumRegistry.translate(enumObj, value, language);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Registers an enumeration and its translations with the engine.
|
|
140
|
+
* @param enumObj The enumeration object
|
|
141
|
+
* @param translations The translations for the enumeration
|
|
142
|
+
* @param enumName The name of the enumeration (for error messages)
|
|
143
|
+
*/
|
|
144
|
+
registerEnum(enumObj, translations, enumName) {
|
|
145
|
+
this.enumRegistry.register(enumObj, translations, enumName);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Safe translation that prevents infinite recursion for error messages
|
|
149
|
+
* @param key The string key to translate
|
|
150
|
+
* @param vars Variables to replace in the translation string
|
|
151
|
+
* @param language The language to translate to
|
|
152
|
+
* @returns The translated string or the key if translation fails
|
|
153
|
+
*/
|
|
154
|
+
safeTranslate(key, vars, language) {
|
|
155
|
+
try {
|
|
156
|
+
const lang = language ?? this.config.defaultLanguage;
|
|
157
|
+
const strings = this.config.strings[lang];
|
|
158
|
+
if (!strings?.[key])
|
|
159
|
+
return key;
|
|
160
|
+
const stringValue = strings[key];
|
|
161
|
+
return (0, utils_1.isTemplate)(key)
|
|
162
|
+
? (0, utils_1.replaceVariables)(stringValue, vars, this.config.constants)
|
|
163
|
+
: stringValue;
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
return key;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Retrieves the string for the given language and key, throwing an error if not found.
|
|
171
|
+
* @param language The language to get the string for
|
|
172
|
+
* @param key The string key to retrieve
|
|
173
|
+
* @returns The string value
|
|
174
|
+
* @throws Error if the language or string key is not found
|
|
175
|
+
*/
|
|
176
|
+
getString(language, key) {
|
|
177
|
+
const strings = this.config.strings[language];
|
|
178
|
+
if (!strings) {
|
|
179
|
+
throw new Error(this.safeTranslate('Error_LanguageNotFound', { language }) ||
|
|
180
|
+
`Language not found: ${language}`);
|
|
181
|
+
}
|
|
182
|
+
const value = strings[key];
|
|
183
|
+
if (!value) {
|
|
184
|
+
throw new Error(this.safeTranslate('Error_StringNotFound', { key }) ||
|
|
185
|
+
`String not found: ${key}`);
|
|
186
|
+
}
|
|
187
|
+
return value;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Gets the language code for the specified language.
|
|
191
|
+
* @param language The language to get the code for
|
|
192
|
+
* @returns The language code
|
|
193
|
+
*/
|
|
194
|
+
getLanguageCode(language) {
|
|
195
|
+
return this.config.languageCodes[language] || language;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Gets the language for the specified language code.
|
|
199
|
+
* @param code The language code to look up
|
|
200
|
+
* @returns The language, or undefined if not found
|
|
201
|
+
*/
|
|
202
|
+
getLanguageFromCode(code) {
|
|
203
|
+
for (const [lang, langCode] of Object.entries(this.config.languageCodes)) {
|
|
204
|
+
if (langCode === code) {
|
|
205
|
+
return lang;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Gets all language codes.
|
|
212
|
+
* @returns A record of all language codes
|
|
213
|
+
*/
|
|
214
|
+
getAllLanguageCodes() {
|
|
215
|
+
return this.config.languageCodes;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Gets all available languages.
|
|
219
|
+
* @returns An array of all available languages
|
|
220
|
+
*/
|
|
221
|
+
getAvailableLanguages() {
|
|
222
|
+
return Object.keys(this.config.strings);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Checks if a language is available.
|
|
226
|
+
* @param language The language to check
|
|
227
|
+
* @returns True if the language is available, false otherwise
|
|
228
|
+
*/
|
|
229
|
+
isLanguageAvailable(language) {
|
|
230
|
+
return Object.keys(this.config.strings).includes(language);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Clears all instances (for testing purposes)
|
|
234
|
+
* @internal
|
|
235
|
+
*/
|
|
236
|
+
static clearInstances() {
|
|
237
|
+
I18nEngine._instances.clear();
|
|
238
|
+
I18nEngine._defaultKey = null;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Removes a specific instance by key
|
|
242
|
+
* @param key The key of the instance to remove
|
|
243
|
+
* @internal
|
|
244
|
+
*/
|
|
245
|
+
static removeInstance(key) {
|
|
246
|
+
const instanceKey = key || I18nEngine.DefaultInstanceKey;
|
|
247
|
+
I18nEngine._instances.delete(instanceKey);
|
|
248
|
+
if (I18nEngine._defaultKey === instanceKey) {
|
|
249
|
+
const nextKey = I18nEngine._instances.keys().next().value;
|
|
250
|
+
I18nEngine._defaultKey =
|
|
251
|
+
I18nEngine._instances.size > 0 && nextKey ? nextKey : null;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
exports.I18nEngine = I18nEngine;
|
|
256
|
+
/**
|
|
257
|
+
* Static instances for semi-singleton pattern
|
|
258
|
+
*/
|
|
259
|
+
I18nEngine._instances = new Map();
|
|
260
|
+
/**
|
|
261
|
+
* Default instance key (first created instance)
|
|
262
|
+
*/
|
|
263
|
+
I18nEngine._defaultKey = null;
|
|
264
|
+
/**
|
|
265
|
+
* Default instance key if none is provided
|
|
266
|
+
*/
|
|
267
|
+
I18nEngine.DefaultInstanceKey = 'default';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from './active-context';
|
|
2
|
+
export * from './context';
|
|
3
|
+
export * from './context-manager';
|
|
4
|
+
export * from './currency';
|
|
5
|
+
export * from './currency-code';
|
|
6
|
+
export * from './currency-format';
|
|
7
|
+
export * from './enum-registry';
|
|
8
|
+
export * from './i18n-engine';
|
|
9
|
+
export * from './template';
|
|
10
|
+
export * from './timezone';
|
|
11
|
+
export * from './types';
|
|
12
|
+
export * from './utils';
|
|
13
|
+
export { I18nEngine as I18n } from './i18n-engine';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.I18n = void 0;
|
|
18
|
+
__exportStar(require("./active-context"), exports);
|
|
19
|
+
__exportStar(require("./context"), exports);
|
|
20
|
+
__exportStar(require("./context-manager"), exports);
|
|
21
|
+
__exportStar(require("./currency"), exports);
|
|
22
|
+
__exportStar(require("./currency-code"), exports);
|
|
23
|
+
__exportStar(require("./currency-format"), exports);
|
|
24
|
+
__exportStar(require("./enum-registry"), exports);
|
|
25
|
+
__exportStar(require("./i18n-engine"), exports);
|
|
26
|
+
__exportStar(require("./template"), exports);
|
|
27
|
+
__exportStar(require("./timezone"), exports);
|
|
28
|
+
__exportStar(require("./types"), exports);
|
|
29
|
+
__exportStar(require("./utils"), exports);
|
|
30
|
+
// Re-export for convenience
|
|
31
|
+
var i18n_engine_1 = require("./i18n-engine");
|
|
32
|
+
Object.defineProperty(exports, "I18n", { enumerable: true, get: function () { return i18n_engine_1.I18nEngine; } });
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template processing utilities for i18n
|
|
3
|
+
*/
|
|
4
|
+
export type EnumKeys<T> = keyof T;
|
|
5
|
+
/**
|
|
6
|
+
* Recursive type to validate that all enum keys in the template string exist in the provided enum type
|
|
7
|
+
*/
|
|
8
|
+
export type IsValidEnumTemplate<T extends string, TEnum> = T extends `${string}{{${string}.${infer Key}}}${infer Rest}` ? Key extends EnumKeys<TEnum> ? IsValidEnumTemplate<Rest, TEnum> : false : true;
|
|
9
|
+
/**
|
|
10
|
+
* Template function that processes {{EnumName.EnumKey}} patterns
|
|
11
|
+
*/
|
|
12
|
+
export declare function createTemplateProcessor<TEnum extends Record<string, string>, TLanguage extends string>(enumObj: TEnum, translateFn: (key: TEnum[keyof TEnum], vars?: Record<string, string | number>, language?: TLanguage) => string, enumName: string): <T extends string>(str: IsValidEnumTemplate<T, TEnum> extends true ? T : never, language?: TLanguage, ...otherVars: Record<string, string | number>[]) => string;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createTemplateProcessor = createTemplateProcessor;
|
|
4
|
+
/**
|
|
5
|
+
* Template function that processes {{EnumName.EnumKey}} patterns
|
|
6
|
+
*/
|
|
7
|
+
function createTemplateProcessor(enumObj, translateFn, enumName) {
|
|
8
|
+
return function t(str, language, ...otherVars) {
|
|
9
|
+
let varIndex = 0;
|
|
10
|
+
const pattern = new RegExp(`\\{\\{${enumName}\\.(\\w+)\\}\\}`, 'g');
|
|
11
|
+
// First replace enum patterns
|
|
12
|
+
let result = str.replace(pattern, (match, enumKey) => {
|
|
13
|
+
const enumValue = enumObj[enumKey];
|
|
14
|
+
if (!enumValue) {
|
|
15
|
+
return match; // Return original if enum key not found
|
|
16
|
+
}
|
|
17
|
+
const needsVars = enumValue
|
|
18
|
+
.toLowerCase()
|
|
19
|
+
.endsWith('template');
|
|
20
|
+
const vars = needsVars ? otherVars[varIndex++] ?? {} : {};
|
|
21
|
+
return translateFn(enumValue, vars, language);
|
|
22
|
+
});
|
|
23
|
+
// Then replace any remaining variables from all otherVars
|
|
24
|
+
const allVars = otherVars.reduce((acc, vars) => ({ ...acc, ...vars }), {});
|
|
25
|
+
result = result.replace(/\{(\w+)\}/g, (match, varName) => {
|
|
26
|
+
return allVars[varName] !== undefined ? String(allVars[varName]) : match;
|
|
27
|
+
});
|
|
28
|
+
return result;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Timezone = void 0;
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
/**
|
|
6
|
+
* Class representing a validated timezone.
|
|
7
|
+
*/
|
|
8
|
+
class Timezone {
|
|
9
|
+
constructor(timezone) {
|
|
10
|
+
if (!(0, utils_1.isValidTimezone)(timezone)) {
|
|
11
|
+
throw new Error(`Invalid timezone: ${timezone}`);
|
|
12
|
+
}
|
|
13
|
+
this._timezone = timezone;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Gets the timezone value.
|
|
17
|
+
*/
|
|
18
|
+
get value() {
|
|
19
|
+
return this._timezone;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.Timezone = Timezone;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { CurrencyCode } from './currency-code';
|
|
2
|
+
import { Timezone } from './timezone';
|
|
3
|
+
/**
|
|
4
|
+
* Standard language contexts
|
|
5
|
+
*/
|
|
6
|
+
export type LanguageContext = 'admin' | 'user' | 'system' | 'api';
|
|
7
|
+
/**
|
|
8
|
+
* Default currency code
|
|
9
|
+
*/
|
|
10
|
+
export declare const DefaultCurrencyCode: string;
|
|
11
|
+
/**
|
|
12
|
+
* Currency position type
|
|
13
|
+
*/
|
|
14
|
+
export type CurrencyPosition = 'prefix' | 'postfix' | 'infix';
|
|
15
|
+
/**
|
|
16
|
+
* Custom language context type
|
|
17
|
+
*/
|
|
18
|
+
export type CustomLanguageContext<T extends string = LanguageContext> = T;
|
|
19
|
+
/**
|
|
20
|
+
* Collection of localized strings for a specific language
|
|
21
|
+
*/
|
|
22
|
+
export type StringsCollection<TStringKey extends string> = Partial<Record<TStringKey, string>>;
|
|
23
|
+
/**
|
|
24
|
+
* Mapping of languages to their respective string collections
|
|
25
|
+
*/
|
|
26
|
+
export type MasterStringsCollection<TStringKey extends string, TLanguage extends string> = Partial<Record<TLanguage, StringsCollection<TStringKey>>>;
|
|
27
|
+
/**
|
|
28
|
+
* Mapping of language codes to their respective languages
|
|
29
|
+
*/
|
|
30
|
+
export type LanguageCodeCollection<TLanguage extends string> = Partial<Record<TLanguage, string>>;
|
|
31
|
+
/**
|
|
32
|
+
* Mapping of enumeration values to their translations in multiple languages
|
|
33
|
+
*/
|
|
34
|
+
export type EnumTranslationMap<TEnum extends string | number, TLanguage extends string> = Partial<Record<TLanguage, Partial<Record<TEnum, string>>>>;
|
|
35
|
+
/**
|
|
36
|
+
* I18n configuration interface
|
|
37
|
+
*/
|
|
38
|
+
export interface I18nConfig<TStringKey extends string, TLanguage extends string, TConstants extends Record<string, any> = Record<string, any>, TTranslationContext extends string = LanguageContext> {
|
|
39
|
+
stringNames: TStringKey[];
|
|
40
|
+
strings: MasterStringsCollection<TStringKey, TLanguage>;
|
|
41
|
+
defaultLanguage: TLanguage;
|
|
42
|
+
defaultTranslationContext: TTranslationContext;
|
|
43
|
+
defaultCurrencyCode: CurrencyCode;
|
|
44
|
+
languageCodes: LanguageCodeCollection<TLanguage>;
|
|
45
|
+
languages: TLanguage[];
|
|
46
|
+
constants?: TConstants;
|
|
47
|
+
enumName?: string;
|
|
48
|
+
enumObj?: Record<string, TStringKey>;
|
|
49
|
+
timezone: Timezone;
|
|
50
|
+
adminTimezone: Timezone;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* I18n context interface
|
|
54
|
+
*/
|
|
55
|
+
export interface I18nContext<TLanguage extends string, TTranslationContext extends string = LanguageContext> {
|
|
56
|
+
language: TLanguage;
|
|
57
|
+
adminLanguage: TLanguage;
|
|
58
|
+
currencyCode: CurrencyCode;
|
|
59
|
+
currentContext: TTranslationContext;
|
|
60
|
+
timezone: Timezone;
|
|
61
|
+
adminTimezone: Timezone;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Generic translation type for any enumeration
|
|
65
|
+
*/
|
|
66
|
+
export type EnumTranslation<T extends string | number> = {
|
|
67
|
+
[K in T]: string;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Generic language translation type for any enumeration
|
|
71
|
+
*/
|
|
72
|
+
export type EnumLanguageTranslation<T extends string | number, TLanguage extends string = string> = Partial<{
|
|
73
|
+
[L in TLanguage]: EnumTranslation<T>;
|
|
74
|
+
}>;
|
|
75
|
+
/**
|
|
76
|
+
* Helper function to create typed translations for an enumeration
|
|
77
|
+
*/
|
|
78
|
+
export declare function createTranslations<T extends string | number, TLanguage extends string>(translations: EnumLanguageTranslation<T, TLanguage>): EnumLanguageTranslation<T, TLanguage>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DefaultCurrencyCode = void 0;
|
|
4
|
+
exports.createTranslations = createTranslations;
|
|
5
|
+
/**
|
|
6
|
+
* Default currency code
|
|
7
|
+
*/
|
|
8
|
+
exports.DefaultCurrencyCode = 'USD';
|
|
9
|
+
/**
|
|
10
|
+
* Helper function to create typed translations for an enumeration
|
|
11
|
+
*/
|
|
12
|
+
function createTranslations(translations) {
|
|
13
|
+
return translations;
|
|
14
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Replaces variables in a string with their corresponding values from vars or constants.
|
|
3
|
+
* @param str - The string containing variables to replace
|
|
4
|
+
* @param vars - An object mapping variable names to their replacement values
|
|
5
|
+
* @param constants - An object containing constant values for replacement
|
|
6
|
+
* @returns The string with variables replaced
|
|
7
|
+
*/
|
|
8
|
+
export declare function replaceVariables(str: string, vars?: Record<string, string | number>, constants?: any): string;
|
|
9
|
+
/**
|
|
10
|
+
* Checks if a given key indicates a template string.
|
|
11
|
+
* @param key - The key to check
|
|
12
|
+
* @returns True if the key indicates a template, false otherwise
|
|
13
|
+
*/
|
|
14
|
+
export declare function isTemplate(key: string): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Checks if a given timezone string is valid.
|
|
17
|
+
* @param timezone - The timezone string to validate
|
|
18
|
+
* @returns
|
|
19
|
+
*/
|
|
20
|
+
export declare function isValidTimezone(timezone: string): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Converts parts to a single string key, joining with underscores.
|
|
23
|
+
* @param parts - The parts to join
|
|
24
|
+
* @returns The joined string key
|
|
25
|
+
*/
|
|
26
|
+
export declare function toStringKey<TStringKey extends string>(...parts: (string)[]): TStringKey;
|
|
27
|
+
/**
|
|
28
|
+
* Converts an enum value to a string key by joining parts with underscores and appending the enum value.
|
|
29
|
+
* @param enumObj - The enum object
|
|
30
|
+
* @param value - The enum value
|
|
31
|
+
* @param parts - Additional parts to join
|
|
32
|
+
* @returns The constructed string key
|
|
33
|
+
*/
|
|
34
|
+
export declare function toStringKeyFromEnum<TStringKey extends string, TEnum extends string>(value: TEnum[keyof TEnum], ...parts: (string)[]): TStringKey;
|
|
35
|
+
/**
|
|
36
|
+
* Builds a reason map from an enum object, mapping each enum value to a string key.
|
|
37
|
+
* @param enumObj - The enum object
|
|
38
|
+
* @param prefixes - Prefixes to prepend to each string key
|
|
39
|
+
* @returns The constructed reason map
|
|
40
|
+
*/
|
|
41
|
+
export declare function buildReasonMap<TStringKey extends string, TEnum extends Record<string, string>>(enumObj: TEnum, ...prefixes: string[]): Record<string, TStringKey>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.replaceVariables = replaceVariables;
|
|
7
|
+
exports.isTemplate = isTemplate;
|
|
8
|
+
exports.isValidTimezone = isValidTimezone;
|
|
9
|
+
exports.toStringKey = toStringKey;
|
|
10
|
+
exports.toStringKeyFromEnum = toStringKeyFromEnum;
|
|
11
|
+
exports.buildReasonMap = buildReasonMap;
|
|
12
|
+
const moment_timezone_1 = __importDefault(require("moment-timezone"));
|
|
13
|
+
/**
|
|
14
|
+
* Replaces variables in a string with their corresponding values from vars or constants.
|
|
15
|
+
* @param str - The string containing variables to replace
|
|
16
|
+
* @param vars - An object mapping variable names to their replacement values
|
|
17
|
+
* @param constants - An object containing constant values for replacement
|
|
18
|
+
* @returns The string with variables replaced
|
|
19
|
+
*/
|
|
20
|
+
function replaceVariables(str, vars, constants) {
|
|
21
|
+
const variables = str.match(/\{(.+?)\}/g);
|
|
22
|
+
if (!variables)
|
|
23
|
+
return str;
|
|
24
|
+
let result = str;
|
|
25
|
+
for (const variable of variables) {
|
|
26
|
+
const varName = variable.slice(1, -1);
|
|
27
|
+
let replacement = '';
|
|
28
|
+
if (vars && varName in vars) {
|
|
29
|
+
replacement = String(vars[varName]);
|
|
30
|
+
}
|
|
31
|
+
else if (constants && varName in constants) {
|
|
32
|
+
replacement = String(constants[varName]);
|
|
33
|
+
}
|
|
34
|
+
if (replacement) {
|
|
35
|
+
result = result.replace(variable, replacement);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Checks if a given key indicates a template string.
|
|
42
|
+
* @param key - The key to check
|
|
43
|
+
* @returns True if the key indicates a template, false otherwise
|
|
44
|
+
*/
|
|
45
|
+
function isTemplate(key) {
|
|
46
|
+
return key.trim().toLowerCase().endsWith('template');
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Checks if a given timezone string is valid.
|
|
50
|
+
* @param timezone - The timezone string to validate
|
|
51
|
+
* @returns
|
|
52
|
+
*/
|
|
53
|
+
function isValidTimezone(timezone) {
|
|
54
|
+
return moment_timezone_1.default.tz.zone(timezone) !== null;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Converts parts to a single string key, joining with underscores.
|
|
58
|
+
* @param parts - The parts to join
|
|
59
|
+
* @returns The joined string key
|
|
60
|
+
*/
|
|
61
|
+
function toStringKey(...parts) {
|
|
62
|
+
return parts.join('_');
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Converts an enum value to a string key by joining parts with underscores and appending the enum value.
|
|
66
|
+
* @param enumObj - The enum object
|
|
67
|
+
* @param value - The enum value
|
|
68
|
+
* @param parts - Additional parts to join
|
|
69
|
+
* @returns The constructed string key
|
|
70
|
+
*/
|
|
71
|
+
function toStringKeyFromEnum(value, ...parts) {
|
|
72
|
+
return parts.join('_') + '_' + String(value);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Builds a reason map from an enum object, mapping each enum value to a string key.
|
|
76
|
+
* @param enumObj - The enum object
|
|
77
|
+
* @param prefixes - Prefixes to prepend to each string key
|
|
78
|
+
* @returns The constructed reason map
|
|
79
|
+
*/
|
|
80
|
+
function buildReasonMap(enumObj, ...prefixes) {
|
|
81
|
+
return Object.values(enumObj).reduce((map, value) => {
|
|
82
|
+
map[value] = toStringKeyFromEnum(value, ...prefixes);
|
|
83
|
+
return map;
|
|
84
|
+
}, {});
|
|
85
|
+
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@digitaldefiance/i18n-lib",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.24",
|
|
4
4
|
"description": "Generic i18n library with enum translation support",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"build": "yarn tsc",
|
|
9
|
-
"test": "yarn jest",
|
|
9
|
+
"test": "yarn jest --detectOpenHandles",
|
|
10
10
|
"lint": "eslint src/**/*.ts tests/**/*.ts",
|
|
11
11
|
"lint:fix": "eslint src/**/*.ts tests/**/*.ts --fix",
|
|
12
12
|
"prettier:check": "prettier --check 'src/**/*.{ts,tsx}' 'tests/**/*.{ts,tsx}'",
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { StringLanguage } from './enumerations/string-language';
|
|
2
|
-
import { IActiveContext } from './interfaces/active-context';
|
|
3
|
-
import { CurrencyCode } from './interfaces/currency-code';
|
|
4
|
-
import { LanguageContext } from './shared-types';
|
|
5
|
-
import { Timezone } from '@digitaldefiance/i18n-lib';
|
|
6
|
-
export declare const GlobalActiveContext: IActiveContext;
|
|
7
|
-
export declare function setUserLanguage(language: StringLanguage): void;
|
|
8
|
-
export declare function setCurrencyCode(code: CurrencyCode): void;
|
|
9
|
-
/**
|
|
10
|
-
* Sets the admin language for console operations
|
|
11
|
-
* @param language The language to set for admin operations
|
|
12
|
-
*/
|
|
13
|
-
export declare function setAdminLanguage(language: StringLanguage): void;
|
|
14
|
-
/**
|
|
15
|
-
* Sets the language context for the current context
|
|
16
|
-
* @param context The language context to set
|
|
17
|
-
*/
|
|
18
|
-
export declare function setLanguageContext(context: LanguageContext): void;
|
|
19
|
-
export declare function setSystemContext(): void;
|
|
20
|
-
export declare function setApiContext(): void;
|
|
21
|
-
export declare function setUserTimezone(tz: Timezone): void;
|
|
22
|
-
export declare function setAdminTimezone(tz: Timezone): void;
|