@fkui/i18next-translate 6.39.0 → 6.41.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/dist/cjs/index.js +88 -90
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +88 -90
- package/dist/esm/index.js.map +1 -1
- package/dist/types/tsdoc-metadata.json +1 -1
- package/package.json +5 -5
package/dist/esm/index.js
CHANGED
|
@@ -2078,7 +2078,7 @@ const defer = () => {
|
|
|
2078
2078
|
};
|
|
2079
2079
|
const makeString = object => {
|
|
2080
2080
|
if (object == null) return '';
|
|
2081
|
-
return
|
|
2081
|
+
return String(object);
|
|
2082
2082
|
};
|
|
2083
2083
|
const copy = (a, s, t) => {
|
|
2084
2084
|
a.forEach(m => {
|
|
@@ -2086,7 +2086,7 @@ const copy = (a, s, t) => {
|
|
|
2086
2086
|
});
|
|
2087
2087
|
};
|
|
2088
2088
|
const lastOfPathSeparatorRegExp = /###/g;
|
|
2089
|
-
const cleanKey = key => key && key.
|
|
2089
|
+
const cleanKey = key => key && key.includes('###') ? key.replace(lastOfPathSeparatorRegExp, '.') : key;
|
|
2090
2090
|
const canNotTraverseDeeper = object => !object || isString(object);
|
|
2091
2091
|
const getLastOfPath = (object, path, Empty) => {
|
|
2092
2092
|
const stack = !isString(path) ? path : path.split('.');
|
|
@@ -2171,7 +2171,7 @@ const deepExtend = (target, source, overwrite) => {
|
|
|
2171
2171
|
return target;
|
|
2172
2172
|
};
|
|
2173
2173
|
const regexEscape = str => str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
|
|
2174
|
-
|
|
2174
|
+
const _entityMap = {
|
|
2175
2175
|
'&': '&',
|
|
2176
2176
|
'<': '<',
|
|
2177
2177
|
'>': '>',
|
|
@@ -2210,7 +2210,7 @@ const looksLikeObjectPathRegExpCache = new RegExpCache(20);
|
|
|
2210
2210
|
const looksLikeObjectPath = (key, nsSeparator, keySeparator) => {
|
|
2211
2211
|
nsSeparator = nsSeparator || '';
|
|
2212
2212
|
keySeparator = keySeparator || '';
|
|
2213
|
-
const possibleChars = chars.filter(c => nsSeparator.
|
|
2213
|
+
const possibleChars = chars.filter(c => !nsSeparator.includes(c) && !keySeparator.includes(c));
|
|
2214
2214
|
if (possibleChars.length === 0) return true;
|
|
2215
2215
|
const r = looksLikeObjectPathRegExpCache.getRegExp(`(${possibleChars.map(c => c === '?' ? '\\?' : c).join('|')})`);
|
|
2216
2216
|
let matched = !r.test(key);
|
|
@@ -2243,7 +2243,7 @@ const deepFind = (obj, path, keySeparator = '.') => {
|
|
|
2243
2243
|
nextPath += tokens[j];
|
|
2244
2244
|
next = current[nextPath];
|
|
2245
2245
|
if (next !== undefined) {
|
|
2246
|
-
if (['string', 'number', 'boolean'].
|
|
2246
|
+
if (['string', 'number', 'boolean'].includes(typeof next) && j < tokens.length - 1) {
|
|
2247
2247
|
continue;
|
|
2248
2248
|
}
|
|
2249
2249
|
i += j - i + 1;
|
|
@@ -2334,6 +2334,14 @@ class EventEmitter {
|
|
|
2334
2334
|
}
|
|
2335
2335
|
this.observers[event].delete(listener);
|
|
2336
2336
|
}
|
|
2337
|
+
once(event, listener) {
|
|
2338
|
+
const wrapper = (...args) => {
|
|
2339
|
+
listener(...args);
|
|
2340
|
+
this.off(event, wrapper);
|
|
2341
|
+
};
|
|
2342
|
+
this.on(event, wrapper);
|
|
2343
|
+
return this;
|
|
2344
|
+
}
|
|
2337
2345
|
emit(event, ...args) {
|
|
2338
2346
|
if (this.observers[event]) {
|
|
2339
2347
|
const cloned = Array.from(this.observers[event].entries());
|
|
@@ -2347,7 +2355,7 @@ class EventEmitter {
|
|
|
2347
2355
|
const cloned = Array.from(this.observers['*'].entries());
|
|
2348
2356
|
cloned.forEach(([observer, numTimesAdded]) => {
|
|
2349
2357
|
for (let i = 0; i < numTimesAdded; i++) {
|
|
2350
|
-
observer
|
|
2358
|
+
observer(event, ...args);
|
|
2351
2359
|
}
|
|
2352
2360
|
});
|
|
2353
2361
|
}
|
|
@@ -2370,7 +2378,7 @@ class ResourceStore extends EventEmitter {
|
|
|
2370
2378
|
}
|
|
2371
2379
|
}
|
|
2372
2380
|
addNamespaces(ns) {
|
|
2373
|
-
if (this.options.ns.
|
|
2381
|
+
if (!this.options.ns.includes(ns)) {
|
|
2374
2382
|
this.options.ns.push(ns);
|
|
2375
2383
|
}
|
|
2376
2384
|
}
|
|
@@ -2384,7 +2392,7 @@ class ResourceStore extends EventEmitter {
|
|
|
2384
2392
|
const keySeparator = options.keySeparator !== undefined ? options.keySeparator : this.options.keySeparator;
|
|
2385
2393
|
const ignoreJSONStructure = options.ignoreJSONStructure !== undefined ? options.ignoreJSONStructure : this.options.ignoreJSONStructure;
|
|
2386
2394
|
let path;
|
|
2387
|
-
if (lng.
|
|
2395
|
+
if (lng.includes('.')) {
|
|
2388
2396
|
path = lng.split('.');
|
|
2389
2397
|
} else {
|
|
2390
2398
|
path = [lng, ns];
|
|
@@ -2399,7 +2407,7 @@ class ResourceStore extends EventEmitter {
|
|
|
2399
2407
|
}
|
|
2400
2408
|
}
|
|
2401
2409
|
const result = getPath(this.data, path);
|
|
2402
|
-
if (!result && !ns && !key && lng.
|
|
2410
|
+
if (!result && !ns && !key && lng.includes('.')) {
|
|
2403
2411
|
lng = path[0];
|
|
2404
2412
|
ns = path[1];
|
|
2405
2413
|
key = path.slice(2).join('.');
|
|
@@ -2413,7 +2421,7 @@ class ResourceStore extends EventEmitter {
|
|
|
2413
2421
|
const keySeparator = options.keySeparator !== undefined ? options.keySeparator : this.options.keySeparator;
|
|
2414
2422
|
let path = [lng, ns];
|
|
2415
2423
|
if (key) path = path.concat(keySeparator ? key.split(keySeparator) : key);
|
|
2416
|
-
if (lng.
|
|
2424
|
+
if (lng.includes('.')) {
|
|
2417
2425
|
path = lng.split('.');
|
|
2418
2426
|
value = ns;
|
|
2419
2427
|
ns = path[1];
|
|
@@ -2437,7 +2445,7 @@ class ResourceStore extends EventEmitter {
|
|
|
2437
2445
|
skipCopy: false
|
|
2438
2446
|
}) {
|
|
2439
2447
|
let path = [lng, ns];
|
|
2440
|
-
if (lng.
|
|
2448
|
+
if (lng.includes('.')) {
|
|
2441
2449
|
path = lng.split('.');
|
|
2442
2450
|
deep = resources;
|
|
2443
2451
|
resources = ns;
|
|
@@ -2515,10 +2523,18 @@ function keysFromSelector(selector, opts) {
|
|
|
2515
2523
|
const {
|
|
2516
2524
|
[PATH_KEY]: path
|
|
2517
2525
|
} = selector(createProxy());
|
|
2518
|
-
|
|
2526
|
+
const keySeparator = opts?.keySeparator ?? '.';
|
|
2527
|
+
const nsSeparator = opts?.nsSeparator ?? ':';
|
|
2528
|
+
if (path.length > 1 && nsSeparator) {
|
|
2529
|
+
const ns = opts?.ns;
|
|
2530
|
+
const nsArray = Array.isArray(ns) ? ns : null;
|
|
2531
|
+
if (nsArray && nsArray.length > 1 && nsArray.slice(1).includes(path[0])) {
|
|
2532
|
+
return `${path[0]}${nsSeparator}${path.slice(1).join(keySeparator)}`;
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
return path.join(keySeparator);
|
|
2519
2536
|
}
|
|
2520
2537
|
|
|
2521
|
-
const checkedLoadedFor = {};
|
|
2522
2538
|
const shouldHandleAsObject = res => !isString(res) && typeof res !== 'boolean' && typeof res !== 'number';
|
|
2523
2539
|
class Translator extends EventEmitter {
|
|
2524
2540
|
constructor(services, options = {}) {
|
|
@@ -2529,6 +2545,7 @@ class Translator extends EventEmitter {
|
|
|
2529
2545
|
this.options.keySeparator = '.';
|
|
2530
2546
|
}
|
|
2531
2547
|
this.logger = baseLogger.create('translator');
|
|
2548
|
+
this.checkedLoadedFor = {};
|
|
2532
2549
|
}
|
|
2533
2550
|
changeLanguage(lng) {
|
|
2534
2551
|
if (lng) this.language = lng;
|
|
@@ -2553,7 +2570,7 @@ class Translator extends EventEmitter {
|
|
|
2553
2570
|
if (nsSeparator === undefined) nsSeparator = ':';
|
|
2554
2571
|
const keySeparator = opt.keySeparator !== undefined ? opt.keySeparator : this.options.keySeparator;
|
|
2555
2572
|
let namespaces = opt.ns || this.options.defaultNS || [];
|
|
2556
|
-
const wouldCheckForNsInKey = nsSeparator && key.
|
|
2573
|
+
const wouldCheckForNsInKey = nsSeparator && key.includes(nsSeparator);
|
|
2557
2574
|
const seemsNaturalLanguage = !this.options.userDefinedKeySeparator && !opt.keySeparator && !this.options.userDefinedNsSeparator && !opt.nsSeparator && !looksLikeObjectPath(key, nsSeparator, keySeparator);
|
|
2558
2575
|
if (wouldCheckForNsInKey && !seemsNaturalLanguage) {
|
|
2559
2576
|
const m = key.match(this.interpolator.nestingRegexp);
|
|
@@ -2564,7 +2581,7 @@ class Translator extends EventEmitter {
|
|
|
2564
2581
|
};
|
|
2565
2582
|
}
|
|
2566
2583
|
const parts = key.split(nsSeparator);
|
|
2567
|
-
if (nsSeparator !== keySeparator || nsSeparator === keySeparator && this.options.ns.
|
|
2584
|
+
if (nsSeparator !== keySeparator || nsSeparator === keySeparator && this.options.ns.includes(parts[0])) namespaces = parts.shift();
|
|
2568
2585
|
key = parts.join(keySeparator);
|
|
2569
2586
|
}
|
|
2570
2587
|
return {
|
|
@@ -2589,6 +2606,10 @@ class Translator extends EventEmitter {
|
|
|
2589
2606
|
...opt
|
|
2590
2607
|
});
|
|
2591
2608
|
if (!Array.isArray(keys)) keys = [String(keys)];
|
|
2609
|
+
keys = keys.map(k => typeof k === 'function' ? keysFromSelector(k, {
|
|
2610
|
+
...this.options,
|
|
2611
|
+
...opt
|
|
2612
|
+
}) : String(k));
|
|
2592
2613
|
const returnDetails = opt.returnDetails !== undefined ? opt.returnDetails : this.options.returnDetails;
|
|
2593
2614
|
const keySeparator = opt.keySeparator !== undefined ? opt.keySeparator : this.options.keySeparator;
|
|
2594
2615
|
const {
|
|
@@ -2647,7 +2668,7 @@ class Translator extends EventEmitter {
|
|
|
2647
2668
|
}
|
|
2648
2669
|
const handleAsObject = shouldHandleAsObject(resForObjHndl);
|
|
2649
2670
|
const resType = Object.prototype.toString.apply(resForObjHndl);
|
|
2650
|
-
if (handleAsObjectInI18nFormat && resForObjHndl && handleAsObject && noObject.
|
|
2671
|
+
if (handleAsObjectInI18nFormat && resForObjHndl && handleAsObject && !noObject.includes(resType) && !(isString(joinArrays) && Array.isArray(resForObjHndl))) {
|
|
2651
2672
|
if (!opt.returnObjects && !this.options.returnObjects) {
|
|
2652
2673
|
if (!this.options.returnedObjectHandler) {
|
|
2653
2674
|
this.logger.warn('accessing an object - but returnObjects options is not enabled!');
|
|
@@ -2743,7 +2764,7 @@ class Translator extends EventEmitter {
|
|
|
2743
2764
|
if (this.options.saveMissingPlurals && needsPluralHandling) {
|
|
2744
2765
|
lngs.forEach(language => {
|
|
2745
2766
|
const suffixes = this.pluralResolver.getSuffixes(language, opt);
|
|
2746
|
-
if (needsZeroSuffixLookup && opt[`defaultValue${this.options.pluralSeparator}zero`] && suffixes.
|
|
2767
|
+
if (needsZeroSuffixLookup && opt[`defaultValue${this.options.pluralSeparator}zero`] && !suffixes.includes(`${this.options.pluralSeparator}zero`)) {
|
|
2747
2768
|
suffixes.push(`${this.options.pluralSeparator}zero`);
|
|
2748
2769
|
}
|
|
2749
2770
|
suffixes.forEach(suffix => {
|
|
@@ -2835,6 +2856,10 @@ class Translator extends EventEmitter {
|
|
|
2835
2856
|
let usedLng;
|
|
2836
2857
|
let usedNS;
|
|
2837
2858
|
if (isString(keys)) keys = [keys];
|
|
2859
|
+
if (Array.isArray(keys)) keys = keys.map(k => typeof k === 'function' ? keysFromSelector(k, {
|
|
2860
|
+
...this.options,
|
|
2861
|
+
...opt
|
|
2862
|
+
}) : k);
|
|
2838
2863
|
keys.forEach(k => {
|
|
2839
2864
|
if (this.isValidLookup(found)) return;
|
|
2840
2865
|
const extracted = this.extractFromKey(k, opt);
|
|
@@ -2849,8 +2874,8 @@ class Translator extends EventEmitter {
|
|
|
2849
2874
|
namespaces.forEach(ns => {
|
|
2850
2875
|
if (this.isValidLookup(found)) return;
|
|
2851
2876
|
usedNS = ns;
|
|
2852
|
-
if (!checkedLoadedFor[`${codes[0]}-${ns}`] && this.utils?.hasLoadedNamespace && !this.utils?.hasLoadedNamespace(usedNS)) {
|
|
2853
|
-
checkedLoadedFor[`${codes[0]}-${ns}`] = true;
|
|
2877
|
+
if (!this.checkedLoadedFor[`${codes[0]}-${ns}`] && this.utils?.hasLoadedNamespace && !this.utils?.hasLoadedNamespace(usedNS)) {
|
|
2878
|
+
this.checkedLoadedFor[`${codes[0]}-${ns}`] = true;
|
|
2854
2879
|
this.logger.warn(`key "${usedKey}" for languages "${codes.join(', ')}" won't get resolved as namespace "${usedNS}" was not yet loaded`, 'This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!');
|
|
2855
2880
|
}
|
|
2856
2881
|
codes.forEach(code => {
|
|
@@ -2865,7 +2890,7 @@ class Translator extends EventEmitter {
|
|
|
2865
2890
|
const zeroSuffix = `${this.options.pluralSeparator}zero`;
|
|
2866
2891
|
const ordinalPrefix = `${this.options.pluralSeparator}ordinal${this.options.pluralSeparator}`;
|
|
2867
2892
|
if (needsPluralHandling) {
|
|
2868
|
-
if (opt.ordinal && pluralSuffix.
|
|
2893
|
+
if (opt.ordinal && pluralSuffix.startsWith(ordinalPrefix)) {
|
|
2869
2894
|
finalKeys.push(key + pluralSuffix.replace(ordinalPrefix, this.options.pluralSeparator));
|
|
2870
2895
|
}
|
|
2871
2896
|
finalKeys.push(key + pluralSuffix);
|
|
@@ -2877,7 +2902,7 @@ class Translator extends EventEmitter {
|
|
|
2877
2902
|
const contextKey = `${key}${this.options.contextSeparator || '_'}${opt.context}`;
|
|
2878
2903
|
finalKeys.push(contextKey);
|
|
2879
2904
|
if (needsPluralHandling) {
|
|
2880
|
-
if (opt.ordinal && pluralSuffix.
|
|
2905
|
+
if (opt.ordinal && pluralSuffix.startsWith(ordinalPrefix)) {
|
|
2881
2906
|
finalKeys.push(contextKey + pluralSuffix.replace(ordinalPrefix, this.options.pluralSeparator));
|
|
2882
2907
|
}
|
|
2883
2908
|
finalKeys.push(contextKey + pluralSuffix);
|
|
@@ -2938,7 +2963,7 @@ class Translator extends EventEmitter {
|
|
|
2938
2963
|
static hasDefaultValue(options) {
|
|
2939
2964
|
const prefix = 'defaultValue';
|
|
2940
2965
|
for (const option in options) {
|
|
2941
|
-
if (Object.prototype.hasOwnProperty.call(options, option) &&
|
|
2966
|
+
if (Object.prototype.hasOwnProperty.call(options, option) && option.startsWith(prefix) && undefined !== options[option]) {
|
|
2942
2967
|
return true;
|
|
2943
2968
|
}
|
|
2944
2969
|
}
|
|
@@ -2954,7 +2979,7 @@ class LanguageUtil {
|
|
|
2954
2979
|
}
|
|
2955
2980
|
getScriptPartFromCode(code) {
|
|
2956
2981
|
code = getCleanedCode(code);
|
|
2957
|
-
if (!code || code.
|
|
2982
|
+
if (!code || !code.includes('-')) return null;
|
|
2958
2983
|
const p = code.split('-');
|
|
2959
2984
|
if (p.length === 2) return null;
|
|
2960
2985
|
p.pop();
|
|
@@ -2963,12 +2988,12 @@ class LanguageUtil {
|
|
|
2963
2988
|
}
|
|
2964
2989
|
getLanguagePartFromCode(code) {
|
|
2965
2990
|
code = getCleanedCode(code);
|
|
2966
|
-
if (!code || code.
|
|
2991
|
+
if (!code || !code.includes('-')) return code;
|
|
2967
2992
|
const p = code.split('-');
|
|
2968
2993
|
return this.formatLanguageCode(p[0]);
|
|
2969
2994
|
}
|
|
2970
2995
|
formatLanguageCode(code) {
|
|
2971
|
-
if (isString(code) && code.
|
|
2996
|
+
if (isString(code) && code.includes('-')) {
|
|
2972
2997
|
let formattedCode;
|
|
2973
2998
|
try {
|
|
2974
2999
|
formattedCode = Intl.getCanonicalLocales(code)[0];
|
|
@@ -2988,7 +3013,7 @@ class LanguageUtil {
|
|
|
2988
3013
|
if (this.options.load === 'languageOnly' || this.options.nonExplicitSupportedLngs) {
|
|
2989
3014
|
code = this.getLanguagePartFromCode(code);
|
|
2990
3015
|
}
|
|
2991
|
-
return !this.supportedLngs || !this.supportedLngs.length || this.supportedLngs.
|
|
3016
|
+
return !this.supportedLngs || !this.supportedLngs.length || this.supportedLngs.includes(code);
|
|
2992
3017
|
}
|
|
2993
3018
|
getBestMatchFromCodes(codes) {
|
|
2994
3019
|
if (!codes) return null;
|
|
@@ -3006,10 +3031,11 @@ class LanguageUtil {
|
|
|
3006
3031
|
const lngOnly = this.getLanguagePartFromCode(code);
|
|
3007
3032
|
if (this.isSupportedCode(lngOnly)) return found = lngOnly;
|
|
3008
3033
|
found = this.options.supportedLngs.find(supportedLng => {
|
|
3009
|
-
if (supportedLng === lngOnly) return
|
|
3010
|
-
if (supportedLng.
|
|
3011
|
-
if (supportedLng.
|
|
3012
|
-
if (supportedLng.
|
|
3034
|
+
if (supportedLng === lngOnly) return true;
|
|
3035
|
+
if (!supportedLng.includes('-') && !lngOnly.includes('-')) return false;
|
|
3036
|
+
if (supportedLng.includes('-') && !lngOnly.includes('-') && supportedLng.slice(0, supportedLng.indexOf('-')) === lngOnly) return true;
|
|
3037
|
+
if (supportedLng.startsWith(lngOnly) && lngOnly.length > 1) return true;
|
|
3038
|
+
return false;
|
|
3013
3039
|
});
|
|
3014
3040
|
});
|
|
3015
3041
|
}
|
|
@@ -3040,7 +3066,7 @@ class LanguageUtil {
|
|
|
3040
3066
|
this.logger.warn(`rejecting language code not found in supportedLngs: ${c}`);
|
|
3041
3067
|
}
|
|
3042
3068
|
};
|
|
3043
|
-
if (isString(code) && (code.
|
|
3069
|
+
if (isString(code) && (code.includes('-') || code.includes('_'))) {
|
|
3044
3070
|
if (this.options.load !== 'languageOnly') addCode(this.formatLanguageCode(code));
|
|
3045
3071
|
if (this.options.load !== 'languageOnly' && this.options.load !== 'currentOnly') addCode(this.getScriptPartFromCode(code));
|
|
3046
3072
|
if (this.options.load !== 'currentOnly') addCode(this.getLanguagePartFromCode(code));
|
|
@@ -3048,7 +3074,7 @@ class LanguageUtil {
|
|
|
3048
3074
|
addCode(this.formatLanguageCode(code));
|
|
3049
3075
|
}
|
|
3050
3076
|
fallbackCodes.forEach(fc => {
|
|
3051
|
-
if (codes.
|
|
3077
|
+
if (!codes.includes(fc)) addCode(this.formatLanguageCode(fc));
|
|
3052
3078
|
});
|
|
3053
3079
|
return codes;
|
|
3054
3080
|
}
|
|
@@ -3204,7 +3230,7 @@ class Interpolator {
|
|
|
3204
3230
|
let replaces;
|
|
3205
3231
|
const defaultData = this.options && this.options.interpolation && this.options.interpolation.defaultVariables || {};
|
|
3206
3232
|
const handleFormat = key => {
|
|
3207
|
-
if (key.
|
|
3233
|
+
if (!key.includes(this.formatSeparator)) {
|
|
3208
3234
|
const path = deepFindWithDefaults(data, defaultData, key, this.options.keySeparator, this.options.ignoreJSONStructure);
|
|
3209
3235
|
return this.alwaysFormat ? this.format(path, undefined, lng, {
|
|
3210
3236
|
...options,
|
|
@@ -3274,7 +3300,7 @@ class Interpolator {
|
|
|
3274
3300
|
let clonedOptions;
|
|
3275
3301
|
const handleHasOptions = (key, inheritedOptions) => {
|
|
3276
3302
|
const sep = this.nestingOptionsSeparator;
|
|
3277
|
-
if (key.
|
|
3303
|
+
if (!key.includes(sep)) return key;
|
|
3278
3304
|
const c = key.split(new RegExp(`${regexEscape(sep)}[ ]*{`));
|
|
3279
3305
|
let optionsString = `{${c[1]}`;
|
|
3280
3306
|
key = c[0];
|
|
@@ -3294,7 +3320,7 @@ class Interpolator {
|
|
|
3294
3320
|
this.logger.warn(`failed parsing options string in nesting for key ${key}`, e);
|
|
3295
3321
|
return `${key}${sep}${optionsString}`;
|
|
3296
3322
|
}
|
|
3297
|
-
if (clonedOptions.defaultValue && clonedOptions.defaultValue.
|
|
3323
|
+
if (clonedOptions.defaultValue && clonedOptions.defaultValue.includes(this.prefix)) delete clonedOptions.defaultValue;
|
|
3298
3324
|
return key;
|
|
3299
3325
|
};
|
|
3300
3326
|
while (match = this.nestingRegexp.exec(str)) {
|
|
@@ -3333,13 +3359,13 @@ class Interpolator {
|
|
|
3333
3359
|
const parseFormatStr = formatStr => {
|
|
3334
3360
|
let formatName = formatStr.toLowerCase().trim();
|
|
3335
3361
|
const formatOptions = {};
|
|
3336
|
-
if (formatStr.
|
|
3362
|
+
if (formatStr.includes('(')) {
|
|
3337
3363
|
const p = formatStr.split('(');
|
|
3338
3364
|
formatName = p[0].toLowerCase().trim();
|
|
3339
|
-
const optStr = p[1].
|
|
3340
|
-
if (formatName === 'currency' && optStr.
|
|
3365
|
+
const optStr = p[1].slice(0, -1);
|
|
3366
|
+
if (formatName === 'currency' && !optStr.includes(':')) {
|
|
3341
3367
|
if (!formatOptions.currency) formatOptions.currency = optStr.trim();
|
|
3342
|
-
} else if (formatName === 'relativetime' && optStr.
|
|
3368
|
+
} else if (formatName === 'relativetime' && !optStr.includes(':')) {
|
|
3343
3369
|
if (!formatOptions.range) formatOptions.range = optStr.trim();
|
|
3344
3370
|
} else {
|
|
3345
3371
|
const opts = optStr.split(';');
|
|
@@ -3433,9 +3459,11 @@ class Formatter {
|
|
|
3433
3459
|
this.formats[name.toLowerCase().trim()] = createCachedFormatter(fc);
|
|
3434
3460
|
}
|
|
3435
3461
|
format(value, format, lng, options = {}) {
|
|
3462
|
+
if (!format) return value;
|
|
3463
|
+
if (value == null) return value;
|
|
3436
3464
|
const formats = format.split(this.formatSeparator);
|
|
3437
|
-
if (formats.length > 1 && formats[0].indexOf('(') > 1 && formats[0].
|
|
3438
|
-
const lastIndex = formats.findIndex(f => f.
|
|
3465
|
+
if (formats.length > 1 && formats[0].indexOf('(') > 1 && !formats[0].includes(')') && formats.find(f => f.includes(')'))) {
|
|
3466
|
+
const lastIndex = formats.findIndex(f => f.includes(')'));
|
|
3439
3467
|
formats[0] = [formats[0], ...formats.splice(1, lastIndex)].join(this.formatSeparator);
|
|
3440
3468
|
}
|
|
3441
3469
|
const result = formats.reduce((mem, f) => {
|
|
@@ -3589,7 +3617,7 @@ class Connector extends EventEmitter {
|
|
|
3589
3617
|
}
|
|
3590
3618
|
if (err && data && tried < this.maxRetries) {
|
|
3591
3619
|
setTimeout(() => {
|
|
3592
|
-
this.read
|
|
3620
|
+
this.read(lng, ns, fcName, tried + 1, wait * 2, callback);
|
|
3593
3621
|
}, wait);
|
|
3594
3622
|
return;
|
|
3595
3623
|
}
|
|
@@ -3693,7 +3721,6 @@ const get = () => ({
|
|
|
3693
3721
|
nonExplicitSupportedLngs: false,
|
|
3694
3722
|
load: 'all',
|
|
3695
3723
|
preload: false,
|
|
3696
|
-
simplifyPluralSuffix: true,
|
|
3697
3724
|
keySeparator: '.',
|
|
3698
3725
|
nsSeparator: ':',
|
|
3699
3726
|
pluralSeparator: '_',
|
|
@@ -3730,7 +3757,6 @@ const get = () => ({
|
|
|
3730
3757
|
},
|
|
3731
3758
|
interpolation: {
|
|
3732
3759
|
escapeValue: true,
|
|
3733
|
-
format: value => value,
|
|
3734
3760
|
prefix: '{{',
|
|
3735
3761
|
suffix: '}}',
|
|
3736
3762
|
formatSeparator: ',',
|
|
@@ -3747,10 +3773,9 @@ const transformOptions = options => {
|
|
|
3747
3773
|
if (isString(options.ns)) options.ns = [options.ns];
|
|
3748
3774
|
if (isString(options.fallbackLng)) options.fallbackLng = [options.fallbackLng];
|
|
3749
3775
|
if (isString(options.fallbackNS)) options.fallbackNS = [options.fallbackNS];
|
|
3750
|
-
if (options.supportedLngs
|
|
3776
|
+
if (options.supportedLngs && !options.supportedLngs.includes('cimode')) {
|
|
3751
3777
|
options.supportedLngs = options.supportedLngs.concat(['cimode']);
|
|
3752
3778
|
}
|
|
3753
|
-
if (typeof options.initImmediate === 'boolean') options.initAsync = options.initImmediate;
|
|
3754
3779
|
return options;
|
|
3755
3780
|
};
|
|
3756
3781
|
|
|
@@ -3763,23 +3788,6 @@ const bindMemberFunctions = inst => {
|
|
|
3763
3788
|
}
|
|
3764
3789
|
});
|
|
3765
3790
|
};
|
|
3766
|
-
const SUPPORT_NOTICE_KEY = '__i18next_supportNoticeShown';
|
|
3767
|
-
const getSupportNoticeShown = () => typeof globalThis !== 'undefined' && !!globalThis[SUPPORT_NOTICE_KEY];
|
|
3768
|
-
const setSupportNoticeShown = () => {
|
|
3769
|
-
if (typeof globalThis !== 'undefined') globalThis[SUPPORT_NOTICE_KEY] = true;
|
|
3770
|
-
};
|
|
3771
|
-
const usesLocize = inst => {
|
|
3772
|
-
if (inst?.modules?.backend?.name?.indexOf('Locize') > 0) return true;
|
|
3773
|
-
if (inst?.modules?.backend?.constructor?.name?.indexOf('Locize') > 0) return true;
|
|
3774
|
-
if (inst?.options?.backend?.backends) {
|
|
3775
|
-
if (inst.options.backend.backends.some(b => b?.name?.indexOf('Locize') > 0 || b?.constructor?.name?.indexOf('Locize') > 0)) return true;
|
|
3776
|
-
}
|
|
3777
|
-
if (inst?.options?.backend?.projectId) return true;
|
|
3778
|
-
if (inst?.options?.backend?.backendOptions) {
|
|
3779
|
-
if (inst.options.backend.backendOptions.some(b => b?.projectId)) return true;
|
|
3780
|
-
}
|
|
3781
|
-
return false;
|
|
3782
|
-
};
|
|
3783
3791
|
class I18n extends EventEmitter {
|
|
3784
3792
|
constructor(options = {}, callback) {
|
|
3785
3793
|
super();
|
|
@@ -3809,7 +3817,7 @@ class I18n extends EventEmitter {
|
|
|
3809
3817
|
if (options.defaultNS == null && options.ns) {
|
|
3810
3818
|
if (isString(options.ns)) {
|
|
3811
3819
|
options.defaultNS = options.ns;
|
|
3812
|
-
} else if (options.ns.
|
|
3820
|
+
} else if (!options.ns.includes('translation')) {
|
|
3813
3821
|
options.defaultNS = options.ns[0];
|
|
3814
3822
|
}
|
|
3815
3823
|
}
|
|
@@ -3832,10 +3840,6 @@ class I18n extends EventEmitter {
|
|
|
3832
3840
|
if (typeof this.options.overloadTranslationOptionHandler !== 'function') {
|
|
3833
3841
|
this.options.overloadTranslationOptionHandler = defOpts.overloadTranslationOptionHandler;
|
|
3834
3842
|
}
|
|
3835
|
-
if (this.options.showSupportNotice !== false && !usesLocize(this) && !getSupportNoticeShown()) {
|
|
3836
|
-
if (typeof console !== 'undefined' && typeof console.info !== 'undefined') console.info('🌐 i18next is maintained with support from Locize — consider powering your project with managed localization (AI, CDN, integrations): https://locize.com 💙');
|
|
3837
|
-
setSupportNoticeShown();
|
|
3838
|
-
}
|
|
3839
3843
|
const createClassOnDemand = ClassOrObject => {
|
|
3840
3844
|
if (!ClassOrObject) return null;
|
|
3841
3845
|
if (typeof ClassOrObject === 'function') return new ClassOrObject();
|
|
@@ -3860,14 +3864,9 @@ class I18n extends EventEmitter {
|
|
|
3860
3864
|
s.resourceStore = this.store;
|
|
3861
3865
|
s.languageUtils = lu;
|
|
3862
3866
|
s.pluralResolver = new PluralResolver(lu, {
|
|
3863
|
-
prepend: this.options.pluralSeparator
|
|
3864
|
-
simplifyPluralSuffix: this.options.simplifyPluralSuffix
|
|
3867
|
+
prepend: this.options.pluralSeparator
|
|
3865
3868
|
});
|
|
3866
|
-
|
|
3867
|
-
if (usingLegacyFormatFunction) {
|
|
3868
|
-
this.logger.deprecate(`init: you are still using the legacy format function, please use the new approach: https://www.i18next.com/translation-function/formatting`);
|
|
3869
|
-
}
|
|
3870
|
-
if (formatter && (!this.options.interpolation.format || this.options.interpolation.format === defOpts.interpolation.format)) {
|
|
3869
|
+
if (formatter) {
|
|
3871
3870
|
s.formatter = createClassOnDemand(formatter);
|
|
3872
3871
|
if (s.formatter.init) s.formatter.init(s, this.options);
|
|
3873
3872
|
this.options.interpolation.format = s.formatter.format.bind(s.formatter);
|
|
@@ -3950,7 +3949,7 @@ class I18n extends EventEmitter {
|
|
|
3950
3949
|
const lngs = this.services.languageUtils.toResolveHierarchy(lng);
|
|
3951
3950
|
lngs.forEach(l => {
|
|
3952
3951
|
if (l === 'cimode') return;
|
|
3953
|
-
if (toLoad.
|
|
3952
|
+
if (!toLoad.includes(l)) toLoad.push(l);
|
|
3954
3953
|
});
|
|
3955
3954
|
};
|
|
3956
3955
|
if (!usedLng) {
|
|
@@ -4015,16 +4014,16 @@ class I18n extends EventEmitter {
|
|
|
4015
4014
|
}
|
|
4016
4015
|
setResolvedLanguage(l) {
|
|
4017
4016
|
if (!l || !this.languages) return;
|
|
4018
|
-
if (['cimode', 'dev'].
|
|
4017
|
+
if (['cimode', 'dev'].includes(l)) return;
|
|
4019
4018
|
for (let li = 0; li < this.languages.length; li++) {
|
|
4020
4019
|
const lngInLngs = this.languages[li];
|
|
4021
|
-
if (['cimode', 'dev'].
|
|
4020
|
+
if (['cimode', 'dev'].includes(lngInLngs)) continue;
|
|
4022
4021
|
if (this.store.hasLanguageSomeTranslations(lngInLngs)) {
|
|
4023
4022
|
this.resolvedLanguage = lngInLngs;
|
|
4024
4023
|
break;
|
|
4025
4024
|
}
|
|
4026
4025
|
}
|
|
4027
|
-
if (!this.resolvedLanguage && this.languages.
|
|
4026
|
+
if (!this.resolvedLanguage && !this.languages.includes(l) && this.store.hasLanguageSomeTranslations(l)) {
|
|
4028
4027
|
this.resolvedLanguage = l;
|
|
4029
4028
|
this.languages.unshift(l);
|
|
4030
4029
|
}
|
|
@@ -4096,21 +4095,20 @@ class I18n extends EventEmitter {
|
|
|
4096
4095
|
o.lngs = o.lngs || fixedT.lngs;
|
|
4097
4096
|
o.ns = o.ns || fixedT.ns;
|
|
4098
4097
|
if (o.keyPrefix !== '') o.keyPrefix = o.keyPrefix || keyPrefix || fixedT.keyPrefix;
|
|
4098
|
+
const selectorOpts = {
|
|
4099
|
+
...this.options,
|
|
4100
|
+
...o
|
|
4101
|
+
};
|
|
4102
|
+
if (typeof o.keyPrefix === 'function') o.keyPrefix = keysFromSelector(o.keyPrefix, selectorOpts);
|
|
4099
4103
|
const keySeparator = this.options.keySeparator || '.';
|
|
4100
4104
|
let resultKey;
|
|
4101
4105
|
if (o.keyPrefix && Array.isArray(key)) {
|
|
4102
4106
|
resultKey = key.map(k => {
|
|
4103
|
-
if (typeof k === 'function') k = keysFromSelector(k,
|
|
4104
|
-
...this.options,
|
|
4105
|
-
...opts
|
|
4106
|
-
});
|
|
4107
|
+
if (typeof k === 'function') k = keysFromSelector(k, selectorOpts);
|
|
4107
4108
|
return `${o.keyPrefix}${keySeparator}${k}`;
|
|
4108
4109
|
});
|
|
4109
4110
|
} else {
|
|
4110
|
-
if (typeof key === 'function') key = keysFromSelector(key,
|
|
4111
|
-
...this.options,
|
|
4112
|
-
...opts
|
|
4113
|
-
});
|
|
4111
|
+
if (typeof key === 'function') key = keysFromSelector(key, selectorOpts);
|
|
4114
4112
|
resultKey = o.keyPrefix ? `${o.keyPrefix}${keySeparator}${key}` : key;
|
|
4115
4113
|
}
|
|
4116
4114
|
return this.t(resultKey, o);
|
|
@@ -4167,7 +4165,7 @@ class I18n extends EventEmitter {
|
|
|
4167
4165
|
}
|
|
4168
4166
|
if (isString(ns)) ns = [ns];
|
|
4169
4167
|
ns.forEach(n => {
|
|
4170
|
-
if (this.options.ns.
|
|
4168
|
+
if (!this.options.ns.includes(n)) this.options.ns.push(n);
|
|
4171
4169
|
});
|
|
4172
4170
|
this.loadResources(err => {
|
|
4173
4171
|
deferred.resolve();
|
|
@@ -4179,7 +4177,7 @@ class I18n extends EventEmitter {
|
|
|
4179
4177
|
const deferred = defer();
|
|
4180
4178
|
if (isString(lngs)) lngs = [lngs];
|
|
4181
4179
|
const preloaded = this.options.preload || [];
|
|
4182
|
-
const newLngs = lngs.filter(lng => preloaded.
|
|
4180
|
+
const newLngs = lngs.filter(lng => !preloaded.includes(lng) && this.services.languageUtils.isSupportedCode(lng));
|
|
4183
4181
|
if (!newLngs.length) {
|
|
4184
4182
|
if (callback) callback();
|
|
4185
4183
|
return Promise.resolve();
|
|
@@ -4204,7 +4202,7 @@ class I18n extends EventEmitter {
|
|
|
4204
4202
|
const rtlLngs = ['ar', 'shu', 'sqr', 'ssh', 'xaa', 'yhd', 'yud', 'aao', 'abh', 'abv', 'acm', 'acq', 'acw', 'acx', 'acy', 'adf', 'ads', 'aeb', 'aec', 'afb', 'ajp', 'apc', 'apd', 'arb', 'arq', 'ars', 'ary', 'arz', 'auz', 'avl', 'ayh', 'ayl', 'ayn', 'ayp', 'bbz', 'pga', 'he', 'iw', 'ps', 'pbt', 'pbu', 'pst', 'prp', 'prd', 'ug', 'ur', 'ydd', 'yds', 'yih', 'ji', 'yi', 'hbo', 'men', 'xmn', 'fa', 'jpr', 'peo', 'pes', 'prs', 'dv', 'sam', 'ckb'];
|
|
4205
4203
|
const languageUtils = this.services?.languageUtils || new LanguageUtil(get());
|
|
4206
4204
|
if (lng.toLowerCase().indexOf('-latn') > 1) return 'ltr';
|
|
4207
|
-
return rtlLngs.
|
|
4205
|
+
return rtlLngs.includes(languageUtils.getLanguagePartFromCode(lng)) || lng.toLowerCase().indexOf('-arab') > 1 ? 'rtl' : 'ltr';
|
|
4208
4206
|
}
|
|
4209
4207
|
static createInstance(options = {}, callback) {
|
|
4210
4208
|
const instance = new I18n(options, callback);
|