@andre1502/react-utilities 0.9.0 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. package/README.md +72 -17
  2. package/dist/Config/Config.js +21 -4
  3. package/dist/Config/Config.js.map +1 -1
  4. package/dist/Config/Output.js +9 -1
  5. package/dist/Config/Output.js.map +1 -1
  6. package/dist/EnvironmentEnum-BjXsfSRZ.js +9 -0
  7. package/dist/EnvironmentEnum-BjXsfSRZ.js.map +1 -0
  8. package/dist/EnvironmentEnum-UcQ6Il1O.js +9 -0
  9. package/dist/EnvironmentEnum-UcQ6Il1O.js.map +1 -0
  10. package/dist/I18n/I18n.d.ts +6 -0
  11. package/dist/I18n/I18n.js +104 -0
  12. package/dist/I18n/I18n.js.map +1 -0
  13. package/dist/I18n-CB7SyXYJ.js +3291 -0
  14. package/dist/I18n-CB7SyXYJ.js.map +1 -0
  15. package/dist/I18n-yXLN_hDO.js +3288 -0
  16. package/dist/I18n-yXLN_hDO.js.map +1 -0
  17. package/dist/config-cli.cjs +34 -5
  18. package/dist/config-cli.cjs.map +1 -1
  19. package/dist/config-cli.d.ts +2 -0
  20. package/dist/config-cli.js +8 -0
  21. package/dist/config-cli.js.map +1 -1
  22. package/dist/config-cli.mjs +32 -7
  23. package/dist/config-cli.mjs.map +1 -1
  24. package/dist/enums/EnvironmentEnum.d.ts +5 -0
  25. package/dist/enums/EnvironmentEnum.js +13 -0
  26. package/dist/enums/EnvironmentEnum.js.map +1 -0
  27. package/dist/i18n.cjs +15 -0
  28. package/dist/i18n.cjs.map +1 -0
  29. package/dist/i18n.d.ts +3 -0
  30. package/dist/i18n.js +28 -0
  31. package/dist/i18n.js.map +1 -0
  32. package/dist/i18n.mjs +4 -0
  33. package/dist/i18n.mjs.map +1 -0
  34. package/dist/index-cli.cjs +5 -0
  35. package/dist/index-cli.cjs.map +1 -1
  36. package/dist/index-cli.mjs +1 -0
  37. package/dist/index-cli.mjs.map +1 -1
  38. package/dist/index-rn.cjs +9 -0
  39. package/dist/index-rn.cjs.map +1 -1
  40. package/dist/index-rn.d.ts +1 -0
  41. package/dist/index-rn.js +11 -0
  42. package/dist/index-rn.js.map +1 -1
  43. package/dist/index-rn.mjs +3 -0
  44. package/dist/index-rn.mjs.map +1 -1
  45. package/dist/index.cjs +9 -0
  46. package/dist/index.cjs.map +1 -1
  47. package/dist/index.d.ts +1 -0
  48. package/dist/index.js +11 -0
  49. package/dist/index.js.map +1 -1
  50. package/dist/index.mjs +3 -0
  51. package/dist/index.mjs.map +1 -1
  52. package/package.json +11 -6
  53. package/src/Config/Config.ts +22 -4
  54. package/src/Config/Output.ts +16 -7
  55. package/src/I18n/I18n.ts +117 -0
  56. package/src/config-cli.ts +2 -0
  57. package/src/enums/EnvironmentEnum.ts +5 -0
  58. package/src/i18n.ts +4 -0
  59. package/src/index-rn.ts +1 -0
  60. package/src/index.ts +1 -0
  61. package/dist/index-fmt.cjs +0 -16
  62. package/dist/index-fmt.cjs.map +0 -1
  63. package/dist/index-fmt.d.ts +0 -1
  64. package/dist/index-fmt.js +0 -17
  65. package/dist/index-fmt.js.map +0 -1
  66. package/dist/index-fmt.mjs +0 -3
  67. package/dist/index-fmt.mjs.map +0 -1
  68. package/src/index-fmt.ts +0 -1
@@ -0,0 +1,3288 @@
1
+ import require$$0 from 'cross-fetch';
2
+
3
+ function _mergeNamespaces(n, m) {
4
+ m.forEach(function (e) {
5
+ e && typeof e !== 'string' && !Array.isArray(e) && Object.keys(e).forEach(function (k) {
6
+ if (k !== 'default' && !(k in n)) {
7
+ var d = Object.getOwnPropertyDescriptor(e, k);
8
+ Object.defineProperty(n, k, d.get ? d : {
9
+ enumerable: true,
10
+ get: function () { return e[k]; }
11
+ });
12
+ }
13
+ });
14
+ });
15
+ return Object.freeze(n);
16
+ }
17
+
18
+ const isString = obj => typeof obj === 'string';
19
+ const defer = () => {
20
+ let res;
21
+ let rej;
22
+ const promise = new Promise((resolve, reject) => {
23
+ res = resolve;
24
+ rej = reject;
25
+ });
26
+ promise.resolve = res;
27
+ promise.reject = rej;
28
+ return promise;
29
+ };
30
+ const makeString = object => {
31
+ if (object == null) return '';
32
+ return '' + object;
33
+ };
34
+ const copy = (a, s, t) => {
35
+ a.forEach(m => {
36
+ if (s[m]) t[m] = s[m];
37
+ });
38
+ };
39
+ const lastOfPathSeparatorRegExp = /###/g;
40
+ const cleanKey = key => key && key.indexOf('###') > -1 ? key.replace(lastOfPathSeparatorRegExp, '.') : key;
41
+ const canNotTraverseDeeper = object => !object || isString(object);
42
+ const getLastOfPath = (object, path, Empty) => {
43
+ const stack = !isString(path) ? path : path.split('.');
44
+ let stackIndex = 0;
45
+ while (stackIndex < stack.length - 1) {
46
+ if (canNotTraverseDeeper(object)) return {};
47
+ const key = cleanKey(stack[stackIndex]);
48
+ if (!object[key] && Empty) object[key] = new Empty();
49
+ if (Object.prototype.hasOwnProperty.call(object, key)) {
50
+ object = object[key];
51
+ } else {
52
+ object = {};
53
+ }
54
+ ++stackIndex;
55
+ }
56
+ if (canNotTraverseDeeper(object)) return {};
57
+ return {
58
+ obj: object,
59
+ k: cleanKey(stack[stackIndex])
60
+ };
61
+ };
62
+ const setPath = (object, path, newValue) => {
63
+ const {
64
+ obj,
65
+ k
66
+ } = getLastOfPath(object, path, Object);
67
+ if (obj !== undefined || path.length === 1) {
68
+ obj[k] = newValue;
69
+ return;
70
+ }
71
+ let e = path[path.length - 1];
72
+ let p = path.slice(0, path.length - 1);
73
+ let last = getLastOfPath(object, p, Object);
74
+ while (last.obj === undefined && p.length) {
75
+ e = `${p[p.length - 1]}.${e}`;
76
+ p = p.slice(0, p.length - 1);
77
+ last = getLastOfPath(object, p, Object);
78
+ if (last && last.obj && typeof last.obj[`${last.k}.${e}`] !== 'undefined') {
79
+ last.obj = undefined;
80
+ }
81
+ }
82
+ last.obj[`${last.k}.${e}`] = newValue;
83
+ };
84
+ const pushPath = (object, path, newValue, concat) => {
85
+ const {
86
+ obj,
87
+ k
88
+ } = getLastOfPath(object, path, Object);
89
+ obj[k] = obj[k] || [];
90
+ obj[k].push(newValue);
91
+ };
92
+ const getPath = (object, path) => {
93
+ const {
94
+ obj,
95
+ k
96
+ } = getLastOfPath(object, path);
97
+ if (!obj) return undefined;
98
+ return obj[k];
99
+ };
100
+ const getPathWithDefaults = (data, defaultData, key) => {
101
+ const value = getPath(data, key);
102
+ if (value !== undefined) {
103
+ return value;
104
+ }
105
+ return getPath(defaultData, key);
106
+ };
107
+ const deepExtend = (target, source, overwrite) => {
108
+ for (const prop in source) {
109
+ if (prop !== '__proto__' && prop !== 'constructor') {
110
+ if (prop in target) {
111
+ if (isString(target[prop]) || target[prop] instanceof String || isString(source[prop]) || source[prop] instanceof String) {
112
+ if (overwrite) target[prop] = source[prop];
113
+ } else {
114
+ deepExtend(target[prop], source[prop], overwrite);
115
+ }
116
+ } else {
117
+ target[prop] = source[prop];
118
+ }
119
+ }
120
+ }
121
+ return target;
122
+ };
123
+ const regexEscape = str => str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
124
+ var _entityMap = {
125
+ '&': '&amp;',
126
+ '<': '&lt;',
127
+ '>': '&gt;',
128
+ '"': '&quot;',
129
+ "'": '&#39;',
130
+ '/': '&#x2F;'
131
+ };
132
+ const escape = data => {
133
+ if (isString(data)) {
134
+ return data.replace(/[&<>"'\/]/g, s => _entityMap[s]);
135
+ }
136
+ return data;
137
+ };
138
+ class RegExpCache {
139
+ constructor(capacity) {
140
+ this.capacity = capacity;
141
+ this.regExpMap = new Map();
142
+ this.regExpQueue = [];
143
+ }
144
+ getRegExp(pattern) {
145
+ const regExpFromCache = this.regExpMap.get(pattern);
146
+ if (regExpFromCache !== undefined) {
147
+ return regExpFromCache;
148
+ }
149
+ const regExpNew = new RegExp(pattern);
150
+ if (this.regExpQueue.length === this.capacity) {
151
+ this.regExpMap.delete(this.regExpQueue.shift());
152
+ }
153
+ this.regExpMap.set(pattern, regExpNew);
154
+ this.regExpQueue.push(pattern);
155
+ return regExpNew;
156
+ }
157
+ }
158
+ const chars = [' ', ',', '?', '!', ';'];
159
+ const looksLikeObjectPathRegExpCache = new RegExpCache(20);
160
+ const looksLikeObjectPath = (key, nsSeparator, keySeparator) => {
161
+ nsSeparator = nsSeparator || '';
162
+ keySeparator = keySeparator || '';
163
+ const possibleChars = chars.filter(c => nsSeparator.indexOf(c) < 0 && keySeparator.indexOf(c) < 0);
164
+ if (possibleChars.length === 0) return true;
165
+ const r = looksLikeObjectPathRegExpCache.getRegExp(`(${possibleChars.map(c => c === '?' ? '\\?' : c).join('|')})`);
166
+ let matched = !r.test(key);
167
+ if (!matched) {
168
+ const ki = key.indexOf(keySeparator);
169
+ if (ki > 0 && !r.test(key.substring(0, ki))) {
170
+ matched = true;
171
+ }
172
+ }
173
+ return matched;
174
+ };
175
+ const deepFind = function (obj, path) {
176
+ let keySeparator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '.';
177
+ if (!obj) return undefined;
178
+ if (obj[path]) return obj[path];
179
+ const tokens = path.split(keySeparator);
180
+ let current = obj;
181
+ for (let i = 0; i < tokens.length;) {
182
+ if (!current || typeof current !== 'object') {
183
+ return undefined;
184
+ }
185
+ let next;
186
+ let nextPath = '';
187
+ for (let j = i; j < tokens.length; ++j) {
188
+ if (j !== i) {
189
+ nextPath += keySeparator;
190
+ }
191
+ nextPath += tokens[j];
192
+ next = current[nextPath];
193
+ if (next !== undefined) {
194
+ if (['string', 'number', 'boolean'].indexOf(typeof next) > -1 && j < tokens.length - 1) {
195
+ continue;
196
+ }
197
+ i += j - i + 1;
198
+ break;
199
+ }
200
+ }
201
+ current = next;
202
+ }
203
+ return current;
204
+ };
205
+ const getCleanedCode = code => code && code.replace('_', '-');
206
+
207
+ const consoleLogger = {
208
+ type: 'logger',
209
+ log(args) {
210
+ this.output('log', args);
211
+ },
212
+ warn(args) {
213
+ this.output('warn', args);
214
+ },
215
+ error(args) {
216
+ this.output('error', args);
217
+ },
218
+ output(type, args) {
219
+ if (console && console[type]) console[type].apply(console, args);
220
+ }
221
+ };
222
+ class Logger {
223
+ constructor(concreteLogger) {
224
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
225
+ this.init(concreteLogger, options);
226
+ }
227
+ init(concreteLogger) {
228
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
229
+ this.prefix = options.prefix || 'i18next:';
230
+ this.logger = concreteLogger || consoleLogger;
231
+ this.options = options;
232
+ this.debug = options.debug;
233
+ }
234
+ log() {
235
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
236
+ args[_key] = arguments[_key];
237
+ }
238
+ return this.forward(args, 'log', '', true);
239
+ }
240
+ warn() {
241
+ for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
242
+ args[_key2] = arguments[_key2];
243
+ }
244
+ return this.forward(args, 'warn', '', true);
245
+ }
246
+ error() {
247
+ for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
248
+ args[_key3] = arguments[_key3];
249
+ }
250
+ return this.forward(args, 'error', '');
251
+ }
252
+ deprecate() {
253
+ for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
254
+ args[_key4] = arguments[_key4];
255
+ }
256
+ return this.forward(args, 'warn', 'WARNING DEPRECATED: ', true);
257
+ }
258
+ forward(args, lvl, prefix, debugOnly) {
259
+ if (debugOnly && !this.debug) return null;
260
+ if (isString(args[0])) args[0] = `${prefix}${this.prefix} ${args[0]}`;
261
+ return this.logger[lvl](args);
262
+ }
263
+ create(moduleName) {
264
+ return new Logger(this.logger, {
265
+ ...{
266
+ prefix: `${this.prefix}:${moduleName}:`
267
+ },
268
+ ...this.options
269
+ });
270
+ }
271
+ clone(options) {
272
+ options = options || this.options;
273
+ options.prefix = options.prefix || this.prefix;
274
+ return new Logger(this.logger, options);
275
+ }
276
+ }
277
+ var baseLogger = new Logger();
278
+
279
+ class EventEmitter {
280
+ constructor() {
281
+ this.observers = {};
282
+ }
283
+ on(events, listener) {
284
+ events.split(' ').forEach(event => {
285
+ if (!this.observers[event]) this.observers[event] = new Map();
286
+ const numListeners = this.observers[event].get(listener) || 0;
287
+ this.observers[event].set(listener, numListeners + 1);
288
+ });
289
+ return this;
290
+ }
291
+ off(event, listener) {
292
+ if (!this.observers[event]) return;
293
+ if (!listener) {
294
+ delete this.observers[event];
295
+ return;
296
+ }
297
+ this.observers[event].delete(listener);
298
+ }
299
+ emit(event) {
300
+ for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
301
+ args[_key - 1] = arguments[_key];
302
+ }
303
+ if (this.observers[event]) {
304
+ const cloned = Array.from(this.observers[event].entries());
305
+ cloned.forEach(_ref => {
306
+ let [observer, numTimesAdded] = _ref;
307
+ for (let i = 0; i < numTimesAdded; i++) {
308
+ observer(...args);
309
+ }
310
+ });
311
+ }
312
+ if (this.observers['*']) {
313
+ const cloned = Array.from(this.observers['*'].entries());
314
+ cloned.forEach(_ref2 => {
315
+ let [observer, numTimesAdded] = _ref2;
316
+ for (let i = 0; i < numTimesAdded; i++) {
317
+ observer.apply(observer, [event, ...args]);
318
+ }
319
+ });
320
+ }
321
+ }
322
+ }
323
+
324
+ class ResourceStore extends EventEmitter {
325
+ constructor(data) {
326
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
327
+ ns: ['translation'],
328
+ defaultNS: 'translation'
329
+ };
330
+ super();
331
+ this.data = data || {};
332
+ this.options = options;
333
+ if (this.options.keySeparator === undefined) {
334
+ this.options.keySeparator = '.';
335
+ }
336
+ if (this.options.ignoreJSONStructure === undefined) {
337
+ this.options.ignoreJSONStructure = true;
338
+ }
339
+ }
340
+ addNamespaces(ns) {
341
+ if (this.options.ns.indexOf(ns) < 0) {
342
+ this.options.ns.push(ns);
343
+ }
344
+ }
345
+ removeNamespaces(ns) {
346
+ const index = this.options.ns.indexOf(ns);
347
+ if (index > -1) {
348
+ this.options.ns.splice(index, 1);
349
+ }
350
+ }
351
+ getResource(lng, ns, key) {
352
+ let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
353
+ const keySeparator = options.keySeparator !== undefined ? options.keySeparator : this.options.keySeparator;
354
+ const ignoreJSONStructure = options.ignoreJSONStructure !== undefined ? options.ignoreJSONStructure : this.options.ignoreJSONStructure;
355
+ let path;
356
+ if (lng.indexOf('.') > -1) {
357
+ path = lng.split('.');
358
+ } else {
359
+ path = [lng, ns];
360
+ if (key) {
361
+ if (Array.isArray(key)) {
362
+ path.push(...key);
363
+ } else if (isString(key) && keySeparator) {
364
+ path.push(...key.split(keySeparator));
365
+ } else {
366
+ path.push(key);
367
+ }
368
+ }
369
+ }
370
+ const result = getPath(this.data, path);
371
+ if (!result && !ns && !key && lng.indexOf('.') > -1) {
372
+ lng = path[0];
373
+ ns = path[1];
374
+ key = path.slice(2).join('.');
375
+ }
376
+ if (result || !ignoreJSONStructure || !isString(key)) return result;
377
+ return deepFind(this.data && this.data[lng] && this.data[lng][ns], key, keySeparator);
378
+ }
379
+ addResource(lng, ns, key, value) {
380
+ let options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {
381
+ silent: false
382
+ };
383
+ const keySeparator = options.keySeparator !== undefined ? options.keySeparator : this.options.keySeparator;
384
+ let path = [lng, ns];
385
+ if (key) path = path.concat(keySeparator ? key.split(keySeparator) : key);
386
+ if (lng.indexOf('.') > -1) {
387
+ path = lng.split('.');
388
+ value = ns;
389
+ ns = path[1];
390
+ }
391
+ this.addNamespaces(ns);
392
+ setPath(this.data, path, value);
393
+ if (!options.silent) this.emit('added', lng, ns, key, value);
394
+ }
395
+ addResources(lng, ns, resources) {
396
+ let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {
397
+ silent: false
398
+ };
399
+ for (const m in resources) {
400
+ if (isString(resources[m]) || Array.isArray(resources[m])) this.addResource(lng, ns, m, resources[m], {
401
+ silent: true
402
+ });
403
+ }
404
+ if (!options.silent) this.emit('added', lng, ns, resources);
405
+ }
406
+ addResourceBundle(lng, ns, resources, deep, overwrite) {
407
+ let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {
408
+ silent: false,
409
+ skipCopy: false
410
+ };
411
+ let path = [lng, ns];
412
+ if (lng.indexOf('.') > -1) {
413
+ path = lng.split('.');
414
+ deep = resources;
415
+ resources = ns;
416
+ ns = path[1];
417
+ }
418
+ this.addNamespaces(ns);
419
+ let pack = getPath(this.data, path) || {};
420
+ if (!options.skipCopy) resources = JSON.parse(JSON.stringify(resources));
421
+ if (deep) {
422
+ deepExtend(pack, resources, overwrite);
423
+ } else {
424
+ pack = {
425
+ ...pack,
426
+ ...resources
427
+ };
428
+ }
429
+ setPath(this.data, path, pack);
430
+ if (!options.silent) this.emit('added', lng, ns, resources);
431
+ }
432
+ removeResourceBundle(lng, ns) {
433
+ if (this.hasResourceBundle(lng, ns)) {
434
+ delete this.data[lng][ns];
435
+ }
436
+ this.removeNamespaces(ns);
437
+ this.emit('removed', lng, ns);
438
+ }
439
+ hasResourceBundle(lng, ns) {
440
+ return this.getResource(lng, ns) !== undefined;
441
+ }
442
+ getResourceBundle(lng, ns) {
443
+ if (!ns) ns = this.options.defaultNS;
444
+ if (this.options.compatibilityAPI === 'v1') return {
445
+ ...{},
446
+ ...this.getResource(lng, ns)
447
+ };
448
+ return this.getResource(lng, ns);
449
+ }
450
+ getDataByLanguage(lng) {
451
+ return this.data[lng];
452
+ }
453
+ hasLanguageSomeTranslations(lng) {
454
+ const data = this.getDataByLanguage(lng);
455
+ const n = data && Object.keys(data) || [];
456
+ return !!n.find(v => data[v] && Object.keys(data[v]).length > 0);
457
+ }
458
+ toJSON() {
459
+ return this.data;
460
+ }
461
+ }
462
+
463
+ var postProcessor = {
464
+ processors: {},
465
+ addPostProcessor(module) {
466
+ this.processors[module.name] = module;
467
+ },
468
+ handle(processors, value, key, options, translator) {
469
+ processors.forEach(processor => {
470
+ if (this.processors[processor]) value = this.processors[processor].process(value, key, options, translator);
471
+ });
472
+ return value;
473
+ }
474
+ };
475
+
476
+ const checkedLoadedFor = {};
477
+ class Translator extends EventEmitter {
478
+ constructor(services) {
479
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
480
+ super();
481
+ copy(['resourceStore', 'languageUtils', 'pluralResolver', 'interpolator', 'backendConnector', 'i18nFormat', 'utils'], services, this);
482
+ this.options = options;
483
+ if (this.options.keySeparator === undefined) {
484
+ this.options.keySeparator = '.';
485
+ }
486
+ this.logger = baseLogger.create('translator');
487
+ }
488
+ changeLanguage(lng) {
489
+ if (lng) this.language = lng;
490
+ }
491
+ exists(key) {
492
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
493
+ interpolation: {}
494
+ };
495
+ if (key === undefined || key === null) {
496
+ return false;
497
+ }
498
+ const resolved = this.resolve(key, options);
499
+ return resolved && resolved.res !== undefined;
500
+ }
501
+ extractFromKey(key, options) {
502
+ let nsSeparator = options.nsSeparator !== undefined ? options.nsSeparator : this.options.nsSeparator;
503
+ if (nsSeparator === undefined) nsSeparator = ':';
504
+ const keySeparator = options.keySeparator !== undefined ? options.keySeparator : this.options.keySeparator;
505
+ let namespaces = options.ns || this.options.defaultNS || [];
506
+ const wouldCheckForNsInKey = nsSeparator && key.indexOf(nsSeparator) > -1;
507
+ const seemsNaturalLanguage = !this.options.userDefinedKeySeparator && !options.keySeparator && !this.options.userDefinedNsSeparator && !options.nsSeparator && !looksLikeObjectPath(key, nsSeparator, keySeparator);
508
+ if (wouldCheckForNsInKey && !seemsNaturalLanguage) {
509
+ const m = key.match(this.interpolator.nestingRegexp);
510
+ if (m && m.length > 0) {
511
+ return {
512
+ key,
513
+ namespaces: isString(namespaces) ? [namespaces] : namespaces
514
+ };
515
+ }
516
+ const parts = key.split(nsSeparator);
517
+ if (nsSeparator !== keySeparator || nsSeparator === keySeparator && this.options.ns.indexOf(parts[0]) > -1) namespaces = parts.shift();
518
+ key = parts.join(keySeparator);
519
+ }
520
+ return {
521
+ key,
522
+ namespaces: isString(namespaces) ? [namespaces] : namespaces
523
+ };
524
+ }
525
+ translate(keys, options, lastKey) {
526
+ if (typeof options !== 'object' && this.options.overloadTranslationOptionHandler) {
527
+ options = this.options.overloadTranslationOptionHandler(arguments);
528
+ }
529
+ if (typeof options === 'object') options = {
530
+ ...options
531
+ };
532
+ if (!options) options = {};
533
+ if (keys === undefined || keys === null) return '';
534
+ if (!Array.isArray(keys)) keys = [String(keys)];
535
+ const returnDetails = options.returnDetails !== undefined ? options.returnDetails : this.options.returnDetails;
536
+ const keySeparator = options.keySeparator !== undefined ? options.keySeparator : this.options.keySeparator;
537
+ const {
538
+ key,
539
+ namespaces
540
+ } = this.extractFromKey(keys[keys.length - 1], options);
541
+ const namespace = namespaces[namespaces.length - 1];
542
+ const lng = options.lng || this.language;
543
+ const appendNamespaceToCIMode = options.appendNamespaceToCIMode || this.options.appendNamespaceToCIMode;
544
+ if (lng && lng.toLowerCase() === 'cimode') {
545
+ if (appendNamespaceToCIMode) {
546
+ const nsSeparator = options.nsSeparator || this.options.nsSeparator;
547
+ if (returnDetails) {
548
+ return {
549
+ res: `${namespace}${nsSeparator}${key}`,
550
+ usedKey: key,
551
+ exactUsedKey: key,
552
+ usedLng: lng,
553
+ usedNS: namespace,
554
+ usedParams: this.getUsedParamsDetails(options)
555
+ };
556
+ }
557
+ return `${namespace}${nsSeparator}${key}`;
558
+ }
559
+ if (returnDetails) {
560
+ return {
561
+ res: key,
562
+ usedKey: key,
563
+ exactUsedKey: key,
564
+ usedLng: lng,
565
+ usedNS: namespace,
566
+ usedParams: this.getUsedParamsDetails(options)
567
+ };
568
+ }
569
+ return key;
570
+ }
571
+ const resolved = this.resolve(keys, options);
572
+ let res = resolved && resolved.res;
573
+ const resUsedKey = resolved && resolved.usedKey || key;
574
+ const resExactUsedKey = resolved && resolved.exactUsedKey || key;
575
+ const resType = Object.prototype.toString.apply(res);
576
+ const noObject = ['[object Number]', '[object Function]', '[object RegExp]'];
577
+ const joinArrays = options.joinArrays !== undefined ? options.joinArrays : this.options.joinArrays;
578
+ const handleAsObjectInI18nFormat = !this.i18nFormat || this.i18nFormat.handleAsObject;
579
+ const handleAsObject = !isString(res) && typeof res !== 'boolean' && typeof res !== 'number';
580
+ if (handleAsObjectInI18nFormat && res && handleAsObject && noObject.indexOf(resType) < 0 && !(isString(joinArrays) && Array.isArray(res))) {
581
+ if (!options.returnObjects && !this.options.returnObjects) {
582
+ if (!this.options.returnedObjectHandler) {
583
+ this.logger.warn('accessing an object - but returnObjects options is not enabled!');
584
+ }
585
+ const r = this.options.returnedObjectHandler ? this.options.returnedObjectHandler(resUsedKey, res, {
586
+ ...options,
587
+ ns: namespaces
588
+ }) : `key '${key} (${this.language})' returned an object instead of string.`;
589
+ if (returnDetails) {
590
+ resolved.res = r;
591
+ resolved.usedParams = this.getUsedParamsDetails(options);
592
+ return resolved;
593
+ }
594
+ return r;
595
+ }
596
+ if (keySeparator) {
597
+ const resTypeIsArray = Array.isArray(res);
598
+ const copy = resTypeIsArray ? [] : {};
599
+ const newKeyToUse = resTypeIsArray ? resExactUsedKey : resUsedKey;
600
+ for (const m in res) {
601
+ if (Object.prototype.hasOwnProperty.call(res, m)) {
602
+ const deepKey = `${newKeyToUse}${keySeparator}${m}`;
603
+ copy[m] = this.translate(deepKey, {
604
+ ...options,
605
+ ...{
606
+ joinArrays: false,
607
+ ns: namespaces
608
+ }
609
+ });
610
+ if (copy[m] === deepKey) copy[m] = res[m];
611
+ }
612
+ }
613
+ res = copy;
614
+ }
615
+ } else if (handleAsObjectInI18nFormat && isString(joinArrays) && Array.isArray(res)) {
616
+ res = res.join(joinArrays);
617
+ if (res) res = this.extendTranslation(res, keys, options, lastKey);
618
+ } else {
619
+ let usedDefault = false;
620
+ let usedKey = false;
621
+ const needsPluralHandling = options.count !== undefined && !isString(options.count);
622
+ const hasDefaultValue = Translator.hasDefaultValue(options);
623
+ const defaultValueSuffix = needsPluralHandling ? this.pluralResolver.getSuffix(lng, options.count, options) : '';
624
+ const defaultValueSuffixOrdinalFallback = options.ordinal && needsPluralHandling ? this.pluralResolver.getSuffix(lng, options.count, {
625
+ ordinal: false
626
+ }) : '';
627
+ const needsZeroSuffixLookup = needsPluralHandling && !options.ordinal && options.count === 0 && this.pluralResolver.shouldUseIntlApi();
628
+ const defaultValue = needsZeroSuffixLookup && options[`defaultValue${this.options.pluralSeparator}zero`] || options[`defaultValue${defaultValueSuffix}`] || options[`defaultValue${defaultValueSuffixOrdinalFallback}`] || options.defaultValue;
629
+ if (!this.isValidLookup(res) && hasDefaultValue) {
630
+ usedDefault = true;
631
+ res = defaultValue;
632
+ }
633
+ if (!this.isValidLookup(res)) {
634
+ usedKey = true;
635
+ res = key;
636
+ }
637
+ const missingKeyNoValueFallbackToKey = options.missingKeyNoValueFallbackToKey || this.options.missingKeyNoValueFallbackToKey;
638
+ const resForMissing = missingKeyNoValueFallbackToKey && usedKey ? undefined : res;
639
+ const updateMissing = hasDefaultValue && defaultValue !== res && this.options.updateMissing;
640
+ if (usedKey || usedDefault || updateMissing) {
641
+ this.logger.log(updateMissing ? 'updateKey' : 'missingKey', lng, namespace, key, updateMissing ? defaultValue : res);
642
+ if (keySeparator) {
643
+ const fk = this.resolve(key, {
644
+ ...options,
645
+ keySeparator: false
646
+ });
647
+ if (fk && fk.res) this.logger.warn('Seems the loaded translations were in flat JSON format instead of nested. Either set keySeparator: false on init or make sure your translations are published in nested format.');
648
+ }
649
+ let lngs = [];
650
+ const fallbackLngs = this.languageUtils.getFallbackCodes(this.options.fallbackLng, options.lng || this.language);
651
+ if (this.options.saveMissingTo === 'fallback' && fallbackLngs && fallbackLngs[0]) {
652
+ for (let i = 0; i < fallbackLngs.length; i++) {
653
+ lngs.push(fallbackLngs[i]);
654
+ }
655
+ } else if (this.options.saveMissingTo === 'all') {
656
+ lngs = this.languageUtils.toResolveHierarchy(options.lng || this.language);
657
+ } else {
658
+ lngs.push(options.lng || this.language);
659
+ }
660
+ const send = (l, k, specificDefaultValue) => {
661
+ const defaultForMissing = hasDefaultValue && specificDefaultValue !== res ? specificDefaultValue : resForMissing;
662
+ if (this.options.missingKeyHandler) {
663
+ this.options.missingKeyHandler(l, namespace, k, defaultForMissing, updateMissing, options);
664
+ } else if (this.backendConnector && this.backendConnector.saveMissing) {
665
+ this.backendConnector.saveMissing(l, namespace, k, defaultForMissing, updateMissing, options);
666
+ }
667
+ this.emit('missingKey', l, namespace, k, res);
668
+ };
669
+ if (this.options.saveMissing) {
670
+ if (this.options.saveMissingPlurals && needsPluralHandling) {
671
+ lngs.forEach(language => {
672
+ const suffixes = this.pluralResolver.getSuffixes(language, options);
673
+ if (needsZeroSuffixLookup && options[`defaultValue${this.options.pluralSeparator}zero`] && suffixes.indexOf(`${this.options.pluralSeparator}zero`) < 0) {
674
+ suffixes.push(`${this.options.pluralSeparator}zero`);
675
+ }
676
+ suffixes.forEach(suffix => {
677
+ send([language], key + suffix, options[`defaultValue${suffix}`] || defaultValue);
678
+ });
679
+ });
680
+ } else {
681
+ send(lngs, key, defaultValue);
682
+ }
683
+ }
684
+ }
685
+ res = this.extendTranslation(res, keys, options, resolved, lastKey);
686
+ if (usedKey && res === key && this.options.appendNamespaceToMissingKey) res = `${namespace}:${key}`;
687
+ if ((usedKey || usedDefault) && this.options.parseMissingKeyHandler) {
688
+ if (this.options.compatibilityAPI !== 'v1') {
689
+ res = this.options.parseMissingKeyHandler(this.options.appendNamespaceToMissingKey ? `${namespace}:${key}` : key, usedDefault ? res : undefined);
690
+ } else {
691
+ res = this.options.parseMissingKeyHandler(res);
692
+ }
693
+ }
694
+ }
695
+ if (returnDetails) {
696
+ resolved.res = res;
697
+ resolved.usedParams = this.getUsedParamsDetails(options);
698
+ return resolved;
699
+ }
700
+ return res;
701
+ }
702
+ extendTranslation(res, key, options, resolved, lastKey) {
703
+ var _this = this;
704
+ if (this.i18nFormat && this.i18nFormat.parse) {
705
+ res = this.i18nFormat.parse(res, {
706
+ ...this.options.interpolation.defaultVariables,
707
+ ...options
708
+ }, options.lng || this.language || resolved.usedLng, resolved.usedNS, resolved.usedKey, {
709
+ resolved
710
+ });
711
+ } else if (!options.skipInterpolation) {
712
+ if (options.interpolation) this.interpolator.init({
713
+ ...options,
714
+ ...{
715
+ interpolation: {
716
+ ...this.options.interpolation,
717
+ ...options.interpolation
718
+ }
719
+ }
720
+ });
721
+ const skipOnVariables = isString(res) && (options && options.interpolation && options.interpolation.skipOnVariables !== undefined ? options.interpolation.skipOnVariables : this.options.interpolation.skipOnVariables);
722
+ let nestBef;
723
+ if (skipOnVariables) {
724
+ const nb = res.match(this.interpolator.nestingRegexp);
725
+ nestBef = nb && nb.length;
726
+ }
727
+ let data = options.replace && !isString(options.replace) ? options.replace : options;
728
+ if (this.options.interpolation.defaultVariables) data = {
729
+ ...this.options.interpolation.defaultVariables,
730
+ ...data
731
+ };
732
+ res = this.interpolator.interpolate(res, data, options.lng || this.language || resolved.usedLng, options);
733
+ if (skipOnVariables) {
734
+ const na = res.match(this.interpolator.nestingRegexp);
735
+ const nestAft = na && na.length;
736
+ if (nestBef < nestAft) options.nest = false;
737
+ }
738
+ if (!options.lng && this.options.compatibilityAPI !== 'v1' && resolved && resolved.res) options.lng = this.language || resolved.usedLng;
739
+ if (options.nest !== false) res = this.interpolator.nest(res, function () {
740
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
741
+ args[_key] = arguments[_key];
742
+ }
743
+ if (lastKey && lastKey[0] === args[0] && !options.context) {
744
+ _this.logger.warn(`It seems you are nesting recursively key: ${args[0]} in key: ${key[0]}`);
745
+ return null;
746
+ }
747
+ return _this.translate(...args, key);
748
+ }, options);
749
+ if (options.interpolation) this.interpolator.reset();
750
+ }
751
+ const postProcess = options.postProcess || this.options.postProcess;
752
+ const postProcessorNames = isString(postProcess) ? [postProcess] : postProcess;
753
+ if (res !== undefined && res !== null && postProcessorNames && postProcessorNames.length && options.applyPostProcessor !== false) {
754
+ res = postProcessor.handle(postProcessorNames, res, key, this.options && this.options.postProcessPassResolved ? {
755
+ i18nResolved: {
756
+ ...resolved,
757
+ usedParams: this.getUsedParamsDetails(options)
758
+ },
759
+ ...options
760
+ } : options, this);
761
+ }
762
+ return res;
763
+ }
764
+ resolve(keys) {
765
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
766
+ let found;
767
+ let usedKey;
768
+ let exactUsedKey;
769
+ let usedLng;
770
+ let usedNS;
771
+ if (isString(keys)) keys = [keys];
772
+ keys.forEach(k => {
773
+ if (this.isValidLookup(found)) return;
774
+ const extracted = this.extractFromKey(k, options);
775
+ const key = extracted.key;
776
+ usedKey = key;
777
+ let namespaces = extracted.namespaces;
778
+ if (this.options.fallbackNS) namespaces = namespaces.concat(this.options.fallbackNS);
779
+ const needsPluralHandling = options.count !== undefined && !isString(options.count);
780
+ const needsZeroSuffixLookup = needsPluralHandling && !options.ordinal && options.count === 0 && this.pluralResolver.shouldUseIntlApi();
781
+ const needsContextHandling = options.context !== undefined && (isString(options.context) || typeof options.context === 'number') && options.context !== '';
782
+ const codes = options.lngs ? options.lngs : this.languageUtils.toResolveHierarchy(options.lng || this.language, options.fallbackLng);
783
+ namespaces.forEach(ns => {
784
+ if (this.isValidLookup(found)) return;
785
+ usedNS = ns;
786
+ if (!checkedLoadedFor[`${codes[0]}-${ns}`] && this.utils && this.utils.hasLoadedNamespace && !this.utils.hasLoadedNamespace(usedNS)) {
787
+ checkedLoadedFor[`${codes[0]}-${ns}`] = true;
788
+ 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!!!');
789
+ }
790
+ codes.forEach(code => {
791
+ if (this.isValidLookup(found)) return;
792
+ usedLng = code;
793
+ const finalKeys = [key];
794
+ if (this.i18nFormat && this.i18nFormat.addLookupKeys) {
795
+ this.i18nFormat.addLookupKeys(finalKeys, key, code, ns, options);
796
+ } else {
797
+ let pluralSuffix;
798
+ if (needsPluralHandling) pluralSuffix = this.pluralResolver.getSuffix(code, options.count, options);
799
+ const zeroSuffix = `${this.options.pluralSeparator}zero`;
800
+ const ordinalPrefix = `${this.options.pluralSeparator}ordinal${this.options.pluralSeparator}`;
801
+ if (needsPluralHandling) {
802
+ finalKeys.push(key + pluralSuffix);
803
+ if (options.ordinal && pluralSuffix.indexOf(ordinalPrefix) === 0) {
804
+ finalKeys.push(key + pluralSuffix.replace(ordinalPrefix, this.options.pluralSeparator));
805
+ }
806
+ if (needsZeroSuffixLookup) {
807
+ finalKeys.push(key + zeroSuffix);
808
+ }
809
+ }
810
+ if (needsContextHandling) {
811
+ const contextKey = `${key}${this.options.contextSeparator}${options.context}`;
812
+ finalKeys.push(contextKey);
813
+ if (needsPluralHandling) {
814
+ finalKeys.push(contextKey + pluralSuffix);
815
+ if (options.ordinal && pluralSuffix.indexOf(ordinalPrefix) === 0) {
816
+ finalKeys.push(contextKey + pluralSuffix.replace(ordinalPrefix, this.options.pluralSeparator));
817
+ }
818
+ if (needsZeroSuffixLookup) {
819
+ finalKeys.push(contextKey + zeroSuffix);
820
+ }
821
+ }
822
+ }
823
+ }
824
+ let possibleKey;
825
+ while (possibleKey = finalKeys.pop()) {
826
+ if (!this.isValidLookup(found)) {
827
+ exactUsedKey = possibleKey;
828
+ found = this.getResource(code, ns, possibleKey, options);
829
+ }
830
+ }
831
+ });
832
+ });
833
+ });
834
+ return {
835
+ res: found,
836
+ usedKey,
837
+ exactUsedKey,
838
+ usedLng,
839
+ usedNS
840
+ };
841
+ }
842
+ isValidLookup(res) {
843
+ return res !== undefined && !(!this.options.returnNull && res === null) && !(!this.options.returnEmptyString && res === '');
844
+ }
845
+ getResource(code, ns, key) {
846
+ let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
847
+ if (this.i18nFormat && this.i18nFormat.getResource) return this.i18nFormat.getResource(code, ns, key, options);
848
+ return this.resourceStore.getResource(code, ns, key, options);
849
+ }
850
+ getUsedParamsDetails() {
851
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
852
+ const optionsKeys = ['defaultValue', 'ordinal', 'context', 'replace', 'lng', 'lngs', 'fallbackLng', 'ns', 'keySeparator', 'nsSeparator', 'returnObjects', 'returnDetails', 'joinArrays', 'postProcess', 'interpolation'];
853
+ const useOptionsReplaceForData = options.replace && !isString(options.replace);
854
+ let data = useOptionsReplaceForData ? options.replace : options;
855
+ if (useOptionsReplaceForData && typeof options.count !== 'undefined') {
856
+ data.count = options.count;
857
+ }
858
+ if (this.options.interpolation.defaultVariables) {
859
+ data = {
860
+ ...this.options.interpolation.defaultVariables,
861
+ ...data
862
+ };
863
+ }
864
+ if (!useOptionsReplaceForData) {
865
+ data = {
866
+ ...data
867
+ };
868
+ for (const key of optionsKeys) {
869
+ delete data[key];
870
+ }
871
+ }
872
+ return data;
873
+ }
874
+ static hasDefaultValue(options) {
875
+ const prefix = 'defaultValue';
876
+ for (const option in options) {
877
+ if (Object.prototype.hasOwnProperty.call(options, option) && prefix === option.substring(0, prefix.length) && undefined !== options[option]) {
878
+ return true;
879
+ }
880
+ }
881
+ return false;
882
+ }
883
+ }
884
+
885
+ const capitalize = string => string.charAt(0).toUpperCase() + string.slice(1);
886
+ class LanguageUtil {
887
+ constructor(options) {
888
+ this.options = options;
889
+ this.supportedLngs = this.options.supportedLngs || false;
890
+ this.logger = baseLogger.create('languageUtils');
891
+ }
892
+ getScriptPartFromCode(code) {
893
+ code = getCleanedCode(code);
894
+ if (!code || code.indexOf('-') < 0) return null;
895
+ const p = code.split('-');
896
+ if (p.length === 2) return null;
897
+ p.pop();
898
+ if (p[p.length - 1].toLowerCase() === 'x') return null;
899
+ return this.formatLanguageCode(p.join('-'));
900
+ }
901
+ getLanguagePartFromCode(code) {
902
+ code = getCleanedCode(code);
903
+ if (!code || code.indexOf('-') < 0) return code;
904
+ const p = code.split('-');
905
+ return this.formatLanguageCode(p[0]);
906
+ }
907
+ formatLanguageCode(code) {
908
+ if (isString(code) && code.indexOf('-') > -1) {
909
+ if (typeof Intl !== 'undefined' && typeof Intl.getCanonicalLocales !== 'undefined') {
910
+ try {
911
+ let formattedCode = Intl.getCanonicalLocales(code)[0];
912
+ if (formattedCode && this.options.lowerCaseLng) {
913
+ formattedCode = formattedCode.toLowerCase();
914
+ }
915
+ if (formattedCode) return formattedCode;
916
+ } catch (e) {}
917
+ }
918
+ const specialCases = ['hans', 'hant', 'latn', 'cyrl', 'cans', 'mong', 'arab'];
919
+ let p = code.split('-');
920
+ if (this.options.lowerCaseLng) {
921
+ p = p.map(part => part.toLowerCase());
922
+ } else if (p.length === 2) {
923
+ p[0] = p[0].toLowerCase();
924
+ p[1] = p[1].toUpperCase();
925
+ if (specialCases.indexOf(p[1].toLowerCase()) > -1) p[1] = capitalize(p[1].toLowerCase());
926
+ } else if (p.length === 3) {
927
+ p[0] = p[0].toLowerCase();
928
+ if (p[1].length === 2) p[1] = p[1].toUpperCase();
929
+ if (p[0] !== 'sgn' && p[2].length === 2) p[2] = p[2].toUpperCase();
930
+ if (specialCases.indexOf(p[1].toLowerCase()) > -1) p[1] = capitalize(p[1].toLowerCase());
931
+ if (specialCases.indexOf(p[2].toLowerCase()) > -1) p[2] = capitalize(p[2].toLowerCase());
932
+ }
933
+ return p.join('-');
934
+ }
935
+ return this.options.cleanCode || this.options.lowerCaseLng ? code.toLowerCase() : code;
936
+ }
937
+ isSupportedCode(code) {
938
+ if (this.options.load === 'languageOnly' || this.options.nonExplicitSupportedLngs) {
939
+ code = this.getLanguagePartFromCode(code);
940
+ }
941
+ return !this.supportedLngs || !this.supportedLngs.length || this.supportedLngs.indexOf(code) > -1;
942
+ }
943
+ getBestMatchFromCodes(codes) {
944
+ if (!codes) return null;
945
+ let found;
946
+ codes.forEach(code => {
947
+ if (found) return;
948
+ const cleanedLng = this.formatLanguageCode(code);
949
+ if (!this.options.supportedLngs || this.isSupportedCode(cleanedLng)) found = cleanedLng;
950
+ });
951
+ if (!found && this.options.supportedLngs) {
952
+ codes.forEach(code => {
953
+ if (found) return;
954
+ const lngOnly = this.getLanguagePartFromCode(code);
955
+ if (this.isSupportedCode(lngOnly)) return found = lngOnly;
956
+ found = this.options.supportedLngs.find(supportedLng => {
957
+ if (supportedLng === lngOnly) return supportedLng;
958
+ if (supportedLng.indexOf('-') < 0 && lngOnly.indexOf('-') < 0) return;
959
+ if (supportedLng.indexOf('-') > 0 && lngOnly.indexOf('-') < 0 && supportedLng.substring(0, supportedLng.indexOf('-')) === lngOnly) return supportedLng;
960
+ if (supportedLng.indexOf(lngOnly) === 0 && lngOnly.length > 1) return supportedLng;
961
+ });
962
+ });
963
+ }
964
+ if (!found) found = this.getFallbackCodes(this.options.fallbackLng)[0];
965
+ return found;
966
+ }
967
+ getFallbackCodes(fallbacks, code) {
968
+ if (!fallbacks) return [];
969
+ if (typeof fallbacks === 'function') fallbacks = fallbacks(code);
970
+ if (isString(fallbacks)) fallbacks = [fallbacks];
971
+ if (Array.isArray(fallbacks)) return fallbacks;
972
+ if (!code) return fallbacks.default || [];
973
+ let found = fallbacks[code];
974
+ if (!found) found = fallbacks[this.getScriptPartFromCode(code)];
975
+ if (!found) found = fallbacks[this.formatLanguageCode(code)];
976
+ if (!found) found = fallbacks[this.getLanguagePartFromCode(code)];
977
+ if (!found) found = fallbacks.default;
978
+ return found || [];
979
+ }
980
+ toResolveHierarchy(code, fallbackCode) {
981
+ const fallbackCodes = this.getFallbackCodes(fallbackCode || this.options.fallbackLng || [], code);
982
+ const codes = [];
983
+ const addCode = c => {
984
+ if (!c) return;
985
+ if (this.isSupportedCode(c)) {
986
+ codes.push(c);
987
+ } else {
988
+ this.logger.warn(`rejecting language code not found in supportedLngs: ${c}`);
989
+ }
990
+ };
991
+ if (isString(code) && (code.indexOf('-') > -1 || code.indexOf('_') > -1)) {
992
+ if (this.options.load !== 'languageOnly') addCode(this.formatLanguageCode(code));
993
+ if (this.options.load !== 'languageOnly' && this.options.load !== 'currentOnly') addCode(this.getScriptPartFromCode(code));
994
+ if (this.options.load !== 'currentOnly') addCode(this.getLanguagePartFromCode(code));
995
+ } else if (isString(code)) {
996
+ addCode(this.formatLanguageCode(code));
997
+ }
998
+ fallbackCodes.forEach(fc => {
999
+ if (codes.indexOf(fc) < 0) addCode(this.formatLanguageCode(fc));
1000
+ });
1001
+ return codes;
1002
+ }
1003
+ }
1004
+
1005
+ let sets = [{
1006
+ lngs: ['ach', 'ak', 'am', 'arn', 'br', 'fil', 'gun', 'ln', 'mfe', 'mg', 'mi', 'oc', 'pt', 'pt-BR', 'tg', 'tl', 'ti', 'tr', 'uz', 'wa'],
1007
+ nr: [1, 2],
1008
+ fc: 1
1009
+ }, {
1010
+ lngs: ['af', 'an', 'ast', 'az', 'bg', 'bn', 'ca', 'da', 'de', 'dev', 'el', 'en', 'eo', 'es', 'et', 'eu', 'fi', 'fo', 'fur', 'fy', 'gl', 'gu', 'ha', 'hi', 'hu', 'hy', 'ia', 'it', 'kk', 'kn', 'ku', 'lb', 'mai', 'ml', 'mn', 'mr', 'nah', 'nap', 'nb', 'ne', 'nl', 'nn', 'no', 'nso', 'pa', 'pap', 'pms', 'ps', 'pt-PT', 'rm', 'sco', 'se', 'si', 'so', 'son', 'sq', 'sv', 'sw', 'ta', 'te', 'tk', 'ur', 'yo'],
1011
+ nr: [1, 2],
1012
+ fc: 2
1013
+ }, {
1014
+ lngs: ['ay', 'bo', 'cgg', 'fa', 'ht', 'id', 'ja', 'jbo', 'ka', 'km', 'ko', 'ky', 'lo', 'ms', 'sah', 'su', 'th', 'tt', 'ug', 'vi', 'wo', 'zh'],
1015
+ nr: [1],
1016
+ fc: 3
1017
+ }, {
1018
+ lngs: ['be', 'bs', 'cnr', 'dz', 'hr', 'ru', 'sr', 'uk'],
1019
+ nr: [1, 2, 5],
1020
+ fc: 4
1021
+ }, {
1022
+ lngs: ['ar'],
1023
+ nr: [0, 1, 2, 3, 11, 100],
1024
+ fc: 5
1025
+ }, {
1026
+ lngs: ['cs', 'sk'],
1027
+ nr: [1, 2, 5],
1028
+ fc: 6
1029
+ }, {
1030
+ lngs: ['csb', 'pl'],
1031
+ nr: [1, 2, 5],
1032
+ fc: 7
1033
+ }, {
1034
+ lngs: ['cy'],
1035
+ nr: [1, 2, 3, 8],
1036
+ fc: 8
1037
+ }, {
1038
+ lngs: ['fr'],
1039
+ nr: [1, 2],
1040
+ fc: 9
1041
+ }, {
1042
+ lngs: ['ga'],
1043
+ nr: [1, 2, 3, 7, 11],
1044
+ fc: 10
1045
+ }, {
1046
+ lngs: ['gd'],
1047
+ nr: [1, 2, 3, 20],
1048
+ fc: 11
1049
+ }, {
1050
+ lngs: ['is'],
1051
+ nr: [1, 2],
1052
+ fc: 12
1053
+ }, {
1054
+ lngs: ['jv'],
1055
+ nr: [0, 1],
1056
+ fc: 13
1057
+ }, {
1058
+ lngs: ['kw'],
1059
+ nr: [1, 2, 3, 4],
1060
+ fc: 14
1061
+ }, {
1062
+ lngs: ['lt'],
1063
+ nr: [1, 2, 10],
1064
+ fc: 15
1065
+ }, {
1066
+ lngs: ['lv'],
1067
+ nr: [1, 2, 0],
1068
+ fc: 16
1069
+ }, {
1070
+ lngs: ['mk'],
1071
+ nr: [1, 2],
1072
+ fc: 17
1073
+ }, {
1074
+ lngs: ['mnk'],
1075
+ nr: [0, 1, 2],
1076
+ fc: 18
1077
+ }, {
1078
+ lngs: ['mt'],
1079
+ nr: [1, 2, 11, 20],
1080
+ fc: 19
1081
+ }, {
1082
+ lngs: ['or'],
1083
+ nr: [2, 1],
1084
+ fc: 2
1085
+ }, {
1086
+ lngs: ['ro'],
1087
+ nr: [1, 2, 20],
1088
+ fc: 20
1089
+ }, {
1090
+ lngs: ['sl'],
1091
+ nr: [5, 1, 2, 3],
1092
+ fc: 21
1093
+ }, {
1094
+ lngs: ['he', 'iw'],
1095
+ nr: [1, 2, 20, 21],
1096
+ fc: 22
1097
+ }];
1098
+ let _rulesPluralsTypes = {
1099
+ 1: n => Number(n > 1),
1100
+ 2: n => Number(n != 1),
1101
+ 3: n => 0,
1102
+ 4: n => Number(n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2),
1103
+ 5: n => Number(n == 0 ? 0 : n == 1 ? 1 : n == 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5),
1104
+ 6: n => Number(n == 1 ? 0 : n >= 2 && n <= 4 ? 1 : 2),
1105
+ 7: n => Number(n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2),
1106
+ 8: n => Number(n == 1 ? 0 : n == 2 ? 1 : n != 8 && n != 11 ? 2 : 3),
1107
+ 9: n => Number(n >= 2),
1108
+ 10: n => Number(n == 1 ? 0 : n == 2 ? 1 : n < 7 ? 2 : n < 11 ? 3 : 4),
1109
+ 11: n => Number(n == 1 || n == 11 ? 0 : n == 2 || n == 12 ? 1 : n > 2 && n < 20 ? 2 : 3),
1110
+ 12: n => Number(n % 10 != 1 || n % 100 == 11),
1111
+ 13: n => Number(n !== 0),
1112
+ 14: n => Number(n == 1 ? 0 : n == 2 ? 1 : n == 3 ? 2 : 3),
1113
+ 15: n => Number(n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2),
1114
+ 16: n => Number(n % 10 == 1 && n % 100 != 11 ? 0 : n !== 0 ? 1 : 2),
1115
+ 17: n => Number(n == 1 || n % 10 == 1 && n % 100 != 11 ? 0 : 1),
1116
+ 18: n => Number(n == 0 ? 0 : n == 1 ? 1 : 2),
1117
+ 19: n => Number(n == 1 ? 0 : n == 0 || n % 100 > 1 && n % 100 < 11 ? 1 : n % 100 > 10 && n % 100 < 20 ? 2 : 3),
1118
+ 20: n => Number(n == 1 ? 0 : n == 0 || n % 100 > 0 && n % 100 < 20 ? 1 : 2),
1119
+ 21: n => Number(n % 100 == 1 ? 1 : n % 100 == 2 ? 2 : n % 100 == 3 || n % 100 == 4 ? 3 : 0),
1120
+ 22: n => Number(n == 1 ? 0 : n == 2 ? 1 : (n < 0 || n > 10) && n % 10 == 0 ? 2 : 3)
1121
+ };
1122
+ const nonIntlVersions = ['v1', 'v2', 'v3'];
1123
+ const intlVersions = ['v4'];
1124
+ const suffixesOrder = {
1125
+ zero: 0,
1126
+ one: 1,
1127
+ two: 2,
1128
+ few: 3,
1129
+ many: 4,
1130
+ other: 5
1131
+ };
1132
+ const createRules = () => {
1133
+ const rules = {};
1134
+ sets.forEach(set => {
1135
+ set.lngs.forEach(l => {
1136
+ rules[l] = {
1137
+ numbers: set.nr,
1138
+ plurals: _rulesPluralsTypes[set.fc]
1139
+ };
1140
+ });
1141
+ });
1142
+ return rules;
1143
+ };
1144
+ class PluralResolver {
1145
+ constructor(languageUtils) {
1146
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1147
+ this.languageUtils = languageUtils;
1148
+ this.options = options;
1149
+ this.logger = baseLogger.create('pluralResolver');
1150
+ if ((!this.options.compatibilityJSON || intlVersions.includes(this.options.compatibilityJSON)) && (typeof Intl === 'undefined' || !Intl.PluralRules)) {
1151
+ this.options.compatibilityJSON = 'v3';
1152
+ this.logger.error('Your environment seems not to be Intl API compatible, use an Intl.PluralRules polyfill. Will fallback to the compatibilityJSON v3 format handling.');
1153
+ }
1154
+ this.rules = createRules();
1155
+ this.pluralRulesCache = {};
1156
+ }
1157
+ addRule(lng, obj) {
1158
+ this.rules[lng] = obj;
1159
+ }
1160
+ clearCache() {
1161
+ this.pluralRulesCache = {};
1162
+ }
1163
+ getRule(code) {
1164
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1165
+ if (this.shouldUseIntlApi()) {
1166
+ try {
1167
+ const cleanedCode = getCleanedCode(code === 'dev' ? 'en' : code);
1168
+ const type = options.ordinal ? 'ordinal' : 'cardinal';
1169
+ const cacheKey = JSON.stringify({
1170
+ cleanedCode,
1171
+ type
1172
+ });
1173
+ if (cacheKey in this.pluralRulesCache) {
1174
+ return this.pluralRulesCache[cacheKey];
1175
+ }
1176
+ const rule = new Intl.PluralRules(cleanedCode, {
1177
+ type
1178
+ });
1179
+ this.pluralRulesCache[cacheKey] = rule;
1180
+ return rule;
1181
+ } catch (err) {
1182
+ return;
1183
+ }
1184
+ }
1185
+ return this.rules[code] || this.rules[this.languageUtils.getLanguagePartFromCode(code)];
1186
+ }
1187
+ needsPlural(code) {
1188
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1189
+ const rule = this.getRule(code, options);
1190
+ if (this.shouldUseIntlApi()) {
1191
+ return rule && rule.resolvedOptions().pluralCategories.length > 1;
1192
+ }
1193
+ return rule && rule.numbers.length > 1;
1194
+ }
1195
+ getPluralFormsOfKey(code, key) {
1196
+ let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
1197
+ return this.getSuffixes(code, options).map(suffix => `${key}${suffix}`);
1198
+ }
1199
+ getSuffixes(code) {
1200
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1201
+ const rule = this.getRule(code, options);
1202
+ if (!rule) {
1203
+ return [];
1204
+ }
1205
+ if (this.shouldUseIntlApi()) {
1206
+ return rule.resolvedOptions().pluralCategories.sort((pluralCategory1, pluralCategory2) => suffixesOrder[pluralCategory1] - suffixesOrder[pluralCategory2]).map(pluralCategory => `${this.options.prepend}${options.ordinal ? `ordinal${this.options.prepend}` : ''}${pluralCategory}`);
1207
+ }
1208
+ return rule.numbers.map(number => this.getSuffix(code, number, options));
1209
+ }
1210
+ getSuffix(code, count) {
1211
+ let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
1212
+ const rule = this.getRule(code, options);
1213
+ if (rule) {
1214
+ if (this.shouldUseIntlApi()) {
1215
+ return `${this.options.prepend}${options.ordinal ? `ordinal${this.options.prepend}` : ''}${rule.select(count)}`;
1216
+ }
1217
+ return this.getSuffixRetroCompatible(rule, count);
1218
+ }
1219
+ this.logger.warn(`no plural rule found for: ${code}`);
1220
+ return '';
1221
+ }
1222
+ getSuffixRetroCompatible(rule, count) {
1223
+ const idx = rule.noAbs ? rule.plurals(count) : rule.plurals(Math.abs(count));
1224
+ let suffix = rule.numbers[idx];
1225
+ if (this.options.simplifyPluralSuffix && rule.numbers.length === 2 && rule.numbers[0] === 1) {
1226
+ if (suffix === 2) {
1227
+ suffix = 'plural';
1228
+ } else if (suffix === 1) {
1229
+ suffix = '';
1230
+ }
1231
+ }
1232
+ const returnSuffix = () => this.options.prepend && suffix.toString() ? this.options.prepend + suffix.toString() : suffix.toString();
1233
+ if (this.options.compatibilityJSON === 'v1') {
1234
+ if (suffix === 1) return '';
1235
+ if (typeof suffix === 'number') return `_plural_${suffix.toString()}`;
1236
+ return returnSuffix();
1237
+ } else if (this.options.compatibilityJSON === 'v2') {
1238
+ return returnSuffix();
1239
+ } else if (this.options.simplifyPluralSuffix && rule.numbers.length === 2 && rule.numbers[0] === 1) {
1240
+ return returnSuffix();
1241
+ }
1242
+ return this.options.prepend && idx.toString() ? this.options.prepend + idx.toString() : idx.toString();
1243
+ }
1244
+ shouldUseIntlApi() {
1245
+ return !nonIntlVersions.includes(this.options.compatibilityJSON);
1246
+ }
1247
+ }
1248
+
1249
+ const deepFindWithDefaults = function (data, defaultData, key) {
1250
+ let keySeparator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '.';
1251
+ let ignoreJSONStructure = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;
1252
+ let path = getPathWithDefaults(data, defaultData, key);
1253
+ if (!path && ignoreJSONStructure && isString(key)) {
1254
+ path = deepFind(data, key, keySeparator);
1255
+ if (path === undefined) path = deepFind(defaultData, key, keySeparator);
1256
+ }
1257
+ return path;
1258
+ };
1259
+ const regexSafe = val => val.replace(/\$/g, '$$$$');
1260
+ class Interpolator {
1261
+ constructor() {
1262
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1263
+ this.logger = baseLogger.create('interpolator');
1264
+ this.options = options;
1265
+ this.format = options.interpolation && options.interpolation.format || (value => value);
1266
+ this.init(options);
1267
+ }
1268
+ init() {
1269
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1270
+ if (!options.interpolation) options.interpolation = {
1271
+ escapeValue: true
1272
+ };
1273
+ const {
1274
+ escape: escape$1,
1275
+ escapeValue,
1276
+ useRawValueToEscape,
1277
+ prefix,
1278
+ prefixEscaped,
1279
+ suffix,
1280
+ suffixEscaped,
1281
+ formatSeparator,
1282
+ unescapeSuffix,
1283
+ unescapePrefix,
1284
+ nestingPrefix,
1285
+ nestingPrefixEscaped,
1286
+ nestingSuffix,
1287
+ nestingSuffixEscaped,
1288
+ nestingOptionsSeparator,
1289
+ maxReplaces,
1290
+ alwaysFormat
1291
+ } = options.interpolation;
1292
+ this.escape = escape$1 !== undefined ? escape$1 : escape;
1293
+ this.escapeValue = escapeValue !== undefined ? escapeValue : true;
1294
+ this.useRawValueToEscape = useRawValueToEscape !== undefined ? useRawValueToEscape : false;
1295
+ this.prefix = prefix ? regexEscape(prefix) : prefixEscaped || '{{';
1296
+ this.suffix = suffix ? regexEscape(suffix) : suffixEscaped || '}}';
1297
+ this.formatSeparator = formatSeparator || ',';
1298
+ this.unescapePrefix = unescapeSuffix ? '' : unescapePrefix || '-';
1299
+ this.unescapeSuffix = this.unescapePrefix ? '' : unescapeSuffix || '';
1300
+ this.nestingPrefix = nestingPrefix ? regexEscape(nestingPrefix) : nestingPrefixEscaped || regexEscape('$t(');
1301
+ this.nestingSuffix = nestingSuffix ? regexEscape(nestingSuffix) : nestingSuffixEscaped || regexEscape(')');
1302
+ this.nestingOptionsSeparator = nestingOptionsSeparator || ',';
1303
+ this.maxReplaces = maxReplaces || 1000;
1304
+ this.alwaysFormat = alwaysFormat !== undefined ? alwaysFormat : false;
1305
+ this.resetRegExp();
1306
+ }
1307
+ reset() {
1308
+ if (this.options) this.init(this.options);
1309
+ }
1310
+ resetRegExp() {
1311
+ const getOrResetRegExp = (existingRegExp, pattern) => {
1312
+ if (existingRegExp && existingRegExp.source === pattern) {
1313
+ existingRegExp.lastIndex = 0;
1314
+ return existingRegExp;
1315
+ }
1316
+ return new RegExp(pattern, 'g');
1317
+ };
1318
+ this.regexp = getOrResetRegExp(this.regexp, `${this.prefix}(.+?)${this.suffix}`);
1319
+ this.regexpUnescape = getOrResetRegExp(this.regexpUnescape, `${this.prefix}${this.unescapePrefix}(.+?)${this.unescapeSuffix}${this.suffix}`);
1320
+ this.nestingRegexp = getOrResetRegExp(this.nestingRegexp, `${this.nestingPrefix}(.+?)${this.nestingSuffix}`);
1321
+ }
1322
+ interpolate(str, data, lng, options) {
1323
+ let match;
1324
+ let value;
1325
+ let replaces;
1326
+ const defaultData = this.options && this.options.interpolation && this.options.interpolation.defaultVariables || {};
1327
+ const handleFormat = key => {
1328
+ if (key.indexOf(this.formatSeparator) < 0) {
1329
+ const path = deepFindWithDefaults(data, defaultData, key, this.options.keySeparator, this.options.ignoreJSONStructure);
1330
+ return this.alwaysFormat ? this.format(path, undefined, lng, {
1331
+ ...options,
1332
+ ...data,
1333
+ interpolationkey: key
1334
+ }) : path;
1335
+ }
1336
+ const p = key.split(this.formatSeparator);
1337
+ const k = p.shift().trim();
1338
+ const f = p.join(this.formatSeparator).trim();
1339
+ return this.format(deepFindWithDefaults(data, defaultData, k, this.options.keySeparator, this.options.ignoreJSONStructure), f, lng, {
1340
+ ...options,
1341
+ ...data,
1342
+ interpolationkey: k
1343
+ });
1344
+ };
1345
+ this.resetRegExp();
1346
+ const missingInterpolationHandler = options && options.missingInterpolationHandler || this.options.missingInterpolationHandler;
1347
+ const skipOnVariables = options && options.interpolation && options.interpolation.skipOnVariables !== undefined ? options.interpolation.skipOnVariables : this.options.interpolation.skipOnVariables;
1348
+ const todos = [{
1349
+ regex: this.regexpUnescape,
1350
+ safeValue: val => regexSafe(val)
1351
+ }, {
1352
+ regex: this.regexp,
1353
+ safeValue: val => this.escapeValue ? regexSafe(this.escape(val)) : regexSafe(val)
1354
+ }];
1355
+ todos.forEach(todo => {
1356
+ replaces = 0;
1357
+ while (match = todo.regex.exec(str)) {
1358
+ const matchedVar = match[1].trim();
1359
+ value = handleFormat(matchedVar);
1360
+ if (value === undefined) {
1361
+ if (typeof missingInterpolationHandler === 'function') {
1362
+ const temp = missingInterpolationHandler(str, match, options);
1363
+ value = isString(temp) ? temp : '';
1364
+ } else if (options && Object.prototype.hasOwnProperty.call(options, matchedVar)) {
1365
+ value = '';
1366
+ } else if (skipOnVariables) {
1367
+ value = match[0];
1368
+ continue;
1369
+ } else {
1370
+ this.logger.warn(`missed to pass in variable ${matchedVar} for interpolating ${str}`);
1371
+ value = '';
1372
+ }
1373
+ } else if (!isString(value) && !this.useRawValueToEscape) {
1374
+ value = makeString(value);
1375
+ }
1376
+ const safeValue = todo.safeValue(value);
1377
+ str = str.replace(match[0], safeValue);
1378
+ if (skipOnVariables) {
1379
+ todo.regex.lastIndex += value.length;
1380
+ todo.regex.lastIndex -= match[0].length;
1381
+ } else {
1382
+ todo.regex.lastIndex = 0;
1383
+ }
1384
+ replaces++;
1385
+ if (replaces >= this.maxReplaces) {
1386
+ break;
1387
+ }
1388
+ }
1389
+ });
1390
+ return str;
1391
+ }
1392
+ nest(str, fc) {
1393
+ let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
1394
+ let match;
1395
+ let value;
1396
+ let clonedOptions;
1397
+ const handleHasOptions = (key, inheritedOptions) => {
1398
+ const sep = this.nestingOptionsSeparator;
1399
+ if (key.indexOf(sep) < 0) return key;
1400
+ const c = key.split(new RegExp(`${sep}[ ]*{`));
1401
+ let optionsString = `{${c[1]}`;
1402
+ key = c[0];
1403
+ optionsString = this.interpolate(optionsString, clonedOptions);
1404
+ const matchedSingleQuotes = optionsString.match(/'/g);
1405
+ const matchedDoubleQuotes = optionsString.match(/"/g);
1406
+ if (matchedSingleQuotes && matchedSingleQuotes.length % 2 === 0 && !matchedDoubleQuotes || matchedDoubleQuotes.length % 2 !== 0) {
1407
+ optionsString = optionsString.replace(/'/g, '"');
1408
+ }
1409
+ try {
1410
+ clonedOptions = JSON.parse(optionsString);
1411
+ if (inheritedOptions) clonedOptions = {
1412
+ ...inheritedOptions,
1413
+ ...clonedOptions
1414
+ };
1415
+ } catch (e) {
1416
+ this.logger.warn(`failed parsing options string in nesting for key ${key}`, e);
1417
+ return `${key}${sep}${optionsString}`;
1418
+ }
1419
+ if (clonedOptions.defaultValue && clonedOptions.defaultValue.indexOf(this.prefix) > -1) delete clonedOptions.defaultValue;
1420
+ return key;
1421
+ };
1422
+ while (match = this.nestingRegexp.exec(str)) {
1423
+ let formatters = [];
1424
+ clonedOptions = {
1425
+ ...options
1426
+ };
1427
+ clonedOptions = clonedOptions.replace && !isString(clonedOptions.replace) ? clonedOptions.replace : clonedOptions;
1428
+ clonedOptions.applyPostProcessor = false;
1429
+ delete clonedOptions.defaultValue;
1430
+ let doReduce = false;
1431
+ if (match[0].indexOf(this.formatSeparator) !== -1 && !/{.*}/.test(match[1])) {
1432
+ const r = match[1].split(this.formatSeparator).map(elem => elem.trim());
1433
+ match[1] = r.shift();
1434
+ formatters = r;
1435
+ doReduce = true;
1436
+ }
1437
+ value = fc(handleHasOptions.call(this, match[1].trim(), clonedOptions), clonedOptions);
1438
+ if (value && match[0] === str && !isString(value)) return value;
1439
+ if (!isString(value)) value = makeString(value);
1440
+ if (!value) {
1441
+ this.logger.warn(`missed to resolve ${match[1]} for nesting ${str}`);
1442
+ value = '';
1443
+ }
1444
+ if (doReduce) {
1445
+ value = formatters.reduce((v, f) => this.format(v, f, options.lng, {
1446
+ ...options,
1447
+ interpolationkey: match[1].trim()
1448
+ }), value.trim());
1449
+ }
1450
+ str = str.replace(match[0], value);
1451
+ this.regexp.lastIndex = 0;
1452
+ }
1453
+ return str;
1454
+ }
1455
+ }
1456
+
1457
+ const parseFormatStr = formatStr => {
1458
+ let formatName = formatStr.toLowerCase().trim();
1459
+ const formatOptions = {};
1460
+ if (formatStr.indexOf('(') > -1) {
1461
+ const p = formatStr.split('(');
1462
+ formatName = p[0].toLowerCase().trim();
1463
+ const optStr = p[1].substring(0, p[1].length - 1);
1464
+ if (formatName === 'currency' && optStr.indexOf(':') < 0) {
1465
+ if (!formatOptions.currency) formatOptions.currency = optStr.trim();
1466
+ } else if (formatName === 'relativetime' && optStr.indexOf(':') < 0) {
1467
+ if (!formatOptions.range) formatOptions.range = optStr.trim();
1468
+ } else {
1469
+ const opts = optStr.split(';');
1470
+ opts.forEach(opt => {
1471
+ if (opt) {
1472
+ const [key, ...rest] = opt.split(':');
1473
+ const val = rest.join(':').trim().replace(/^'+|'+$/g, '');
1474
+ const trimmedKey = key.trim();
1475
+ if (!formatOptions[trimmedKey]) formatOptions[trimmedKey] = val;
1476
+ if (val === 'false') formatOptions[trimmedKey] = false;
1477
+ if (val === 'true') formatOptions[trimmedKey] = true;
1478
+ if (!isNaN(val)) formatOptions[trimmedKey] = parseInt(val, 10);
1479
+ }
1480
+ });
1481
+ }
1482
+ }
1483
+ return {
1484
+ formatName,
1485
+ formatOptions
1486
+ };
1487
+ };
1488
+ const createCachedFormatter = fn => {
1489
+ const cache = {};
1490
+ return (val, lng, options) => {
1491
+ let optForCache = options;
1492
+ if (options && options.interpolationkey && options.formatParams && options.formatParams[options.interpolationkey] && options[options.interpolationkey]) {
1493
+ optForCache = {
1494
+ ...optForCache,
1495
+ [options.interpolationkey]: undefined
1496
+ };
1497
+ }
1498
+ const key = lng + JSON.stringify(optForCache);
1499
+ let formatter = cache[key];
1500
+ if (!formatter) {
1501
+ formatter = fn(getCleanedCode(lng), options);
1502
+ cache[key] = formatter;
1503
+ }
1504
+ return formatter(val);
1505
+ };
1506
+ };
1507
+ class Formatter {
1508
+ constructor() {
1509
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1510
+ this.logger = baseLogger.create('formatter');
1511
+ this.options = options;
1512
+ this.formats = {
1513
+ number: createCachedFormatter((lng, opt) => {
1514
+ const formatter = new Intl.NumberFormat(lng, {
1515
+ ...opt
1516
+ });
1517
+ return val => formatter.format(val);
1518
+ }),
1519
+ currency: createCachedFormatter((lng, opt) => {
1520
+ const formatter = new Intl.NumberFormat(lng, {
1521
+ ...opt,
1522
+ style: 'currency'
1523
+ });
1524
+ return val => formatter.format(val);
1525
+ }),
1526
+ datetime: createCachedFormatter((lng, opt) => {
1527
+ const formatter = new Intl.DateTimeFormat(lng, {
1528
+ ...opt
1529
+ });
1530
+ return val => formatter.format(val);
1531
+ }),
1532
+ relativetime: createCachedFormatter((lng, opt) => {
1533
+ const formatter = new Intl.RelativeTimeFormat(lng, {
1534
+ ...opt
1535
+ });
1536
+ return val => formatter.format(val, opt.range || 'day');
1537
+ }),
1538
+ list: createCachedFormatter((lng, opt) => {
1539
+ const formatter = new Intl.ListFormat(lng, {
1540
+ ...opt
1541
+ });
1542
+ return val => formatter.format(val);
1543
+ })
1544
+ };
1545
+ this.init(options);
1546
+ }
1547
+ init(services) {
1548
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
1549
+ interpolation: {}
1550
+ };
1551
+ this.formatSeparator = options.interpolation.formatSeparator || ',';
1552
+ }
1553
+ add(name, fc) {
1554
+ this.formats[name.toLowerCase().trim()] = fc;
1555
+ }
1556
+ addCached(name, fc) {
1557
+ this.formats[name.toLowerCase().trim()] = createCachedFormatter(fc);
1558
+ }
1559
+ format(value, format, lng) {
1560
+ let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
1561
+ const formats = format.split(this.formatSeparator);
1562
+ if (formats.length > 1 && formats[0].indexOf('(') > 1 && formats[0].indexOf(')') < 0 && formats.find(f => f.indexOf(')') > -1)) {
1563
+ const lastIndex = formats.findIndex(f => f.indexOf(')') > -1);
1564
+ formats[0] = [formats[0], ...formats.splice(1, lastIndex)].join(this.formatSeparator);
1565
+ }
1566
+ const result = formats.reduce((mem, f) => {
1567
+ const {
1568
+ formatName,
1569
+ formatOptions
1570
+ } = parseFormatStr(f);
1571
+ if (this.formats[formatName]) {
1572
+ let formatted = mem;
1573
+ try {
1574
+ const valOptions = options && options.formatParams && options.formatParams[options.interpolationkey] || {};
1575
+ const l = valOptions.locale || valOptions.lng || options.locale || options.lng || lng;
1576
+ formatted = this.formats[formatName](mem, l, {
1577
+ ...formatOptions,
1578
+ ...options,
1579
+ ...valOptions
1580
+ });
1581
+ } catch (error) {
1582
+ this.logger.warn(error);
1583
+ }
1584
+ return formatted;
1585
+ } else {
1586
+ this.logger.warn(`there was no format function for ${formatName}`);
1587
+ }
1588
+ return mem;
1589
+ }, value);
1590
+ return result;
1591
+ }
1592
+ }
1593
+
1594
+ const removePending = (q, name) => {
1595
+ if (q.pending[name] !== undefined) {
1596
+ delete q.pending[name];
1597
+ q.pendingCount--;
1598
+ }
1599
+ };
1600
+ class Connector extends EventEmitter {
1601
+ constructor(backend, store, services) {
1602
+ let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
1603
+ super();
1604
+ this.backend = backend;
1605
+ this.store = store;
1606
+ this.services = services;
1607
+ this.languageUtils = services.languageUtils;
1608
+ this.options = options;
1609
+ this.logger = baseLogger.create('backendConnector');
1610
+ this.waitingReads = [];
1611
+ this.maxParallelReads = options.maxParallelReads || 10;
1612
+ this.readingCalls = 0;
1613
+ this.maxRetries = options.maxRetries >= 0 ? options.maxRetries : 5;
1614
+ this.retryTimeout = options.retryTimeout >= 1 ? options.retryTimeout : 350;
1615
+ this.state = {};
1616
+ this.queue = [];
1617
+ if (this.backend && this.backend.init) {
1618
+ this.backend.init(services, options.backend, options);
1619
+ }
1620
+ }
1621
+ queueLoad(languages, namespaces, options, callback) {
1622
+ const toLoad = {};
1623
+ const pending = {};
1624
+ const toLoadLanguages = {};
1625
+ const toLoadNamespaces = {};
1626
+ languages.forEach(lng => {
1627
+ let hasAllNamespaces = true;
1628
+ namespaces.forEach(ns => {
1629
+ const name = `${lng}|${ns}`;
1630
+ if (!options.reload && this.store.hasResourceBundle(lng, ns)) {
1631
+ this.state[name] = 2;
1632
+ } else if (this.state[name] < 0) ; else if (this.state[name] === 1) {
1633
+ if (pending[name] === undefined) pending[name] = true;
1634
+ } else {
1635
+ this.state[name] = 1;
1636
+ hasAllNamespaces = false;
1637
+ if (pending[name] === undefined) pending[name] = true;
1638
+ if (toLoad[name] === undefined) toLoad[name] = true;
1639
+ if (toLoadNamespaces[ns] === undefined) toLoadNamespaces[ns] = true;
1640
+ }
1641
+ });
1642
+ if (!hasAllNamespaces) toLoadLanguages[lng] = true;
1643
+ });
1644
+ if (Object.keys(toLoad).length || Object.keys(pending).length) {
1645
+ this.queue.push({
1646
+ pending,
1647
+ pendingCount: Object.keys(pending).length,
1648
+ loaded: {},
1649
+ errors: [],
1650
+ callback
1651
+ });
1652
+ }
1653
+ return {
1654
+ toLoad: Object.keys(toLoad),
1655
+ pending: Object.keys(pending),
1656
+ toLoadLanguages: Object.keys(toLoadLanguages),
1657
+ toLoadNamespaces: Object.keys(toLoadNamespaces)
1658
+ };
1659
+ }
1660
+ loaded(name, err, data) {
1661
+ const s = name.split('|');
1662
+ const lng = s[0];
1663
+ const ns = s[1];
1664
+ if (err) this.emit('failedLoading', lng, ns, err);
1665
+ if (!err && data) {
1666
+ this.store.addResourceBundle(lng, ns, data, undefined, undefined, {
1667
+ skipCopy: true
1668
+ });
1669
+ }
1670
+ this.state[name] = err ? -1 : 2;
1671
+ if (err && data) this.state[name] = 0;
1672
+ const loaded = {};
1673
+ this.queue.forEach(q => {
1674
+ pushPath(q.loaded, [lng], ns);
1675
+ removePending(q, name);
1676
+ if (err) q.errors.push(err);
1677
+ if (q.pendingCount === 0 && !q.done) {
1678
+ Object.keys(q.loaded).forEach(l => {
1679
+ if (!loaded[l]) loaded[l] = {};
1680
+ const loadedKeys = q.loaded[l];
1681
+ if (loadedKeys.length) {
1682
+ loadedKeys.forEach(n => {
1683
+ if (loaded[l][n] === undefined) loaded[l][n] = true;
1684
+ });
1685
+ }
1686
+ });
1687
+ q.done = true;
1688
+ if (q.errors.length) {
1689
+ q.callback(q.errors);
1690
+ } else {
1691
+ q.callback();
1692
+ }
1693
+ }
1694
+ });
1695
+ this.emit('loaded', loaded);
1696
+ this.queue = this.queue.filter(q => !q.done);
1697
+ }
1698
+ read(lng, ns, fcName) {
1699
+ let tried = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
1700
+ let wait = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : this.retryTimeout;
1701
+ let callback = arguments.length > 5 ? arguments[5] : undefined;
1702
+ if (!lng.length) return callback(null, {});
1703
+ if (this.readingCalls >= this.maxParallelReads) {
1704
+ this.waitingReads.push({
1705
+ lng,
1706
+ ns,
1707
+ fcName,
1708
+ tried,
1709
+ wait,
1710
+ callback
1711
+ });
1712
+ return;
1713
+ }
1714
+ this.readingCalls++;
1715
+ const resolver = (err, data) => {
1716
+ this.readingCalls--;
1717
+ if (this.waitingReads.length > 0) {
1718
+ const next = this.waitingReads.shift();
1719
+ this.read(next.lng, next.ns, next.fcName, next.tried, next.wait, next.callback);
1720
+ }
1721
+ if (err && data && tried < this.maxRetries) {
1722
+ setTimeout(() => {
1723
+ this.read.call(this, lng, ns, fcName, tried + 1, wait * 2, callback);
1724
+ }, wait);
1725
+ return;
1726
+ }
1727
+ callback(err, data);
1728
+ };
1729
+ const fc = this.backend[fcName].bind(this.backend);
1730
+ if (fc.length === 2) {
1731
+ try {
1732
+ const r = fc(lng, ns);
1733
+ if (r && typeof r.then === 'function') {
1734
+ r.then(data => resolver(null, data)).catch(resolver);
1735
+ } else {
1736
+ resolver(null, r);
1737
+ }
1738
+ } catch (err) {
1739
+ resolver(err);
1740
+ }
1741
+ return;
1742
+ }
1743
+ return fc(lng, ns, resolver);
1744
+ }
1745
+ prepareLoading(languages, namespaces) {
1746
+ let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
1747
+ let callback = arguments.length > 3 ? arguments[3] : undefined;
1748
+ if (!this.backend) {
1749
+ this.logger.warn('No backend was added via i18next.use. Will not load resources.');
1750
+ return callback && callback();
1751
+ }
1752
+ if (isString(languages)) languages = this.languageUtils.toResolveHierarchy(languages);
1753
+ if (isString(namespaces)) namespaces = [namespaces];
1754
+ const toLoad = this.queueLoad(languages, namespaces, options, callback);
1755
+ if (!toLoad.toLoad.length) {
1756
+ if (!toLoad.pending.length) callback();
1757
+ return null;
1758
+ }
1759
+ toLoad.toLoad.forEach(name => {
1760
+ this.loadOne(name);
1761
+ });
1762
+ }
1763
+ load(languages, namespaces, callback) {
1764
+ this.prepareLoading(languages, namespaces, {}, callback);
1765
+ }
1766
+ reload(languages, namespaces, callback) {
1767
+ this.prepareLoading(languages, namespaces, {
1768
+ reload: true
1769
+ }, callback);
1770
+ }
1771
+ loadOne(name) {
1772
+ let prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
1773
+ const s = name.split('|');
1774
+ const lng = s[0];
1775
+ const ns = s[1];
1776
+ this.read(lng, ns, 'read', undefined, undefined, (err, data) => {
1777
+ if (err) this.logger.warn(`${prefix}loading namespace ${ns} for language ${lng} failed`, err);
1778
+ if (!err && data) this.logger.log(`${prefix}loaded namespace ${ns} for language ${lng}`, data);
1779
+ this.loaded(name, err, data);
1780
+ });
1781
+ }
1782
+ saveMissing(languages, namespace, key, fallbackValue, isUpdate) {
1783
+ let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
1784
+ let clb = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : () => {};
1785
+ if (this.services.utils && this.services.utils.hasLoadedNamespace && !this.services.utils.hasLoadedNamespace(namespace)) {
1786
+ this.logger.warn(`did not save key "${key}" as the namespace "${namespace}" 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!!!');
1787
+ return;
1788
+ }
1789
+ if (key === undefined || key === null || key === '') return;
1790
+ if (this.backend && this.backend.create) {
1791
+ const opts = {
1792
+ ...options,
1793
+ isUpdate
1794
+ };
1795
+ const fc = this.backend.create.bind(this.backend);
1796
+ if (fc.length < 6) {
1797
+ try {
1798
+ let r;
1799
+ if (fc.length === 5) {
1800
+ r = fc(languages, namespace, key, fallbackValue, opts);
1801
+ } else {
1802
+ r = fc(languages, namespace, key, fallbackValue);
1803
+ }
1804
+ if (r && typeof r.then === 'function') {
1805
+ r.then(data => clb(null, data)).catch(clb);
1806
+ } else {
1807
+ clb(null, r);
1808
+ }
1809
+ } catch (err) {
1810
+ clb(err);
1811
+ }
1812
+ } else {
1813
+ fc(languages, namespace, key, fallbackValue, clb, opts);
1814
+ }
1815
+ }
1816
+ if (!languages || !languages[0]) return;
1817
+ this.store.addResource(languages[0], namespace, key, fallbackValue);
1818
+ }
1819
+ }
1820
+
1821
+ const get = () => ({
1822
+ debug: false,
1823
+ initImmediate: true,
1824
+ ns: ['translation'],
1825
+ defaultNS: ['translation'],
1826
+ fallbackLng: ['dev'],
1827
+ fallbackNS: false,
1828
+ supportedLngs: false,
1829
+ nonExplicitSupportedLngs: false,
1830
+ load: 'all',
1831
+ preload: false,
1832
+ simplifyPluralSuffix: true,
1833
+ keySeparator: '.',
1834
+ nsSeparator: ':',
1835
+ pluralSeparator: '_',
1836
+ contextSeparator: '_',
1837
+ partialBundledLanguages: false,
1838
+ saveMissing: false,
1839
+ updateMissing: false,
1840
+ saveMissingTo: 'fallback',
1841
+ saveMissingPlurals: true,
1842
+ missingKeyHandler: false,
1843
+ missingInterpolationHandler: false,
1844
+ postProcess: false,
1845
+ postProcessPassResolved: false,
1846
+ returnNull: false,
1847
+ returnEmptyString: true,
1848
+ returnObjects: false,
1849
+ joinArrays: false,
1850
+ returnedObjectHandler: false,
1851
+ parseMissingKeyHandler: false,
1852
+ appendNamespaceToMissingKey: false,
1853
+ appendNamespaceToCIMode: false,
1854
+ overloadTranslationOptionHandler: args => {
1855
+ let ret = {};
1856
+ if (typeof args[1] === 'object') ret = args[1];
1857
+ if (isString(args[1])) ret.defaultValue = args[1];
1858
+ if (isString(args[2])) ret.tDescription = args[2];
1859
+ if (typeof args[2] === 'object' || typeof args[3] === 'object') {
1860
+ const options = args[3] || args[2];
1861
+ Object.keys(options).forEach(key => {
1862
+ ret[key] = options[key];
1863
+ });
1864
+ }
1865
+ return ret;
1866
+ },
1867
+ interpolation: {
1868
+ escapeValue: true,
1869
+ format: value => value,
1870
+ prefix: '{{',
1871
+ suffix: '}}',
1872
+ formatSeparator: ',',
1873
+ unescapePrefix: '-',
1874
+ nestingPrefix: '$t(',
1875
+ nestingSuffix: ')',
1876
+ nestingOptionsSeparator: ',',
1877
+ maxReplaces: 1000,
1878
+ skipOnVariables: true
1879
+ }
1880
+ });
1881
+ const transformOptions = options => {
1882
+ if (isString(options.ns)) options.ns = [options.ns];
1883
+ if (isString(options.fallbackLng)) options.fallbackLng = [options.fallbackLng];
1884
+ if (isString(options.fallbackNS)) options.fallbackNS = [options.fallbackNS];
1885
+ if (options.supportedLngs && options.supportedLngs.indexOf('cimode') < 0) {
1886
+ options.supportedLngs = options.supportedLngs.concat(['cimode']);
1887
+ }
1888
+ return options;
1889
+ };
1890
+
1891
+ const noop = () => {};
1892
+ const bindMemberFunctions = inst => {
1893
+ const mems = Object.getOwnPropertyNames(Object.getPrototypeOf(inst));
1894
+ mems.forEach(mem => {
1895
+ if (typeof inst[mem] === 'function') {
1896
+ inst[mem] = inst[mem].bind(inst);
1897
+ }
1898
+ });
1899
+ };
1900
+ class I18n extends EventEmitter {
1901
+ constructor() {
1902
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1903
+ let callback = arguments.length > 1 ? arguments[1] : undefined;
1904
+ super();
1905
+ this.options = transformOptions(options);
1906
+ this.services = {};
1907
+ this.logger = baseLogger;
1908
+ this.modules = {
1909
+ external: []
1910
+ };
1911
+ bindMemberFunctions(this);
1912
+ if (callback && !this.isInitialized && !options.isClone) {
1913
+ if (!this.options.initImmediate) {
1914
+ this.init(options, callback);
1915
+ return this;
1916
+ }
1917
+ setTimeout(() => {
1918
+ this.init(options, callback);
1919
+ }, 0);
1920
+ }
1921
+ }
1922
+ init() {
1923
+ var _this = this;
1924
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1925
+ let callback = arguments.length > 1 ? arguments[1] : undefined;
1926
+ this.isInitializing = true;
1927
+ if (typeof options === 'function') {
1928
+ callback = options;
1929
+ options = {};
1930
+ }
1931
+ if (!options.defaultNS && options.defaultNS !== false && options.ns) {
1932
+ if (isString(options.ns)) {
1933
+ options.defaultNS = options.ns;
1934
+ } else if (options.ns.indexOf('translation') < 0) {
1935
+ options.defaultNS = options.ns[0];
1936
+ }
1937
+ }
1938
+ const defOpts = get();
1939
+ this.options = {
1940
+ ...defOpts,
1941
+ ...this.options,
1942
+ ...transformOptions(options)
1943
+ };
1944
+ if (this.options.compatibilityAPI !== 'v1') {
1945
+ this.options.interpolation = {
1946
+ ...defOpts.interpolation,
1947
+ ...this.options.interpolation
1948
+ };
1949
+ }
1950
+ if (options.keySeparator !== undefined) {
1951
+ this.options.userDefinedKeySeparator = options.keySeparator;
1952
+ }
1953
+ if (options.nsSeparator !== undefined) {
1954
+ this.options.userDefinedNsSeparator = options.nsSeparator;
1955
+ }
1956
+ const createClassOnDemand = ClassOrObject => {
1957
+ if (!ClassOrObject) return null;
1958
+ if (typeof ClassOrObject === 'function') return new ClassOrObject();
1959
+ return ClassOrObject;
1960
+ };
1961
+ if (!this.options.isClone) {
1962
+ if (this.modules.logger) {
1963
+ baseLogger.init(createClassOnDemand(this.modules.logger), this.options);
1964
+ } else {
1965
+ baseLogger.init(null, this.options);
1966
+ }
1967
+ let formatter;
1968
+ if (this.modules.formatter) {
1969
+ formatter = this.modules.formatter;
1970
+ } else if (typeof Intl !== 'undefined') {
1971
+ formatter = Formatter;
1972
+ }
1973
+ const lu = new LanguageUtil(this.options);
1974
+ this.store = new ResourceStore(this.options.resources, this.options);
1975
+ const s = this.services;
1976
+ s.logger = baseLogger;
1977
+ s.resourceStore = this.store;
1978
+ s.languageUtils = lu;
1979
+ s.pluralResolver = new PluralResolver(lu, {
1980
+ prepend: this.options.pluralSeparator,
1981
+ compatibilityJSON: this.options.compatibilityJSON,
1982
+ simplifyPluralSuffix: this.options.simplifyPluralSuffix
1983
+ });
1984
+ if (formatter && (!this.options.interpolation.format || this.options.interpolation.format === defOpts.interpolation.format)) {
1985
+ s.formatter = createClassOnDemand(formatter);
1986
+ s.formatter.init(s, this.options);
1987
+ this.options.interpolation.format = s.formatter.format.bind(s.formatter);
1988
+ }
1989
+ s.interpolator = new Interpolator(this.options);
1990
+ s.utils = {
1991
+ hasLoadedNamespace: this.hasLoadedNamespace.bind(this)
1992
+ };
1993
+ s.backendConnector = new Connector(createClassOnDemand(this.modules.backend), s.resourceStore, s, this.options);
1994
+ s.backendConnector.on('*', function (event) {
1995
+ for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
1996
+ args[_key - 1] = arguments[_key];
1997
+ }
1998
+ _this.emit(event, ...args);
1999
+ });
2000
+ if (this.modules.languageDetector) {
2001
+ s.languageDetector = createClassOnDemand(this.modules.languageDetector);
2002
+ if (s.languageDetector.init) s.languageDetector.init(s, this.options.detection, this.options);
2003
+ }
2004
+ if (this.modules.i18nFormat) {
2005
+ s.i18nFormat = createClassOnDemand(this.modules.i18nFormat);
2006
+ if (s.i18nFormat.init) s.i18nFormat.init(this);
2007
+ }
2008
+ this.translator = new Translator(this.services, this.options);
2009
+ this.translator.on('*', function (event) {
2010
+ for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
2011
+ args[_key2 - 1] = arguments[_key2];
2012
+ }
2013
+ _this.emit(event, ...args);
2014
+ });
2015
+ this.modules.external.forEach(m => {
2016
+ if (m.init) m.init(this);
2017
+ });
2018
+ }
2019
+ this.format = this.options.interpolation.format;
2020
+ if (!callback) callback = noop;
2021
+ if (this.options.fallbackLng && !this.services.languageDetector && !this.options.lng) {
2022
+ const codes = this.services.languageUtils.getFallbackCodes(this.options.fallbackLng);
2023
+ if (codes.length > 0 && codes[0] !== 'dev') this.options.lng = codes[0];
2024
+ }
2025
+ if (!this.services.languageDetector && !this.options.lng) {
2026
+ this.logger.warn('init: no languageDetector is used and no lng is defined');
2027
+ }
2028
+ const storeApi = ['getResource', 'hasResourceBundle', 'getResourceBundle', 'getDataByLanguage'];
2029
+ storeApi.forEach(fcName => {
2030
+ this[fcName] = function () {
2031
+ return _this.store[fcName](...arguments);
2032
+ };
2033
+ });
2034
+ const storeApiChained = ['addResource', 'addResources', 'addResourceBundle', 'removeResourceBundle'];
2035
+ storeApiChained.forEach(fcName => {
2036
+ this[fcName] = function () {
2037
+ _this.store[fcName](...arguments);
2038
+ return _this;
2039
+ };
2040
+ });
2041
+ const deferred = defer();
2042
+ const load = () => {
2043
+ const finish = (err, t) => {
2044
+ this.isInitializing = false;
2045
+ if (this.isInitialized && !this.initializedStoreOnce) this.logger.warn('init: i18next is already initialized. You should call init just once!');
2046
+ this.isInitialized = true;
2047
+ if (!this.options.isClone) this.logger.log('initialized', this.options);
2048
+ this.emit('initialized', this.options);
2049
+ deferred.resolve(t);
2050
+ callback(err, t);
2051
+ };
2052
+ if (this.languages && this.options.compatibilityAPI !== 'v1' && !this.isInitialized) return finish(null, this.t.bind(this));
2053
+ this.changeLanguage(this.options.lng, finish);
2054
+ };
2055
+ if (this.options.resources || !this.options.initImmediate) {
2056
+ load();
2057
+ } else {
2058
+ setTimeout(load, 0);
2059
+ }
2060
+ return deferred;
2061
+ }
2062
+ loadResources(language) {
2063
+ let callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop;
2064
+ let usedCallback = callback;
2065
+ const usedLng = isString(language) ? language : this.language;
2066
+ if (typeof language === 'function') usedCallback = language;
2067
+ if (!this.options.resources || this.options.partialBundledLanguages) {
2068
+ if (usedLng && usedLng.toLowerCase() === 'cimode' && (!this.options.preload || this.options.preload.length === 0)) return usedCallback();
2069
+ const toLoad = [];
2070
+ const append = lng => {
2071
+ if (!lng) return;
2072
+ if (lng === 'cimode') return;
2073
+ const lngs = this.services.languageUtils.toResolveHierarchy(lng);
2074
+ lngs.forEach(l => {
2075
+ if (l === 'cimode') return;
2076
+ if (toLoad.indexOf(l) < 0) toLoad.push(l);
2077
+ });
2078
+ };
2079
+ if (!usedLng) {
2080
+ const fallbacks = this.services.languageUtils.getFallbackCodes(this.options.fallbackLng);
2081
+ fallbacks.forEach(l => append(l));
2082
+ } else {
2083
+ append(usedLng);
2084
+ }
2085
+ if (this.options.preload) {
2086
+ this.options.preload.forEach(l => append(l));
2087
+ }
2088
+ this.services.backendConnector.load(toLoad, this.options.ns, e => {
2089
+ if (!e && !this.resolvedLanguage && this.language) this.setResolvedLanguage(this.language);
2090
+ usedCallback(e);
2091
+ });
2092
+ } else {
2093
+ usedCallback(null);
2094
+ }
2095
+ }
2096
+ reloadResources(lngs, ns, callback) {
2097
+ const deferred = defer();
2098
+ if (typeof lngs === 'function') {
2099
+ callback = lngs;
2100
+ lngs = undefined;
2101
+ }
2102
+ if (typeof ns === 'function') {
2103
+ callback = ns;
2104
+ ns = undefined;
2105
+ }
2106
+ if (!lngs) lngs = this.languages;
2107
+ if (!ns) ns = this.options.ns;
2108
+ if (!callback) callback = noop;
2109
+ this.services.backendConnector.reload(lngs, ns, err => {
2110
+ deferred.resolve();
2111
+ callback(err);
2112
+ });
2113
+ return deferred;
2114
+ }
2115
+ use(module) {
2116
+ if (!module) throw new Error('You are passing an undefined module! Please check the object you are passing to i18next.use()');
2117
+ if (!module.type) throw new Error('You are passing a wrong module! Please check the object you are passing to i18next.use()');
2118
+ if (module.type === 'backend') {
2119
+ this.modules.backend = module;
2120
+ }
2121
+ if (module.type === 'logger' || module.log && module.warn && module.error) {
2122
+ this.modules.logger = module;
2123
+ }
2124
+ if (module.type === 'languageDetector') {
2125
+ this.modules.languageDetector = module;
2126
+ }
2127
+ if (module.type === 'i18nFormat') {
2128
+ this.modules.i18nFormat = module;
2129
+ }
2130
+ if (module.type === 'postProcessor') {
2131
+ postProcessor.addPostProcessor(module);
2132
+ }
2133
+ if (module.type === 'formatter') {
2134
+ this.modules.formatter = module;
2135
+ }
2136
+ if (module.type === '3rdParty') {
2137
+ this.modules.external.push(module);
2138
+ }
2139
+ return this;
2140
+ }
2141
+ setResolvedLanguage(l) {
2142
+ if (!l || !this.languages) return;
2143
+ if (['cimode', 'dev'].indexOf(l) > -1) return;
2144
+ for (let li = 0; li < this.languages.length; li++) {
2145
+ const lngInLngs = this.languages[li];
2146
+ if (['cimode', 'dev'].indexOf(lngInLngs) > -1) continue;
2147
+ if (this.store.hasLanguageSomeTranslations(lngInLngs)) {
2148
+ this.resolvedLanguage = lngInLngs;
2149
+ break;
2150
+ }
2151
+ }
2152
+ }
2153
+ changeLanguage(lng, callback) {
2154
+ var _this2 = this;
2155
+ this.isLanguageChangingTo = lng;
2156
+ const deferred = defer();
2157
+ this.emit('languageChanging', lng);
2158
+ const setLngProps = l => {
2159
+ this.language = l;
2160
+ this.languages = this.services.languageUtils.toResolveHierarchy(l);
2161
+ this.resolvedLanguage = undefined;
2162
+ this.setResolvedLanguage(l);
2163
+ };
2164
+ const done = (err, l) => {
2165
+ if (l) {
2166
+ setLngProps(l);
2167
+ this.translator.changeLanguage(l);
2168
+ this.isLanguageChangingTo = undefined;
2169
+ this.emit('languageChanged', l);
2170
+ this.logger.log('languageChanged', l);
2171
+ } else {
2172
+ this.isLanguageChangingTo = undefined;
2173
+ }
2174
+ deferred.resolve(function () {
2175
+ return _this2.t(...arguments);
2176
+ });
2177
+ if (callback) callback(err, function () {
2178
+ return _this2.t(...arguments);
2179
+ });
2180
+ };
2181
+ const setLng = lngs => {
2182
+ if (!lng && !lngs && this.services.languageDetector) lngs = [];
2183
+ const l = isString(lngs) ? lngs : this.services.languageUtils.getBestMatchFromCodes(lngs);
2184
+ if (l) {
2185
+ if (!this.language) {
2186
+ setLngProps(l);
2187
+ }
2188
+ if (!this.translator.language) this.translator.changeLanguage(l);
2189
+ if (this.services.languageDetector && this.services.languageDetector.cacheUserLanguage) this.services.languageDetector.cacheUserLanguage(l);
2190
+ }
2191
+ this.loadResources(l, err => {
2192
+ done(err, l);
2193
+ });
2194
+ };
2195
+ if (!lng && this.services.languageDetector && !this.services.languageDetector.async) {
2196
+ setLng(this.services.languageDetector.detect());
2197
+ } else if (!lng && this.services.languageDetector && this.services.languageDetector.async) {
2198
+ if (this.services.languageDetector.detect.length === 0) {
2199
+ this.services.languageDetector.detect().then(setLng);
2200
+ } else {
2201
+ this.services.languageDetector.detect(setLng);
2202
+ }
2203
+ } else {
2204
+ setLng(lng);
2205
+ }
2206
+ return deferred;
2207
+ }
2208
+ getFixedT(lng, ns, keyPrefix) {
2209
+ var _this3 = this;
2210
+ const fixedT = function (key, opts) {
2211
+ let options;
2212
+ if (typeof opts !== 'object') {
2213
+ for (var _len3 = arguments.length, rest = new Array(_len3 > 2 ? _len3 - 2 : 0), _key3 = 2; _key3 < _len3; _key3++) {
2214
+ rest[_key3 - 2] = arguments[_key3];
2215
+ }
2216
+ options = _this3.options.overloadTranslationOptionHandler([key, opts].concat(rest));
2217
+ } else {
2218
+ options = {
2219
+ ...opts
2220
+ };
2221
+ }
2222
+ options.lng = options.lng || fixedT.lng;
2223
+ options.lngs = options.lngs || fixedT.lngs;
2224
+ options.ns = options.ns || fixedT.ns;
2225
+ if (options.keyPrefix !== '') options.keyPrefix = options.keyPrefix || keyPrefix || fixedT.keyPrefix;
2226
+ const keySeparator = _this3.options.keySeparator || '.';
2227
+ let resultKey;
2228
+ if (options.keyPrefix && Array.isArray(key)) {
2229
+ resultKey = key.map(k => `${options.keyPrefix}${keySeparator}${k}`);
2230
+ } else {
2231
+ resultKey = options.keyPrefix ? `${options.keyPrefix}${keySeparator}${key}` : key;
2232
+ }
2233
+ return _this3.t(resultKey, options);
2234
+ };
2235
+ if (isString(lng)) {
2236
+ fixedT.lng = lng;
2237
+ } else {
2238
+ fixedT.lngs = lng;
2239
+ }
2240
+ fixedT.ns = ns;
2241
+ fixedT.keyPrefix = keyPrefix;
2242
+ return fixedT;
2243
+ }
2244
+ t() {
2245
+ return this.translator && this.translator.translate(...arguments);
2246
+ }
2247
+ exists() {
2248
+ return this.translator && this.translator.exists(...arguments);
2249
+ }
2250
+ setDefaultNamespace(ns) {
2251
+ this.options.defaultNS = ns;
2252
+ }
2253
+ hasLoadedNamespace(ns) {
2254
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
2255
+ if (!this.isInitialized) {
2256
+ this.logger.warn('hasLoadedNamespace: i18next was not initialized', this.languages);
2257
+ return false;
2258
+ }
2259
+ if (!this.languages || !this.languages.length) {
2260
+ this.logger.warn('hasLoadedNamespace: i18n.languages were undefined or empty', this.languages);
2261
+ return false;
2262
+ }
2263
+ const lng = options.lng || this.resolvedLanguage || this.languages[0];
2264
+ const fallbackLng = this.options ? this.options.fallbackLng : false;
2265
+ const lastLng = this.languages[this.languages.length - 1];
2266
+ if (lng.toLowerCase() === 'cimode') return true;
2267
+ const loadNotPending = (l, n) => {
2268
+ const loadState = this.services.backendConnector.state[`${l}|${n}`];
2269
+ return loadState === -1 || loadState === 0 || loadState === 2;
2270
+ };
2271
+ if (options.precheck) {
2272
+ const preResult = options.precheck(this, loadNotPending);
2273
+ if (preResult !== undefined) return preResult;
2274
+ }
2275
+ if (this.hasResourceBundle(lng, ns)) return true;
2276
+ if (!this.services.backendConnector.backend || this.options.resources && !this.options.partialBundledLanguages) return true;
2277
+ if (loadNotPending(lng, ns) && (!fallbackLng || loadNotPending(lastLng, ns))) return true;
2278
+ return false;
2279
+ }
2280
+ loadNamespaces(ns, callback) {
2281
+ const deferred = defer();
2282
+ if (!this.options.ns) {
2283
+ if (callback) callback();
2284
+ return Promise.resolve();
2285
+ }
2286
+ if (isString(ns)) ns = [ns];
2287
+ ns.forEach(n => {
2288
+ if (this.options.ns.indexOf(n) < 0) this.options.ns.push(n);
2289
+ });
2290
+ this.loadResources(err => {
2291
+ deferred.resolve();
2292
+ if (callback) callback(err);
2293
+ });
2294
+ return deferred;
2295
+ }
2296
+ loadLanguages(lngs, callback) {
2297
+ const deferred = defer();
2298
+ if (isString(lngs)) lngs = [lngs];
2299
+ const preloaded = this.options.preload || [];
2300
+ const newLngs = lngs.filter(lng => preloaded.indexOf(lng) < 0 && this.services.languageUtils.isSupportedCode(lng));
2301
+ if (!newLngs.length) {
2302
+ if (callback) callback();
2303
+ return Promise.resolve();
2304
+ }
2305
+ this.options.preload = preloaded.concat(newLngs);
2306
+ this.loadResources(err => {
2307
+ deferred.resolve();
2308
+ if (callback) callback(err);
2309
+ });
2310
+ return deferred;
2311
+ }
2312
+ dir(lng) {
2313
+ if (!lng) lng = this.resolvedLanguage || (this.languages && this.languages.length > 0 ? this.languages[0] : this.language);
2314
+ if (!lng) return 'rtl';
2315
+ 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'];
2316
+ const languageUtils = this.services && this.services.languageUtils || new LanguageUtil(get());
2317
+ return rtlLngs.indexOf(languageUtils.getLanguagePartFromCode(lng)) > -1 || lng.toLowerCase().indexOf('-arab') > 1 ? 'rtl' : 'ltr';
2318
+ }
2319
+ static createInstance() {
2320
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2321
+ let callback = arguments.length > 1 ? arguments[1] : undefined;
2322
+ return new I18n(options, callback);
2323
+ }
2324
+ cloneInstance() {
2325
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2326
+ let callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop;
2327
+ const forkResourceStore = options.forkResourceStore;
2328
+ if (forkResourceStore) delete options.forkResourceStore;
2329
+ const mergedOptions = {
2330
+ ...this.options,
2331
+ ...options,
2332
+ ...{
2333
+ isClone: true
2334
+ }
2335
+ };
2336
+ const clone = new I18n(mergedOptions);
2337
+ if (options.debug !== undefined || options.prefix !== undefined) {
2338
+ clone.logger = clone.logger.clone(options);
2339
+ }
2340
+ const membersToCopy = ['store', 'services', 'language'];
2341
+ membersToCopy.forEach(m => {
2342
+ clone[m] = this[m];
2343
+ });
2344
+ clone.services = {
2345
+ ...this.services
2346
+ };
2347
+ clone.services.utils = {
2348
+ hasLoadedNamespace: clone.hasLoadedNamespace.bind(clone)
2349
+ };
2350
+ if (forkResourceStore) {
2351
+ clone.store = new ResourceStore(this.store.data, mergedOptions);
2352
+ clone.services.resourceStore = clone.store;
2353
+ }
2354
+ clone.translator = new Translator(clone.services, mergedOptions);
2355
+ clone.translator.on('*', function (event) {
2356
+ for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
2357
+ args[_key4 - 1] = arguments[_key4];
2358
+ }
2359
+ clone.emit(event, ...args);
2360
+ });
2361
+ clone.init(mergedOptions, callback);
2362
+ clone.translator.options = mergedOptions;
2363
+ clone.translator.backendConnector.services.utils = {
2364
+ hasLoadedNamespace: clone.hasLoadedNamespace.bind(clone)
2365
+ };
2366
+ return clone;
2367
+ }
2368
+ toJSON() {
2369
+ return {
2370
+ options: this.options,
2371
+ store: this.store,
2372
+ language: this.language,
2373
+ languages: this.languages,
2374
+ resolvedLanguage: this.resolvedLanguage
2375
+ };
2376
+ }
2377
+ }
2378
+ const instance = I18n.createInstance();
2379
+ instance.createInstance = I18n.createInstance;
2380
+
2381
+ instance.createInstance;
2382
+ instance.dir;
2383
+ instance.init;
2384
+ instance.loadResources;
2385
+ instance.reloadResources;
2386
+ instance.use;
2387
+ instance.changeLanguage;
2388
+ instance.getFixedT;
2389
+ instance.t;
2390
+ instance.exists;
2391
+ instance.setDefaultNamespace;
2392
+ instance.hasLoadedNamespace;
2393
+ instance.loadNamespaces;
2394
+ instance.loadLanguages;
2395
+
2396
+ function _classCallCheck$1(a, n) {
2397
+ if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
2398
+ }
2399
+
2400
+ function _typeof$3(o) {
2401
+ "@babel/helpers - typeof";
2402
+
2403
+ return _typeof$3 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
2404
+ return typeof o;
2405
+ } : function (o) {
2406
+ return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
2407
+ }, _typeof$3(o);
2408
+ }
2409
+
2410
+ function toPrimitive(t, r) {
2411
+ if ("object" != _typeof$3(t) || !t) return t;
2412
+ var e = t[Symbol.toPrimitive];
2413
+ if (void 0 !== e) {
2414
+ var i = e.call(t, r);
2415
+ if ("object" != _typeof$3(i)) return i;
2416
+ throw new TypeError("@@toPrimitive must return a primitive value.");
2417
+ }
2418
+ return (String )(t);
2419
+ }
2420
+
2421
+ function toPropertyKey(t) {
2422
+ var i = toPrimitive(t, "string");
2423
+ return "symbol" == _typeof$3(i) ? i : i + "";
2424
+ }
2425
+
2426
+ function _defineProperties$1(e, r) {
2427
+ for (var t = 0; t < r.length; t++) {
2428
+ var o = r[t];
2429
+ o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, toPropertyKey(o.key), o);
2430
+ }
2431
+ }
2432
+ function _createClass$1(e, r, t) {
2433
+ return r && _defineProperties$1(e.prototype, r), Object.defineProperty(e, "prototype", {
2434
+ writable: !1
2435
+ }), e;
2436
+ }
2437
+
2438
+ var arr = [];
2439
+ var each = arr.forEach;
2440
+ var slice = arr.slice;
2441
+ function defaults(obj) {
2442
+ each.call(slice.call(arguments, 1), function (source) {
2443
+ if (source) {
2444
+ for (var prop in source) {
2445
+ if (obj[prop] === undefined) obj[prop] = source[prop];
2446
+ }
2447
+ }
2448
+ });
2449
+ return obj;
2450
+ }
2451
+ function createClassOnDemand(ClassOrObject) {
2452
+ if (!ClassOrObject) return null;
2453
+ if (typeof ClassOrObject === 'function') return new ClassOrObject();
2454
+ return ClassOrObject;
2455
+ }
2456
+
2457
+ function getDefaults$2() {
2458
+ return {
2459
+ handleEmptyResourcesAsFailed: true,
2460
+ cacheHitMode: 'none'
2461
+ // reloadInterval: typeof window !== 'undefined' ? false : 60 * 60 * 1000
2462
+ // refreshExpirationTime: 60 * 60 * 1000
2463
+ };
2464
+ }
2465
+
2466
+ function handleCorrectReadFunction(backend, language, namespace, resolver) {
2467
+ var fc = backend.read.bind(backend);
2468
+ if (fc.length === 2) {
2469
+ // no callback
2470
+ try {
2471
+ var r = fc(language, namespace);
2472
+ if (r && typeof r.then === 'function') {
2473
+ // promise
2474
+ r.then(function (data) {
2475
+ return resolver(null, data);
2476
+ })["catch"](resolver);
2477
+ } else {
2478
+ // sync
2479
+ resolver(null, r);
2480
+ }
2481
+ } catch (err) {
2482
+ resolver(err);
2483
+ }
2484
+ return;
2485
+ }
2486
+
2487
+ // normal with callback
2488
+ fc(language, namespace, resolver);
2489
+ }
2490
+ var Backend$1 = /*#__PURE__*/function () {
2491
+ function Backend(services) {
2492
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
2493
+ var i18nextOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
2494
+ _classCallCheck$1(this, Backend);
2495
+ this.backends = [];
2496
+ this.type = 'backend';
2497
+ this.allOptions = i18nextOptions;
2498
+ this.init(services, options);
2499
+ }
2500
+ _createClass$1(Backend, [{
2501
+ key: "init",
2502
+ value: function init(services) {
2503
+ var _this = this;
2504
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
2505
+ var i18nextOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
2506
+ this.services = services;
2507
+ this.options = defaults(options, this.options || {}, getDefaults$2());
2508
+ this.allOptions = i18nextOptions;
2509
+ this.options.backends && this.options.backends.forEach(function (b, i) {
2510
+ _this.backends[i] = _this.backends[i] || createClassOnDemand(b);
2511
+ _this.backends[i].init(services, _this.options.backendOptions && _this.options.backendOptions[i] || {}, i18nextOptions);
2512
+ });
2513
+ if (this.services && this.options.reloadInterval) {
2514
+ setInterval(function () {
2515
+ return _this.reload();
2516
+ }, this.options.reloadInterval);
2517
+ }
2518
+ }
2519
+ }, {
2520
+ key: "read",
2521
+ value: function read(language, namespace, callback) {
2522
+ var _this2 = this;
2523
+ var bLen = this.backends.length;
2524
+ var loadPosition = function loadPosition(pos) {
2525
+ if (pos >= bLen) return callback(new Error('non of the backend loaded data', true)); // failed pass retry flag
2526
+ var isLastBackend = pos === bLen - 1;
2527
+ var lengthCheckAmount = _this2.options.handleEmptyResourcesAsFailed && !isLastBackend ? 0 : -1;
2528
+ var backend = _this2.backends[pos];
2529
+ if (backend.read) {
2530
+ handleCorrectReadFunction(backend, language, namespace, function (err, data, savedAt) {
2531
+ if (!err && data && Object.keys(data).length > lengthCheckAmount) {
2532
+ callback(null, data, pos);
2533
+ savePosition(pos - 1, data); // save one in front
2534
+ if (backend.save && _this2.options.cacheHitMode && ['refresh', 'refreshAndUpdateStore'].indexOf(_this2.options.cacheHitMode) > -1) {
2535
+ if (savedAt && _this2.options.refreshExpirationTime && savedAt + _this2.options.refreshExpirationTime > Date.now()) return;
2536
+ var nextBackend = _this2.backends[pos + 1];
2537
+ if (nextBackend && nextBackend.read) {
2538
+ handleCorrectReadFunction(nextBackend, language, namespace, function (err, data) {
2539
+ if (err) return;
2540
+ if (!data) return;
2541
+ if (Object.keys(data).length <= lengthCheckAmount) return;
2542
+ savePosition(pos, data);
2543
+ if (_this2.options.cacheHitMode !== 'refreshAndUpdateStore') return;
2544
+ if (_this2.services && _this2.services.resourceStore) {
2545
+ _this2.services.resourceStore.addResourceBundle(language, namespace, data);
2546
+ }
2547
+ });
2548
+ }
2549
+ }
2550
+ } else {
2551
+ loadPosition(pos + 1); // try load from next
2552
+ }
2553
+ });
2554
+ } else {
2555
+ loadPosition(pos + 1); // try load from next
2556
+ }
2557
+ };
2558
+
2559
+ var savePosition = function savePosition(pos, data) {
2560
+ if (pos < 0) return;
2561
+ var backend = _this2.backends[pos];
2562
+ if (backend.save) {
2563
+ backend.save(language, namespace, data);
2564
+ savePosition(pos - 1, data);
2565
+ } else {
2566
+ savePosition(pos - 1, data);
2567
+ }
2568
+ };
2569
+ loadPosition(0);
2570
+ }
2571
+ }, {
2572
+ key: "create",
2573
+ value: function create(languages, namespace, key, fallbackValue) {
2574
+ var clb = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : function () {};
2575
+ var opts = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
2576
+ this.backends.forEach(function (b) {
2577
+ if (!b.create) return;
2578
+ var fc = b.create.bind(b);
2579
+ if (fc.length < 6) {
2580
+ // no callback
2581
+ try {
2582
+ var r;
2583
+ if (fc.length === 5) {
2584
+ // future callback-less api for i18next-locize-backend
2585
+ r = fc(languages, namespace, key, fallbackValue, opts);
2586
+ } else {
2587
+ r = fc(languages, namespace, key, fallbackValue);
2588
+ }
2589
+ if (r && typeof r.then === 'function') {
2590
+ // promise
2591
+ r.then(function (data) {
2592
+ return clb(null, data);
2593
+ })["catch"](clb);
2594
+ } else {
2595
+ // sync
2596
+ clb(null, r);
2597
+ }
2598
+ } catch (err) {
2599
+ clb(err);
2600
+ }
2601
+ return;
2602
+ }
2603
+
2604
+ // normal with callback
2605
+ fc(languages, namespace, key, fallbackValue, clb /* unused callback */, opts);
2606
+ });
2607
+ }
2608
+ }, {
2609
+ key: "reload",
2610
+ value: function reload() {
2611
+ var _this3 = this;
2612
+ var _this$services = this.services,
2613
+ backendConnector = _this$services.backendConnector,
2614
+ languageUtils = _this$services.languageUtils,
2615
+ logger = _this$services.logger;
2616
+ var currentLanguage = backendConnector.language;
2617
+ if (currentLanguage && currentLanguage.toLowerCase() === 'cimode') return; // avoid loading resources for cimode
2618
+
2619
+ var toLoad = [];
2620
+ var append = function append(lng) {
2621
+ var lngs = languageUtils.toResolveHierarchy(lng);
2622
+ lngs.forEach(function (l) {
2623
+ if (toLoad.indexOf(l) < 0) toLoad.push(l);
2624
+ });
2625
+ };
2626
+ append(currentLanguage);
2627
+ if (this.allOptions.preload) this.allOptions.preload.forEach(function (l) {
2628
+ return append(l);
2629
+ });
2630
+ toLoad.forEach(function (lng) {
2631
+ _this3.allOptions.ns.forEach(function (ns) {
2632
+ backendConnector.read(lng, ns, 'read', null, null, function (err, data) {
2633
+ if (err) logger.warn("loading namespace ".concat(ns, " for language ").concat(lng, " failed"), err);
2634
+ if (!err && data) logger.log("loaded namespace ".concat(ns, " for language ").concat(lng), data);
2635
+ backendConnector.loaded("".concat(lng, "|").concat(ns), err, data);
2636
+ });
2637
+ });
2638
+ });
2639
+ }
2640
+ }]);
2641
+ return Backend;
2642
+ }();
2643
+ Backend$1.type = 'backend';
2644
+
2645
+ function _typeof$2(o) { "@babel/helpers - typeof"; return _typeof$2 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof$2(o); }
2646
+ function hasXMLHttpRequest() {
2647
+ return typeof XMLHttpRequest === 'function' || (typeof XMLHttpRequest === "undefined" ? "undefined" : _typeof$2(XMLHttpRequest)) === 'object';
2648
+ }
2649
+ function isPromise(maybePromise) {
2650
+ return !!maybePromise && typeof maybePromise.then === 'function';
2651
+ }
2652
+ function makePromise(maybePromise) {
2653
+ if (isPromise(maybePromise)) {
2654
+ return maybePromise;
2655
+ }
2656
+ return Promise.resolve(maybePromise);
2657
+ }
2658
+
2659
+ var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
2660
+
2661
+ function getDefaultExportFromCjs (x) {
2662
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
2663
+ }
2664
+
2665
+ var getFetch$1 = {exports: {}};
2666
+
2667
+ (function (module, exports) {
2668
+ var fetchApi;
2669
+ if (typeof fetch === 'function') {
2670
+ if (typeof commonjsGlobal !== 'undefined' && commonjsGlobal.fetch) {
2671
+ fetchApi = commonjsGlobal.fetch;
2672
+ } else if (typeof window !== 'undefined' && window.fetch) {
2673
+ fetchApi = window.fetch;
2674
+ } else {
2675
+ fetchApi = fetch;
2676
+ }
2677
+ }
2678
+
2679
+ if (typeof require !== 'undefined' && typeof window === 'undefined') {
2680
+ var f = fetchApi || require$$0;
2681
+ if (f.default) f = f.default;
2682
+ exports.default = f;
2683
+ module.exports = exports.default;
2684
+ }
2685
+ } (getFetch$1, getFetch$1.exports));
2686
+
2687
+ var getFetchExports = getFetch$1.exports;
2688
+ var getFetch = /*@__PURE__*/getDefaultExportFromCjs(getFetchExports);
2689
+
2690
+ var fetchNode = /*#__PURE__*/_mergeNamespaces({
2691
+ __proto__: null,
2692
+ default: getFetch
2693
+ }, [getFetchExports]);
2694
+
2695
+ function ownKeys$2(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
2696
+ function _objectSpread$2(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$2(Object(t), !0).forEach(function (r) { _defineProperty$2(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$2(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
2697
+ function _defineProperty$2(e, r, t) { return (r = _toPropertyKey$1(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
2698
+ function _toPropertyKey$1(t) { var i = _toPrimitive$1(t, "string"); return "symbol" == _typeof$1(i) ? i : i + ""; }
2699
+ function _toPrimitive$1(t, r) { if ("object" != _typeof$1(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof$1(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
2700
+ function _typeof$1(o) { "@babel/helpers - typeof"; return _typeof$1 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof$1(o); }
2701
+ var fetchApi;
2702
+ if (typeof fetch === 'function') {
2703
+ if (typeof global !== 'undefined' && global.fetch) {
2704
+ fetchApi = global.fetch;
2705
+ } else if (typeof window !== 'undefined' && window.fetch) {
2706
+ fetchApi = window.fetch;
2707
+ } else {
2708
+ fetchApi = fetch;
2709
+ }
2710
+ }
2711
+ var XmlHttpRequestApi;
2712
+ if (hasXMLHttpRequest()) {
2713
+ if (typeof global !== 'undefined' && global.XMLHttpRequest) {
2714
+ XmlHttpRequestApi = global.XMLHttpRequest;
2715
+ } else if (typeof window !== 'undefined' && window.XMLHttpRequest) {
2716
+ XmlHttpRequestApi = window.XMLHttpRequest;
2717
+ }
2718
+ }
2719
+ var ActiveXObjectApi;
2720
+ if (typeof ActiveXObject === 'function') {
2721
+ if (typeof global !== 'undefined' && global.ActiveXObject) {
2722
+ ActiveXObjectApi = global.ActiveXObject;
2723
+ } else if (typeof window !== 'undefined' && window.ActiveXObject) {
2724
+ ActiveXObjectApi = window.ActiveXObject;
2725
+ }
2726
+ }
2727
+ if (!fetchApi && fetchNode && !XmlHttpRequestApi && !ActiveXObjectApi) fetchApi = getFetch || fetchNode;
2728
+ if (typeof fetchApi !== 'function') fetchApi = undefined;
2729
+ var addQueryString = function addQueryString(url, params) {
2730
+ if (params && _typeof$1(params) === 'object') {
2731
+ var queryString = '';
2732
+ for (var paramName in params) {
2733
+ queryString += '&' + encodeURIComponent(paramName) + '=' + encodeURIComponent(params[paramName]);
2734
+ }
2735
+ if (!queryString) return url;
2736
+ url = url + (url.indexOf('?') !== -1 ? '&' : '?') + queryString.slice(1);
2737
+ }
2738
+ return url;
2739
+ };
2740
+ var fetchIt = function fetchIt(url, fetchOptions, callback, altFetch) {
2741
+ var resolver = function resolver(response) {
2742
+ if (!response.ok) return callback(response.statusText || 'Error', {
2743
+ status: response.status
2744
+ });
2745
+ response.text().then(function (data) {
2746
+ callback(null, {
2747
+ status: response.status,
2748
+ data: data
2749
+ });
2750
+ }).catch(callback);
2751
+ };
2752
+ if (altFetch) {
2753
+ var altResponse = altFetch(url, fetchOptions);
2754
+ if (altResponse instanceof Promise) {
2755
+ altResponse.then(resolver).catch(callback);
2756
+ return;
2757
+ }
2758
+ }
2759
+ if (typeof fetch === 'function') {
2760
+ fetch(url, fetchOptions).then(resolver).catch(callback);
2761
+ } else {
2762
+ fetchApi(url, fetchOptions).then(resolver).catch(callback);
2763
+ }
2764
+ };
2765
+ var omitFetchOptions = false;
2766
+ var requestWithFetch = function requestWithFetch(options, url, payload, callback) {
2767
+ if (options.queryStringParams) {
2768
+ url = addQueryString(url, options.queryStringParams);
2769
+ }
2770
+ var headers = _objectSpread$2({}, typeof options.customHeaders === 'function' ? options.customHeaders() : options.customHeaders);
2771
+ if (typeof window === 'undefined' && typeof global !== 'undefined' && typeof global.process !== 'undefined' && global.process.versions && global.process.versions.node) {
2772
+ headers['User-Agent'] = "i18next-http-backend (node/".concat(global.process.version, "; ").concat(global.process.platform, " ").concat(global.process.arch, ")");
2773
+ }
2774
+ if (payload) headers['Content-Type'] = 'application/json';
2775
+ var reqOptions = typeof options.requestOptions === 'function' ? options.requestOptions(payload) : options.requestOptions;
2776
+ var fetchOptions = _objectSpread$2({
2777
+ method: payload ? 'POST' : 'GET',
2778
+ body: payload ? options.stringify(payload) : undefined,
2779
+ headers: headers
2780
+ }, omitFetchOptions ? {} : reqOptions);
2781
+ var altFetch = typeof options.alternateFetch === 'function' && options.alternateFetch.length >= 1 ? options.alternateFetch : undefined;
2782
+ try {
2783
+ fetchIt(url, fetchOptions, callback, altFetch);
2784
+ } catch (e) {
2785
+ if (!reqOptions || Object.keys(reqOptions).length === 0 || !e.message || e.message.indexOf('not implemented') < 0) {
2786
+ return callback(e);
2787
+ }
2788
+ try {
2789
+ Object.keys(reqOptions).forEach(function (opt) {
2790
+ delete fetchOptions[opt];
2791
+ });
2792
+ fetchIt(url, fetchOptions, callback, altFetch);
2793
+ omitFetchOptions = true;
2794
+ } catch (err) {
2795
+ callback(err);
2796
+ }
2797
+ }
2798
+ };
2799
+ var requestWithXmlHttpRequest = function requestWithXmlHttpRequest(options, url, payload, callback) {
2800
+ if (payload && _typeof$1(payload) === 'object') {
2801
+ payload = addQueryString('', payload).slice(1);
2802
+ }
2803
+ if (options.queryStringParams) {
2804
+ url = addQueryString(url, options.queryStringParams);
2805
+ }
2806
+ try {
2807
+ var x;
2808
+ if (XmlHttpRequestApi) {
2809
+ x = new XmlHttpRequestApi();
2810
+ } else {
2811
+ x = new ActiveXObjectApi('MSXML2.XMLHTTP.3.0');
2812
+ }
2813
+ x.open(payload ? 'POST' : 'GET', url, 1);
2814
+ if (!options.crossDomain) {
2815
+ x.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
2816
+ }
2817
+ x.withCredentials = !!options.withCredentials;
2818
+ if (payload) {
2819
+ x.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
2820
+ }
2821
+ if (x.overrideMimeType) {
2822
+ x.overrideMimeType('application/json');
2823
+ }
2824
+ var h = options.customHeaders;
2825
+ h = typeof h === 'function' ? h() : h;
2826
+ if (h) {
2827
+ for (var i in h) {
2828
+ x.setRequestHeader(i, h[i]);
2829
+ }
2830
+ }
2831
+ x.onreadystatechange = function () {
2832
+ x.readyState > 3 && callback(x.status >= 400 ? x.statusText : null, {
2833
+ status: x.status,
2834
+ data: x.responseText
2835
+ });
2836
+ };
2837
+ x.send(payload);
2838
+ } catch (e) {
2839
+ console && console.log(e);
2840
+ }
2841
+ };
2842
+ var request = function request(options, url, payload, callback) {
2843
+ if (typeof payload === 'function') {
2844
+ callback = payload;
2845
+ payload = undefined;
2846
+ }
2847
+ callback = callback || function () {};
2848
+ if (fetchApi && url.indexOf('file:') !== 0) {
2849
+ return requestWithFetch(options, url, payload, callback);
2850
+ }
2851
+ if (hasXMLHttpRequest() || typeof ActiveXObject === 'function') {
2852
+ return requestWithXmlHttpRequest(options, url, payload, callback);
2853
+ }
2854
+ callback(new Error('No fetch and no xhr implementation found!'));
2855
+ };
2856
+
2857
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2858
+ function ownKeys$1(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
2859
+ function _objectSpread$1(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$1(Object(t), !0).forEach(function (r) { _defineProperty$1(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$1(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
2860
+ function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
2861
+ function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
2862
+ function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
2863
+ function _defineProperty$1(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
2864
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
2865
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
2866
+ var getDefaults$1 = function getDefaults() {
2867
+ return {
2868
+ loadPath: '/locales/{{lng}}/{{ns}}.json',
2869
+ addPath: '/locales/add/{{lng}}/{{ns}}',
2870
+ parse: function parse(data) {
2871
+ return JSON.parse(data);
2872
+ },
2873
+ stringify: JSON.stringify,
2874
+ parsePayload: function parsePayload(namespace, key, fallbackValue) {
2875
+ return _defineProperty$1({}, key, fallbackValue || '');
2876
+ },
2877
+ parseLoadPayload: function parseLoadPayload(languages, namespaces) {
2878
+ return undefined;
2879
+ },
2880
+ request: request,
2881
+ reloadInterval: typeof window !== 'undefined' ? false : 60 * 60 * 1000,
2882
+ customHeaders: {},
2883
+ queryStringParams: {},
2884
+ crossDomain: false,
2885
+ withCredentials: false,
2886
+ overrideMimeType: false,
2887
+ requestOptions: {
2888
+ mode: 'cors',
2889
+ credentials: 'same-origin',
2890
+ cache: 'default'
2891
+ }
2892
+ };
2893
+ };
2894
+ var Backend = function () {
2895
+ function Backend(services) {
2896
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
2897
+ var allOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
2898
+ _classCallCheck(this, Backend);
2899
+ this.services = services;
2900
+ this.options = options;
2901
+ this.allOptions = allOptions;
2902
+ this.type = 'backend';
2903
+ this.init(services, options, allOptions);
2904
+ }
2905
+ return _createClass(Backend, [{
2906
+ key: "init",
2907
+ value: function init(services) {
2908
+ var _this = this;
2909
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
2910
+ var allOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
2911
+ this.services = services;
2912
+ this.options = _objectSpread$1(_objectSpread$1(_objectSpread$1({}, getDefaults$1()), this.options || {}), options);
2913
+ this.allOptions = allOptions;
2914
+ if (this.services && this.options.reloadInterval) {
2915
+ var timer = setInterval(function () {
2916
+ return _this.reload();
2917
+ }, this.options.reloadInterval);
2918
+ if (_typeof(timer) === 'object' && typeof timer.unref === 'function') timer.unref();
2919
+ }
2920
+ }
2921
+ }, {
2922
+ key: "readMulti",
2923
+ value: function readMulti(languages, namespaces, callback) {
2924
+ this._readAny(languages, languages, namespaces, namespaces, callback);
2925
+ }
2926
+ }, {
2927
+ key: "read",
2928
+ value: function read(language, namespace, callback) {
2929
+ this._readAny([language], language, [namespace], namespace, callback);
2930
+ }
2931
+ }, {
2932
+ key: "_readAny",
2933
+ value: function _readAny(languages, loadUrlLanguages, namespaces, loadUrlNamespaces, callback) {
2934
+ var _this2 = this;
2935
+ var loadPath = this.options.loadPath;
2936
+ if (typeof this.options.loadPath === 'function') {
2937
+ loadPath = this.options.loadPath(languages, namespaces);
2938
+ }
2939
+ loadPath = makePromise(loadPath);
2940
+ loadPath.then(function (resolvedLoadPath) {
2941
+ if (!resolvedLoadPath) return callback(null, {});
2942
+ var url = _this2.services.interpolator.interpolate(resolvedLoadPath, {
2943
+ lng: languages.join('+'),
2944
+ ns: namespaces.join('+')
2945
+ });
2946
+ _this2.loadUrl(url, callback, loadUrlLanguages, loadUrlNamespaces);
2947
+ });
2948
+ }
2949
+ }, {
2950
+ key: "loadUrl",
2951
+ value: function loadUrl(url, callback, languages, namespaces) {
2952
+ var _this3 = this;
2953
+ var lng = typeof languages === 'string' ? [languages] : languages;
2954
+ var ns = typeof namespaces === 'string' ? [namespaces] : namespaces;
2955
+ var payload = this.options.parseLoadPayload(lng, ns);
2956
+ this.options.request(this.options, url, payload, function (err, res) {
2957
+ if (res && (res.status >= 500 && res.status < 600 || !res.status)) return callback('failed loading ' + url + '; status code: ' + res.status, true);
2958
+ if (res && res.status >= 400 && res.status < 500) return callback('failed loading ' + url + '; status code: ' + res.status, false);
2959
+ if (!res && err && err.message) {
2960
+ var errorMessage = err.message.toLowerCase();
2961
+ var isNetworkError = ['failed', 'fetch', 'network', 'load'].find(function (term) {
2962
+ return errorMessage.indexOf(term) > -1;
2963
+ });
2964
+ if (isNetworkError) {
2965
+ return callback('failed loading ' + url + ': ' + err.message, true);
2966
+ }
2967
+ }
2968
+ if (err) return callback(err, false);
2969
+ var ret, parseErr;
2970
+ try {
2971
+ if (typeof res.data === 'string') {
2972
+ ret = _this3.options.parse(res.data, languages, namespaces);
2973
+ } else {
2974
+ ret = res.data;
2975
+ }
2976
+ } catch (e) {
2977
+ parseErr = 'failed parsing ' + url + ' to json';
2978
+ }
2979
+ if (parseErr) return callback(parseErr, false);
2980
+ callback(null, ret);
2981
+ });
2982
+ }
2983
+ }, {
2984
+ key: "create",
2985
+ value: function create(languages, namespace, key, fallbackValue, callback) {
2986
+ var _this4 = this;
2987
+ if (!this.options.addPath) return;
2988
+ if (typeof languages === 'string') languages = [languages];
2989
+ var payload = this.options.parsePayload(namespace, key, fallbackValue);
2990
+ var finished = 0;
2991
+ var dataArray = [];
2992
+ var resArray = [];
2993
+ languages.forEach(function (lng) {
2994
+ var addPath = _this4.options.addPath;
2995
+ if (typeof _this4.options.addPath === 'function') {
2996
+ addPath = _this4.options.addPath(lng, namespace);
2997
+ }
2998
+ var url = _this4.services.interpolator.interpolate(addPath, {
2999
+ lng: lng,
3000
+ ns: namespace
3001
+ });
3002
+ _this4.options.request(_this4.options, url, payload, function (data, res) {
3003
+ finished += 1;
3004
+ dataArray.push(data);
3005
+ resArray.push(res);
3006
+ if (finished === languages.length) {
3007
+ if (typeof callback === 'function') callback(dataArray, resArray);
3008
+ }
3009
+ });
3010
+ });
3011
+ }
3012
+ }, {
3013
+ key: "reload",
3014
+ value: function reload() {
3015
+ var _this5 = this;
3016
+ var _this$services = this.services,
3017
+ backendConnector = _this$services.backendConnector,
3018
+ languageUtils = _this$services.languageUtils,
3019
+ logger = _this$services.logger;
3020
+ var currentLanguage = backendConnector.language;
3021
+ if (currentLanguage && currentLanguage.toLowerCase() === 'cimode') return;
3022
+ var toLoad = [];
3023
+ var append = function append(lng) {
3024
+ var lngs = languageUtils.toResolveHierarchy(lng);
3025
+ lngs.forEach(function (l) {
3026
+ if (toLoad.indexOf(l) < 0) toLoad.push(l);
3027
+ });
3028
+ };
3029
+ append(currentLanguage);
3030
+ if (this.allOptions.preload) this.allOptions.preload.forEach(function (l) {
3031
+ return append(l);
3032
+ });
3033
+ toLoad.forEach(function (lng) {
3034
+ _this5.allOptions.ns.forEach(function (ns) {
3035
+ backendConnector.read(lng, ns, 'read', null, null, function (err, data) {
3036
+ if (err) logger.warn("loading namespace ".concat(ns, " for language ").concat(lng, " failed"), err);
3037
+ if (!err && data) logger.log("loaded namespace ".concat(ns, " for language ").concat(lng), data);
3038
+ backendConnector.loaded("".concat(lng, "|").concat(ns), err, data);
3039
+ });
3040
+ });
3041
+ });
3042
+ }
3043
+ }]);
3044
+ }();
3045
+ Backend.type = 'backend';
3046
+
3047
+ function _defineProperty(e, r, t) {
3048
+ return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
3049
+ value: t,
3050
+ enumerable: !0,
3051
+ configurable: !0,
3052
+ writable: !0
3053
+ }) : e[r] = t, e;
3054
+ }
3055
+
3056
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3057
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
3058
+ /* eslint-disable max-classes-per-file */
3059
+ var Storage = /*#__PURE__*/function () {
3060
+ function Storage(options) {
3061
+ _classCallCheck$1(this, Storage);
3062
+ this.store = options.store;
3063
+ }
3064
+ _createClass$1(Storage, [{
3065
+ key: "setItem",
3066
+ value: function setItem(key, value) {
3067
+ if (this.store) {
3068
+ try {
3069
+ this.store.setItem(key, value);
3070
+ } catch (e) {
3071
+ // f.log('failed to set value for key "' + key + '" to localStorage.');
3072
+ }
3073
+ }
3074
+ }
3075
+ }, {
3076
+ key: "getItem",
3077
+ value: function getItem(key, value) {
3078
+ if (this.store) {
3079
+ try {
3080
+ return this.store.getItem(key, value);
3081
+ } catch (e) {
3082
+ // f.log('failed to get value for key "' + key + '" from localStorage.');
3083
+ }
3084
+ }
3085
+ return undefined;
3086
+ }
3087
+ }]);
3088
+ return Storage;
3089
+ }();
3090
+ function getDefaults() {
3091
+ var store = null;
3092
+ try {
3093
+ store = window.localStorage;
3094
+ } catch (e) {
3095
+ if (typeof window !== 'undefined') {
3096
+ console.log('Failed to load local storage.', e);
3097
+ }
3098
+ }
3099
+ return {
3100
+ prefix: 'i18next_res_',
3101
+ expirationTime: 7 * 24 * 60 * 60 * 1000,
3102
+ defaultVersion: undefined,
3103
+ versions: {},
3104
+ store: store
3105
+ };
3106
+ }
3107
+ var Cache = /*#__PURE__*/function () {
3108
+ function Cache(services) {
3109
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
3110
+ _classCallCheck$1(this, Cache);
3111
+ this.init(services, options);
3112
+ this.type = 'backend';
3113
+ }
3114
+ _createClass$1(Cache, [{
3115
+ key: "init",
3116
+ value: function init(services) {
3117
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
3118
+ this.services = services;
3119
+ this.options = _objectSpread(_objectSpread(_objectSpread({}, getDefaults()), this.options), options);
3120
+ this.storage = new Storage(this.options);
3121
+ }
3122
+ }, {
3123
+ key: "read",
3124
+ value: function read(language, namespace, callback) {
3125
+ var nowMS = Date.now();
3126
+ if (!this.storage.store) {
3127
+ return callback(null, null);
3128
+ }
3129
+ var local = this.storage.getItem("".concat(this.options.prefix).concat(language, "-").concat(namespace));
3130
+ if (local) {
3131
+ local = JSON.parse(local);
3132
+ var version = this.getVersion(language);
3133
+ if (
3134
+ // expiration field is mandatory, and should not be expired
3135
+ local.i18nStamp && local.i18nStamp + this.options.expirationTime > nowMS &&
3136
+ // there should be no language version set, or if it is, it should match the one in translation
3137
+ version === local.i18nVersion) {
3138
+ var i18nStamp = local.i18nStamp;
3139
+ delete local.i18nVersion;
3140
+ delete local.i18nStamp;
3141
+ return callback(null, local, i18nStamp);
3142
+ }
3143
+ }
3144
+ return callback(null, null);
3145
+ }
3146
+ }, {
3147
+ key: "save",
3148
+ value: function save(language, namespace, data) {
3149
+ if (this.storage.store) {
3150
+ data.i18nStamp = Date.now();
3151
+
3152
+ // language version (if set)
3153
+ var version = this.getVersion(language);
3154
+ if (version) {
3155
+ data.i18nVersion = version;
3156
+ }
3157
+
3158
+ // save
3159
+ this.storage.setItem("".concat(this.options.prefix).concat(language, "-").concat(namespace), JSON.stringify(data));
3160
+ }
3161
+ }
3162
+ }, {
3163
+ key: "getVersion",
3164
+ value: function getVersion(language) {
3165
+ return this.options.versions[language] || this.options.defaultVersion;
3166
+ }
3167
+ }]);
3168
+ return Cache;
3169
+ }();
3170
+ Cache.type = 'backend';
3171
+
3172
+ var resourcesToBackend = function resourcesToBackend(res) {
3173
+ return {
3174
+ type: 'backend',
3175
+ init: function init(services, backendOptions, i18nextOptions) {},
3176
+ read: function read(language, namespace, callback) {
3177
+ if (typeof res === 'function') {
3178
+ if (res.length < 3) {
3179
+ try {
3180
+ var r = res(language, namespace);
3181
+ if (r && typeof r.then === 'function') {
3182
+ r.then(function (data) {
3183
+ return callback(null, data && data.default || data);
3184
+ }).catch(callback);
3185
+ } else {
3186
+ callback(null, r);
3187
+ }
3188
+ } catch (err) {
3189
+ callback(err);
3190
+ }
3191
+ return;
3192
+ }
3193
+ res(language, namespace, callback);
3194
+ return;
3195
+ }
3196
+ callback(null, res && res[language] && res[language][namespace]);
3197
+ }
3198
+ };
3199
+ };
3200
+
3201
+ const getV = divider => {
3202
+ return Math.floor(Date.now() / divider);
3203
+ };
3204
+ const initI18n = (initReactI18next, lang, fallbackLang, langCacheExpiredTimeMs, resources, version, withLocalstorageBackend, cdnUrl, debug) => {
3205
+ let backends = [];
3206
+ let backendOptions = [];
3207
+ const langs = Object.keys(resources);
3208
+ // https://www.i18next.com/how-to/backend-fallback
3209
+ if (withLocalstorageBackend) {
3210
+ const versions = {};
3211
+ langs.forEach(value => Object.assign(versions, {
3212
+ [value]: version
3213
+ }));
3214
+ backends.push(Cache);
3215
+ backendOptions.push({
3216
+ // prefix for stored languages
3217
+ prefix: `i18next_res_`,
3218
+ // expiration
3219
+ expirationTime: langCacheExpiredTimeMs,
3220
+ // language versions
3221
+ versions: versions
3222
+ });
3223
+ }
3224
+ if (cdnUrl) {
3225
+ backends.push(Backend);
3226
+ backendOptions.push({
3227
+ // load resources from url path
3228
+ loadPath: `${cdnUrl}/locales/{{lng}}.json`,
3229
+ // adds parameters to resource URL. 'example.com' -> 'example.com?v=1.3.5'
3230
+ queryStringParams: {
3231
+ v: `${version}.${getV(langCacheExpiredTimeMs)}`
3232
+ },
3233
+ reloadInterval: langCacheExpiredTimeMs // can be used to reload resources in a specific interval (milliseconds) (useful in server environments)
3234
+ });
3235
+ }
3236
+ backends.push(resourcesToBackend(resources));
3237
+ // https://www.i18next.com/misc/creating-own-plugins#languagedetector
3238
+ const languageDetector = {
3239
+ type: 'languageDetector',
3240
+ name: 'customDetector',
3241
+ async: false,
3242
+ init: () => {
3243
+ /* use services and options */
3244
+ },
3245
+ detect: callback => {
3246
+ return lang;
3247
+ }
3248
+ };
3249
+ const config = {
3250
+ debug: debug ?? false,
3251
+ compatibilityJSON: 'v4',
3252
+ ns: ['translation'],
3253
+ defaultNS: 'translation',
3254
+ lng: lang,
3255
+ fallbackLng: fallbackLang,
3256
+ load: 'currentOnly',
3257
+ keySeparator: false,
3258
+ nonExplicitSupportedLngs: true,
3259
+ backend: {
3260
+ backends: backends,
3261
+ backendOptions: backendOptions,
3262
+ cacheHitMode: 'refreshAndUpdateStore',
3263
+ reloadInterval: langCacheExpiredTimeMs,
3264
+ refreshExpirationTime: langCacheExpiredTimeMs // only after determined time it should trigger a refresh if necessary
3265
+ },
3266
+ react: {
3267
+ bindI18nStore: 'added' // this way, when the HttpBackend delivers new translations (thanks to refreshAndUpdateStore), the UI gets updated
3268
+ },
3269
+ interpolation: {
3270
+ escapeValue: false // react already safes from xss
3271
+ }
3272
+ };
3273
+ if (!instance.isInitialized) {
3274
+ instance.use(Backend$1).use(languageDetector).use(initReactI18next) // passes i18n down to react-i18next
3275
+ .init(config, (ex, t) => {
3276
+ if (ex) {
3277
+ console.error(`Error when i18n init`, ex);
3278
+ return;
3279
+ }
3280
+ setInterval(() => {
3281
+ instance.reloadResources();
3282
+ }, langCacheExpiredTimeMs);
3283
+ });
3284
+ }
3285
+ };
3286
+
3287
+ export { getV as g, initI18n as i };
3288
+ //# sourceMappingURL=I18n-yXLN_hDO.js.map