locl-js 1.0.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +518 -0
- package/dist/LocL-fN9Yari8.d.mts +437 -0
- package/dist/LocL-fN9Yari8.d.ts +437 -0
- package/dist/compat.d.mts +44 -0
- package/dist/compat.d.ts +44 -0
- package/dist/compat.js +137 -0
- package/dist/compat.mjs +111 -0
- package/dist/index.d.mts +20 -341
- package/dist/index.d.ts +20 -341
- package/dist/index.js +288 -76
- package/dist/index.mjs +283 -73
- package/dist/react.d.mts +120 -0
- package/dist/react.d.ts +120 -0
- package/dist/react.js +228 -0
- package/dist/react.mjs +188 -0
- package/package.json +24 -1
- package/readme.md +0 -321
package/dist/index.js
CHANGED
|
@@ -18,11 +18,13 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
|
|
20
20
|
// src/index.ts
|
|
21
|
-
var
|
|
22
|
-
__export(
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
LocL: () => LocL,
|
|
24
|
+
defineResources: () => defineResources,
|
|
23
25
|
initLocL: () => initLocL
|
|
24
26
|
});
|
|
25
|
-
module.exports = __toCommonJS(
|
|
27
|
+
module.exports = __toCommonJS(src_exports);
|
|
26
28
|
|
|
27
29
|
// src/formatters.ts
|
|
28
30
|
var defaultFormatters = {
|
|
@@ -192,25 +194,26 @@ var LocL = class _LocL {
|
|
|
192
194
|
constructor(config) {
|
|
193
195
|
this.cache = /* @__PURE__ */ new Map();
|
|
194
196
|
this.proxyCache = /* @__PURE__ */ new WeakMap();
|
|
197
|
+
this.pluralRulesCache = /* @__PURE__ */ new Map();
|
|
198
|
+
this.subscribers = /* @__PURE__ */ new Set();
|
|
199
|
+
this.rootInstance = this;
|
|
195
200
|
if (!config.resources) {
|
|
196
201
|
throw new Error("[LocL] `resources` is required");
|
|
197
202
|
}
|
|
198
203
|
if (!config.fallbackLanguage) {
|
|
199
204
|
throw new Error("[LocL] `fallbackLanguage` is required");
|
|
200
205
|
}
|
|
201
|
-
config = {
|
|
206
|
+
this.config = {
|
|
202
207
|
useDefaultFormatters: true,
|
|
203
208
|
devMode: false,
|
|
204
209
|
useCache: true,
|
|
205
210
|
...config
|
|
206
211
|
};
|
|
207
|
-
|
|
208
|
-
this.config = config;
|
|
212
|
+
this.resources = { ...config.resources };
|
|
209
213
|
this.language = this.isLanguage(config.language) ?? config.fallbackLanguage;
|
|
210
214
|
this.fallbackLanguage = config.fallbackLanguage;
|
|
211
215
|
this.scope = config.scope;
|
|
212
|
-
this.
|
|
213
|
-
this.formatters = config.useDefaultFormatters ? { ...defaultFormatters, ...config.formatters ?? {} } : { ...config.formatters ?? {} };
|
|
216
|
+
this.formatters = this.config.useDefaultFormatters ? { ...defaultFormatters, ...config.formatters ?? {} } : { ...config.formatters ?? {} };
|
|
214
217
|
}
|
|
215
218
|
/**
|
|
216
219
|
* Creates a new proxy translator instance with a different configuration.
|
|
@@ -222,22 +225,39 @@ var LocL = class _LocL {
|
|
|
222
225
|
* @returns A new proxy `LocL` instance.
|
|
223
226
|
*/
|
|
224
227
|
withConfig(config) {
|
|
228
|
+
const root = this.rootInstance;
|
|
225
229
|
const cacheKey = `proxy::${config.language ?? this.language}::${Array.isArray(config.scope) ? config.scope.join("|") : config.scope ?? "*"}`;
|
|
226
|
-
if (
|
|
227
|
-
return
|
|
230
|
+
if (root.cache.has(cacheKey)) {
|
|
231
|
+
return root.cache.get(cacheKey);
|
|
228
232
|
}
|
|
229
|
-
const result = new Proxy(
|
|
230
|
-
get(target, prop) {
|
|
233
|
+
const result = new Proxy(root, {
|
|
234
|
+
get(target, prop, receiver) {
|
|
231
235
|
if (prop === "language") {
|
|
232
236
|
return config.language ?? target.language;
|
|
233
237
|
}
|
|
234
238
|
if (prop === "scope") {
|
|
235
|
-
return config.scope;
|
|
239
|
+
return config.scope !== void 0 ? config.scope : target.scope;
|
|
240
|
+
}
|
|
241
|
+
if (prop === "rootInstance") {
|
|
242
|
+
return target;
|
|
243
|
+
}
|
|
244
|
+
if (prop === "subscribe" && config.language !== void 0) {
|
|
245
|
+
return (listener) => {
|
|
246
|
+
try {
|
|
247
|
+
listener(config.language, config.language);
|
|
248
|
+
} catch (err) {
|
|
249
|
+
console.error("[LocL] Error in subscriber:", err);
|
|
250
|
+
}
|
|
251
|
+
return () => {
|
|
252
|
+
};
|
|
253
|
+
};
|
|
236
254
|
}
|
|
237
|
-
return target
|
|
255
|
+
return Reflect.get(target, prop, receiver);
|
|
238
256
|
}
|
|
239
257
|
});
|
|
240
|
-
|
|
258
|
+
if (root.config.useCache) {
|
|
259
|
+
root.cache.set(cacheKey, result);
|
|
260
|
+
}
|
|
241
261
|
return result;
|
|
242
262
|
}
|
|
243
263
|
/**
|
|
@@ -249,18 +269,106 @@ var LocL = class _LocL {
|
|
|
249
269
|
clone(language = this.language, scope) {
|
|
250
270
|
return new _LocL({
|
|
251
271
|
...this.config,
|
|
272
|
+
resources: this.resources,
|
|
252
273
|
language,
|
|
253
274
|
scope
|
|
254
275
|
});
|
|
255
276
|
}
|
|
277
|
+
/**
|
|
278
|
+
* Subscribes a listener to language changes.
|
|
279
|
+
* Conforms to the standard reactive store contract (e.g. Svelte stores).
|
|
280
|
+
* Calls the listener immediately with the current language and returns an unsubscribe function.
|
|
281
|
+
* @param listener - The subscriber callback function.
|
|
282
|
+
* @returns An unsubscribe function.
|
|
283
|
+
*/
|
|
284
|
+
subscribe(listener) {
|
|
285
|
+
this.subscribers.add(listener);
|
|
286
|
+
try {
|
|
287
|
+
listener(this.language, this.language);
|
|
288
|
+
} catch (err) {
|
|
289
|
+
console.error("[LocL] Error in initial subscriber call:", err);
|
|
290
|
+
}
|
|
291
|
+
return () => {
|
|
292
|
+
this.subscribers.delete(listener);
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Gets the current active language.
|
|
297
|
+
*/
|
|
298
|
+
getLanguage() {
|
|
299
|
+
return this.language;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Adds or overrides a single translation key at runtime.
|
|
303
|
+
* @param lang - Target language code.
|
|
304
|
+
* @param key - Dotted path key.
|
|
305
|
+
* @param value - The translation value.
|
|
306
|
+
*/
|
|
307
|
+
addResource(lang, key, value) {
|
|
308
|
+
if (!this.resources[lang]) {
|
|
309
|
+
this.resources[lang] = {};
|
|
310
|
+
}
|
|
311
|
+
const keys = key.split(".");
|
|
312
|
+
let current = this.resources[lang];
|
|
313
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
314
|
+
const k = keys[i];
|
|
315
|
+
if (k === "__proto__" || k === "constructor" || k === "prototype") {
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
if (!current[k] || typeof current[k] !== "object") {
|
|
319
|
+
current[k] = {};
|
|
320
|
+
}
|
|
321
|
+
current = current[k];
|
|
322
|
+
}
|
|
323
|
+
const lastKey = keys[keys.length - 1];
|
|
324
|
+
if (lastKey !== "__proto__" && lastKey !== "constructor" && lastKey !== "prototype") {
|
|
325
|
+
current[lastKey] = value;
|
|
326
|
+
}
|
|
327
|
+
this.invalidateCacheForLang(lang);
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Deeply merges a resource bundle into the specified language at runtime.
|
|
331
|
+
* @param lang - Target language code.
|
|
332
|
+
* @param bundle - Object of translations to merge.
|
|
333
|
+
*/
|
|
334
|
+
addResources(lang, bundle) {
|
|
335
|
+
if (!this.resources[lang]) {
|
|
336
|
+
this.resources[lang] = {};
|
|
337
|
+
}
|
|
338
|
+
const deepMerge = (target, source) => {
|
|
339
|
+
for (const k of Object.keys(source)) {
|
|
340
|
+
if (k === "__proto__" || k === "constructor" || k === "prototype") {
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
if (source[k] && typeof source[k] === "object" && !Array.isArray(source[k])) {
|
|
344
|
+
if (!target[k] || typeof target[k] !== "object") {
|
|
345
|
+
target[k] = {};
|
|
346
|
+
}
|
|
347
|
+
deepMerge(target[k], source[k]);
|
|
348
|
+
} else {
|
|
349
|
+
target[k] = source[k];
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
deepMerge(this.resources[lang], bundle);
|
|
354
|
+
this.invalidateCacheForLang(lang);
|
|
355
|
+
}
|
|
256
356
|
/**
|
|
257
357
|
* Changes the current language of the translator.
|
|
258
358
|
* @param lang - The new language to set.
|
|
259
359
|
*/
|
|
260
360
|
changeLanguage(lang) {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
361
|
+
const validated = this.isLanguage(lang);
|
|
362
|
+
if (validated && validated !== this.language) {
|
|
363
|
+
const prev = this.language;
|
|
364
|
+
this.language = validated;
|
|
365
|
+
for (const sub of this.subscribers) {
|
|
366
|
+
try {
|
|
367
|
+
sub(this.language, prev);
|
|
368
|
+
} catch (err) {
|
|
369
|
+
console.error("[LocL] Error in subscriber:", err);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
264
372
|
}
|
|
265
373
|
}
|
|
266
374
|
t(key, values, format) {
|
|
@@ -269,6 +377,9 @@ var LocL = class _LocL {
|
|
|
269
377
|
}
|
|
270
378
|
const pluralCheckResult = this.checkPlural(key, values);
|
|
271
379
|
if (pluralCheckResult !== void 0) {
|
|
380
|
+
if (format && format.formatter) {
|
|
381
|
+
return this.applyFormat(pluralCheckResult, format.formatter, format.args);
|
|
382
|
+
}
|
|
272
383
|
return pluralCheckResult;
|
|
273
384
|
}
|
|
274
385
|
const result = this.lookupWithFallback(key);
|
|
@@ -299,45 +410,54 @@ var LocL = class _LocL {
|
|
|
299
410
|
format(value, formatter, args) {
|
|
300
411
|
return this.applyFormat(value, formatter, args);
|
|
301
412
|
}
|
|
413
|
+
plural(key, values, format) {
|
|
414
|
+
return this.t(key, values, format);
|
|
415
|
+
}
|
|
302
416
|
/**
|
|
303
|
-
* Translates a key
|
|
304
|
-
*
|
|
305
|
-
* @param key - The
|
|
306
|
-
* @param
|
|
307
|
-
* @param
|
|
308
|
-
* @returns
|
|
417
|
+
* Translates a key and interpolates rich elements using tag functions.
|
|
418
|
+
* Matches `<tag>content</tag>` in translation templates.
|
|
419
|
+
* @param key - The key to translate.
|
|
420
|
+
* @param tags - An object mapping tag names to functions that transform their inner content.
|
|
421
|
+
* @param values - Values to interpolate into variable placeholders ({name}, {{name}}).
|
|
422
|
+
* @returns An array of chunks (strings and custom rendered tag values).
|
|
423
|
+
* @example
|
|
424
|
+
* ```ts
|
|
425
|
+
* translator.rich("terms", {
|
|
426
|
+
* link: (content) => `<a href="/terms">${content}</a>`
|
|
427
|
+
* }, { name: "Alice" });
|
|
428
|
+
* ```
|
|
309
429
|
*/
|
|
310
|
-
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
this.config.devMode && console.warn(`[LocL] Missing plural: "${baseKey}" in "${this.language}"`);
|
|
323
|
-
interpolated = baseKey;
|
|
430
|
+
rich(key, tags, values) {
|
|
431
|
+
const rawStr = this.t(key, values);
|
|
432
|
+
if (typeof rawStr !== "string") {
|
|
433
|
+
return [rawStr];
|
|
434
|
+
}
|
|
435
|
+
const tagRegex = /<([a-zA-Z0-9_-]+)>([\s\S]*?)<\/\1>/g;
|
|
436
|
+
const result = [];
|
|
437
|
+
let lastIndex = 0;
|
|
438
|
+
let match;
|
|
439
|
+
while ((match = tagRegex.exec(rawStr)) !== null) {
|
|
440
|
+
if (match.index > lastIndex) {
|
|
441
|
+
result.push(rawStr.slice(lastIndex, match.index));
|
|
324
442
|
}
|
|
325
|
-
|
|
326
|
-
const
|
|
327
|
-
const
|
|
328
|
-
|
|
443
|
+
const tagName = match[1];
|
|
444
|
+
const content = match[2];
|
|
445
|
+
const renderer = tags[tagName];
|
|
446
|
+
typeof renderer === "function" ? result.push(renderer(content)) : result.push(match[0]);
|
|
447
|
+
lastIndex = match.index + match[0].length;
|
|
329
448
|
}
|
|
330
|
-
if (
|
|
331
|
-
|
|
449
|
+
if (lastIndex < rawStr.length) {
|
|
450
|
+
result.push(rawStr.slice(lastIndex));
|
|
332
451
|
}
|
|
333
|
-
return
|
|
452
|
+
return result;
|
|
334
453
|
}
|
|
335
454
|
get(key) {
|
|
336
455
|
const base = this.buildTranslationObject(this.language);
|
|
337
456
|
if (!key) {
|
|
338
|
-
return base;
|
|
457
|
+
return base ? this.makeReadOnly(base) : void 0;
|
|
339
458
|
}
|
|
340
|
-
|
|
459
|
+
const val = this.lookupWithFallback(key, base);
|
|
460
|
+
return val && typeof val === "object" ? this.makeReadOnly(val) : val;
|
|
341
461
|
}
|
|
342
462
|
/**
|
|
343
463
|
* Gets a nested object from the translations.
|
|
@@ -352,12 +472,27 @@ var LocL = class _LocL {
|
|
|
352
472
|
if (!value) {
|
|
353
473
|
return null;
|
|
354
474
|
}
|
|
355
|
-
const
|
|
356
|
-
|
|
475
|
+
const available = Object.keys(this.resources);
|
|
476
|
+
if (available.includes(value)) {
|
|
477
|
+
return value;
|
|
478
|
+
}
|
|
479
|
+
const prefix = value.substring(0, 2);
|
|
480
|
+
if (available.includes(prefix)) {
|
|
481
|
+
return prefix;
|
|
482
|
+
}
|
|
483
|
+
return null;
|
|
357
484
|
}
|
|
358
485
|
getCacheKey(language) {
|
|
359
|
-
const scopeKey = Array.isArray(this.scope) ? this.scope.join("|") : this.scope
|
|
360
|
-
return `${language
|
|
486
|
+
const scopeKey = Array.isArray(this.scope) ? this.scope.join("|") : this.scope;
|
|
487
|
+
return `${language}::${scopeKey}`;
|
|
488
|
+
}
|
|
489
|
+
invalidateCacheForLang(lang) {
|
|
490
|
+
const prefix = `${lang}::`;
|
|
491
|
+
for (const key of this.cache.keys()) {
|
|
492
|
+
if (key.startsWith(prefix)) {
|
|
493
|
+
this.cache.delete(key);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
361
496
|
}
|
|
362
497
|
lookupWithFallback(key, base) {
|
|
363
498
|
const keys = key.split(".");
|
|
@@ -375,7 +510,7 @@ var LocL = class _LocL {
|
|
|
375
510
|
return result;
|
|
376
511
|
}
|
|
377
512
|
buildTranslationObject(language) {
|
|
378
|
-
const langObject = this.
|
|
513
|
+
const langObject = this.resources[language];
|
|
379
514
|
if (!this.scope) {
|
|
380
515
|
return langObject;
|
|
381
516
|
}
|
|
@@ -406,11 +541,10 @@ var LocL = class _LocL {
|
|
|
406
541
|
}, combined);
|
|
407
542
|
}
|
|
408
543
|
}
|
|
409
|
-
const roCombined = this.makeReadOnly(combined);
|
|
410
544
|
if (this.config.useCache) {
|
|
411
|
-
this.cache.set(cacheKey,
|
|
545
|
+
this.cache.set(cacheKey, combined);
|
|
412
546
|
}
|
|
413
|
-
return
|
|
547
|
+
return combined;
|
|
414
548
|
}
|
|
415
549
|
if (this.config.useCache) {
|
|
416
550
|
this.cache.set(cacheKey, void 0);
|
|
@@ -440,13 +574,54 @@ var LocL = class _LocL {
|
|
|
440
574
|
}
|
|
441
575
|
return current;
|
|
442
576
|
}
|
|
577
|
+
getPluralRules(lang) {
|
|
578
|
+
let rules = this.pluralRulesCache.get(lang);
|
|
579
|
+
if (!rules) {
|
|
580
|
+
rules = new Intl.PluralRules(lang);
|
|
581
|
+
this.pluralRulesCache.set(lang, rules);
|
|
582
|
+
}
|
|
583
|
+
return rules;
|
|
584
|
+
}
|
|
443
585
|
checkPlural(key, values) {
|
|
444
|
-
if (values?.count !== void 0 && !key.match(/_(one|few|many|other)$/)) {
|
|
445
|
-
const category = this.
|
|
446
|
-
const
|
|
447
|
-
|
|
448
|
-
|
|
586
|
+
if (values?.count !== void 0 && !key.match(/_(zero|one|two|few|many|other)$/)) {
|
|
587
|
+
const category = this.getPluralRules(this.language).select(values.count);
|
|
588
|
+
const baseValue = this.lookupWithFallback(key, void 0);
|
|
589
|
+
if (baseValue && typeof baseValue === "object") {
|
|
590
|
+
if (values.count === 0 && "zero" in baseValue) {
|
|
591
|
+
return this.interpolate(baseValue.zero, values);
|
|
592
|
+
}
|
|
593
|
+
if (category in baseValue) {
|
|
594
|
+
return this.interpolate(baseValue[category], values);
|
|
595
|
+
} else if ("other" in baseValue) {
|
|
596
|
+
this.config.devMode && console.warn(`[LocL] Missing plural: "${key}" in "${this.language}"`);
|
|
597
|
+
return this.interpolate(baseValue.other, values);
|
|
598
|
+
} else {
|
|
599
|
+
this.config.devMode && console.warn(`[LocL] Missing plural: "${key}" in "${this.language}"`);
|
|
600
|
+
return key;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
if (values.count === 0) {
|
|
604
|
+
const zeroResult = this.lookupWithFallback(`${key}_zero`, void 0);
|
|
605
|
+
if (zeroResult !== void 0) {
|
|
606
|
+
return this.interpolate(zeroResult, values);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
const categoryResult = this.lookupWithFallback(`${key}_${category}`, void 0);
|
|
610
|
+
if (categoryResult !== void 0) {
|
|
611
|
+
return this.interpolate(categoryResult, values);
|
|
612
|
+
}
|
|
613
|
+
const otherResult = this.lookupWithFallback(`${key}_other`, void 0);
|
|
614
|
+
if (otherResult !== void 0) {
|
|
615
|
+
this.config.devMode && console.warn(`[LocL] Missing plural: "${key}" in "${this.language}"`);
|
|
616
|
+
return this.interpolate(otherResult, values);
|
|
617
|
+
}
|
|
618
|
+
const anySuffixExists = ["zero", "one", "two", "few", "many"].some((cat) => this.lookupWithFallback(`${key}_${cat}`, void 0) !== void 0);
|
|
619
|
+
if (anySuffixExists) {
|
|
620
|
+
this.config.devMode && console.warn(`[LocL] Missing plural: "${key}" in "${this.language}"`);
|
|
621
|
+
return key;
|
|
622
|
+
}
|
|
449
623
|
}
|
|
624
|
+
return void 0;
|
|
450
625
|
}
|
|
451
626
|
interpolate(result, values) {
|
|
452
627
|
if (!values || typeof result !== "string") {
|
|
@@ -464,34 +639,66 @@ var LocL = class _LocL {
|
|
|
464
639
|
depth--;
|
|
465
640
|
if (depth === 0 && start >= 0) {
|
|
466
641
|
const raw = result.slice(start, i + 1);
|
|
467
|
-
|
|
642
|
+
let inner = raw.slice(1, -1);
|
|
643
|
+
if (inner.startsWith("{") && inner.endsWith("}")) {
|
|
644
|
+
inner = inner.slice(1, -1);
|
|
645
|
+
}
|
|
646
|
+
tokens.push({ raw, inner });
|
|
468
647
|
start = -1;
|
|
469
648
|
}
|
|
470
649
|
}
|
|
471
650
|
}
|
|
472
651
|
let output = result;
|
|
652
|
+
const processed = /* @__PURE__ */ new Set();
|
|
473
653
|
for (const token of tokens) {
|
|
654
|
+
if (processed.has(token.raw)) {
|
|
655
|
+
continue;
|
|
656
|
+
}
|
|
657
|
+
processed.add(token.raw);
|
|
474
658
|
let replacement = "";
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
659
|
+
const selectMatch = token.inner.match(/^\s*([^,]+),\s*select\s*,\s*([\s\S]+)$/);
|
|
660
|
+
if (selectMatch) {
|
|
661
|
+
const field = selectMatch[1].trim();
|
|
662
|
+
const casesBody = selectMatch[2];
|
|
663
|
+
const value = String(values[field] ?? "other");
|
|
664
|
+
const caseMap = {};
|
|
665
|
+
let i = 0;
|
|
666
|
+
while (i < casesBody.length) {
|
|
667
|
+
while (i < casesBody.length && /\s/.test(casesBody[i])) i++;
|
|
668
|
+
if (i >= casesBody.length) break;
|
|
669
|
+
let keyStart = i;
|
|
670
|
+
while (i < casesBody.length && casesBody[i] !== "{" && !/\s/.test(casesBody[i])) i++;
|
|
671
|
+
const caseKey = casesBody.slice(keyStart, i).trim();
|
|
672
|
+
while (i < casesBody.length && casesBody[i] !== "{") i++;
|
|
673
|
+
if (casesBody[i] === "{") {
|
|
674
|
+
let bodyDepth = 1;
|
|
675
|
+
let bodyStart = i + 1;
|
|
676
|
+
i++;
|
|
677
|
+
while (i < casesBody.length && bodyDepth > 0) {
|
|
678
|
+
if (casesBody[i] === "{") bodyDepth++;
|
|
679
|
+
else if (casesBody[i] === "}") bodyDepth--;
|
|
680
|
+
i++;
|
|
681
|
+
}
|
|
682
|
+
const caseText = casesBody.slice(bodyStart, i - 1).trim();
|
|
683
|
+
if (caseKey) {
|
|
684
|
+
caseMap[caseKey] = caseText;
|
|
685
|
+
}
|
|
485
686
|
}
|
|
486
|
-
replacement = caseMap[value] ?? caseMap.other ?? "";
|
|
487
687
|
}
|
|
688
|
+
const rawReplacement = caseMap[value] ?? caseMap.other ?? "";
|
|
689
|
+
replacement = rawReplacement.includes("{") ? this.interpolate(rawReplacement, values) : rawReplacement;
|
|
488
690
|
} else {
|
|
489
691
|
const [fieldName, formatterAndArgs] = token.inner.split("|").map((x) => x.trim());
|
|
490
692
|
const [formatterName, argsStr] = formatterAndArgs ? formatterAndArgs.split(":") : [];
|
|
491
|
-
const args = argsStr ? argsStr.split(",") : [];
|
|
693
|
+
const args = argsStr ? argsStr.split(",").map((a) => a.trim()) : [];
|
|
492
694
|
const val = values[fieldName];
|
|
493
|
-
if (formatterName
|
|
494
|
-
|
|
695
|
+
if (formatterName) {
|
|
696
|
+
if (this.formatters?.[formatterName]) {
|
|
697
|
+
replacement = this.formatters[formatterName](val, args);
|
|
698
|
+
} else {
|
|
699
|
+
this.config.devMode && console.warn(`[LocL] Formatter "${formatterName}" not found.`);
|
|
700
|
+
replacement = val !== void 0 ? String(val) : token.raw;
|
|
701
|
+
}
|
|
495
702
|
} else if (val instanceof Date) {
|
|
496
703
|
replacement = new Intl.DateTimeFormat(this.language).format(val);
|
|
497
704
|
} else if (typeof val === "number") {
|
|
@@ -500,7 +707,7 @@ var LocL = class _LocL {
|
|
|
500
707
|
replacement = val !== void 0 ? String(val) : token.raw;
|
|
501
708
|
}
|
|
502
709
|
}
|
|
503
|
-
output = output.
|
|
710
|
+
output = output.split(token.raw).join(replacement);
|
|
504
711
|
}
|
|
505
712
|
return output;
|
|
506
713
|
}
|
|
@@ -536,7 +743,12 @@ var LocL = class _LocL {
|
|
|
536
743
|
function initLocL(config) {
|
|
537
744
|
return new LocL(config);
|
|
538
745
|
}
|
|
746
|
+
function defineResources(resources) {
|
|
747
|
+
return resources;
|
|
748
|
+
}
|
|
539
749
|
// Annotate the CommonJS export names for ESM import in node:
|
|
540
750
|
0 && (module.exports = {
|
|
751
|
+
LocL,
|
|
752
|
+
defineResources,
|
|
541
753
|
initLocL
|
|
542
754
|
});
|