@andre1502/react-utilities 0.9.1 → 0.9.2

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