i18next 25.10.9 → 26.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/LICENSE +1 -1
- package/dist/cjs/i18next.js +61 -85
- package/dist/esm/i18next.bundled.js +61 -85
- package/dist/esm/i18next.js +61 -85
- package/dist/esm/package.json +1 -1
- package/dist/umd/i18next.js +61 -85
- package/dist/umd/i18next.min.js +1 -1
- package/eslint.config.mjs +32 -0
- package/i18next.js +61 -85
- package/i18next.min.js +1 -1
- package/index.d.mts +1 -1
- package/index.d.ts +10 -1
- package/package.json +11 -16
- package/typescript/options.d.ts +0 -22
- package/jsr.json +0 -15
package/LICENSE
CHANGED
package/dist/cjs/i18next.js
CHANGED
|
@@ -14,7 +14,7 @@ const defer = () => {
|
|
|
14
14
|
};
|
|
15
15
|
const makeString = object => {
|
|
16
16
|
if (object == null) return '';
|
|
17
|
-
return
|
|
17
|
+
return String(object);
|
|
18
18
|
};
|
|
19
19
|
const copy = (a, s, t) => {
|
|
20
20
|
a.forEach(m => {
|
|
@@ -22,7 +22,7 @@ const copy = (a, s, t) => {
|
|
|
22
22
|
});
|
|
23
23
|
};
|
|
24
24
|
const lastOfPathSeparatorRegExp = /###/g;
|
|
25
|
-
const cleanKey = key => key && key.
|
|
25
|
+
const cleanKey = key => key && key.includes('###') ? key.replace(lastOfPathSeparatorRegExp, '.') : key;
|
|
26
26
|
const canNotTraverseDeeper = object => !object || isString(object);
|
|
27
27
|
const getLastOfPath = (object, path, Empty) => {
|
|
28
28
|
const stack = !isString(path) ? path : path.split('.');
|
|
@@ -107,7 +107,7 @@ const deepExtend = (target, source, overwrite) => {
|
|
|
107
107
|
return target;
|
|
108
108
|
};
|
|
109
109
|
const regexEscape = str => str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
|
|
110
|
-
|
|
110
|
+
const _entityMap = {
|
|
111
111
|
'&': '&',
|
|
112
112
|
'<': '<',
|
|
113
113
|
'>': '>',
|
|
@@ -146,7 +146,7 @@ const looksLikeObjectPathRegExpCache = new RegExpCache(20);
|
|
|
146
146
|
const looksLikeObjectPath = (key, nsSeparator, keySeparator) => {
|
|
147
147
|
nsSeparator = nsSeparator || '';
|
|
148
148
|
keySeparator = keySeparator || '';
|
|
149
|
-
const possibleChars = chars.filter(c => nsSeparator.
|
|
149
|
+
const possibleChars = chars.filter(c => !nsSeparator.includes(c) && !keySeparator.includes(c));
|
|
150
150
|
if (possibleChars.length === 0) return true;
|
|
151
151
|
const r = looksLikeObjectPathRegExpCache.getRegExp(`(${possibleChars.map(c => c === '?' ? '\\?' : c).join('|')})`);
|
|
152
152
|
let matched = !r.test(key);
|
|
@@ -179,7 +179,7 @@ const deepFind = (obj, path, keySeparator = '.') => {
|
|
|
179
179
|
nextPath += tokens[j];
|
|
180
180
|
next = current[nextPath];
|
|
181
181
|
if (next !== undefined) {
|
|
182
|
-
if (['string', 'number', 'boolean'].
|
|
182
|
+
if (['string', 'number', 'boolean'].includes(typeof next) && j < tokens.length - 1) {
|
|
183
183
|
continue;
|
|
184
184
|
}
|
|
185
185
|
i += j - i + 1;
|
|
@@ -270,6 +270,14 @@ class EventEmitter {
|
|
|
270
270
|
}
|
|
271
271
|
this.observers[event].delete(listener);
|
|
272
272
|
}
|
|
273
|
+
once(event, listener) {
|
|
274
|
+
const wrapper = (...args) => {
|
|
275
|
+
listener(...args);
|
|
276
|
+
this.off(event, wrapper);
|
|
277
|
+
};
|
|
278
|
+
this.on(event, wrapper);
|
|
279
|
+
return this;
|
|
280
|
+
}
|
|
273
281
|
emit(event, ...args) {
|
|
274
282
|
if (this.observers[event]) {
|
|
275
283
|
const cloned = Array.from(this.observers[event].entries());
|
|
@@ -283,7 +291,7 @@ class EventEmitter {
|
|
|
283
291
|
const cloned = Array.from(this.observers['*'].entries());
|
|
284
292
|
cloned.forEach(([observer, numTimesAdded]) => {
|
|
285
293
|
for (let i = 0; i < numTimesAdded; i++) {
|
|
286
|
-
observer
|
|
294
|
+
observer(event, ...args);
|
|
287
295
|
}
|
|
288
296
|
});
|
|
289
297
|
}
|
|
@@ -306,7 +314,7 @@ class ResourceStore extends EventEmitter {
|
|
|
306
314
|
}
|
|
307
315
|
}
|
|
308
316
|
addNamespaces(ns) {
|
|
309
|
-
if (this.options.ns.
|
|
317
|
+
if (!this.options.ns.includes(ns)) {
|
|
310
318
|
this.options.ns.push(ns);
|
|
311
319
|
}
|
|
312
320
|
}
|
|
@@ -320,7 +328,7 @@ class ResourceStore extends EventEmitter {
|
|
|
320
328
|
const keySeparator = options.keySeparator !== undefined ? options.keySeparator : this.options.keySeparator;
|
|
321
329
|
const ignoreJSONStructure = options.ignoreJSONStructure !== undefined ? options.ignoreJSONStructure : this.options.ignoreJSONStructure;
|
|
322
330
|
let path;
|
|
323
|
-
if (lng.
|
|
331
|
+
if (lng.includes('.')) {
|
|
324
332
|
path = lng.split('.');
|
|
325
333
|
} else {
|
|
326
334
|
path = [lng, ns];
|
|
@@ -335,7 +343,7 @@ class ResourceStore extends EventEmitter {
|
|
|
335
343
|
}
|
|
336
344
|
}
|
|
337
345
|
const result = getPath(this.data, path);
|
|
338
|
-
if (!result && !ns && !key && lng.
|
|
346
|
+
if (!result && !ns && !key && lng.includes('.')) {
|
|
339
347
|
lng = path[0];
|
|
340
348
|
ns = path[1];
|
|
341
349
|
key = path.slice(2).join('.');
|
|
@@ -349,7 +357,7 @@ class ResourceStore extends EventEmitter {
|
|
|
349
357
|
const keySeparator = options.keySeparator !== undefined ? options.keySeparator : this.options.keySeparator;
|
|
350
358
|
let path = [lng, ns];
|
|
351
359
|
if (key) path = path.concat(keySeparator ? key.split(keySeparator) : key);
|
|
352
|
-
if (lng.
|
|
360
|
+
if (lng.includes('.')) {
|
|
353
361
|
path = lng.split('.');
|
|
354
362
|
value = ns;
|
|
355
363
|
ns = path[1];
|
|
@@ -373,7 +381,7 @@ class ResourceStore extends EventEmitter {
|
|
|
373
381
|
skipCopy: false
|
|
374
382
|
}) {
|
|
375
383
|
let path = [lng, ns];
|
|
376
|
-
if (lng.
|
|
384
|
+
if (lng.includes('.')) {
|
|
377
385
|
path = lng.split('.');
|
|
378
386
|
deep = resources;
|
|
379
387
|
resources = ns;
|
|
@@ -463,7 +471,6 @@ function keysFromSelector(selector, opts) {
|
|
|
463
471
|
return path.join(keySeparator);
|
|
464
472
|
}
|
|
465
473
|
|
|
466
|
-
const checkedLoadedFor = {};
|
|
467
474
|
const shouldHandleAsObject = res => !isString(res) && typeof res !== 'boolean' && typeof res !== 'number';
|
|
468
475
|
class Translator extends EventEmitter {
|
|
469
476
|
constructor(services, options = {}) {
|
|
@@ -474,6 +481,7 @@ class Translator extends EventEmitter {
|
|
|
474
481
|
this.options.keySeparator = '.';
|
|
475
482
|
}
|
|
476
483
|
this.logger = baseLogger.create('translator');
|
|
484
|
+
this.checkedLoadedFor = {};
|
|
477
485
|
}
|
|
478
486
|
changeLanguage(lng) {
|
|
479
487
|
if (lng) this.language = lng;
|
|
@@ -498,7 +506,7 @@ class Translator extends EventEmitter {
|
|
|
498
506
|
if (nsSeparator === undefined) nsSeparator = ':';
|
|
499
507
|
const keySeparator = opt.keySeparator !== undefined ? opt.keySeparator : this.options.keySeparator;
|
|
500
508
|
let namespaces = opt.ns || this.options.defaultNS || [];
|
|
501
|
-
const wouldCheckForNsInKey = nsSeparator && key.
|
|
509
|
+
const wouldCheckForNsInKey = nsSeparator && key.includes(nsSeparator);
|
|
502
510
|
const seemsNaturalLanguage = !this.options.userDefinedKeySeparator && !opt.keySeparator && !this.options.userDefinedNsSeparator && !opt.nsSeparator && !looksLikeObjectPath(key, nsSeparator, keySeparator);
|
|
503
511
|
if (wouldCheckForNsInKey && !seemsNaturalLanguage) {
|
|
504
512
|
const m = key.match(this.interpolator.nestingRegexp);
|
|
@@ -509,7 +517,7 @@ class Translator extends EventEmitter {
|
|
|
509
517
|
};
|
|
510
518
|
}
|
|
511
519
|
const parts = key.split(nsSeparator);
|
|
512
|
-
if (nsSeparator !== keySeparator || nsSeparator === keySeparator && this.options.ns.
|
|
520
|
+
if (nsSeparator !== keySeparator || nsSeparator === keySeparator && this.options.ns.includes(parts[0])) namespaces = parts.shift();
|
|
513
521
|
key = parts.join(keySeparator);
|
|
514
522
|
}
|
|
515
523
|
return {
|
|
@@ -596,7 +604,7 @@ class Translator extends EventEmitter {
|
|
|
596
604
|
}
|
|
597
605
|
const handleAsObject = shouldHandleAsObject(resForObjHndl);
|
|
598
606
|
const resType = Object.prototype.toString.apply(resForObjHndl);
|
|
599
|
-
if (handleAsObjectInI18nFormat && resForObjHndl && handleAsObject && noObject.
|
|
607
|
+
if (handleAsObjectInI18nFormat && resForObjHndl && handleAsObject && !noObject.includes(resType) && !(isString(joinArrays) && Array.isArray(resForObjHndl))) {
|
|
600
608
|
if (!opt.returnObjects && !this.options.returnObjects) {
|
|
601
609
|
if (!this.options.returnedObjectHandler) {
|
|
602
610
|
this.logger.warn('accessing an object - but returnObjects options is not enabled!');
|
|
@@ -692,7 +700,7 @@ class Translator extends EventEmitter {
|
|
|
692
700
|
if (this.options.saveMissingPlurals && needsPluralHandling) {
|
|
693
701
|
lngs.forEach(language => {
|
|
694
702
|
const suffixes = this.pluralResolver.getSuffixes(language, opt);
|
|
695
|
-
if (needsZeroSuffixLookup && opt[`defaultValue${this.options.pluralSeparator}zero`] && suffixes.
|
|
703
|
+
if (needsZeroSuffixLookup && opt[`defaultValue${this.options.pluralSeparator}zero`] && !suffixes.includes(`${this.options.pluralSeparator}zero`)) {
|
|
696
704
|
suffixes.push(`${this.options.pluralSeparator}zero`);
|
|
697
705
|
}
|
|
698
706
|
suffixes.forEach(suffix => {
|
|
@@ -802,8 +810,8 @@ class Translator extends EventEmitter {
|
|
|
802
810
|
namespaces.forEach(ns => {
|
|
803
811
|
if (this.isValidLookup(found)) return;
|
|
804
812
|
usedNS = ns;
|
|
805
|
-
if (!checkedLoadedFor[`${codes[0]}-${ns}`] && this.utils?.hasLoadedNamespace && !this.utils?.hasLoadedNamespace(usedNS)) {
|
|
806
|
-
checkedLoadedFor[`${codes[0]}-${ns}`] = true;
|
|
813
|
+
if (!this.checkedLoadedFor[`${codes[0]}-${ns}`] && this.utils?.hasLoadedNamespace && !this.utils?.hasLoadedNamespace(usedNS)) {
|
|
814
|
+
this.checkedLoadedFor[`${codes[0]}-${ns}`] = true;
|
|
807
815
|
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!!!');
|
|
808
816
|
}
|
|
809
817
|
codes.forEach(code => {
|
|
@@ -818,7 +826,7 @@ class Translator extends EventEmitter {
|
|
|
818
826
|
const zeroSuffix = `${this.options.pluralSeparator}zero`;
|
|
819
827
|
const ordinalPrefix = `${this.options.pluralSeparator}ordinal${this.options.pluralSeparator}`;
|
|
820
828
|
if (needsPluralHandling) {
|
|
821
|
-
if (opt.ordinal && pluralSuffix.
|
|
829
|
+
if (opt.ordinal && pluralSuffix.startsWith(ordinalPrefix)) {
|
|
822
830
|
finalKeys.push(key + pluralSuffix.replace(ordinalPrefix, this.options.pluralSeparator));
|
|
823
831
|
}
|
|
824
832
|
finalKeys.push(key + pluralSuffix);
|
|
@@ -830,7 +838,7 @@ class Translator extends EventEmitter {
|
|
|
830
838
|
const contextKey = `${key}${this.options.contextSeparator || '_'}${opt.context}`;
|
|
831
839
|
finalKeys.push(contextKey);
|
|
832
840
|
if (needsPluralHandling) {
|
|
833
|
-
if (opt.ordinal && pluralSuffix.
|
|
841
|
+
if (opt.ordinal && pluralSuffix.startsWith(ordinalPrefix)) {
|
|
834
842
|
finalKeys.push(contextKey + pluralSuffix.replace(ordinalPrefix, this.options.pluralSeparator));
|
|
835
843
|
}
|
|
836
844
|
finalKeys.push(contextKey + pluralSuffix);
|
|
@@ -891,7 +899,7 @@ class Translator extends EventEmitter {
|
|
|
891
899
|
static hasDefaultValue(options) {
|
|
892
900
|
const prefix = 'defaultValue';
|
|
893
901
|
for (const option in options) {
|
|
894
|
-
if (Object.prototype.hasOwnProperty.call(options, option) &&
|
|
902
|
+
if (Object.prototype.hasOwnProperty.call(options, option) && option.startsWith(prefix) && undefined !== options[option]) {
|
|
895
903
|
return true;
|
|
896
904
|
}
|
|
897
905
|
}
|
|
@@ -907,7 +915,7 @@ class LanguageUtil {
|
|
|
907
915
|
}
|
|
908
916
|
getScriptPartFromCode(code) {
|
|
909
917
|
code = getCleanedCode(code);
|
|
910
|
-
if (!code || code.
|
|
918
|
+
if (!code || !code.includes('-')) return null;
|
|
911
919
|
const p = code.split('-');
|
|
912
920
|
if (p.length === 2) return null;
|
|
913
921
|
p.pop();
|
|
@@ -916,12 +924,12 @@ class LanguageUtil {
|
|
|
916
924
|
}
|
|
917
925
|
getLanguagePartFromCode(code) {
|
|
918
926
|
code = getCleanedCode(code);
|
|
919
|
-
if (!code || code.
|
|
927
|
+
if (!code || !code.includes('-')) return code;
|
|
920
928
|
const p = code.split('-');
|
|
921
929
|
return this.formatLanguageCode(p[0]);
|
|
922
930
|
}
|
|
923
931
|
formatLanguageCode(code) {
|
|
924
|
-
if (isString(code) && code.
|
|
932
|
+
if (isString(code) && code.includes('-')) {
|
|
925
933
|
let formattedCode;
|
|
926
934
|
try {
|
|
927
935
|
formattedCode = Intl.getCanonicalLocales(code)[0];
|
|
@@ -941,7 +949,7 @@ class LanguageUtil {
|
|
|
941
949
|
if (this.options.load === 'languageOnly' || this.options.nonExplicitSupportedLngs) {
|
|
942
950
|
code = this.getLanguagePartFromCode(code);
|
|
943
951
|
}
|
|
944
|
-
return !this.supportedLngs || !this.supportedLngs.length || this.supportedLngs.
|
|
952
|
+
return !this.supportedLngs || !this.supportedLngs.length || this.supportedLngs.includes(code);
|
|
945
953
|
}
|
|
946
954
|
getBestMatchFromCodes(codes) {
|
|
947
955
|
if (!codes) return null;
|
|
@@ -959,10 +967,11 @@ class LanguageUtil {
|
|
|
959
967
|
const lngOnly = this.getLanguagePartFromCode(code);
|
|
960
968
|
if (this.isSupportedCode(lngOnly)) return found = lngOnly;
|
|
961
969
|
found = this.options.supportedLngs.find(supportedLng => {
|
|
962
|
-
if (supportedLng === lngOnly) return
|
|
963
|
-
if (supportedLng.
|
|
964
|
-
if (supportedLng.
|
|
965
|
-
if (supportedLng.
|
|
970
|
+
if (supportedLng === lngOnly) return true;
|
|
971
|
+
if (!supportedLng.includes('-') && !lngOnly.includes('-')) return false;
|
|
972
|
+
if (supportedLng.includes('-') && !lngOnly.includes('-') && supportedLng.slice(0, supportedLng.indexOf('-')) === lngOnly) return true;
|
|
973
|
+
if (supportedLng.startsWith(lngOnly) && lngOnly.length > 1) return true;
|
|
974
|
+
return false;
|
|
966
975
|
});
|
|
967
976
|
});
|
|
968
977
|
}
|
|
@@ -993,7 +1002,7 @@ class LanguageUtil {
|
|
|
993
1002
|
this.logger.warn(`rejecting language code not found in supportedLngs: ${c}`);
|
|
994
1003
|
}
|
|
995
1004
|
};
|
|
996
|
-
if (isString(code) && (code.
|
|
1005
|
+
if (isString(code) && (code.includes('-') || code.includes('_'))) {
|
|
997
1006
|
if (this.options.load !== 'languageOnly') addCode(this.formatLanguageCode(code));
|
|
998
1007
|
if (this.options.load !== 'languageOnly' && this.options.load !== 'currentOnly') addCode(this.getScriptPartFromCode(code));
|
|
999
1008
|
if (this.options.load !== 'currentOnly') addCode(this.getLanguagePartFromCode(code));
|
|
@@ -1001,7 +1010,7 @@ class LanguageUtil {
|
|
|
1001
1010
|
addCode(this.formatLanguageCode(code));
|
|
1002
1011
|
}
|
|
1003
1012
|
fallbackCodes.forEach(fc => {
|
|
1004
|
-
if (codes.
|
|
1013
|
+
if (!codes.includes(fc)) addCode(this.formatLanguageCode(fc));
|
|
1005
1014
|
});
|
|
1006
1015
|
return codes;
|
|
1007
1016
|
}
|
|
@@ -1157,7 +1166,7 @@ class Interpolator {
|
|
|
1157
1166
|
let replaces;
|
|
1158
1167
|
const defaultData = this.options && this.options.interpolation && this.options.interpolation.defaultVariables || {};
|
|
1159
1168
|
const handleFormat = key => {
|
|
1160
|
-
if (key.
|
|
1169
|
+
if (!key.includes(this.formatSeparator)) {
|
|
1161
1170
|
const path = deepFindWithDefaults(data, defaultData, key, this.options.keySeparator, this.options.ignoreJSONStructure);
|
|
1162
1171
|
return this.alwaysFormat ? this.format(path, undefined, lng, {
|
|
1163
1172
|
...options,
|
|
@@ -1227,7 +1236,7 @@ class Interpolator {
|
|
|
1227
1236
|
let clonedOptions;
|
|
1228
1237
|
const handleHasOptions = (key, inheritedOptions) => {
|
|
1229
1238
|
const sep = this.nestingOptionsSeparator;
|
|
1230
|
-
if (key.
|
|
1239
|
+
if (!key.includes(sep)) return key;
|
|
1231
1240
|
const c = key.split(new RegExp(`${regexEscape(sep)}[ ]*{`));
|
|
1232
1241
|
let optionsString = `{${c[1]}`;
|
|
1233
1242
|
key = c[0];
|
|
@@ -1247,7 +1256,7 @@ class Interpolator {
|
|
|
1247
1256
|
this.logger.warn(`failed parsing options string in nesting for key ${key}`, e);
|
|
1248
1257
|
return `${key}${sep}${optionsString}`;
|
|
1249
1258
|
}
|
|
1250
|
-
if (clonedOptions.defaultValue && clonedOptions.defaultValue.
|
|
1259
|
+
if (clonedOptions.defaultValue && clonedOptions.defaultValue.includes(this.prefix)) delete clonedOptions.defaultValue;
|
|
1251
1260
|
return key;
|
|
1252
1261
|
};
|
|
1253
1262
|
while (match = this.nestingRegexp.exec(str)) {
|
|
@@ -1286,13 +1295,13 @@ class Interpolator {
|
|
|
1286
1295
|
const parseFormatStr = formatStr => {
|
|
1287
1296
|
let formatName = formatStr.toLowerCase().trim();
|
|
1288
1297
|
const formatOptions = {};
|
|
1289
|
-
if (formatStr.
|
|
1298
|
+
if (formatStr.includes('(')) {
|
|
1290
1299
|
const p = formatStr.split('(');
|
|
1291
1300
|
formatName = p[0].toLowerCase().trim();
|
|
1292
|
-
const optStr = p[1].
|
|
1293
|
-
if (formatName === 'currency' && optStr.
|
|
1301
|
+
const optStr = p[1].slice(0, -1);
|
|
1302
|
+
if (formatName === 'currency' && !optStr.includes(':')) {
|
|
1294
1303
|
if (!formatOptions.currency) formatOptions.currency = optStr.trim();
|
|
1295
|
-
} else if (formatName === 'relativetime' && optStr.
|
|
1304
|
+
} else if (formatName === 'relativetime' && !optStr.includes(':')) {
|
|
1296
1305
|
if (!formatOptions.range) formatOptions.range = optStr.trim();
|
|
1297
1306
|
} else {
|
|
1298
1307
|
const opts = optStr.split(';');
|
|
@@ -1387,8 +1396,8 @@ class Formatter {
|
|
|
1387
1396
|
}
|
|
1388
1397
|
format(value, format, lng, options = {}) {
|
|
1389
1398
|
const formats = format.split(this.formatSeparator);
|
|
1390
|
-
if (formats.length > 1 && formats[0].indexOf('(') > 1 && formats[0].
|
|
1391
|
-
const lastIndex = formats.findIndex(f => f.
|
|
1399
|
+
if (formats.length > 1 && formats[0].indexOf('(') > 1 && !formats[0].includes(')') && formats.find(f => f.includes(')'))) {
|
|
1400
|
+
const lastIndex = formats.findIndex(f => f.includes(')'));
|
|
1392
1401
|
formats[0] = [formats[0], ...formats.splice(1, lastIndex)].join(this.formatSeparator);
|
|
1393
1402
|
}
|
|
1394
1403
|
const result = formats.reduce((mem, f) => {
|
|
@@ -1542,7 +1551,7 @@ class Connector extends EventEmitter {
|
|
|
1542
1551
|
}
|
|
1543
1552
|
if (err && data && tried < this.maxRetries) {
|
|
1544
1553
|
setTimeout(() => {
|
|
1545
|
-
this.read
|
|
1554
|
+
this.read(lng, ns, fcName, tried + 1, wait * 2, callback);
|
|
1546
1555
|
}, wait);
|
|
1547
1556
|
return;
|
|
1548
1557
|
}
|
|
@@ -1646,7 +1655,6 @@ const get = () => ({
|
|
|
1646
1655
|
nonExplicitSupportedLngs: false,
|
|
1647
1656
|
load: 'all',
|
|
1648
1657
|
preload: false,
|
|
1649
|
-
simplifyPluralSuffix: true,
|
|
1650
1658
|
keySeparator: '.',
|
|
1651
1659
|
nsSeparator: ':',
|
|
1652
1660
|
pluralSeparator: '_',
|
|
@@ -1683,7 +1691,6 @@ const get = () => ({
|
|
|
1683
1691
|
},
|
|
1684
1692
|
interpolation: {
|
|
1685
1693
|
escapeValue: true,
|
|
1686
|
-
format: value => value,
|
|
1687
1694
|
prefix: '{{',
|
|
1688
1695
|
suffix: '}}',
|
|
1689
1696
|
formatSeparator: ',',
|
|
@@ -1700,10 +1707,9 @@ const transformOptions = options => {
|
|
|
1700
1707
|
if (isString(options.ns)) options.ns = [options.ns];
|
|
1701
1708
|
if (isString(options.fallbackLng)) options.fallbackLng = [options.fallbackLng];
|
|
1702
1709
|
if (isString(options.fallbackNS)) options.fallbackNS = [options.fallbackNS];
|
|
1703
|
-
if (options.supportedLngs
|
|
1710
|
+
if (options.supportedLngs && !options.supportedLngs.includes('cimode')) {
|
|
1704
1711
|
options.supportedLngs = options.supportedLngs.concat(['cimode']);
|
|
1705
1712
|
}
|
|
1706
|
-
if (typeof options.initImmediate === 'boolean') options.initAsync = options.initImmediate;
|
|
1707
1713
|
return options;
|
|
1708
1714
|
};
|
|
1709
1715
|
|
|
@@ -1716,27 +1722,6 @@ const bindMemberFunctions = inst => {
|
|
|
1716
1722
|
}
|
|
1717
1723
|
});
|
|
1718
1724
|
};
|
|
1719
|
-
const SUPPORT_NOTICE_KEY = '__i18next_supportNoticeShown';
|
|
1720
|
-
const getSupportNoticeShown = () => {
|
|
1721
|
-
if (typeof globalThis !== 'undefined' && !!globalThis[SUPPORT_NOTICE_KEY]) return true;
|
|
1722
|
-
if (typeof process !== 'undefined' && process.env && process.env.I18NEXT_NO_SUPPORT_NOTICE) return true;
|
|
1723
|
-
return false;
|
|
1724
|
-
};
|
|
1725
|
-
const setSupportNoticeShown = () => {
|
|
1726
|
-
if (typeof globalThis !== 'undefined') globalThis[SUPPORT_NOTICE_KEY] = true;
|
|
1727
|
-
};
|
|
1728
|
-
const usesLocize = inst => {
|
|
1729
|
-
if (inst?.modules?.backend?.name?.indexOf('Locize') > 0) return true;
|
|
1730
|
-
if (inst?.modules?.backend?.constructor?.name?.indexOf('Locize') > 0) return true;
|
|
1731
|
-
if (inst?.options?.backend?.backends) {
|
|
1732
|
-
if (inst.options.backend.backends.some(b => b?.name?.indexOf('Locize') > 0 || b?.constructor?.name?.indexOf('Locize') > 0)) return true;
|
|
1733
|
-
}
|
|
1734
|
-
if (inst?.options?.backend?.projectId) return true;
|
|
1735
|
-
if (inst?.options?.backend?.backendOptions) {
|
|
1736
|
-
if (inst.options.backend.backendOptions.some(b => b?.projectId)) return true;
|
|
1737
|
-
}
|
|
1738
|
-
return false;
|
|
1739
|
-
};
|
|
1740
1725
|
class I18n extends EventEmitter {
|
|
1741
1726
|
constructor(options = {}, callback) {
|
|
1742
1727
|
super();
|
|
@@ -1766,7 +1751,7 @@ class I18n extends EventEmitter {
|
|
|
1766
1751
|
if (options.defaultNS == null && options.ns) {
|
|
1767
1752
|
if (isString(options.ns)) {
|
|
1768
1753
|
options.defaultNS = options.ns;
|
|
1769
|
-
} else if (options.ns.
|
|
1754
|
+
} else if (!options.ns.includes('translation')) {
|
|
1770
1755
|
options.defaultNS = options.ns[0];
|
|
1771
1756
|
}
|
|
1772
1757
|
}
|
|
@@ -1789,10 +1774,6 @@ class I18n extends EventEmitter {
|
|
|
1789
1774
|
if (typeof this.options.overloadTranslationOptionHandler !== 'function') {
|
|
1790
1775
|
this.options.overloadTranslationOptionHandler = defOpts.overloadTranslationOptionHandler;
|
|
1791
1776
|
}
|
|
1792
|
-
if (this.options.showSupportNotice !== false && !usesLocize(this) && !getSupportNoticeShown()) {
|
|
1793
|
-
if (typeof console !== 'undefined' && typeof console.info !== 'undefined') console.info('🌐 i18next is made possible by our own product, Locize — consider powering your project with managed localization (AI, CDN, integrations): https://locize.com 💙');
|
|
1794
|
-
setSupportNoticeShown();
|
|
1795
|
-
}
|
|
1796
1777
|
const createClassOnDemand = ClassOrObject => {
|
|
1797
1778
|
if (!ClassOrObject) return null;
|
|
1798
1779
|
if (typeof ClassOrObject === 'function') return new ClassOrObject();
|
|
@@ -1817,14 +1798,9 @@ class I18n extends EventEmitter {
|
|
|
1817
1798
|
s.resourceStore = this.store;
|
|
1818
1799
|
s.languageUtils = lu;
|
|
1819
1800
|
s.pluralResolver = new PluralResolver(lu, {
|
|
1820
|
-
prepend: this.options.pluralSeparator
|
|
1821
|
-
simplifyPluralSuffix: this.options.simplifyPluralSuffix
|
|
1801
|
+
prepend: this.options.pluralSeparator
|
|
1822
1802
|
});
|
|
1823
|
-
|
|
1824
|
-
if (usingLegacyFormatFunction) {
|
|
1825
|
-
this.logger.deprecate(`init: you are still using the legacy format function, please use the new approach: https://www.i18next.com/translation-function/formatting`);
|
|
1826
|
-
}
|
|
1827
|
-
if (formatter && (!this.options.interpolation.format || this.options.interpolation.format === defOpts.interpolation.format)) {
|
|
1803
|
+
if (formatter) {
|
|
1828
1804
|
s.formatter = createClassOnDemand(formatter);
|
|
1829
1805
|
if (s.formatter.init) s.formatter.init(s, this.options);
|
|
1830
1806
|
this.options.interpolation.format = s.formatter.format.bind(s.formatter);
|
|
@@ -1907,7 +1883,7 @@ class I18n extends EventEmitter {
|
|
|
1907
1883
|
const lngs = this.services.languageUtils.toResolveHierarchy(lng);
|
|
1908
1884
|
lngs.forEach(l => {
|
|
1909
1885
|
if (l === 'cimode') return;
|
|
1910
|
-
if (toLoad.
|
|
1886
|
+
if (!toLoad.includes(l)) toLoad.push(l);
|
|
1911
1887
|
});
|
|
1912
1888
|
};
|
|
1913
1889
|
if (!usedLng) {
|
|
@@ -1972,16 +1948,16 @@ class I18n extends EventEmitter {
|
|
|
1972
1948
|
}
|
|
1973
1949
|
setResolvedLanguage(l) {
|
|
1974
1950
|
if (!l || !this.languages) return;
|
|
1975
|
-
if (['cimode', 'dev'].
|
|
1951
|
+
if (['cimode', 'dev'].includes(l)) return;
|
|
1976
1952
|
for (let li = 0; li < this.languages.length; li++) {
|
|
1977
1953
|
const lngInLngs = this.languages[li];
|
|
1978
|
-
if (['cimode', 'dev'].
|
|
1954
|
+
if (['cimode', 'dev'].includes(lngInLngs)) continue;
|
|
1979
1955
|
if (this.store.hasLanguageSomeTranslations(lngInLngs)) {
|
|
1980
1956
|
this.resolvedLanguage = lngInLngs;
|
|
1981
1957
|
break;
|
|
1982
1958
|
}
|
|
1983
1959
|
}
|
|
1984
|
-
if (!this.resolvedLanguage && this.languages.
|
|
1960
|
+
if (!this.resolvedLanguage && !this.languages.includes(l) && this.store.hasLanguageSomeTranslations(l)) {
|
|
1985
1961
|
this.resolvedLanguage = l;
|
|
1986
1962
|
this.languages.unshift(l);
|
|
1987
1963
|
}
|
|
@@ -2123,7 +2099,7 @@ class I18n extends EventEmitter {
|
|
|
2123
2099
|
}
|
|
2124
2100
|
if (isString(ns)) ns = [ns];
|
|
2125
2101
|
ns.forEach(n => {
|
|
2126
|
-
if (this.options.ns.
|
|
2102
|
+
if (!this.options.ns.includes(n)) this.options.ns.push(n);
|
|
2127
2103
|
});
|
|
2128
2104
|
this.loadResources(err => {
|
|
2129
2105
|
deferred.resolve();
|
|
@@ -2135,7 +2111,7 @@ class I18n extends EventEmitter {
|
|
|
2135
2111
|
const deferred = defer();
|
|
2136
2112
|
if (isString(lngs)) lngs = [lngs];
|
|
2137
2113
|
const preloaded = this.options.preload || [];
|
|
2138
|
-
const newLngs = lngs.filter(lng => preloaded.
|
|
2114
|
+
const newLngs = lngs.filter(lng => !preloaded.includes(lng) && this.services.languageUtils.isSupportedCode(lng));
|
|
2139
2115
|
if (!newLngs.length) {
|
|
2140
2116
|
if (callback) callback();
|
|
2141
2117
|
return Promise.resolve();
|
|
@@ -2160,7 +2136,7 @@ class I18n extends EventEmitter {
|
|
|
2160
2136
|
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'];
|
|
2161
2137
|
const languageUtils = this.services?.languageUtils || new LanguageUtil(get());
|
|
2162
2138
|
if (lng.toLowerCase().indexOf('-latn') > 1) return 'ltr';
|
|
2163
|
-
return rtlLngs.
|
|
2139
|
+
return rtlLngs.includes(languageUtils.getLanguagePartFromCode(lng)) || lng.toLowerCase().indexOf('-arab') > 1 ? 'rtl' : 'ltr';
|
|
2164
2140
|
}
|
|
2165
2141
|
static createInstance(options = {}, callback) {
|
|
2166
2142
|
const instance = new I18n(options, callback);
|