willba-component-library 0.3.27 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/README.md +75 -113
  2. package/lib/components/FilterBar/FilterBar.d.ts +1 -1
  3. package/lib/components/FilterCalendar/FilterCalendar.d.ts +1 -1
  4. package/lib/core/i18n/I18nProvider.d.ts +6 -0
  5. package/lib/core/i18n/index.d.ts +1 -0
  6. package/lib/embed.d.ts +18 -0
  7. package/lib/embed.esm.js +74 -0
  8. package/lib/embed.esm.js.map +1 -0
  9. package/lib/embed.umd.js +74 -0
  10. package/lib/embed.umd.js.map +1 -0
  11. package/lib/i18n.d.ts +2 -2
  12. package/lib/index.d.ts +2 -2
  13. package/lib/index.esm.js +1111 -930
  14. package/lib/index.esm.js.map +1 -1
  15. package/lib/index.js +1110 -929
  16. package/lib/index.js.map +1 -1
  17. package/package.json +9 -1
  18. package/.nvmrc +0 -1
  19. package/.storybook/main.ts +0 -17
  20. package/.storybook/preview.ts +0 -15
  21. package/lib/components/FilterBar/components/buttons/index.d.ts +0 -4
  22. package/lib/components/FilterBar/components/buttons/select-button/SelectButton.d.ts +0 -13
  23. package/lib/components/FilterBar/components/buttons/tab-button/TabButton.d.ts +0 -10
  24. package/lib/components/FilterBar/components/cards/image-card/ImageCard.d.ts +0 -11
  25. package/lib/components/FilterBar/components/cards/index.d.ts +0 -1
  26. package/lib/components/FilterBar/components/categories/Categories.d.ts +0 -8
  27. package/lib/components/FilterBar/components/common/FilterSectionHeader.d.ts +0 -8
  28. package/lib/components/FilterBar/components/dates/Dates.d.ts +0 -17
  29. package/lib/components/FilterBar/components/dates/index.d.ts +0 -1
  30. package/lib/components/FilterBar/components/guests/GuestCount/GuestCount.d.ts +0 -4
  31. package/lib/components/FilterBar/components/guests/Guests.d.ts +0 -12
  32. package/lib/components/FilterBar/components/locations/Locations.d.ts +0 -14
  33. package/lib/components/FilterBar/hooks/useFilterBar.d.ts +0 -32
  34. package/lib/components/FilterBar/hooks/useFilterUi.d.ts +0 -8
  35. package/lib/components/FilterBar/utils/calculateDropdownPosition.d.ts +0 -12
  36. package/lib/components/FilterBar/utils/getLocalizedContent.d.ts +0 -8
  37. package/lib/core/components/buttons/close-button/CloseButton.d.ts +0 -7
  38. package/lib/core/components/buttons/submit-button/SubmitButton.d.ts +0 -14
  39. package/lib/index.umd.js +0 -12489
  40. package/lib/index.umd.js.map +0 -1
  41. package/prettier.config.js +0 -6
  42. package/rollup.config.mjs +0 -63
  43. package/src/assets/IconsSvg.tsx +0 -69
  44. package/src/components/Button/Button.stories.tsx +0 -34
  45. package/src/components/Button/Button.tsx +0 -56
  46. package/src/components/Button/button.css +0 -30
  47. package/src/components/Button/index.ts +0 -1
  48. package/src/components/FilterBar/FilterBar.css +0 -35
  49. package/src/components/FilterBar/FilterBar.stories.tsx +0 -116
  50. package/src/components/FilterBar/FilterBar.tsx +0 -64
  51. package/src/components/FilterBar/FilterBarTypes.ts +0 -71
  52. package/src/components/FilterBar/components/Divider/Divider.css +0 -14
  53. package/src/components/FilterBar/components/Divider/Divider.tsx +0 -7
  54. package/src/components/FilterBar/components/FilterControls/FilterControls.css +0 -22
  55. package/src/components/FilterBar/components/FilterControls/FilterControls.tsx +0 -139
  56. package/src/components/FilterBar/components/FilterPanels/Categories/Categories.css +0 -21
  57. package/src/components/FilterBar/components/FilterPanels/Categories/Categories.tsx +0 -49
  58. package/src/components/FilterBar/components/FilterPanels/Dates/Dates.css +0 -9
  59. package/src/components/FilterBar/components/FilterPanels/Dates/Dates.tsx +0 -60
  60. package/src/components/FilterBar/components/FilterPanels/FilterPanels.css +0 -22
  61. package/src/components/FilterBar/components/FilterPanels/FilterPanels.tsx +0 -111
  62. package/src/components/FilterBar/components/FilterPanels/Guests/GuestCount/GuestCount.css +0 -58
  63. package/src/components/FilterBar/components/FilterPanels/Guests/GuestCount/GuestCount.tsx +0 -85
  64. package/src/components/FilterBar/components/FilterPanels/Guests/Guests.css +0 -24
  65. package/src/components/FilterBar/components/FilterPanels/Guests/Guests.tsx +0 -59
  66. package/src/components/FilterBar/components/FilterPanels/Locations/Locations.css +0 -16
  67. package/src/components/FilterBar/components/FilterPanels/Locations/Locations.tsx +0 -94
  68. package/src/components/FilterBar/components/FilterPanels/SectionHeader/SectionHeader.css +0 -34
  69. package/src/components/FilterBar/components/FilterPanels/SectionHeader/SectionHeader.tsx +0 -17
  70. package/src/components/FilterBar/components/FilterTabs/FilterTabs.css +0 -10
  71. package/src/components/FilterBar/components/FilterTabs/FilterTabs.tsx +0 -50
  72. package/src/components/FilterBar/components/ImageCard/ImageCard.css +0 -30
  73. package/src/components/FilterBar/components/ImageCard/ImageCard.tsx +0 -45
  74. package/src/components/FilterBar/components/SelectButton/SelectButton.css +0 -76
  75. package/src/components/FilterBar/components/SelectButton/SelectButton.tsx +0 -54
  76. package/src/components/FilterBar/components/TabButton/TabButton.css +0 -36
  77. package/src/components/FilterBar/components/TabButton/TabButton.tsx +0 -23
  78. package/src/components/FilterBar/components/index.ts +0 -6
  79. package/src/components/FilterBar/hooks/index.ts +0 -5
  80. package/src/components/FilterBar/hooks/useFilterActions.tsx +0 -126
  81. package/src/components/FilterBar/hooks/useFilterRefs.tsx +0 -21
  82. package/src/components/FilterBar/hooks/useFilterState.tsx +0 -86
  83. package/src/components/FilterBar/hooks/usePanelPosition.tsx +0 -52
  84. package/src/components/FilterBar/hooks/useScrollInToView.tsx +0 -29
  85. package/src/components/FilterBar/index.ts +0 -3
  86. package/src/components/FilterBar/providers/FilterBarProvider.tsx +0 -172
  87. package/src/components/FilterBar/providers/index.ts +0 -1
  88. package/src/components/FilterBar/utils/ageCategoriesRules.ts +0 -27
  89. package/src/components/FilterBar/utils/index.tsx +0 -3
  90. package/src/components/FilterBar/utils/parseGuests.tsx +0 -65
  91. package/src/components/FilterBar/utils/parseLocations.ts +0 -28
  92. package/src/components/FilterCalendar/FilterCalendar.css +0 -109
  93. package/src/components/FilterCalendar/FilterCalendar.stories.tsx +0 -554
  94. package/src/components/FilterCalendar/FilterCalendar.tsx +0 -115
  95. package/src/components/FilterCalendar/FilterCalendarTypes.ts +0 -11
  96. package/src/components/FilterCalendar/components/Footer.tsx +0 -96
  97. package/src/components/FilterCalendar/hooks/useFilterCalendar.ts +0 -163
  98. package/src/components/FilterCalendar/index.ts +0 -3
  99. package/src/core/components/buttons/CloseButton/CloseButton.css +0 -33
  100. package/src/core/components/buttons/CloseButton/CloseButton.tsx +0 -16
  101. package/src/core/components/buttons/SubmitButton/SubmitButton.css +0 -54
  102. package/src/core/components/buttons/SubmitButton/SubmitButton.tsx +0 -42
  103. package/src/core/components/calendar/Calendar.css +0 -280
  104. package/src/core/components/calendar/Calendar.tsx +0 -253
  105. package/src/core/components/calendar/CalendarTypes.ts +0 -48
  106. package/src/core/components/calendar/hooks/index.ts +0 -3
  107. package/src/core/components/calendar/hooks/useCalendarLoadingSpinner.tsx +0 -19
  108. package/src/core/components/calendar/hooks/useCalendarTooltips.tsx +0 -125
  109. package/src/core/components/calendar/hooks/useUpdateDisabledDates.tsx +0 -105
  110. package/src/core/components/calendar/utils/calendarSelectionRules.tsx +0 -180
  111. package/src/core/components/calendar/utils/checkForContinuousSelection.tsx +0 -86
  112. package/src/core/components/calendar/utils/disabledDatesByPage.tsx +0 -31
  113. package/src/core/components/calendar/utils/handleCalendarModifiers.tsx +0 -118
  114. package/src/core/components/calendar/utils/handleRangeContextDisabledDates.tsx +0 -75
  115. package/src/core/components/calendar/utils/index.ts +0 -8
  116. package/src/core/components/calendar/utils/nightsCount.tsx +0 -19
  117. package/src/core/components/calendar/utils/parseDate.tsx +0 -17
  118. package/src/core/components/calendar/utils/parseDates.tsx +0 -12
  119. package/src/core/components/index.ts +0 -7
  120. package/src/core/hooks/index.ts +0 -4
  121. package/src/core/hooks/useAutoFocus.tsx +0 -27
  122. package/src/core/hooks/useAwaitRender.tsx +0 -12
  123. package/src/core/hooks/useCloseFilterSection.tsx +0 -29
  124. package/src/core/hooks/useUpdateTranslations.tsx +0 -14
  125. package/src/i18n.ts +0 -27
  126. package/src/index.ts +0 -8
  127. package/src/locales/en/common.json +0 -18
  128. package/src/locales/en/filterBar.json +0 -33
  129. package/src/locales/fi/common.json +0 -19
  130. package/src/locales/fi/filterBar.json +0 -33
  131. package/src/themes/Default.css +0 -69
  132. package/src/themes/useTheme.tsx +0 -27
  133. package/stories/Button.stories.ts +0 -50
  134. package/stories/Button.tsx +0 -53
  135. package/stories/Configure.mdx +0 -364
  136. package/stories/Header.stories.ts +0 -27
  137. package/stories/Header.tsx +0 -70
  138. package/stories/Page.stories.ts +0 -29
  139. package/stories/Page.tsx +0 -91
  140. package/stories/assets/accessibility.png +0 -0
  141. package/stories/assets/accessibility.svg +0 -5
  142. package/stories/assets/addon-library.png +0 -0
  143. package/stories/assets/assets.png +0 -0
  144. package/stories/assets/context.png +0 -0
  145. package/stories/assets/discord.svg +0 -15
  146. package/stories/assets/docs.png +0 -0
  147. package/stories/assets/figma-plugin.png +0 -0
  148. package/stories/assets/github.svg +0 -3
  149. package/stories/assets/share.png +0 -0
  150. package/stories/assets/styling.png +0 -0
  151. package/stories/assets/testing.png +0 -0
  152. package/stories/assets/theming.png +0 -0
  153. package/stories/assets/tutorials.svg +0 -12
  154. package/stories/assets/youtube.svg +0 -4
  155. package/stories/button.css +0 -30
  156. package/stories/header.css +0 -32
  157. package/stories/page.css +0 -69
  158. package/tsconfig.json +0 -29
  159. /package/lib/components/FilterBar/components/{divider → Divider}/Divider.d.ts +0 -0
package/lib/index.esm.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import React__default, { useState, useEffect, createContext, useContext, useRef, forwardRef, useLayoutEffect, useMemo } from 'react';
2
+ import React__default, { useState, useEffect, createContext, useContext, useRef, useMemo, createElement, forwardRef, useLayoutEffect } from 'react';
3
3
 
4
4
  /******************************************************************************
5
5
  Copyright (c) Microsoft Corporation.
@@ -222,6 +222,331 @@ var useAwaitRender = function () {
222
222
  return null;
223
223
  };
224
224
 
225
+ function warn() {
226
+ if (console && console.warn) {
227
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
228
+ args[_key] = arguments[_key];
229
+ }
230
+ if (typeof args[0] === 'string') args[0] = `react-i18next:: ${args[0]}`;
231
+ console.warn(...args);
232
+ }
233
+ }
234
+ const alreadyWarned = {};
235
+ function warnOnce() {
236
+ for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
237
+ args[_key2] = arguments[_key2];
238
+ }
239
+ if (typeof args[0] === 'string' && alreadyWarned[args[0]]) return;
240
+ if (typeof args[0] === 'string') alreadyWarned[args[0]] = new Date();
241
+ warn(...args);
242
+ }
243
+ const loadedClb = (i18n, cb) => () => {
244
+ if (i18n.isInitialized) {
245
+ cb();
246
+ } else {
247
+ const initialized = () => {
248
+ setTimeout(() => {
249
+ i18n.off('initialized', initialized);
250
+ }, 0);
251
+ cb();
252
+ };
253
+ i18n.on('initialized', initialized);
254
+ }
255
+ };
256
+ function loadNamespaces(i18n, ns, cb) {
257
+ i18n.loadNamespaces(ns, loadedClb(i18n, cb));
258
+ }
259
+ function loadLanguages(i18n, lng, ns, cb) {
260
+ if (typeof ns === 'string') ns = [ns];
261
+ ns.forEach(n => {
262
+ if (i18n.options.ns.indexOf(n) < 0) i18n.options.ns.push(n);
263
+ });
264
+ i18n.loadLanguages(lng, loadedClb(i18n, cb));
265
+ }
266
+ function oldI18nextHasLoadedNamespace(ns, i18n) {
267
+ let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
268
+ const lng = i18n.languages[0];
269
+ const fallbackLng = i18n.options ? i18n.options.fallbackLng : false;
270
+ const lastLng = i18n.languages[i18n.languages.length - 1];
271
+ if (lng.toLowerCase() === 'cimode') return true;
272
+ const loadNotPending = (l, n) => {
273
+ const loadState = i18n.services.backendConnector.state[`${l}|${n}`];
274
+ return loadState === -1 || loadState === 2;
275
+ };
276
+ if (options.bindI18n && options.bindI18n.indexOf('languageChanging') > -1 && i18n.services.backendConnector.backend && i18n.isLanguageChangingTo && !loadNotPending(i18n.isLanguageChangingTo, ns)) return false;
277
+ if (i18n.hasResourceBundle(lng, ns)) return true;
278
+ if (!i18n.services.backendConnector.backend || i18n.options.resources && !i18n.options.partialBundledLanguages) return true;
279
+ if (loadNotPending(lng, ns) && (!fallbackLng || loadNotPending(lastLng, ns))) return true;
280
+ return false;
281
+ }
282
+ function hasLoadedNamespace(ns, i18n) {
283
+ let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
284
+ if (!i18n.languages || !i18n.languages.length) {
285
+ warnOnce('i18n.languages were undefined or empty', i18n.languages);
286
+ return true;
287
+ }
288
+ const isNewerI18next = i18n.options.ignoreJSONStructure !== undefined;
289
+ if (!isNewerI18next) {
290
+ return oldI18nextHasLoadedNamespace(ns, i18n, options);
291
+ }
292
+ return i18n.hasLoadedNamespace(ns, {
293
+ lng: options.lng,
294
+ precheck: (i18nInstance, loadNotPending) => {
295
+ if (options.bindI18n && options.bindI18n.indexOf('languageChanging') > -1 && i18nInstance.services.backendConnector.backend && i18nInstance.isLanguageChangingTo && !loadNotPending(i18nInstance.isLanguageChangingTo, ns)) return false;
296
+ }
297
+ });
298
+ }
299
+
300
+ const matchHtmlEntity = /&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34|nbsp|#160|copy|#169|reg|#174|hellip|#8230|#x2F|#47);/g;
301
+ const htmlEntities = {
302
+ '&amp;': '&',
303
+ '&#38;': '&',
304
+ '&lt;': '<',
305
+ '&#60;': '<',
306
+ '&gt;': '>',
307
+ '&#62;': '>',
308
+ '&apos;': "'",
309
+ '&#39;': "'",
310
+ '&quot;': '"',
311
+ '&#34;': '"',
312
+ '&nbsp;': ' ',
313
+ '&#160;': ' ',
314
+ '&copy;': '©',
315
+ '&#169;': '©',
316
+ '&reg;': '®',
317
+ '&#174;': '®',
318
+ '&hellip;': '…',
319
+ '&#8230;': '…',
320
+ '&#x2F;': '/',
321
+ '&#47;': '/'
322
+ };
323
+ const unescapeHtmlEntity = m => htmlEntities[m];
324
+ const unescape = text => text.replace(matchHtmlEntity, unescapeHtmlEntity);
325
+
326
+ let defaultOptions$1 = {
327
+ bindI18n: 'languageChanged',
328
+ bindI18nStore: '',
329
+ transEmptyNodeValue: '',
330
+ transSupportBasicHtmlNodes: true,
331
+ transWrapTextNodes: '',
332
+ transKeepBasicHtmlNodesFor: ['br', 'strong', 'i', 'p'],
333
+ useSuspense: true,
334
+ unescape
335
+ };
336
+ function setDefaults() {
337
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
338
+ defaultOptions$1 = {
339
+ ...defaultOptions$1,
340
+ ...options
341
+ };
342
+ }
343
+ function getDefaults() {
344
+ return defaultOptions$1;
345
+ }
346
+
347
+ let i18nInstance;
348
+ function setI18n(instance) {
349
+ i18nInstance = instance;
350
+ }
351
+ function getI18n() {
352
+ return i18nInstance;
353
+ }
354
+
355
+ const initReactI18next = {
356
+ type: '3rdParty',
357
+ init(instance) {
358
+ setDefaults(instance.options.react);
359
+ setI18n(instance);
360
+ }
361
+ };
362
+
363
+ const I18nContext = createContext();
364
+ class ReportNamespaces {
365
+ constructor() {
366
+ this.usedNamespaces = {};
367
+ }
368
+ addUsedNamespaces(namespaces) {
369
+ namespaces.forEach(ns => {
370
+ if (!this.usedNamespaces[ns]) this.usedNamespaces[ns] = true;
371
+ });
372
+ }
373
+ getUsedNamespaces() {
374
+ return Object.keys(this.usedNamespaces);
375
+ }
376
+ }
377
+
378
+ const usePrevious = (value, ignore) => {
379
+ const ref = useRef();
380
+ useEffect(() => {
381
+ ref.current = ignore ? ref.current : value;
382
+ }, [value, ignore]);
383
+ return ref.current;
384
+ };
385
+ function useTranslation(ns) {
386
+ let props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
387
+ const {
388
+ i18n: i18nFromProps
389
+ } = props;
390
+ const {
391
+ i18n: i18nFromContext,
392
+ defaultNS: defaultNSFromContext
393
+ } = useContext(I18nContext) || {};
394
+ const i18n = i18nFromProps || i18nFromContext || getI18n();
395
+ if (i18n && !i18n.reportNamespaces) i18n.reportNamespaces = new ReportNamespaces();
396
+ if (!i18n) {
397
+ warnOnce('You will need to pass in an i18next instance by using initReactI18next');
398
+ const notReadyT = (k, optsOrDefaultValue) => {
399
+ if (typeof optsOrDefaultValue === 'string') return optsOrDefaultValue;
400
+ if (optsOrDefaultValue && typeof optsOrDefaultValue === 'object' && typeof optsOrDefaultValue.defaultValue === 'string') return optsOrDefaultValue.defaultValue;
401
+ return Array.isArray(k) ? k[k.length - 1] : k;
402
+ };
403
+ const retNotReady = [notReadyT, {}, false];
404
+ retNotReady.t = notReadyT;
405
+ retNotReady.i18n = {};
406
+ retNotReady.ready = false;
407
+ return retNotReady;
408
+ }
409
+ if (i18n.options.react && i18n.options.react.wait !== undefined) warnOnce('It seems you are still using the old wait option, you may migrate to the new useSuspense behaviour.');
410
+ const i18nOptions = {
411
+ ...getDefaults(),
412
+ ...i18n.options.react,
413
+ ...props
414
+ };
415
+ const {
416
+ useSuspense,
417
+ keyPrefix
418
+ } = i18nOptions;
419
+ let namespaces = ns || defaultNSFromContext || i18n.options && i18n.options.defaultNS;
420
+ namespaces = typeof namespaces === 'string' ? [namespaces] : namespaces || ['translation'];
421
+ if (i18n.reportNamespaces.addUsedNamespaces) i18n.reportNamespaces.addUsedNamespaces(namespaces);
422
+ const ready = (i18n.isInitialized || i18n.initializedStoreOnce) && namespaces.every(n => hasLoadedNamespace(n, i18n, i18nOptions));
423
+ function getT() {
424
+ return i18n.getFixedT(props.lng || null, i18nOptions.nsMode === 'fallback' ? namespaces : namespaces[0], keyPrefix);
425
+ }
426
+ const [t, setT] = useState(getT);
427
+ let joinedNS = namespaces.join();
428
+ if (props.lng) joinedNS = `${props.lng}${joinedNS}`;
429
+ const previousJoinedNS = usePrevious(joinedNS);
430
+ const isMounted = useRef(true);
431
+ useEffect(() => {
432
+ const {
433
+ bindI18n,
434
+ bindI18nStore
435
+ } = i18nOptions;
436
+ isMounted.current = true;
437
+ if (!ready && !useSuspense) {
438
+ if (props.lng) {
439
+ loadLanguages(i18n, props.lng, namespaces, () => {
440
+ if (isMounted.current) setT(getT);
441
+ });
442
+ } else {
443
+ loadNamespaces(i18n, namespaces, () => {
444
+ if (isMounted.current) setT(getT);
445
+ });
446
+ }
447
+ }
448
+ if (ready && previousJoinedNS && previousJoinedNS !== joinedNS && isMounted.current) {
449
+ setT(getT);
450
+ }
451
+ function boundReset() {
452
+ if (isMounted.current) setT(getT);
453
+ }
454
+ if (bindI18n && i18n) i18n.on(bindI18n, boundReset);
455
+ if (bindI18nStore && i18n) i18n.store.on(bindI18nStore, boundReset);
456
+ return () => {
457
+ isMounted.current = false;
458
+ if (bindI18n && i18n) bindI18n.split(' ').forEach(e => i18n.off(e, boundReset));
459
+ if (bindI18nStore && i18n) bindI18nStore.split(' ').forEach(e => i18n.store.off(e, boundReset));
460
+ };
461
+ }, [i18n, joinedNS]);
462
+ const isInitial = useRef(true);
463
+ useEffect(() => {
464
+ if (isMounted.current && !isInitial.current) {
465
+ setT(getT);
466
+ }
467
+ isInitial.current = false;
468
+ }, [i18n, keyPrefix]);
469
+ const ret = [t, i18n, ready];
470
+ ret.t = t;
471
+ ret.i18n = i18n;
472
+ ret.ready = ready;
473
+ if (ready) return ret;
474
+ if (!ready && !useSuspense) return ret;
475
+ throw new Promise(resolve => {
476
+ if (props.lng) {
477
+ loadLanguages(i18n, props.lng, namespaces, () => resolve());
478
+ } else {
479
+ loadNamespaces(i18n, namespaces, () => resolve());
480
+ }
481
+ });
482
+ }
483
+
484
+ function I18nextProvider(_ref) {
485
+ let {
486
+ i18n,
487
+ defaultNS,
488
+ children
489
+ } = _ref;
490
+ const value = useMemo(() => ({
491
+ i18n,
492
+ defaultNS
493
+ }), [i18n, defaultNS]);
494
+ return createElement(I18nContext.Provider, {
495
+ value
496
+ }, children);
497
+ }
498
+
499
+ var useUpdateTranslations = function (_a) {
500
+ var language = _a.language;
501
+ var i18n = useTranslation().i18n;
502
+ useEffect(function () {
503
+ if (language && i18n.language !== language) {
504
+ i18n.changeLanguage(language);
505
+ }
506
+ }, [language, i18n]);
507
+ };
508
+
509
+ // TODO - Refactor and rename this hook
510
+ var useCloseFilterSection = function (_a) {
511
+ var handleSelectedFilter = _a.handleSelectedFilter;
512
+ var filterSectionRef = useRef(null);
513
+ useEffect(function () {
514
+ var handleClickOutside = function (event) {
515
+ if (filterSectionRef.current &&
516
+ !filterSectionRef.current.contains(event.target)) {
517
+ handleSelectedFilter(false);
518
+ }
519
+ };
520
+ document.addEventListener('mousedown', handleClickOutside);
521
+ return function () {
522
+ document.removeEventListener('mousedown', handleClickOutside);
523
+ };
524
+ }, [filterSectionRef]);
525
+ return { filterSectionRef: filterSectionRef };
526
+ };
527
+
528
+ var useAutoFocus = function (autoFocus) {
529
+ var ref = useRef(null);
530
+ useEffect(function () {
531
+ if (!autoFocus || !ref.current)
532
+ return;
533
+ var attemptFocus = function (attempts) {
534
+ if (attempts === void 0) { attempts = 0; }
535
+ if (attempts > 20 || !ref.current)
536
+ return;
537
+ var focusable = ref.current.querySelector('button:not([disabled]), [tabindex]:not([tabindex="-1"])');
538
+ if (focusable) {
539
+ focusable.focus();
540
+ }
541
+ else {
542
+ requestAnimationFrame(function () { return attemptFocus(attempts + 1); });
543
+ }
544
+ };
545
+ requestAnimationFrame(function () { return attemptFocus(); });
546
+ }, [autoFocus]);
547
+ return ref;
548
+ };
549
+
225
550
  const isString = obj => typeof obj === 'string';
226
551
  const defer = () => {
227
552
  let res;
@@ -282,7 +607,7 @@ const setPath = (object, path, newValue) => {
282
607
  e = `${p[p.length - 1]}.${e}`;
283
608
  p = p.slice(0, p.length - 1);
284
609
  last = getLastOfPath(object, p, Object);
285
- if (last?.obj && typeof last.obj[`${last.k}.${e}`] !== 'undefined') {
610
+ if (last && last.obj && typeof last.obj[`${last.k}.${e}`] !== 'undefined') {
286
611
  last.obj = undefined;
287
612
  }
288
613
  }
@@ -302,7 +627,6 @@ const getPath = (object, path) => {
302
627
  k
303
628
  } = getLastOfPath(object, path);
304
629
  if (!obj) return undefined;
305
- if (!Object.prototype.hasOwnProperty.call(obj, k)) return undefined;
306
630
  return obj[k];
307
631
  };
308
632
  const getPathWithDefaults = (data, defaultData, key) => {
@@ -380,12 +704,10 @@ const looksLikeObjectPath = (key, nsSeparator, keySeparator) => {
380
704
  }
381
705
  return matched;
382
706
  };
383
- const deepFind = (obj, path, keySeparator = '.') => {
707
+ const deepFind = function (obj, path) {
708
+ let keySeparator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '.';
384
709
  if (!obj) return undefined;
385
- if (obj[path]) {
386
- if (!Object.prototype.hasOwnProperty.call(obj, path)) return undefined;
387
- return obj[path];
388
- }
710
+ if (obj[path]) return obj[path];
389
711
  const tokens = path.split(keySeparator);
390
712
  let current = obj;
391
713
  for (let i = 0; i < tokens.length;) {
@@ -412,7 +734,7 @@ const deepFind = (obj, path, keySeparator = '.') => {
412
734
  }
413
735
  return current;
414
736
  };
415
- const getCleanedCode = code => code?.replace('_', '-');
737
+ const getCleanedCode = code => code && code.replace('_', '-');
416
738
 
417
739
  const consoleLogger = {
418
740
  type: 'logger',
@@ -426,29 +748,43 @@ const consoleLogger = {
426
748
  this.output('error', args);
427
749
  },
428
750
  output(type, args) {
429
- console?.[type]?.apply?.(console, args);
751
+ if (console && console[type]) console[type].apply(console, args);
430
752
  }
431
753
  };
432
754
  class Logger {
433
- constructor(concreteLogger, options = {}) {
755
+ constructor(concreteLogger) {
756
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
434
757
  this.init(concreteLogger, options);
435
758
  }
436
- init(concreteLogger, options = {}) {
759
+ init(concreteLogger) {
760
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
437
761
  this.prefix = options.prefix || 'i18next:';
438
762
  this.logger = concreteLogger || consoleLogger;
439
763
  this.options = options;
440
764
  this.debug = options.debug;
441
765
  }
442
- log(...args) {
766
+ log() {
767
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
768
+ args[_key] = arguments[_key];
769
+ }
443
770
  return this.forward(args, 'log', '', true);
444
771
  }
445
- warn(...args) {
772
+ warn() {
773
+ for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
774
+ args[_key2] = arguments[_key2];
775
+ }
446
776
  return this.forward(args, 'warn', '', true);
447
777
  }
448
- error(...args) {
778
+ error() {
779
+ for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
780
+ args[_key3] = arguments[_key3];
781
+ }
449
782
  return this.forward(args, 'error', '');
450
783
  }
451
- deprecate(...args) {
784
+ deprecate() {
785
+ for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
786
+ args[_key4] = arguments[_key4];
787
+ }
452
788
  return this.forward(args, 'warn', 'WARNING DEPRECATED: ', true);
453
789
  }
454
790
  forward(args, lvl, prefix, debugOnly) {
@@ -492,10 +828,14 @@ class EventEmitter {
492
828
  }
493
829
  this.observers[event].delete(listener);
494
830
  }
495
- emit(event, ...args) {
831
+ emit(event) {
832
+ for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
833
+ args[_key - 1] = arguments[_key];
834
+ }
496
835
  if (this.observers[event]) {
497
836
  const cloned = Array.from(this.observers[event].entries());
498
- cloned.forEach(([observer, numTimesAdded]) => {
837
+ cloned.forEach(_ref => {
838
+ let [observer, numTimesAdded] = _ref;
499
839
  for (let i = 0; i < numTimesAdded; i++) {
500
840
  observer(...args);
501
841
  }
@@ -503,7 +843,8 @@ class EventEmitter {
503
843
  }
504
844
  if (this.observers['*']) {
505
845
  const cloned = Array.from(this.observers['*'].entries());
506
- cloned.forEach(([observer, numTimesAdded]) => {
846
+ cloned.forEach(_ref2 => {
847
+ let [observer, numTimesAdded] = _ref2;
507
848
  for (let i = 0; i < numTimesAdded; i++) {
508
849
  observer.apply(observer, [event, ...args]);
509
850
  }
@@ -513,10 +854,11 @@ class EventEmitter {
513
854
  }
514
855
 
515
856
  class ResourceStore extends EventEmitter {
516
- constructor(data, options = {
517
- ns: ['translation'],
518
- defaultNS: 'translation'
519
- }) {
857
+ constructor(data) {
858
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
859
+ ns: ['translation'],
860
+ defaultNS: 'translation'
861
+ };
520
862
  super();
521
863
  this.data = data || {};
522
864
  this.options = options;
@@ -538,7 +880,8 @@ class ResourceStore extends EventEmitter {
538
880
  this.options.ns.splice(index, 1);
539
881
  }
540
882
  }
541
- getResource(lng, ns, key, options = {}) {
883
+ getResource(lng, ns, key) {
884
+ let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
542
885
  const keySeparator = options.keySeparator !== undefined ? options.keySeparator : this.options.keySeparator;
543
886
  const ignoreJSONStructure = options.ignoreJSONStructure !== undefined ? options.ignoreJSONStructure : this.options.ignoreJSONStructure;
544
887
  let path;
@@ -563,11 +906,12 @@ class ResourceStore extends EventEmitter {
563
906
  key = path.slice(2).join('.');
564
907
  }
565
908
  if (result || !ignoreJSONStructure || !isString(key)) return result;
566
- return deepFind(this.data?.[lng]?.[ns], key, keySeparator);
909
+ return deepFind(this.data && this.data[lng] && this.data[lng][ns], key, keySeparator);
567
910
  }
568
- addResource(lng, ns, key, value, options = {
569
- silent: false
570
- }) {
911
+ addResource(lng, ns, key, value) {
912
+ let options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {
913
+ silent: false
914
+ };
571
915
  const keySeparator = options.keySeparator !== undefined ? options.keySeparator : this.options.keySeparator;
572
916
  let path = [lng, ns];
573
917
  if (key) path = path.concat(keySeparator ? key.split(keySeparator) : key);
@@ -580,9 +924,10 @@ class ResourceStore extends EventEmitter {
580
924
  setPath(this.data, path, value);
581
925
  if (!options.silent) this.emit('added', lng, ns, key, value);
582
926
  }
583
- addResources(lng, ns, resources, options = {
584
- silent: false
585
- }) {
927
+ addResources(lng, ns, resources) {
928
+ let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {
929
+ silent: false
930
+ };
586
931
  for (const m in resources) {
587
932
  if (isString(resources[m]) || Array.isArray(resources[m])) this.addResource(lng, ns, m, resources[m], {
588
933
  silent: true
@@ -590,10 +935,11 @@ class ResourceStore extends EventEmitter {
590
935
  }
591
936
  if (!options.silent) this.emit('added', lng, ns, resources);
592
937
  }
593
- addResourceBundle(lng, ns, resources, deep, overwrite, options = {
594
- silent: false,
595
- skipCopy: false
596
- }) {
938
+ addResourceBundle(lng, ns, resources, deep, overwrite) {
939
+ let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {
940
+ silent: false,
941
+ skipCopy: false
942
+ };
597
943
  let path = [lng, ns];
598
944
  if (lng.indexOf('.') > -1) {
599
945
  path = lng.split('.');
@@ -627,6 +973,10 @@ class ResourceStore extends EventEmitter {
627
973
  }
628
974
  getResourceBundle(lng, ns) {
629
975
  if (!ns) ns = this.options.defaultNS;
976
+ if (this.options.compatibilityAPI === 'v1') return {
977
+ ...{},
978
+ ...this.getResource(lng, ns)
979
+ };
630
980
  return this.getResource(lng, ns);
631
981
  }
632
982
  getDataByLanguage(lng) {
@@ -649,37 +999,16 @@ var postProcessor = {
649
999
  },
650
1000
  handle(processors, value, key, options, translator) {
651
1001
  processors.forEach(processor => {
652
- value = this.processors[processor]?.process(value, key, options, translator) ?? value;
1002
+ if (this.processors[processor]) value = this.processors[processor].process(value, key, options, translator);
653
1003
  });
654
1004
  return value;
655
1005
  }
656
1006
  };
657
1007
 
658
- const PATH_KEY = Symbol('i18next/PATH_KEY');
659
- function createProxy() {
660
- const state = [];
661
- const handler = Object.create(null);
662
- let proxy;
663
- handler.get = (target, key) => {
664
- proxy?.revoke?.();
665
- if (key === PATH_KEY) return state;
666
- state.push(key);
667
- proxy = Proxy.revocable(target, handler);
668
- return proxy.proxy;
669
- };
670
- return Proxy.revocable(Object.create(null), handler).proxy;
671
- }
672
- function keysFromSelector(selector, opts) {
673
- const {
674
- [PATH_KEY]: path
675
- } = selector(createProxy());
676
- return path.join(opts?.keySeparator ?? '.');
677
- }
678
-
679
1008
  const checkedLoadedFor = {};
680
- const shouldHandleAsObject = res => !isString(res) && typeof res !== 'boolean' && typeof res !== 'number';
681
1009
  class Translator extends EventEmitter {
682
- constructor(services, options = {}) {
1010
+ constructor(services) {
1011
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
683
1012
  super();
684
1013
  copy(['resourceStore', 'languageUtils', 'pluralResolver', 'interpolator', 'backendConnector', 'i18nFormat', 'utils'], services, this);
685
1014
  this.options = options;
@@ -691,28 +1020,23 @@ class Translator extends EventEmitter {
691
1020
  changeLanguage(lng) {
692
1021
  if (lng) this.language = lng;
693
1022
  }
694
- exists(key, o = {
695
- interpolation: {}
696
- }) {
697
- const opt = {
698
- ...o
1023
+ exists(key) {
1024
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
1025
+ interpolation: {}
699
1026
  };
700
- if (key == null) return false;
701
- const resolved = this.resolve(key, opt);
702
- if (resolved?.res === undefined) return false;
703
- const isObject = shouldHandleAsObject(resolved.res);
704
- if (opt.returnObjects === false && isObject) {
1027
+ if (key === undefined || key === null) {
705
1028
  return false;
706
1029
  }
707
- return true;
1030
+ const resolved = this.resolve(key, options);
1031
+ return resolved && resolved.res !== undefined;
708
1032
  }
709
- extractFromKey(key, opt) {
710
- let nsSeparator = opt.nsSeparator !== undefined ? opt.nsSeparator : this.options.nsSeparator;
1033
+ extractFromKey(key, options) {
1034
+ let nsSeparator = options.nsSeparator !== undefined ? options.nsSeparator : this.options.nsSeparator;
711
1035
  if (nsSeparator === undefined) nsSeparator = ':';
712
- const keySeparator = opt.keySeparator !== undefined ? opt.keySeparator : this.options.keySeparator;
713
- let namespaces = opt.ns || this.options.defaultNS || [];
1036
+ const keySeparator = options.keySeparator !== undefined ? options.keySeparator : this.options.keySeparator;
1037
+ let namespaces = options.ns || this.options.defaultNS || [];
714
1038
  const wouldCheckForNsInKey = nsSeparator && key.indexOf(nsSeparator) > -1;
715
- const seemsNaturalLanguage = !this.options.userDefinedKeySeparator && !opt.keySeparator && !this.options.userDefinedNsSeparator && !opt.nsSeparator && !looksLikeObjectPath(key, nsSeparator, keySeparator);
1039
+ const seemsNaturalLanguage = !this.options.userDefinedKeySeparator && !options.keySeparator && !this.options.userDefinedNsSeparator && !options.nsSeparator && !looksLikeObjectPath(key, nsSeparator, keySeparator);
716
1040
  if (wouldCheckForNsInKey && !seemsNaturalLanguage) {
717
1041
  const m = key.match(this.interpolator.nestingRegexp);
718
1042
  if (m && m.length > 0) {
@@ -730,36 +1054,28 @@ class Translator extends EventEmitter {
730
1054
  namespaces: isString(namespaces) ? [namespaces] : namespaces
731
1055
  };
732
1056
  }
733
- translate(keys, o, lastKey) {
734
- let opt = typeof o === 'object' ? {
735
- ...o
736
- } : o;
737
- if (typeof opt !== 'object' && this.options.overloadTranslationOptionHandler) {
738
- opt = this.options.overloadTranslationOptionHandler(arguments);
1057
+ translate(keys, options, lastKey) {
1058
+ if (typeof options !== 'object' && this.options.overloadTranslationOptionHandler) {
1059
+ options = this.options.overloadTranslationOptionHandler(arguments);
739
1060
  }
740
- if (typeof opt === 'object') opt = {
741
- ...opt
1061
+ if (typeof options === 'object') options = {
1062
+ ...options
742
1063
  };
743
- if (!opt) opt = {};
744
- if (keys == null) return '';
745
- if (typeof keys === 'function') keys = keysFromSelector(keys, {
746
- ...this.options,
747
- ...opt
748
- });
1064
+ if (!options) options = {};
1065
+ if (keys === undefined || keys === null) return '';
749
1066
  if (!Array.isArray(keys)) keys = [String(keys)];
750
- const returnDetails = opt.returnDetails !== undefined ? opt.returnDetails : this.options.returnDetails;
751
- const keySeparator = opt.keySeparator !== undefined ? opt.keySeparator : this.options.keySeparator;
1067
+ const returnDetails = options.returnDetails !== undefined ? options.returnDetails : this.options.returnDetails;
1068
+ const keySeparator = options.keySeparator !== undefined ? options.keySeparator : this.options.keySeparator;
752
1069
  const {
753
1070
  key,
754
1071
  namespaces
755
- } = this.extractFromKey(keys[keys.length - 1], opt);
1072
+ } = this.extractFromKey(keys[keys.length - 1], options);
756
1073
  const namespace = namespaces[namespaces.length - 1];
757
- let nsSeparator = opt.nsSeparator !== undefined ? opt.nsSeparator : this.options.nsSeparator;
758
- if (nsSeparator === undefined) nsSeparator = ':';
759
- const lng = opt.lng || this.language;
760
- const appendNamespaceToCIMode = opt.appendNamespaceToCIMode || this.options.appendNamespaceToCIMode;
761
- if (lng?.toLowerCase() === 'cimode') {
1074
+ const lng = options.lng || this.language;
1075
+ const appendNamespaceToCIMode = options.appendNamespaceToCIMode || this.options.appendNamespaceToCIMode;
1076
+ if (lng && lng.toLowerCase() === 'cimode') {
762
1077
  if (appendNamespaceToCIMode) {
1078
+ const nsSeparator = options.nsSeparator || this.options.nsSeparator;
763
1079
  if (returnDetails) {
764
1080
  return {
765
1081
  res: `${namespace}${nsSeparator}${key}`,
@@ -767,7 +1083,7 @@ class Translator extends EventEmitter {
767
1083
  exactUsedKey: key,
768
1084
  usedLng: lng,
769
1085
  usedNS: namespace,
770
- usedParams: this.getUsedParamsDetails(opt)
1086
+ usedParams: this.getUsedParamsDetails(options)
771
1087
  };
772
1088
  }
773
1089
  return `${namespace}${nsSeparator}${key}`;
@@ -779,84 +1095,69 @@ class Translator extends EventEmitter {
779
1095
  exactUsedKey: key,
780
1096
  usedLng: lng,
781
1097
  usedNS: namespace,
782
- usedParams: this.getUsedParamsDetails(opt)
1098
+ usedParams: this.getUsedParamsDetails(options)
783
1099
  };
784
1100
  }
785
1101
  return key;
786
1102
  }
787
- const resolved = this.resolve(keys, opt);
788
- let res = resolved?.res;
789
- const resUsedKey = resolved?.usedKey || key;
790
- const resExactUsedKey = resolved?.exactUsedKey || key;
1103
+ const resolved = this.resolve(keys, options);
1104
+ let res = resolved && resolved.res;
1105
+ const resUsedKey = resolved && resolved.usedKey || key;
1106
+ const resExactUsedKey = resolved && resolved.exactUsedKey || key;
1107
+ const resType = Object.prototype.toString.apply(res);
791
1108
  const noObject = ['[object Number]', '[object Function]', '[object RegExp]'];
792
- const joinArrays = opt.joinArrays !== undefined ? opt.joinArrays : this.options.joinArrays;
1109
+ const joinArrays = options.joinArrays !== undefined ? options.joinArrays : this.options.joinArrays;
793
1110
  const handleAsObjectInI18nFormat = !this.i18nFormat || this.i18nFormat.handleAsObject;
794
- const needsPluralHandling = opt.count !== undefined && !isString(opt.count);
795
- const hasDefaultValue = Translator.hasDefaultValue(opt);
796
- const defaultValueSuffix = needsPluralHandling ? this.pluralResolver.getSuffix(lng, opt.count, opt) : '';
797
- const defaultValueSuffixOrdinalFallback = opt.ordinal && needsPluralHandling ? this.pluralResolver.getSuffix(lng, opt.count, {
798
- ordinal: false
799
- }) : '';
800
- const needsZeroSuffixLookup = needsPluralHandling && !opt.ordinal && opt.count === 0;
801
- const defaultValue = needsZeroSuffixLookup && opt[`defaultValue${this.options.pluralSeparator}zero`] || opt[`defaultValue${defaultValueSuffix}`] || opt[`defaultValue${defaultValueSuffixOrdinalFallback}`] || opt.defaultValue;
802
- let resForObjHndl = res;
803
- if (handleAsObjectInI18nFormat && !res && hasDefaultValue) {
804
- resForObjHndl = defaultValue;
805
- }
806
- const handleAsObject = shouldHandleAsObject(resForObjHndl);
807
- const resType = Object.prototype.toString.apply(resForObjHndl);
808
- if (handleAsObjectInI18nFormat && resForObjHndl && handleAsObject && noObject.indexOf(resType) < 0 && !(isString(joinArrays) && Array.isArray(resForObjHndl))) {
809
- if (!opt.returnObjects && !this.options.returnObjects) {
1111
+ const handleAsObject = !isString(res) && typeof res !== 'boolean' && typeof res !== 'number';
1112
+ if (handleAsObjectInI18nFormat && res && handleAsObject && noObject.indexOf(resType) < 0 && !(isString(joinArrays) && Array.isArray(res))) {
1113
+ if (!options.returnObjects && !this.options.returnObjects) {
810
1114
  if (!this.options.returnedObjectHandler) {
811
1115
  this.logger.warn('accessing an object - but returnObjects options is not enabled!');
812
1116
  }
813
- const r = this.options.returnedObjectHandler ? this.options.returnedObjectHandler(resUsedKey, resForObjHndl, {
814
- ...opt,
1117
+ const r = this.options.returnedObjectHandler ? this.options.returnedObjectHandler(resUsedKey, res, {
1118
+ ...options,
815
1119
  ns: namespaces
816
1120
  }) : `key '${key} (${this.language})' returned an object instead of string.`;
817
1121
  if (returnDetails) {
818
1122
  resolved.res = r;
819
- resolved.usedParams = this.getUsedParamsDetails(opt);
1123
+ resolved.usedParams = this.getUsedParamsDetails(options);
820
1124
  return resolved;
821
1125
  }
822
1126
  return r;
823
1127
  }
824
1128
  if (keySeparator) {
825
- const resTypeIsArray = Array.isArray(resForObjHndl);
1129
+ const resTypeIsArray = Array.isArray(res);
826
1130
  const copy = resTypeIsArray ? [] : {};
827
1131
  const newKeyToUse = resTypeIsArray ? resExactUsedKey : resUsedKey;
828
- for (const m in resForObjHndl) {
829
- if (Object.prototype.hasOwnProperty.call(resForObjHndl, m)) {
1132
+ for (const m in res) {
1133
+ if (Object.prototype.hasOwnProperty.call(res, m)) {
830
1134
  const deepKey = `${newKeyToUse}${keySeparator}${m}`;
831
- if (hasDefaultValue && !res) {
832
- copy[m] = this.translate(deepKey, {
833
- ...opt,
834
- defaultValue: shouldHandleAsObject(defaultValue) ? defaultValue[m] : undefined,
835
- ...{
836
- joinArrays: false,
837
- ns: namespaces
838
- }
839
- });
840
- } else {
841
- copy[m] = this.translate(deepKey, {
842
- ...opt,
843
- ...{
844
- joinArrays: false,
845
- ns: namespaces
846
- }
847
- });
848
- }
849
- if (copy[m] === deepKey) copy[m] = resForObjHndl[m];
1135
+ copy[m] = this.translate(deepKey, {
1136
+ ...options,
1137
+ ...{
1138
+ joinArrays: false,
1139
+ ns: namespaces
1140
+ }
1141
+ });
1142
+ if (copy[m] === deepKey) copy[m] = res[m];
850
1143
  }
851
1144
  }
852
1145
  res = copy;
853
1146
  }
854
1147
  } else if (handleAsObjectInI18nFormat && isString(joinArrays) && Array.isArray(res)) {
855
1148
  res = res.join(joinArrays);
856
- if (res) res = this.extendTranslation(res, keys, opt, lastKey);
1149
+ if (res) res = this.extendTranslation(res, keys, options, lastKey);
857
1150
  } else {
858
1151
  let usedDefault = false;
859
1152
  let usedKey = false;
1153
+ const needsPluralHandling = options.count !== undefined && !isString(options.count);
1154
+ const hasDefaultValue = Translator.hasDefaultValue(options);
1155
+ const defaultValueSuffix = needsPluralHandling ? this.pluralResolver.getSuffix(lng, options.count, options) : '';
1156
+ const defaultValueSuffixOrdinalFallback = options.ordinal && needsPluralHandling ? this.pluralResolver.getSuffix(lng, options.count, {
1157
+ ordinal: false
1158
+ }) : '';
1159
+ const needsZeroSuffixLookup = needsPluralHandling && !options.ordinal && options.count === 0 && this.pluralResolver.shouldUseIntlApi();
1160
+ const defaultValue = needsZeroSuffixLookup && options[`defaultValue${this.options.pluralSeparator}zero`] || options[`defaultValue${defaultValueSuffix}`] || options[`defaultValue${defaultValueSuffixOrdinalFallback}`] || options.defaultValue;
860
1161
  if (!this.isValidLookup(res) && hasDefaultValue) {
861
1162
  usedDefault = true;
862
1163
  res = defaultValue;
@@ -865,47 +1166,47 @@ class Translator extends EventEmitter {
865
1166
  usedKey = true;
866
1167
  res = key;
867
1168
  }
868
- const missingKeyNoValueFallbackToKey = opt.missingKeyNoValueFallbackToKey || this.options.missingKeyNoValueFallbackToKey;
1169
+ const missingKeyNoValueFallbackToKey = options.missingKeyNoValueFallbackToKey || this.options.missingKeyNoValueFallbackToKey;
869
1170
  const resForMissing = missingKeyNoValueFallbackToKey && usedKey ? undefined : res;
870
1171
  const updateMissing = hasDefaultValue && defaultValue !== res && this.options.updateMissing;
871
1172
  if (usedKey || usedDefault || updateMissing) {
872
1173
  this.logger.log(updateMissing ? 'updateKey' : 'missingKey', lng, namespace, key, updateMissing ? defaultValue : res);
873
1174
  if (keySeparator) {
874
1175
  const fk = this.resolve(key, {
875
- ...opt,
1176
+ ...options,
876
1177
  keySeparator: false
877
1178
  });
878
1179
  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.');
879
1180
  }
880
1181
  let lngs = [];
881
- const fallbackLngs = this.languageUtils.getFallbackCodes(this.options.fallbackLng, opt.lng || this.language);
1182
+ const fallbackLngs = this.languageUtils.getFallbackCodes(this.options.fallbackLng, options.lng || this.language);
882
1183
  if (this.options.saveMissingTo === 'fallback' && fallbackLngs && fallbackLngs[0]) {
883
1184
  for (let i = 0; i < fallbackLngs.length; i++) {
884
1185
  lngs.push(fallbackLngs[i]);
885
1186
  }
886
1187
  } else if (this.options.saveMissingTo === 'all') {
887
- lngs = this.languageUtils.toResolveHierarchy(opt.lng || this.language);
1188
+ lngs = this.languageUtils.toResolveHierarchy(options.lng || this.language);
888
1189
  } else {
889
- lngs.push(opt.lng || this.language);
1190
+ lngs.push(options.lng || this.language);
890
1191
  }
891
1192
  const send = (l, k, specificDefaultValue) => {
892
1193
  const defaultForMissing = hasDefaultValue && specificDefaultValue !== res ? specificDefaultValue : resForMissing;
893
1194
  if (this.options.missingKeyHandler) {
894
- this.options.missingKeyHandler(l, namespace, k, defaultForMissing, updateMissing, opt);
895
- } else if (this.backendConnector?.saveMissing) {
896
- this.backendConnector.saveMissing(l, namespace, k, defaultForMissing, updateMissing, opt);
1195
+ this.options.missingKeyHandler(l, namespace, k, defaultForMissing, updateMissing, options);
1196
+ } else if (this.backendConnector && this.backendConnector.saveMissing) {
1197
+ this.backendConnector.saveMissing(l, namespace, k, defaultForMissing, updateMissing, options);
897
1198
  }
898
1199
  this.emit('missingKey', l, namespace, k, res);
899
1200
  };
900
1201
  if (this.options.saveMissing) {
901
1202
  if (this.options.saveMissingPlurals && needsPluralHandling) {
902
1203
  lngs.forEach(language => {
903
- const suffixes = this.pluralResolver.getSuffixes(language, opt);
904
- if (needsZeroSuffixLookup && opt[`defaultValue${this.options.pluralSeparator}zero`] && suffixes.indexOf(`${this.options.pluralSeparator}zero`) < 0) {
1204
+ const suffixes = this.pluralResolver.getSuffixes(language, options);
1205
+ if (needsZeroSuffixLookup && options[`defaultValue${this.options.pluralSeparator}zero`] && suffixes.indexOf(`${this.options.pluralSeparator}zero`) < 0) {
905
1206
  suffixes.push(`${this.options.pluralSeparator}zero`);
906
1207
  }
907
1208
  suffixes.forEach(suffix => {
908
- send([language], key + suffix, opt[`defaultValue${suffix}`] || defaultValue);
1209
+ send([language], key + suffix, options[`defaultValue${suffix}`] || defaultValue);
909
1210
  });
910
1211
  });
911
1212
  } else {
@@ -913,80 +1214,87 @@ class Translator extends EventEmitter {
913
1214
  }
914
1215
  }
915
1216
  }
916
- res = this.extendTranslation(res, keys, opt, resolved, lastKey);
917
- if (usedKey && res === key && this.options.appendNamespaceToMissingKey) {
918
- res = `${namespace}${nsSeparator}${key}`;
919
- }
1217
+ res = this.extendTranslation(res, keys, options, resolved, lastKey);
1218
+ if (usedKey && res === key && this.options.appendNamespaceToMissingKey) res = `${namespace}:${key}`;
920
1219
  if ((usedKey || usedDefault) && this.options.parseMissingKeyHandler) {
921
- res = this.options.parseMissingKeyHandler(this.options.appendNamespaceToMissingKey ? `${namespace}${nsSeparator}${key}` : key, usedDefault ? res : undefined, opt);
1220
+ if (this.options.compatibilityAPI !== 'v1') {
1221
+ res = this.options.parseMissingKeyHandler(this.options.appendNamespaceToMissingKey ? `${namespace}:${key}` : key, usedDefault ? res : undefined);
1222
+ } else {
1223
+ res = this.options.parseMissingKeyHandler(res);
1224
+ }
922
1225
  }
923
1226
  }
924
1227
  if (returnDetails) {
925
1228
  resolved.res = res;
926
- resolved.usedParams = this.getUsedParamsDetails(opt);
1229
+ resolved.usedParams = this.getUsedParamsDetails(options);
927
1230
  return resolved;
928
1231
  }
929
1232
  return res;
930
1233
  }
931
- extendTranslation(res, key, opt, resolved, lastKey) {
932
- if (this.i18nFormat?.parse) {
1234
+ extendTranslation(res, key, options, resolved, lastKey) {
1235
+ var _this = this;
1236
+ if (this.i18nFormat && this.i18nFormat.parse) {
933
1237
  res = this.i18nFormat.parse(res, {
934
1238
  ...this.options.interpolation.defaultVariables,
935
- ...opt
936
- }, opt.lng || this.language || resolved.usedLng, resolved.usedNS, resolved.usedKey, {
1239
+ ...options
1240
+ }, options.lng || this.language || resolved.usedLng, resolved.usedNS, resolved.usedKey, {
937
1241
  resolved
938
1242
  });
939
- } else if (!opt.skipInterpolation) {
940
- if (opt.interpolation) this.interpolator.init({
941
- ...opt,
1243
+ } else if (!options.skipInterpolation) {
1244
+ if (options.interpolation) this.interpolator.init({
1245
+ ...options,
942
1246
  ...{
943
1247
  interpolation: {
944
1248
  ...this.options.interpolation,
945
- ...opt.interpolation
1249
+ ...options.interpolation
946
1250
  }
947
1251
  }
948
1252
  });
949
- const skipOnVariables = isString(res) && (opt?.interpolation?.skipOnVariables !== undefined ? opt.interpolation.skipOnVariables : this.options.interpolation.skipOnVariables);
1253
+ const skipOnVariables = isString(res) && (options && options.interpolation && options.interpolation.skipOnVariables !== undefined ? options.interpolation.skipOnVariables : this.options.interpolation.skipOnVariables);
950
1254
  let nestBef;
951
1255
  if (skipOnVariables) {
952
1256
  const nb = res.match(this.interpolator.nestingRegexp);
953
1257
  nestBef = nb && nb.length;
954
1258
  }
955
- let data = opt.replace && !isString(opt.replace) ? opt.replace : opt;
1259
+ let data = options.replace && !isString(options.replace) ? options.replace : options;
956
1260
  if (this.options.interpolation.defaultVariables) data = {
957
1261
  ...this.options.interpolation.defaultVariables,
958
1262
  ...data
959
1263
  };
960
- res = this.interpolator.interpolate(res, data, opt.lng || this.language || resolved.usedLng, opt);
1264
+ res = this.interpolator.interpolate(res, data, options.lng || this.language || resolved.usedLng, options);
961
1265
  if (skipOnVariables) {
962
1266
  const na = res.match(this.interpolator.nestingRegexp);
963
1267
  const nestAft = na && na.length;
964
- if (nestBef < nestAft) opt.nest = false;
1268
+ if (nestBef < nestAft) options.nest = false;
965
1269
  }
966
- if (!opt.lng && resolved && resolved.res) opt.lng = this.language || resolved.usedLng;
967
- if (opt.nest !== false) res = this.interpolator.nest(res, (...args) => {
968
- if (lastKey?.[0] === args[0] && !opt.context) {
969
- this.logger.warn(`It seems you are nesting recursively key: ${args[0]} in key: ${key[0]}`);
1270
+ if (!options.lng && this.options.compatibilityAPI !== 'v1' && resolved && resolved.res) options.lng = this.language || resolved.usedLng;
1271
+ if (options.nest !== false) res = this.interpolator.nest(res, function () {
1272
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
1273
+ args[_key] = arguments[_key];
1274
+ }
1275
+ if (lastKey && lastKey[0] === args[0] && !options.context) {
1276
+ _this.logger.warn(`It seems you are nesting recursively key: ${args[0]} in key: ${key[0]}`);
970
1277
  return null;
971
1278
  }
972
- return this.translate(...args, key);
973
- }, opt);
974
- if (opt.interpolation) this.interpolator.reset();
1279
+ return _this.translate(...args, key);
1280
+ }, options);
1281
+ if (options.interpolation) this.interpolator.reset();
975
1282
  }
976
- const postProcess = opt.postProcess || this.options.postProcess;
1283
+ const postProcess = options.postProcess || this.options.postProcess;
977
1284
  const postProcessorNames = isString(postProcess) ? [postProcess] : postProcess;
978
- if (res != null && postProcessorNames?.length && opt.applyPostProcessor !== false) {
1285
+ if (res !== undefined && res !== null && postProcessorNames && postProcessorNames.length && options.applyPostProcessor !== false) {
979
1286
  res = postProcessor.handle(postProcessorNames, res, key, this.options && this.options.postProcessPassResolved ? {
980
1287
  i18nResolved: {
981
1288
  ...resolved,
982
- usedParams: this.getUsedParamsDetails(opt)
1289
+ usedParams: this.getUsedParamsDetails(options)
983
1290
  },
984
- ...opt
985
- } : opt, this);
1291
+ ...options
1292
+ } : options, this);
986
1293
  }
987
1294
  return res;
988
1295
  }
989
- resolve(keys, opt = {}) {
1296
+ resolve(keys) {
1297
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
990
1298
  let found;
991
1299
  let usedKey;
992
1300
  let exactUsedKey;
@@ -995,19 +1303,19 @@ class Translator extends EventEmitter {
995
1303
  if (isString(keys)) keys = [keys];
996
1304
  keys.forEach(k => {
997
1305
  if (this.isValidLookup(found)) return;
998
- const extracted = this.extractFromKey(k, opt);
1306
+ const extracted = this.extractFromKey(k, options);
999
1307
  const key = extracted.key;
1000
1308
  usedKey = key;
1001
1309
  let namespaces = extracted.namespaces;
1002
1310
  if (this.options.fallbackNS) namespaces = namespaces.concat(this.options.fallbackNS);
1003
- const needsPluralHandling = opt.count !== undefined && !isString(opt.count);
1004
- const needsZeroSuffixLookup = needsPluralHandling && !opt.ordinal && opt.count === 0;
1005
- const needsContextHandling = opt.context !== undefined && (isString(opt.context) || typeof opt.context === 'number') && opt.context !== '';
1006
- const codes = opt.lngs ? opt.lngs : this.languageUtils.toResolveHierarchy(opt.lng || this.language, opt.fallbackLng);
1311
+ const needsPluralHandling = options.count !== undefined && !isString(options.count);
1312
+ const needsZeroSuffixLookup = needsPluralHandling && !options.ordinal && options.count === 0 && this.pluralResolver.shouldUseIntlApi();
1313
+ const needsContextHandling = options.context !== undefined && (isString(options.context) || typeof options.context === 'number') && options.context !== '';
1314
+ const codes = options.lngs ? options.lngs : this.languageUtils.toResolveHierarchy(options.lng || this.language, options.fallbackLng);
1007
1315
  namespaces.forEach(ns => {
1008
1316
  if (this.isValidLookup(found)) return;
1009
1317
  usedNS = ns;
1010
- if (!checkedLoadedFor[`${codes[0]}-${ns}`] && this.utils?.hasLoadedNamespace && !this.utils?.hasLoadedNamespace(usedNS)) {
1318
+ if (!checkedLoadedFor[`${codes[0]}-${ns}`] && this.utils && this.utils.hasLoadedNamespace && !this.utils.hasLoadedNamespace(usedNS)) {
1011
1319
  checkedLoadedFor[`${codes[0]}-${ns}`] = true;
1012
1320
  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!!!');
1013
1321
  }
@@ -1015,30 +1323,30 @@ class Translator extends EventEmitter {
1015
1323
  if (this.isValidLookup(found)) return;
1016
1324
  usedLng = code;
1017
1325
  const finalKeys = [key];
1018
- if (this.i18nFormat?.addLookupKeys) {
1019
- this.i18nFormat.addLookupKeys(finalKeys, key, code, ns, opt);
1326
+ if (this.i18nFormat && this.i18nFormat.addLookupKeys) {
1327
+ this.i18nFormat.addLookupKeys(finalKeys, key, code, ns, options);
1020
1328
  } else {
1021
1329
  let pluralSuffix;
1022
- if (needsPluralHandling) pluralSuffix = this.pluralResolver.getSuffix(code, opt.count, opt);
1330
+ if (needsPluralHandling) pluralSuffix = this.pluralResolver.getSuffix(code, options.count, options);
1023
1331
  const zeroSuffix = `${this.options.pluralSeparator}zero`;
1024
1332
  const ordinalPrefix = `${this.options.pluralSeparator}ordinal${this.options.pluralSeparator}`;
1025
1333
  if (needsPluralHandling) {
1026
- if (opt.ordinal && pluralSuffix.indexOf(ordinalPrefix) === 0) {
1334
+ finalKeys.push(key + pluralSuffix);
1335
+ if (options.ordinal && pluralSuffix.indexOf(ordinalPrefix) === 0) {
1027
1336
  finalKeys.push(key + pluralSuffix.replace(ordinalPrefix, this.options.pluralSeparator));
1028
1337
  }
1029
- finalKeys.push(key + pluralSuffix);
1030
1338
  if (needsZeroSuffixLookup) {
1031
1339
  finalKeys.push(key + zeroSuffix);
1032
1340
  }
1033
1341
  }
1034
1342
  if (needsContextHandling) {
1035
- const contextKey = `${key}${this.options.contextSeparator || '_'}${opt.context}`;
1343
+ const contextKey = `${key}${this.options.contextSeparator}${options.context}`;
1036
1344
  finalKeys.push(contextKey);
1037
1345
  if (needsPluralHandling) {
1038
- if (opt.ordinal && pluralSuffix.indexOf(ordinalPrefix) === 0) {
1346
+ finalKeys.push(contextKey + pluralSuffix);
1347
+ if (options.ordinal && pluralSuffix.indexOf(ordinalPrefix) === 0) {
1039
1348
  finalKeys.push(contextKey + pluralSuffix.replace(ordinalPrefix, this.options.pluralSeparator));
1040
1349
  }
1041
- finalKeys.push(contextKey + pluralSuffix);
1042
1350
  if (needsZeroSuffixLookup) {
1043
1351
  finalKeys.push(contextKey + zeroSuffix);
1044
1352
  }
@@ -1049,7 +1357,7 @@ class Translator extends EventEmitter {
1049
1357
  while (possibleKey = finalKeys.pop()) {
1050
1358
  if (!this.isValidLookup(found)) {
1051
1359
  exactUsedKey = possibleKey;
1052
- found = this.getResource(code, ns, possibleKey, opt);
1360
+ found = this.getResource(code, ns, possibleKey, options);
1053
1361
  }
1054
1362
  }
1055
1363
  });
@@ -1066,11 +1374,13 @@ class Translator extends EventEmitter {
1066
1374
  isValidLookup(res) {
1067
1375
  return res !== undefined && !(!this.options.returnNull && res === null) && !(!this.options.returnEmptyString && res === '');
1068
1376
  }
1069
- getResource(code, ns, key, options = {}) {
1070
- if (this.i18nFormat?.getResource) return this.i18nFormat.getResource(code, ns, key, options);
1377
+ getResource(code, ns, key) {
1378
+ let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
1379
+ if (this.i18nFormat && this.i18nFormat.getResource) return this.i18nFormat.getResource(code, ns, key, options);
1071
1380
  return this.resourceStore.getResource(code, ns, key, options);
1072
1381
  }
1073
- getUsedParamsDetails(options = {}) {
1382
+ getUsedParamsDetails() {
1383
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1074
1384
  const optionsKeys = ['defaultValue', 'ordinal', 'context', 'replace', 'lng', 'lngs', 'fallbackLng', 'ns', 'keySeparator', 'nsSeparator', 'returnObjects', 'returnDetails', 'joinArrays', 'postProcess', 'interpolation'];
1075
1385
  const useOptionsReplaceForData = options.replace && !isString(options.replace);
1076
1386
  let data = useOptionsReplaceForData ? options.replace : options;
@@ -1104,6 +1414,7 @@ class Translator extends EventEmitter {
1104
1414
  }
1105
1415
  }
1106
1416
 
1417
+ const capitalize = string => string.charAt(0).toUpperCase() + string.slice(1);
1107
1418
  class LanguageUtil {
1108
1419
  constructor(options) {
1109
1420
  this.options = options;
@@ -1127,18 +1438,31 @@ class LanguageUtil {
1127
1438
  }
1128
1439
  formatLanguageCode(code) {
1129
1440
  if (isString(code) && code.indexOf('-') > -1) {
1130
- let formattedCode;
1131
- try {
1132
- formattedCode = Intl.getCanonicalLocales(code)[0];
1133
- } catch (e) {}
1134
- if (formattedCode && this.options.lowerCaseLng) {
1135
- formattedCode = formattedCode.toLowerCase();
1441
+ if (typeof Intl !== 'undefined' && typeof Intl.getCanonicalLocales !== 'undefined') {
1442
+ try {
1443
+ let formattedCode = Intl.getCanonicalLocales(code)[0];
1444
+ if (formattedCode && this.options.lowerCaseLng) {
1445
+ formattedCode = formattedCode.toLowerCase();
1446
+ }
1447
+ if (formattedCode) return formattedCode;
1448
+ } catch (e) {}
1136
1449
  }
1137
- if (formattedCode) return formattedCode;
1450
+ const specialCases = ['hans', 'hant', 'latn', 'cyrl', 'cans', 'mong', 'arab'];
1451
+ let p = code.split('-');
1138
1452
  if (this.options.lowerCaseLng) {
1139
- return code.toLowerCase();
1453
+ p = p.map(part => part.toLowerCase());
1454
+ } else if (p.length === 2) {
1455
+ p[0] = p[0].toLowerCase();
1456
+ p[1] = p[1].toUpperCase();
1457
+ if (specialCases.indexOf(p[1].toLowerCase()) > -1) p[1] = capitalize(p[1].toLowerCase());
1458
+ } else if (p.length === 3) {
1459
+ p[0] = p[0].toLowerCase();
1460
+ if (p[1].length === 2) p[1] = p[1].toUpperCase();
1461
+ if (p[0] !== 'sgn' && p[2].length === 2) p[2] = p[2].toUpperCase();
1462
+ if (specialCases.indexOf(p[1].toLowerCase()) > -1) p[1] = capitalize(p[1].toLowerCase());
1463
+ if (specialCases.indexOf(p[2].toLowerCase()) > -1) p[2] = capitalize(p[2].toLowerCase());
1140
1464
  }
1141
- return code;
1465
+ return p.join('-');
1142
1466
  }
1143
1467
  return this.options.cleanCode || this.options.lowerCaseLng ? code.toLowerCase() : code;
1144
1468
  }
@@ -1159,8 +1483,6 @@ class LanguageUtil {
1159
1483
  if (!found && this.options.supportedLngs) {
1160
1484
  codes.forEach(code => {
1161
1485
  if (found) return;
1162
- const lngScOnly = this.getScriptPartFromCode(code);
1163
- if (this.isSupportedCode(lngScOnly)) return found = lngScOnly;
1164
1486
  const lngOnly = this.getLanguagePartFromCode(code);
1165
1487
  if (this.isSupportedCode(lngOnly)) return found = lngOnly;
1166
1488
  found = this.options.supportedLngs.find(supportedLng => {
@@ -1188,7 +1510,7 @@ class LanguageUtil {
1188
1510
  return found || [];
1189
1511
  }
1190
1512
  toResolveHierarchy(code, fallbackCode) {
1191
- const fallbackCodes = this.getFallbackCodes((fallbackCode === false ? [] : fallbackCode) || this.options.fallbackLng || [], code);
1513
+ const fallbackCodes = this.getFallbackCodes(fallbackCode || this.options.fallbackLng || [], code);
1192
1514
  const codes = [];
1193
1515
  const addCode = c => {
1194
1516
  if (!c) return;
@@ -1212,6 +1534,125 @@ class LanguageUtil {
1212
1534
  }
1213
1535
  }
1214
1536
 
1537
+ let sets = [{
1538
+ lngs: ['ach', 'ak', 'am', 'arn', 'br', 'fil', 'gun', 'ln', 'mfe', 'mg', 'mi', 'oc', 'pt', 'pt-BR', 'tg', 'tl', 'ti', 'tr', 'uz', 'wa'],
1539
+ nr: [1, 2],
1540
+ fc: 1
1541
+ }, {
1542
+ 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'],
1543
+ nr: [1, 2],
1544
+ fc: 2
1545
+ }, {
1546
+ lngs: ['ay', 'bo', 'cgg', 'fa', 'ht', 'id', 'ja', 'jbo', 'ka', 'km', 'ko', 'ky', 'lo', 'ms', 'sah', 'su', 'th', 'tt', 'ug', 'vi', 'wo', 'zh'],
1547
+ nr: [1],
1548
+ fc: 3
1549
+ }, {
1550
+ lngs: ['be', 'bs', 'cnr', 'dz', 'hr', 'ru', 'sr', 'uk'],
1551
+ nr: [1, 2, 5],
1552
+ fc: 4
1553
+ }, {
1554
+ lngs: ['ar'],
1555
+ nr: [0, 1, 2, 3, 11, 100],
1556
+ fc: 5
1557
+ }, {
1558
+ lngs: ['cs', 'sk'],
1559
+ nr: [1, 2, 5],
1560
+ fc: 6
1561
+ }, {
1562
+ lngs: ['csb', 'pl'],
1563
+ nr: [1, 2, 5],
1564
+ fc: 7
1565
+ }, {
1566
+ lngs: ['cy'],
1567
+ nr: [1, 2, 3, 8],
1568
+ fc: 8
1569
+ }, {
1570
+ lngs: ['fr'],
1571
+ nr: [1, 2],
1572
+ fc: 9
1573
+ }, {
1574
+ lngs: ['ga'],
1575
+ nr: [1, 2, 3, 7, 11],
1576
+ fc: 10
1577
+ }, {
1578
+ lngs: ['gd'],
1579
+ nr: [1, 2, 3, 20],
1580
+ fc: 11
1581
+ }, {
1582
+ lngs: ['is'],
1583
+ nr: [1, 2],
1584
+ fc: 12
1585
+ }, {
1586
+ lngs: ['jv'],
1587
+ nr: [0, 1],
1588
+ fc: 13
1589
+ }, {
1590
+ lngs: ['kw'],
1591
+ nr: [1, 2, 3, 4],
1592
+ fc: 14
1593
+ }, {
1594
+ lngs: ['lt'],
1595
+ nr: [1, 2, 10],
1596
+ fc: 15
1597
+ }, {
1598
+ lngs: ['lv'],
1599
+ nr: [1, 2, 0],
1600
+ fc: 16
1601
+ }, {
1602
+ lngs: ['mk'],
1603
+ nr: [1, 2],
1604
+ fc: 17
1605
+ }, {
1606
+ lngs: ['mnk'],
1607
+ nr: [0, 1, 2],
1608
+ fc: 18
1609
+ }, {
1610
+ lngs: ['mt'],
1611
+ nr: [1, 2, 11, 20],
1612
+ fc: 19
1613
+ }, {
1614
+ lngs: ['or'],
1615
+ nr: [2, 1],
1616
+ fc: 2
1617
+ }, {
1618
+ lngs: ['ro'],
1619
+ nr: [1, 2, 20],
1620
+ fc: 20
1621
+ }, {
1622
+ lngs: ['sl'],
1623
+ nr: [5, 1, 2, 3],
1624
+ fc: 21
1625
+ }, {
1626
+ lngs: ['he', 'iw'],
1627
+ nr: [1, 2, 20, 21],
1628
+ fc: 22
1629
+ }];
1630
+ let _rulesPluralsTypes = {
1631
+ 1: n => Number(n > 1),
1632
+ 2: n => Number(n != 1),
1633
+ 3: n => 0,
1634
+ 4: n => Number(n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2),
1635
+ 5: n => Number(n == 0 ? 0 : n == 1 ? 1 : n == 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5),
1636
+ 6: n => Number(n == 1 ? 0 : n >= 2 && n <= 4 ? 1 : 2),
1637
+ 7: n => Number(n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2),
1638
+ 8: n => Number(n == 1 ? 0 : n == 2 ? 1 : n != 8 && n != 11 ? 2 : 3),
1639
+ 9: n => Number(n >= 2),
1640
+ 10: n => Number(n == 1 ? 0 : n == 2 ? 1 : n < 7 ? 2 : n < 11 ? 3 : 4),
1641
+ 11: n => Number(n == 1 || n == 11 ? 0 : n == 2 || n == 12 ? 1 : n > 2 && n < 20 ? 2 : 3),
1642
+ 12: n => Number(n % 10 != 1 || n % 100 == 11),
1643
+ 13: n => Number(n !== 0),
1644
+ 14: n => Number(n == 1 ? 0 : n == 2 ? 1 : n == 3 ? 2 : 3),
1645
+ 15: n => Number(n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2),
1646
+ 16: n => Number(n % 10 == 1 && n % 100 != 11 ? 0 : n !== 0 ? 1 : 2),
1647
+ 17: n => Number(n == 1 || n % 10 == 1 && n % 100 != 11 ? 0 : 1),
1648
+ 18: n => Number(n == 0 ? 0 : n == 1 ? 1 : 2),
1649
+ 19: n => Number(n == 1 ? 0 : n == 0 || n % 100 > 1 && n % 100 < 11 ? 1 : n % 100 > 10 && n % 100 < 20 ? 2 : 3),
1650
+ 20: n => Number(n == 1 ? 0 : n == 0 || n % 100 > 0 && n % 100 < 20 ? 1 : 2),
1651
+ 21: n => Number(n % 100 == 1 ? 1 : n % 100 == 2 ? 2 : n % 100 == 3 || n % 100 == 4 ? 3 : 0),
1652
+ 22: n => Number(n == 1 ? 0 : n == 2 ? 1 : (n < 0 || n > 10) && n % 10 == 0 ? 2 : 3)
1653
+ };
1654
+ const nonIntlVersions = ['v1', 'v2', 'v3'];
1655
+ const intlVersions = ['v4'];
1215
1656
  const suffixesOrder = {
1216
1657
  zero: 0,
1217
1658
  one: 1,
@@ -1220,74 +1661,129 @@ const suffixesOrder = {
1220
1661
  many: 4,
1221
1662
  other: 5
1222
1663
  };
1223
- const dummyRule = {
1224
- select: count => count === 1 ? 'one' : 'other',
1225
- resolvedOptions: () => ({
1226
- pluralCategories: ['one', 'other']
1227
- })
1664
+ const createRules = () => {
1665
+ const rules = {};
1666
+ sets.forEach(set => {
1667
+ set.lngs.forEach(l => {
1668
+ rules[l] = {
1669
+ numbers: set.nr,
1670
+ plurals: _rulesPluralsTypes[set.fc]
1671
+ };
1672
+ });
1673
+ });
1674
+ return rules;
1228
1675
  };
1229
1676
  class PluralResolver {
1230
- constructor(languageUtils, options = {}) {
1677
+ constructor(languageUtils) {
1678
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1231
1679
  this.languageUtils = languageUtils;
1232
1680
  this.options = options;
1233
1681
  this.logger = baseLogger.create('pluralResolver');
1682
+ if ((!this.options.compatibilityJSON || intlVersions.includes(this.options.compatibilityJSON)) && (typeof Intl === 'undefined' || !Intl.PluralRules)) {
1683
+ this.options.compatibilityJSON = 'v3';
1684
+ 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.');
1685
+ }
1686
+ this.rules = createRules();
1234
1687
  this.pluralRulesCache = {};
1235
1688
  }
1689
+ addRule(lng, obj) {
1690
+ this.rules[lng] = obj;
1691
+ }
1236
1692
  clearCache() {
1237
1693
  this.pluralRulesCache = {};
1238
1694
  }
1239
- getRule(code, options = {}) {
1240
- const cleanedCode = getCleanedCode(code === 'dev' ? 'en' : code);
1241
- const type = options.ordinal ? 'ordinal' : 'cardinal';
1242
- const cacheKey = JSON.stringify({
1243
- cleanedCode,
1244
- type
1245
- });
1246
- if (cacheKey in this.pluralRulesCache) {
1247
- return this.pluralRulesCache[cacheKey];
1248
- }
1249
- let rule;
1250
- try {
1251
- rule = new Intl.PluralRules(cleanedCode, {
1695
+ getRule(code) {
1696
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1697
+ if (this.shouldUseIntlApi()) {
1698
+ const cleanedCode = getCleanedCode(code === 'dev' ? 'en' : code);
1699
+ const type = options.ordinal ? 'ordinal' : 'cardinal';
1700
+ const cacheKey = JSON.stringify({
1701
+ cleanedCode,
1252
1702
  type
1253
1703
  });
1254
- } catch (err) {
1255
- if (typeof Intl === 'undefined') {
1256
- this.logger.error('No Intl support, please use an Intl polyfill!');
1257
- return dummyRule;
1704
+ if (cacheKey in this.pluralRulesCache) {
1705
+ return this.pluralRulesCache[cacheKey];
1706
+ }
1707
+ let rule;
1708
+ try {
1709
+ rule = new Intl.PluralRules(cleanedCode, {
1710
+ type
1711
+ });
1712
+ } catch (err) {
1713
+ if (!code.match(/-|_/)) return;
1714
+ const lngPart = this.languageUtils.getLanguagePartFromCode(code);
1715
+ rule = this.getRule(lngPart, options);
1258
1716
  }
1259
- if (!code.match(/-|_/)) return dummyRule;
1260
- const lngPart = this.languageUtils.getLanguagePartFromCode(code);
1261
- rule = this.getRule(lngPart, options);
1717
+ this.pluralRulesCache[cacheKey] = rule;
1718
+ return rule;
1262
1719
  }
1263
- this.pluralRulesCache[cacheKey] = rule;
1264
- return rule;
1720
+ return this.rules[code] || this.rules[this.languageUtils.getLanguagePartFromCode(code)];
1265
1721
  }
1266
- needsPlural(code, options = {}) {
1267
- let rule = this.getRule(code, options);
1268
- if (!rule) rule = this.getRule('dev', options);
1269
- return rule?.resolvedOptions().pluralCategories.length > 1;
1722
+ needsPlural(code) {
1723
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1724
+ const rule = this.getRule(code, options);
1725
+ if (this.shouldUseIntlApi()) {
1726
+ return rule && rule.resolvedOptions().pluralCategories.length > 1;
1727
+ }
1728
+ return rule && rule.numbers.length > 1;
1270
1729
  }
1271
- getPluralFormsOfKey(code, key, options = {}) {
1730
+ getPluralFormsOfKey(code, key) {
1731
+ let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
1272
1732
  return this.getSuffixes(code, options).map(suffix => `${key}${suffix}`);
1273
1733
  }
1274
- getSuffixes(code, options = {}) {
1275
- let rule = this.getRule(code, options);
1276
- if (!rule) rule = this.getRule('dev', options);
1277
- if (!rule) return [];
1278
- return rule.resolvedOptions().pluralCategories.sort((pluralCategory1, pluralCategory2) => suffixesOrder[pluralCategory1] - suffixesOrder[pluralCategory2]).map(pluralCategory => `${this.options.prepend}${options.ordinal ? `ordinal${this.options.prepend}` : ''}${pluralCategory}`);
1734
+ getSuffixes(code) {
1735
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1736
+ const rule = this.getRule(code, options);
1737
+ if (!rule) {
1738
+ return [];
1739
+ }
1740
+ if (this.shouldUseIntlApi()) {
1741
+ return rule.resolvedOptions().pluralCategories.sort((pluralCategory1, pluralCategory2) => suffixesOrder[pluralCategory1] - suffixesOrder[pluralCategory2]).map(pluralCategory => `${this.options.prepend}${options.ordinal ? `ordinal${this.options.prepend}` : ''}${pluralCategory}`);
1742
+ }
1743
+ return rule.numbers.map(number => this.getSuffix(code, number, options));
1279
1744
  }
1280
- getSuffix(code, count, options = {}) {
1745
+ getSuffix(code, count) {
1746
+ let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
1281
1747
  const rule = this.getRule(code, options);
1282
1748
  if (rule) {
1283
- return `${this.options.prepend}${options.ordinal ? `ordinal${this.options.prepend}` : ''}${rule.select(count)}`;
1749
+ if (this.shouldUseIntlApi()) {
1750
+ return `${this.options.prepend}${options.ordinal ? `ordinal${this.options.prepend}` : ''}${rule.select(count)}`;
1751
+ }
1752
+ return this.getSuffixRetroCompatible(rule, count);
1284
1753
  }
1285
1754
  this.logger.warn(`no plural rule found for: ${code}`);
1286
- return this.getSuffix('dev', count, options);
1755
+ return '';
1756
+ }
1757
+ getSuffixRetroCompatible(rule, count) {
1758
+ const idx = rule.noAbs ? rule.plurals(count) : rule.plurals(Math.abs(count));
1759
+ let suffix = rule.numbers[idx];
1760
+ if (this.options.simplifyPluralSuffix && rule.numbers.length === 2 && rule.numbers[0] === 1) {
1761
+ if (suffix === 2) {
1762
+ suffix = 'plural';
1763
+ } else if (suffix === 1) {
1764
+ suffix = '';
1765
+ }
1766
+ }
1767
+ const returnSuffix = () => this.options.prepend && suffix.toString() ? this.options.prepend + suffix.toString() : suffix.toString();
1768
+ if (this.options.compatibilityJSON === 'v1') {
1769
+ if (suffix === 1) return '';
1770
+ if (typeof suffix === 'number') return `_plural_${suffix.toString()}`;
1771
+ return returnSuffix();
1772
+ } else if (this.options.compatibilityJSON === 'v2') {
1773
+ return returnSuffix();
1774
+ } else if (this.options.simplifyPluralSuffix && rule.numbers.length === 2 && rule.numbers[0] === 1) {
1775
+ return returnSuffix();
1776
+ }
1777
+ return this.options.prepend && idx.toString() ? this.options.prepend + idx.toString() : idx.toString();
1778
+ }
1779
+ shouldUseIntlApi() {
1780
+ return !nonIntlVersions.includes(this.options.compatibilityJSON);
1287
1781
  }
1288
1782
  }
1289
1783
 
1290
- const deepFindWithDefaults = (data, defaultData, key, keySeparator = '.', ignoreJSONStructure = true) => {
1784
+ const deepFindWithDefaults = function (data, defaultData, key) {
1785
+ let keySeparator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '.';
1786
+ let ignoreJSONStructure = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;
1291
1787
  let path = getPathWithDefaults(data, defaultData, key);
1292
1788
  if (!path && ignoreJSONStructure && isString(key)) {
1293
1789
  path = deepFind(data, key, keySeparator);
@@ -1297,13 +1793,15 @@ const deepFindWithDefaults = (data, defaultData, key, keySeparator = '.', ignore
1297
1793
  };
1298
1794
  const regexSafe = val => val.replace(/\$/g, '$$$$');
1299
1795
  class Interpolator {
1300
- constructor(options = {}) {
1796
+ constructor() {
1797
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1301
1798
  this.logger = baseLogger.create('interpolator');
1302
1799
  this.options = options;
1303
- this.format = options?.interpolation?.format || (value => value);
1800
+ this.format = options.interpolation && options.interpolation.format || (value => value);
1304
1801
  this.init(options);
1305
1802
  }
1306
- init(options = {}) {
1803
+ init() {
1804
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1307
1805
  if (!options.interpolation) options.interpolation = {
1308
1806
  escapeValue: true
1309
1807
  };
@@ -1346,7 +1844,7 @@ class Interpolator {
1346
1844
  }
1347
1845
  resetRegExp() {
1348
1846
  const getOrResetRegExp = (existingRegExp, pattern) => {
1349
- if (existingRegExp?.source === pattern) {
1847
+ if (existingRegExp && existingRegExp.source === pattern) {
1350
1848
  existingRegExp.lastIndex = 0;
1351
1849
  return existingRegExp;
1352
1850
  }
@@ -1354,7 +1852,7 @@ class Interpolator {
1354
1852
  };
1355
1853
  this.regexp = getOrResetRegExp(this.regexp, `${this.prefix}(.+?)${this.suffix}`);
1356
1854
  this.regexpUnescape = getOrResetRegExp(this.regexpUnescape, `${this.prefix}${this.unescapePrefix}(.+?)${this.unescapeSuffix}${this.suffix}`);
1357
- this.nestingRegexp = getOrResetRegExp(this.nestingRegexp, `${this.nestingPrefix}((?:[^()"']+|"[^"]*"|'[^']*'|\\((?:[^()]|"[^"]*"|'[^']*')*\\))*?)${this.nestingSuffix}`);
1855
+ this.nestingRegexp = getOrResetRegExp(this.nestingRegexp, `${this.nestingPrefix}(.+?)${this.nestingSuffix}`);
1358
1856
  }
1359
1857
  interpolate(str, data, lng, options) {
1360
1858
  let match;
@@ -1380,8 +1878,8 @@ class Interpolator {
1380
1878
  });
1381
1879
  };
1382
1880
  this.resetRegExp();
1383
- const missingInterpolationHandler = options?.missingInterpolationHandler || this.options.missingInterpolationHandler;
1384
- const skipOnVariables = options?.interpolation?.skipOnVariables !== undefined ? options.interpolation.skipOnVariables : this.options.interpolation.skipOnVariables;
1881
+ const missingInterpolationHandler = options && options.missingInterpolationHandler || this.options.missingInterpolationHandler;
1882
+ const skipOnVariables = options && options.interpolation && options.interpolation.skipOnVariables !== undefined ? options.interpolation.skipOnVariables : this.options.interpolation.skipOnVariables;
1385
1883
  const todos = [{
1386
1884
  regex: this.regexpUnescape,
1387
1885
  safeValue: val => regexSafe(val)
@@ -1426,20 +1924,21 @@ class Interpolator {
1426
1924
  });
1427
1925
  return str;
1428
1926
  }
1429
- nest(str, fc, options = {}) {
1927
+ nest(str, fc) {
1928
+ let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
1430
1929
  let match;
1431
1930
  let value;
1432
1931
  let clonedOptions;
1433
1932
  const handleHasOptions = (key, inheritedOptions) => {
1434
1933
  const sep = this.nestingOptionsSeparator;
1435
1934
  if (key.indexOf(sep) < 0) return key;
1436
- const c = key.split(new RegExp(`${regexEscape(sep)}[ ]*{`));
1935
+ const c = key.split(new RegExp(`${sep}[ ]*{`));
1437
1936
  let optionsString = `{${c[1]}`;
1438
1937
  key = c[0];
1439
1938
  optionsString = this.interpolate(optionsString, clonedOptions);
1440
1939
  const matchedSingleQuotes = optionsString.match(/'/g);
1441
1940
  const matchedDoubleQuotes = optionsString.match(/"/g);
1442
- if ((matchedSingleQuotes?.length ?? 0) % 2 === 0 && !matchedDoubleQuotes || (matchedDoubleQuotes?.length ?? 0) % 2 !== 0) {
1941
+ if (matchedSingleQuotes && matchedSingleQuotes.length % 2 === 0 && !matchedDoubleQuotes || matchedDoubleQuotes.length % 2 !== 0) {
1443
1942
  optionsString = optionsString.replace(/'/g, '"');
1444
1943
  }
1445
1944
  try {
@@ -1463,10 +1962,12 @@ class Interpolator {
1463
1962
  clonedOptions = clonedOptions.replace && !isString(clonedOptions.replace) ? clonedOptions.replace : clonedOptions;
1464
1963
  clonedOptions.applyPostProcessor = false;
1465
1964
  delete clonedOptions.defaultValue;
1466
- const keyEndIndex = /{.*}/.test(match[1]) ? match[1].lastIndexOf('}') + 1 : match[1].indexOf(this.formatSeparator);
1467
- if (keyEndIndex !== -1) {
1468
- formatters = match[1].slice(keyEndIndex).split(this.formatSeparator).map(elem => elem.trim()).filter(Boolean);
1469
- match[1] = match[1].slice(0, keyEndIndex);
1965
+ let doReduce = false;
1966
+ if (match[0].indexOf(this.formatSeparator) !== -1 && !/{.*}/.test(match[1])) {
1967
+ const r = match[1].split(this.formatSeparator).map(elem => elem.trim());
1968
+ match[1] = r.shift();
1969
+ formatters = r;
1970
+ doReduce = true;
1470
1971
  }
1471
1972
  value = fc(handleHasOptions.call(this, match[1].trim(), clonedOptions), clonedOptions);
1472
1973
  if (value && match[0] === str && !isString(value)) return value;
@@ -1475,7 +1976,7 @@ class Interpolator {
1475
1976
  this.logger.warn(`missed to resolve ${match[1]} for nesting ${str}`);
1476
1977
  value = '';
1477
1978
  }
1478
- if (formatters.length) {
1979
+ if (doReduce) {
1479
1980
  value = formatters.reduce((v, f) => this.format(v, f, options.lng, {
1480
1981
  ...options,
1481
1982
  interpolationkey: match[1].trim()
@@ -1521,68 +2022,68 @@ const parseFormatStr = formatStr => {
1521
2022
  };
1522
2023
  const createCachedFormatter = fn => {
1523
2024
  const cache = {};
1524
- return (v, l, o) => {
1525
- let optForCache = o;
1526
- if (o && o.interpolationkey && o.formatParams && o.formatParams[o.interpolationkey] && o[o.interpolationkey]) {
2025
+ return (val, lng, options) => {
2026
+ let optForCache = options;
2027
+ if (options && options.interpolationkey && options.formatParams && options.formatParams[options.interpolationkey] && options[options.interpolationkey]) {
1527
2028
  optForCache = {
1528
2029
  ...optForCache,
1529
- [o.interpolationkey]: undefined
2030
+ [options.interpolationkey]: undefined
1530
2031
  };
1531
2032
  }
1532
- const key = l + JSON.stringify(optForCache);
1533
- let frm = cache[key];
1534
- if (!frm) {
1535
- frm = fn(getCleanedCode(l), o);
1536
- cache[key] = frm;
2033
+ const key = lng + JSON.stringify(optForCache);
2034
+ let formatter = cache[key];
2035
+ if (!formatter) {
2036
+ formatter = fn(getCleanedCode(lng), options);
2037
+ cache[key] = formatter;
1537
2038
  }
1538
- return frm(v);
2039
+ return formatter(val);
1539
2040
  };
1540
2041
  };
1541
- const createNonCachedFormatter = fn => (v, l, o) => fn(getCleanedCode(l), o)(v);
1542
2042
  class Formatter {
1543
- constructor(options = {}) {
2043
+ constructor() {
2044
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1544
2045
  this.logger = baseLogger.create('formatter');
1545
2046
  this.options = options;
1546
- this.init(options);
1547
- }
1548
- init(services, options = {
1549
- interpolation: {}
1550
- }) {
1551
- this.formatSeparator = options.interpolation.formatSeparator || ',';
1552
- const cf = options.cacheInBuiltFormats ? createCachedFormatter : createNonCachedFormatter;
1553
2047
  this.formats = {
1554
- number: cf((lng, opt) => {
2048
+ number: createCachedFormatter((lng, opt) => {
1555
2049
  const formatter = new Intl.NumberFormat(lng, {
1556
2050
  ...opt
1557
2051
  });
1558
2052
  return val => formatter.format(val);
1559
2053
  }),
1560
- currency: cf((lng, opt) => {
2054
+ currency: createCachedFormatter((lng, opt) => {
1561
2055
  const formatter = new Intl.NumberFormat(lng, {
1562
2056
  ...opt,
1563
2057
  style: 'currency'
1564
2058
  });
1565
2059
  return val => formatter.format(val);
1566
2060
  }),
1567
- datetime: cf((lng, opt) => {
2061
+ datetime: createCachedFormatter((lng, opt) => {
1568
2062
  const formatter = new Intl.DateTimeFormat(lng, {
1569
2063
  ...opt
1570
2064
  });
1571
2065
  return val => formatter.format(val);
1572
2066
  }),
1573
- relativetime: cf((lng, opt) => {
2067
+ relativetime: createCachedFormatter((lng, opt) => {
1574
2068
  const formatter = new Intl.RelativeTimeFormat(lng, {
1575
2069
  ...opt
1576
2070
  });
1577
2071
  return val => formatter.format(val, opt.range || 'day');
1578
2072
  }),
1579
- list: cf((lng, opt) => {
2073
+ list: createCachedFormatter((lng, opt) => {
1580
2074
  const formatter = new Intl.ListFormat(lng, {
1581
2075
  ...opt
1582
2076
  });
1583
2077
  return val => formatter.format(val);
1584
2078
  })
1585
2079
  };
2080
+ this.init(options);
2081
+ }
2082
+ init(services) {
2083
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
2084
+ interpolation: {}
2085
+ };
2086
+ this.formatSeparator = options.interpolation.formatSeparator || ',';
1586
2087
  }
1587
2088
  add(name, fc) {
1588
2089
  this.formats[name.toLowerCase().trim()] = fc;
@@ -1590,7 +2091,8 @@ class Formatter {
1590
2091
  addCached(name, fc) {
1591
2092
  this.formats[name.toLowerCase().trim()] = createCachedFormatter(fc);
1592
2093
  }
1593
- format(value, format, lng, options = {}) {
2094
+ format(value, format, lng) {
2095
+ let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
1594
2096
  const formats = format.split(this.formatSeparator);
1595
2097
  if (formats.length > 1 && formats[0].indexOf('(') > 1 && formats[0].indexOf(')') < 0 && formats.find(f => f.indexOf(')') > -1)) {
1596
2098
  const lastIndex = formats.findIndex(f => f.indexOf(')') > -1);
@@ -1604,7 +2106,7 @@ class Formatter {
1604
2106
  if (this.formats[formatName]) {
1605
2107
  let formatted = mem;
1606
2108
  try {
1607
- const valOptions = options?.formatParams?.[options.interpolationkey] || {};
2109
+ const valOptions = options && options.formatParams && options.formatParams[options.interpolationkey] || {};
1608
2110
  const l = valOptions.locale || valOptions.lng || options.locale || options.lng || lng;
1609
2111
  formatted = this.formats[formatName](mem, l, {
1610
2112
  ...formatOptions,
@@ -1631,7 +2133,8 @@ const removePending = (q, name) => {
1631
2133
  }
1632
2134
  };
1633
2135
  class Connector extends EventEmitter {
1634
- constructor(backend, store, services, options = {}) {
2136
+ constructor(backend, store, services) {
2137
+ let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
1635
2138
  super();
1636
2139
  this.backend = backend;
1637
2140
  this.store = store;
@@ -1646,7 +2149,9 @@ class Connector extends EventEmitter {
1646
2149
  this.retryTimeout = options.retryTimeout >= 1 ? options.retryTimeout : 350;
1647
2150
  this.state = {};
1648
2151
  this.queue = [];
1649
- this.backend?.init?.(services, options.backend, options);
2152
+ if (this.backend && this.backend.init) {
2153
+ this.backend.init(services, options.backend, options);
2154
+ }
1650
2155
  }
1651
2156
  queueLoad(languages, namespaces, options, callback) {
1652
2157
  const toLoad = {};
@@ -1725,7 +2230,10 @@ class Connector extends EventEmitter {
1725
2230
  this.emit('loaded', loaded);
1726
2231
  this.queue = this.queue.filter(q => !q.done);
1727
2232
  }
1728
- read(lng, ns, fcName, tried = 0, wait = this.retryTimeout, callback) {
2233
+ read(lng, ns, fcName) {
2234
+ let tried = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
2235
+ let wait = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : this.retryTimeout;
2236
+ let callback = arguments.length > 5 ? arguments[5] : undefined;
1729
2237
  if (!lng.length) return callback(null, {});
1730
2238
  if (this.readingCalls >= this.maxParallelReads) {
1731
2239
  this.waitingReads.push({
@@ -1769,7 +2277,9 @@ class Connector extends EventEmitter {
1769
2277
  }
1770
2278
  return fc(lng, ns, resolver);
1771
2279
  }
1772
- prepareLoading(languages, namespaces, options = {}, callback) {
2280
+ prepareLoading(languages, namespaces) {
2281
+ let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
2282
+ let callback = arguments.length > 3 ? arguments[3] : undefined;
1773
2283
  if (!this.backend) {
1774
2284
  this.logger.warn('No backend was added via i18next.use. Will not load resources.');
1775
2285
  return callback && callback();
@@ -1793,7 +2303,8 @@ class Connector extends EventEmitter {
1793
2303
  reload: true
1794
2304
  }, callback);
1795
2305
  }
1796
- loadOne(name, prefix = '') {
2306
+ loadOne(name) {
2307
+ let prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
1797
2308
  const s = name.split('|');
1798
2309
  const lng = s[0];
1799
2310
  const ns = s[1];
@@ -1803,13 +2314,15 @@ class Connector extends EventEmitter {
1803
2314
  this.loaded(name, err, data);
1804
2315
  });
1805
2316
  }
1806
- saveMissing(languages, namespace, key, fallbackValue, isUpdate, options = {}, clb = () => {}) {
1807
- if (this.services?.utils?.hasLoadedNamespace && !this.services?.utils?.hasLoadedNamespace(namespace)) {
2317
+ saveMissing(languages, namespace, key, fallbackValue, isUpdate) {
2318
+ let options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
2319
+ let clb = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : () => {};
2320
+ if (this.services.utils && this.services.utils.hasLoadedNamespace && !this.services.utils.hasLoadedNamespace(namespace)) {
1808
2321
  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!!!');
1809
2322
  return;
1810
2323
  }
1811
2324
  if (key === undefined || key === null || key === '') return;
1812
- if (this.backend?.create) {
2325
+ if (this.backend && this.backend.create) {
1813
2326
  const opts = {
1814
2327
  ...options,
1815
2328
  isUpdate
@@ -1842,7 +2355,7 @@ class Connector extends EventEmitter {
1842
2355
 
1843
2356
  const get = () => ({
1844
2357
  debug: false,
1845
- initAsync: true,
2358
+ initImmediate: true,
1846
2359
  ns: ['translation'],
1847
2360
  defaultNS: ['translation'],
1848
2361
  fallbackLng: ['dev'],
@@ -1898,17 +2411,15 @@ const get = () => ({
1898
2411
  nestingOptionsSeparator: ',',
1899
2412
  maxReplaces: 1000,
1900
2413
  skipOnVariables: true
1901
- },
1902
- cacheInBuiltFormats: true
2414
+ }
1903
2415
  });
1904
2416
  const transformOptions = options => {
1905
2417
  if (isString(options.ns)) options.ns = [options.ns];
1906
2418
  if (isString(options.fallbackLng)) options.fallbackLng = [options.fallbackLng];
1907
2419
  if (isString(options.fallbackNS)) options.fallbackNS = [options.fallbackNS];
1908
- if (options.supportedLngs?.indexOf?.('cimode') < 0) {
2420
+ if (options.supportedLngs && options.supportedLngs.indexOf('cimode') < 0) {
1909
2421
  options.supportedLngs = options.supportedLngs.concat(['cimode']);
1910
2422
  }
1911
- if (typeof options.initImmediate === 'boolean') options.initAsync = options.initImmediate;
1912
2423
  return options;
1913
2424
  };
1914
2425
 
@@ -1921,17 +2432,10 @@ const bindMemberFunctions = inst => {
1921
2432
  }
1922
2433
  });
1923
2434
  };
1924
- let supportNoticeShown = false;
1925
- const usesLocize = inst => {
1926
- if (inst?.modules?.backend?.name?.indexOf('Locize') > 0) return true;
1927
- if (inst?.modules?.backend?.constructor?.name?.indexOf('Locize') > 0) return true;
1928
- if (inst?.options?.backend?.backends) {
1929
- if (inst.options.backend.backends.some(b => b?.name?.indexOf('Locize') > 0 || b?.constructor?.name?.indexOf('Locize') > 0)) return true;
1930
- }
1931
- return false;
1932
- };
1933
2435
  class I18n extends EventEmitter {
1934
- constructor(options = {}, callback) {
2436
+ constructor() {
2437
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2438
+ let callback = arguments.length > 1 ? arguments[1] : undefined;
1935
2439
  super();
1936
2440
  this.options = transformOptions(options);
1937
2441
  this.services = {};
@@ -1941,7 +2445,7 @@ class I18n extends EventEmitter {
1941
2445
  };
1942
2446
  bindMemberFunctions(this);
1943
2447
  if (callback && !this.isInitialized && !options.isClone) {
1944
- if (!this.options.initAsync) {
2448
+ if (!this.options.initImmediate) {
1945
2449
  this.init(options, callback);
1946
2450
  return this;
1947
2451
  }
@@ -1950,13 +2454,16 @@ class I18n extends EventEmitter {
1950
2454
  }, 0);
1951
2455
  }
1952
2456
  }
1953
- init(options = {}, callback) {
2457
+ init() {
2458
+ var _this = this;
2459
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2460
+ let callback = arguments.length > 1 ? arguments[1] : undefined;
1954
2461
  this.isInitializing = true;
1955
2462
  if (typeof options === 'function') {
1956
2463
  callback = options;
1957
2464
  options = {};
1958
2465
  }
1959
- if (options.defaultNS == null && options.ns) {
2466
+ if (!options.defaultNS && options.defaultNS !== false && options.ns) {
1960
2467
  if (isString(options.ns)) {
1961
2468
  options.defaultNS = options.ns;
1962
2469
  } else if (options.ns.indexOf('translation') < 0) {
@@ -1969,23 +2476,18 @@ class I18n extends EventEmitter {
1969
2476
  ...this.options,
1970
2477
  ...transformOptions(options)
1971
2478
  };
1972
- this.options.interpolation = {
1973
- ...defOpts.interpolation,
1974
- ...this.options.interpolation
1975
- };
2479
+ if (this.options.compatibilityAPI !== 'v1') {
2480
+ this.options.interpolation = {
2481
+ ...defOpts.interpolation,
2482
+ ...this.options.interpolation
2483
+ };
2484
+ }
1976
2485
  if (options.keySeparator !== undefined) {
1977
2486
  this.options.userDefinedKeySeparator = options.keySeparator;
1978
2487
  }
1979
2488
  if (options.nsSeparator !== undefined) {
1980
2489
  this.options.userDefinedNsSeparator = options.nsSeparator;
1981
2490
  }
1982
- if (typeof this.options.overloadTranslationOptionHandler !== 'function') {
1983
- this.options.overloadTranslationOptionHandler = defOpts.overloadTranslationOptionHandler;
1984
- }
1985
- if (this.options.showSupportNotice !== false && !usesLocize(this) && !supportNoticeShown) {
1986
- if (typeof console !== 'undefined' && typeof console.info !== 'undefined') console.info('🌐 i18next is maintained with support from Locize — consider powering your project with managed localization (AI, CDN, integrations): https://locize.com 💙');
1987
- supportNoticeShown = true;
1988
- }
1989
2491
  const createClassOnDemand = ClassOrObject => {
1990
2492
  if (!ClassOrObject) return null;
1991
2493
  if (typeof ClassOrObject === 'function') return new ClassOrObject();
@@ -2000,7 +2502,7 @@ class I18n extends EventEmitter {
2000
2502
  let formatter;
2001
2503
  if (this.modules.formatter) {
2002
2504
  formatter = this.modules.formatter;
2003
- } else {
2505
+ } else if (typeof Intl !== 'undefined') {
2004
2506
  formatter = Formatter;
2005
2507
  }
2006
2508
  const lu = new LanguageUtil(this.options);
@@ -2011,15 +2513,12 @@ class I18n extends EventEmitter {
2011
2513
  s.languageUtils = lu;
2012
2514
  s.pluralResolver = new PluralResolver(lu, {
2013
2515
  prepend: this.options.pluralSeparator,
2516
+ compatibilityJSON: this.options.compatibilityJSON,
2014
2517
  simplifyPluralSuffix: this.options.simplifyPluralSuffix
2015
2518
  });
2016
- const usingLegacyFormatFunction = this.options.interpolation.format && this.options.interpolation.format !== defOpts.interpolation.format;
2017
- if (usingLegacyFormatFunction) {
2018
- this.logger.deprecate(`init: you are still using the legacy format function, please use the new approach: https://www.i18next.com/translation-function/formatting`);
2019
- }
2020
2519
  if (formatter && (!this.options.interpolation.format || this.options.interpolation.format === defOpts.interpolation.format)) {
2021
2520
  s.formatter = createClassOnDemand(formatter);
2022
- if (s.formatter.init) s.formatter.init(s, this.options);
2521
+ s.formatter.init(s, this.options);
2023
2522
  this.options.interpolation.format = s.formatter.format.bind(s.formatter);
2024
2523
  }
2025
2524
  s.interpolator = new Interpolator(this.options);
@@ -2027,8 +2526,11 @@ class I18n extends EventEmitter {
2027
2526
  hasLoadedNamespace: this.hasLoadedNamespace.bind(this)
2028
2527
  };
2029
2528
  s.backendConnector = new Connector(createClassOnDemand(this.modules.backend), s.resourceStore, s, this.options);
2030
- s.backendConnector.on('*', (event, ...args) => {
2031
- this.emit(event, ...args);
2529
+ s.backendConnector.on('*', function (event) {
2530
+ for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
2531
+ args[_key - 1] = arguments[_key];
2532
+ }
2533
+ _this.emit(event, ...args);
2032
2534
  });
2033
2535
  if (this.modules.languageDetector) {
2034
2536
  s.languageDetector = createClassOnDemand(this.modules.languageDetector);
@@ -2039,8 +2541,11 @@ class I18n extends EventEmitter {
2039
2541
  if (s.i18nFormat.init) s.i18nFormat.init(this);
2040
2542
  }
2041
2543
  this.translator = new Translator(this.services, this.options);
2042
- this.translator.on('*', (event, ...args) => {
2043
- this.emit(event, ...args);
2544
+ this.translator.on('*', function (event) {
2545
+ for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
2546
+ args[_key2 - 1] = arguments[_key2];
2547
+ }
2548
+ _this.emit(event, ...args);
2044
2549
  });
2045
2550
  this.modules.external.forEach(m => {
2046
2551
  if (m.init) m.init(this);
@@ -2057,13 +2562,15 @@ class I18n extends EventEmitter {
2057
2562
  }
2058
2563
  const storeApi = ['getResource', 'hasResourceBundle', 'getResourceBundle', 'getDataByLanguage'];
2059
2564
  storeApi.forEach(fcName => {
2060
- this[fcName] = (...args) => this.store[fcName](...args);
2565
+ this[fcName] = function () {
2566
+ return _this.store[fcName](...arguments);
2567
+ };
2061
2568
  });
2062
2569
  const storeApiChained = ['addResource', 'addResources', 'addResourceBundle', 'removeResourceBundle'];
2063
2570
  storeApiChained.forEach(fcName => {
2064
- this[fcName] = (...args) => {
2065
- this.store[fcName](...args);
2066
- return this;
2571
+ this[fcName] = function () {
2572
+ _this.store[fcName](...arguments);
2573
+ return _this;
2067
2574
  };
2068
2575
  });
2069
2576
  const deferred = defer();
@@ -2077,22 +2584,23 @@ class I18n extends EventEmitter {
2077
2584
  deferred.resolve(t);
2078
2585
  callback(err, t);
2079
2586
  };
2080
- if (this.languages && !this.isInitialized) return finish(null, this.t.bind(this));
2587
+ if (this.languages && this.options.compatibilityAPI !== 'v1' && !this.isInitialized) return finish(null, this.t.bind(this));
2081
2588
  this.changeLanguage(this.options.lng, finish);
2082
2589
  };
2083
- if (this.options.resources || !this.options.initAsync) {
2590
+ if (this.options.resources || !this.options.initImmediate) {
2084
2591
  load();
2085
2592
  } else {
2086
2593
  setTimeout(load, 0);
2087
2594
  }
2088
2595
  return deferred;
2089
2596
  }
2090
- loadResources(language, callback = noop) {
2597
+ loadResources(language) {
2598
+ let callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop;
2091
2599
  let usedCallback = callback;
2092
2600
  const usedLng = isString(language) ? language : this.language;
2093
2601
  if (typeof language === 'function') usedCallback = language;
2094
2602
  if (!this.options.resources || this.options.partialBundledLanguages) {
2095
- if (usedLng?.toLowerCase() === 'cimode' && (!this.options.preload || this.options.preload.length === 0)) return usedCallback();
2603
+ if (usedLng && usedLng.toLowerCase() === 'cimode' && (!this.options.preload || this.options.preload.length === 0)) return usedCallback();
2096
2604
  const toLoad = [];
2097
2605
  const append = lng => {
2098
2606
  if (!lng) return;
@@ -2109,7 +2617,9 @@ class I18n extends EventEmitter {
2109
2617
  } else {
2110
2618
  append(usedLng);
2111
2619
  }
2112
- this.options.preload?.forEach?.(l => append(l));
2620
+ if (this.options.preload) {
2621
+ this.options.preload.forEach(l => append(l));
2622
+ }
2113
2623
  this.services.backendConnector.load(toLoad, this.options.ns, e => {
2114
2624
  if (!e && !this.resolvedLanguage && this.language) this.setResolvedLanguage(this.language);
2115
2625
  usedCallback(e);
@@ -2174,542 +2684,249 @@ class I18n extends EventEmitter {
2174
2684
  break;
2175
2685
  }
2176
2686
  }
2177
- if (!this.resolvedLanguage && this.languages.indexOf(l) < 0 && this.store.hasLanguageSomeTranslations(l)) {
2178
- this.resolvedLanguage = l;
2179
- this.languages.unshift(l);
2180
- }
2181
2687
  }
2182
2688
  changeLanguage(lng, callback) {
2689
+ var _this2 = this;
2183
2690
  this.isLanguageChangingTo = lng;
2184
2691
  const deferred = defer();
2185
2692
  this.emit('languageChanging', lng);
2186
- const setLngProps = l => {
2187
- this.language = l;
2188
- this.languages = this.services.languageUtils.toResolveHierarchy(l);
2189
- this.resolvedLanguage = undefined;
2190
- this.setResolvedLanguage(l);
2191
- };
2192
- const done = (err, l) => {
2193
- if (l) {
2194
- if (this.isLanguageChangingTo === lng) {
2195
- setLngProps(l);
2196
- this.translator.changeLanguage(l);
2197
- this.isLanguageChangingTo = undefined;
2198
- this.emit('languageChanged', l);
2199
- this.logger.log('languageChanged', l);
2200
- }
2201
- } else {
2202
- this.isLanguageChangingTo = undefined;
2203
- }
2204
- deferred.resolve((...args) => this.t(...args));
2205
- if (callback) callback(err, (...args) => this.t(...args));
2206
- };
2207
- const setLng = lngs => {
2208
- if (!lng && !lngs && this.services.languageDetector) lngs = [];
2209
- const fl = isString(lngs) ? lngs : lngs && lngs[0];
2210
- const l = this.store.hasLanguageSomeTranslations(fl) ? fl : this.services.languageUtils.getBestMatchFromCodes(isString(lngs) ? [lngs] : lngs);
2211
- if (l) {
2212
- if (!this.language) {
2213
- setLngProps(l);
2214
- }
2215
- if (!this.translator.language) this.translator.changeLanguage(l);
2216
- this.services.languageDetector?.cacheUserLanguage?.(l);
2217
- }
2218
- this.loadResources(l, err => {
2219
- done(err, l);
2220
- });
2221
- };
2222
- if (!lng && this.services.languageDetector && !this.services.languageDetector.async) {
2223
- setLng(this.services.languageDetector.detect());
2224
- } else if (!lng && this.services.languageDetector && this.services.languageDetector.async) {
2225
- if (this.services.languageDetector.detect.length === 0) {
2226
- this.services.languageDetector.detect().then(setLng);
2227
- } else {
2228
- this.services.languageDetector.detect(setLng);
2229
- }
2230
- } else {
2231
- setLng(lng);
2232
- }
2233
- return deferred;
2234
- }
2235
- getFixedT(lng, ns, keyPrefix) {
2236
- const fixedT = (key, opts, ...rest) => {
2237
- let o;
2238
- if (typeof opts !== 'object') {
2239
- o = this.options.overloadTranslationOptionHandler([key, opts].concat(rest));
2240
- } else {
2241
- o = {
2242
- ...opts
2243
- };
2244
- }
2245
- o.lng = o.lng || fixedT.lng;
2246
- o.lngs = o.lngs || fixedT.lngs;
2247
- o.ns = o.ns || fixedT.ns;
2248
- if (o.keyPrefix !== '') o.keyPrefix = o.keyPrefix || keyPrefix || fixedT.keyPrefix;
2249
- const keySeparator = this.options.keySeparator || '.';
2250
- let resultKey;
2251
- if (o.keyPrefix && Array.isArray(key)) {
2252
- resultKey = key.map(k => {
2253
- if (typeof k === 'function') k = keysFromSelector(k, {
2254
- ...this.options,
2255
- ...opts
2256
- });
2257
- return `${o.keyPrefix}${keySeparator}${k}`;
2258
- });
2259
- } else {
2260
- if (typeof key === 'function') key = keysFromSelector(key, {
2261
- ...this.options,
2262
- ...opts
2263
- });
2264
- resultKey = o.keyPrefix ? `${o.keyPrefix}${keySeparator}${key}` : key;
2265
- }
2266
- return this.t(resultKey, o);
2267
- };
2268
- if (isString(lng)) {
2269
- fixedT.lng = lng;
2270
- } else {
2271
- fixedT.lngs = lng;
2272
- }
2273
- fixedT.ns = ns;
2274
- fixedT.keyPrefix = keyPrefix;
2275
- return fixedT;
2276
- }
2277
- t(...args) {
2278
- return this.translator?.translate(...args);
2279
- }
2280
- exists(...args) {
2281
- return this.translator?.exists(...args);
2282
- }
2283
- setDefaultNamespace(ns) {
2284
- this.options.defaultNS = ns;
2285
- }
2286
- hasLoadedNamespace(ns, options = {}) {
2287
- if (!this.isInitialized) {
2288
- this.logger.warn('hasLoadedNamespace: i18next was not initialized', this.languages);
2289
- return false;
2290
- }
2291
- if (!this.languages || !this.languages.length) {
2292
- this.logger.warn('hasLoadedNamespace: i18n.languages were undefined or empty', this.languages);
2293
- return false;
2294
- }
2295
- const lng = options.lng || this.resolvedLanguage || this.languages[0];
2296
- const fallbackLng = this.options ? this.options.fallbackLng : false;
2297
- const lastLng = this.languages[this.languages.length - 1];
2298
- if (lng.toLowerCase() === 'cimode') return true;
2299
- const loadNotPending = (l, n) => {
2300
- const loadState = this.services.backendConnector.state[`${l}|${n}`];
2301
- return loadState === -1 || loadState === 0 || loadState === 2;
2302
- };
2303
- if (options.precheck) {
2304
- const preResult = options.precheck(this, loadNotPending);
2305
- if (preResult !== undefined) return preResult;
2306
- }
2307
- if (this.hasResourceBundle(lng, ns)) return true;
2308
- if (!this.services.backendConnector.backend || this.options.resources && !this.options.partialBundledLanguages) return true;
2309
- if (loadNotPending(lng, ns) && (!fallbackLng || loadNotPending(lastLng, ns))) return true;
2310
- return false;
2311
- }
2312
- loadNamespaces(ns, callback) {
2313
- const deferred = defer();
2314
- if (!this.options.ns) {
2315
- if (callback) callback();
2316
- return Promise.resolve();
2317
- }
2318
- if (isString(ns)) ns = [ns];
2319
- ns.forEach(n => {
2320
- if (this.options.ns.indexOf(n) < 0) this.options.ns.push(n);
2321
- });
2322
- this.loadResources(err => {
2323
- deferred.resolve();
2324
- if (callback) callback(err);
2325
- });
2326
- return deferred;
2327
- }
2328
- loadLanguages(lngs, callback) {
2329
- const deferred = defer();
2330
- if (isString(lngs)) lngs = [lngs];
2331
- const preloaded = this.options.preload || [];
2332
- const newLngs = lngs.filter(lng => preloaded.indexOf(lng) < 0 && this.services.languageUtils.isSupportedCode(lng));
2333
- if (!newLngs.length) {
2334
- if (callback) callback();
2335
- return Promise.resolve();
2336
- }
2337
- this.options.preload = preloaded.concat(newLngs);
2338
- this.loadResources(err => {
2339
- deferred.resolve();
2340
- if (callback) callback(err);
2341
- });
2342
- return deferred;
2343
- }
2344
- dir(lng) {
2345
- if (!lng) lng = this.resolvedLanguage || (this.languages?.length > 0 ? this.languages[0] : this.language);
2346
- if (!lng) return 'rtl';
2347
- try {
2348
- const l = new Intl.Locale(lng);
2349
- if (l && l.getTextInfo) {
2350
- const ti = l.getTextInfo();
2351
- if (ti && ti.direction) return ti.direction;
2352
- }
2353
- } catch (e) {}
2354
- 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'];
2355
- const languageUtils = this.services?.languageUtils || new LanguageUtil(get());
2356
- if (lng.toLowerCase().indexOf('-latn') > 1) return 'ltr';
2357
- return rtlLngs.indexOf(languageUtils.getLanguagePartFromCode(lng)) > -1 || lng.toLowerCase().indexOf('-arab') > 1 ? 'rtl' : 'ltr';
2358
- }
2359
- static createInstance(options = {}, callback) {
2360
- const instance = new I18n(options, callback);
2361
- instance.createInstance = I18n.createInstance;
2362
- return instance;
2363
- }
2364
- cloneInstance(options = {}, callback = noop) {
2365
- const forkResourceStore = options.forkResourceStore;
2366
- if (forkResourceStore) delete options.forkResourceStore;
2367
- const mergedOptions = {
2368
- ...this.options,
2369
- ...options,
2370
- ...{
2371
- isClone: true
2372
- }
2693
+ const setLngProps = l => {
2694
+ this.language = l;
2695
+ this.languages = this.services.languageUtils.toResolveHierarchy(l);
2696
+ this.resolvedLanguage = undefined;
2697
+ this.setResolvedLanguage(l);
2373
2698
  };
2374
- const clone = new I18n(mergedOptions);
2375
- if (options.debug !== undefined || options.prefix !== undefined) {
2376
- clone.logger = clone.logger.clone(options);
2377
- }
2378
- const membersToCopy = ['store', 'services', 'language'];
2379
- membersToCopy.forEach(m => {
2380
- clone[m] = this[m];
2381
- });
2382
- clone.services = {
2383
- ...this.services
2699
+ const done = (err, l) => {
2700
+ if (l) {
2701
+ setLngProps(l);
2702
+ this.translator.changeLanguage(l);
2703
+ this.isLanguageChangingTo = undefined;
2704
+ this.emit('languageChanged', l);
2705
+ this.logger.log('languageChanged', l);
2706
+ } else {
2707
+ this.isLanguageChangingTo = undefined;
2708
+ }
2709
+ deferred.resolve(function () {
2710
+ return _this2.t(...arguments);
2711
+ });
2712
+ if (callback) callback(err, function () {
2713
+ return _this2.t(...arguments);
2714
+ });
2384
2715
  };
2385
- clone.services.utils = {
2386
- hasLoadedNamespace: clone.hasLoadedNamespace.bind(clone)
2716
+ const setLng = lngs => {
2717
+ if (!lng && !lngs && this.services.languageDetector) lngs = [];
2718
+ const l = isString(lngs) ? lngs : this.services.languageUtils.getBestMatchFromCodes(lngs);
2719
+ if (l) {
2720
+ if (!this.language) {
2721
+ setLngProps(l);
2722
+ }
2723
+ if (!this.translator.language) this.translator.changeLanguage(l);
2724
+ if (this.services.languageDetector && this.services.languageDetector.cacheUserLanguage) this.services.languageDetector.cacheUserLanguage(l);
2725
+ }
2726
+ this.loadResources(l, err => {
2727
+ done(err, l);
2728
+ });
2387
2729
  };
2388
- if (forkResourceStore) {
2389
- const clonedData = Object.keys(this.store.data).reduce((prev, l) => {
2390
- prev[l] = {
2391
- ...this.store.data[l]
2392
- };
2393
- prev[l] = Object.keys(prev[l]).reduce((acc, n) => {
2394
- acc[n] = {
2395
- ...prev[l][n]
2396
- };
2397
- return acc;
2398
- }, prev[l]);
2399
- return prev;
2400
- }, {});
2401
- clone.store = new ResourceStore(clonedData, mergedOptions);
2402
- clone.services.resourceStore = clone.store;
2403
- }
2404
- if (options.interpolation) {
2405
- const defOpts = get();
2406
- const mergedInterpolation = {
2407
- ...defOpts.interpolation,
2408
- ...this.options.interpolation,
2409
- ...options.interpolation
2410
- };
2411
- const mergedForInterpolator = {
2412
- ...mergedOptions,
2413
- interpolation: mergedInterpolation
2414
- };
2415
- clone.services.interpolator = new Interpolator(mergedForInterpolator);
2730
+ if (!lng && this.services.languageDetector && !this.services.languageDetector.async) {
2731
+ setLng(this.services.languageDetector.detect());
2732
+ } else if (!lng && this.services.languageDetector && this.services.languageDetector.async) {
2733
+ if (this.services.languageDetector.detect.length === 0) {
2734
+ this.services.languageDetector.detect().then(setLng);
2735
+ } else {
2736
+ this.services.languageDetector.detect(setLng);
2737
+ }
2738
+ } else {
2739
+ setLng(lng);
2416
2740
  }
2417
- clone.translator = new Translator(clone.services, mergedOptions);
2418
- clone.translator.on('*', (event, ...args) => {
2419
- clone.emit(event, ...args);
2420
- });
2421
- clone.init(mergedOptions, callback);
2422
- clone.translator.options = mergedOptions;
2423
- clone.translator.backendConnector.services.utils = {
2424
- hasLoadedNamespace: clone.hasLoadedNamespace.bind(clone)
2425
- };
2426
- return clone;
2741
+ return deferred;
2427
2742
  }
2428
- toJSON() {
2429
- return {
2430
- options: this.options,
2431
- store: this.store,
2432
- language: this.language,
2433
- languages: this.languages,
2434
- resolvedLanguage: this.resolvedLanguage
2743
+ getFixedT(lng, ns, keyPrefix) {
2744
+ var _this3 = this;
2745
+ const fixedT = function (key, opts) {
2746
+ let options;
2747
+ if (typeof opts !== 'object') {
2748
+ for (var _len3 = arguments.length, rest = new Array(_len3 > 2 ? _len3 - 2 : 0), _key3 = 2; _key3 < _len3; _key3++) {
2749
+ rest[_key3 - 2] = arguments[_key3];
2750
+ }
2751
+ options = _this3.options.overloadTranslationOptionHandler([key, opts].concat(rest));
2752
+ } else {
2753
+ options = {
2754
+ ...opts
2755
+ };
2756
+ }
2757
+ options.lng = options.lng || fixedT.lng;
2758
+ options.lngs = options.lngs || fixedT.lngs;
2759
+ options.ns = options.ns || fixedT.ns;
2760
+ if (options.keyPrefix !== '') options.keyPrefix = options.keyPrefix || keyPrefix || fixedT.keyPrefix;
2761
+ const keySeparator = _this3.options.keySeparator || '.';
2762
+ let resultKey;
2763
+ if (options.keyPrefix && Array.isArray(key)) {
2764
+ resultKey = key.map(k => `${options.keyPrefix}${keySeparator}${k}`);
2765
+ } else {
2766
+ resultKey = options.keyPrefix ? `${options.keyPrefix}${keySeparator}${key}` : key;
2767
+ }
2768
+ return _this3.t(resultKey, options);
2435
2769
  };
2436
- }
2437
- }
2438
- const instance = I18n.createInstance();
2439
-
2440
- instance.createInstance;
2441
- instance.dir;
2442
- instance.init;
2443
- instance.loadResources;
2444
- instance.reloadResources;
2445
- instance.use;
2446
- instance.changeLanguage;
2447
- instance.getFixedT;
2448
- instance.t;
2449
- instance.exists;
2450
- instance.setDefaultNamespace;
2451
- instance.hasLoadedNamespace;
2452
- instance.loadNamespaces;
2453
- instance.loadLanguages;
2454
-
2455
- function warn() {
2456
- if (console && console.warn) {
2457
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
2458
- args[_key] = arguments[_key];
2770
+ if (isString(lng)) {
2771
+ fixedT.lng = lng;
2772
+ } else {
2773
+ fixedT.lngs = lng;
2459
2774
  }
2460
- if (typeof args[0] === 'string') args[0] = `react-i18next:: ${args[0]}`;
2461
- console.warn(...args);
2462
- }
2463
- }
2464
- const alreadyWarned = {};
2465
- function warnOnce() {
2466
- for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
2467
- args[_key2] = arguments[_key2];
2775
+ fixedT.ns = ns;
2776
+ fixedT.keyPrefix = keyPrefix;
2777
+ return fixedT;
2468
2778
  }
2469
- if (typeof args[0] === 'string' && alreadyWarned[args[0]]) return;
2470
- if (typeof args[0] === 'string') alreadyWarned[args[0]] = new Date();
2471
- warn(...args);
2472
- }
2473
- const loadedClb = (i18n, cb) => () => {
2474
- if (i18n.isInitialized) {
2475
- cb();
2476
- } else {
2477
- const initialized = () => {
2478
- setTimeout(() => {
2479
- i18n.off('initialized', initialized);
2480
- }, 0);
2481
- cb();
2482
- };
2483
- i18n.on('initialized', initialized);
2779
+ t() {
2780
+ return this.translator && this.translator.translate(...arguments);
2484
2781
  }
2485
- };
2486
- function loadNamespaces(i18n, ns, cb) {
2487
- i18n.loadNamespaces(ns, loadedClb(i18n, cb));
2488
- }
2489
- function loadLanguages(i18n, lng, ns, cb) {
2490
- if (typeof ns === 'string') ns = [ns];
2491
- ns.forEach(n => {
2492
- if (i18n.options.ns.indexOf(n) < 0) i18n.options.ns.push(n);
2493
- });
2494
- i18n.loadLanguages(lng, loadedClb(i18n, cb));
2495
- }
2496
- function oldI18nextHasLoadedNamespace(ns, i18n) {
2497
- let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
2498
- const lng = i18n.languages[0];
2499
- const fallbackLng = i18n.options ? i18n.options.fallbackLng : false;
2500
- const lastLng = i18n.languages[i18n.languages.length - 1];
2501
- if (lng.toLowerCase() === 'cimode') return true;
2502
- const loadNotPending = (l, n) => {
2503
- const loadState = i18n.services.backendConnector.state[`${l}|${n}`];
2504
- return loadState === -1 || loadState === 2;
2505
- };
2506
- if (options.bindI18n && options.bindI18n.indexOf('languageChanging') > -1 && i18n.services.backendConnector.backend && i18n.isLanguageChangingTo && !loadNotPending(i18n.isLanguageChangingTo, ns)) return false;
2507
- if (i18n.hasResourceBundle(lng, ns)) return true;
2508
- if (!i18n.services.backendConnector.backend || i18n.options.resources && !i18n.options.partialBundledLanguages) return true;
2509
- if (loadNotPending(lng, ns) && (!fallbackLng || loadNotPending(lastLng, ns))) return true;
2510
- return false;
2511
- }
2512
- function hasLoadedNamespace(ns, i18n) {
2513
- let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
2514
- if (!i18n.languages || !i18n.languages.length) {
2515
- warnOnce('i18n.languages were undefined or empty', i18n.languages);
2516
- return true;
2782
+ exists() {
2783
+ return this.translator && this.translator.exists(...arguments);
2517
2784
  }
2518
- const isNewerI18next = i18n.options.ignoreJSONStructure !== undefined;
2519
- if (!isNewerI18next) {
2520
- return oldI18nextHasLoadedNamespace(ns, i18n, options);
2785
+ setDefaultNamespace(ns) {
2786
+ this.options.defaultNS = ns;
2521
2787
  }
2522
- return i18n.hasLoadedNamespace(ns, {
2523
- lng: options.lng,
2524
- precheck: (i18nInstance, loadNotPending) => {
2525
- if (options.bindI18n && options.bindI18n.indexOf('languageChanging') > -1 && i18nInstance.services.backendConnector.backend && i18nInstance.isLanguageChangingTo && !loadNotPending(i18nInstance.isLanguageChangingTo, ns)) return false;
2788
+ hasLoadedNamespace(ns) {
2789
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
2790
+ if (!this.isInitialized) {
2791
+ this.logger.warn('hasLoadedNamespace: i18next was not initialized', this.languages);
2792
+ return false;
2526
2793
  }
2527
- });
2528
- }
2529
-
2530
- const matchHtmlEntity = /&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34|nbsp|#160|copy|#169|reg|#174|hellip|#8230|#x2F|#47);/g;
2531
- const htmlEntities = {
2532
- '&amp;': '&',
2533
- '&#38;': '&',
2534
- '&lt;': '<',
2535
- '&#60;': '<',
2536
- '&gt;': '>',
2537
- '&#62;': '>',
2538
- '&apos;': "'",
2539
- '&#39;': "'",
2540
- '&quot;': '"',
2541
- '&#34;': '"',
2542
- '&nbsp;': ' ',
2543
- '&#160;': ' ',
2544
- '&copy;': '©',
2545
- '&#169;': '©',
2546
- '&reg;': '®',
2547
- '&#174;': '®',
2548
- '&hellip;': '…',
2549
- '&#8230;': '…',
2550
- '&#x2F;': '/',
2551
- '&#47;': '/'
2552
- };
2553
- const unescapeHtmlEntity = m => htmlEntities[m];
2554
- const unescape = text => text.replace(matchHtmlEntity, unescapeHtmlEntity);
2555
-
2556
- let defaultOptions$1 = {
2557
- bindI18n: 'languageChanged',
2558
- bindI18nStore: '',
2559
- transEmptyNodeValue: '',
2560
- transSupportBasicHtmlNodes: true,
2561
- transWrapTextNodes: '',
2562
- transKeepBasicHtmlNodesFor: ['br', 'strong', 'i', 'p'],
2563
- useSuspense: true,
2564
- unescape
2565
- };
2566
- function setDefaults() {
2567
- let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2568
- defaultOptions$1 = {
2569
- ...defaultOptions$1,
2570
- ...options
2571
- };
2572
- }
2573
- function getDefaults() {
2574
- return defaultOptions$1;
2575
- }
2576
-
2577
- let i18nInstance;
2578
- function setI18n(instance) {
2579
- i18nInstance = instance;
2580
- }
2581
- function getI18n() {
2582
- return i18nInstance;
2583
- }
2584
-
2585
- const initReactI18next = {
2586
- type: '3rdParty',
2587
- init(instance) {
2588
- setDefaults(instance.options.react);
2589
- setI18n(instance);
2590
- }
2591
- };
2592
-
2593
- const I18nContext = createContext();
2594
- class ReportNamespaces {
2595
- constructor() {
2596
- this.usedNamespaces = {};
2794
+ if (!this.languages || !this.languages.length) {
2795
+ this.logger.warn('hasLoadedNamespace: i18n.languages were undefined or empty', this.languages);
2796
+ return false;
2797
+ }
2798
+ const lng = options.lng || this.resolvedLanguage || this.languages[0];
2799
+ const fallbackLng = this.options ? this.options.fallbackLng : false;
2800
+ const lastLng = this.languages[this.languages.length - 1];
2801
+ if (lng.toLowerCase() === 'cimode') return true;
2802
+ const loadNotPending = (l, n) => {
2803
+ const loadState = this.services.backendConnector.state[`${l}|${n}`];
2804
+ return loadState === -1 || loadState === 0 || loadState === 2;
2805
+ };
2806
+ if (options.precheck) {
2807
+ const preResult = options.precheck(this, loadNotPending);
2808
+ if (preResult !== undefined) return preResult;
2809
+ }
2810
+ if (this.hasResourceBundle(lng, ns)) return true;
2811
+ if (!this.services.backendConnector.backend || this.options.resources && !this.options.partialBundledLanguages) return true;
2812
+ if (loadNotPending(lng, ns) && (!fallbackLng || loadNotPending(lastLng, ns))) return true;
2813
+ return false;
2597
2814
  }
2598
- addUsedNamespaces(namespaces) {
2599
- namespaces.forEach(ns => {
2600
- if (!this.usedNamespaces[ns]) this.usedNamespaces[ns] = true;
2815
+ loadNamespaces(ns, callback) {
2816
+ const deferred = defer();
2817
+ if (!this.options.ns) {
2818
+ if (callback) callback();
2819
+ return Promise.resolve();
2820
+ }
2821
+ if (isString(ns)) ns = [ns];
2822
+ ns.forEach(n => {
2823
+ if (this.options.ns.indexOf(n) < 0) this.options.ns.push(n);
2601
2824
  });
2825
+ this.loadResources(err => {
2826
+ deferred.resolve();
2827
+ if (callback) callback(err);
2828
+ });
2829
+ return deferred;
2602
2830
  }
2603
- getUsedNamespaces() {
2604
- return Object.keys(this.usedNamespaces);
2831
+ loadLanguages(lngs, callback) {
2832
+ const deferred = defer();
2833
+ if (isString(lngs)) lngs = [lngs];
2834
+ const preloaded = this.options.preload || [];
2835
+ const newLngs = lngs.filter(lng => preloaded.indexOf(lng) < 0 && this.services.languageUtils.isSupportedCode(lng));
2836
+ if (!newLngs.length) {
2837
+ if (callback) callback();
2838
+ return Promise.resolve();
2839
+ }
2840
+ this.options.preload = preloaded.concat(newLngs);
2841
+ this.loadResources(err => {
2842
+ deferred.resolve();
2843
+ if (callback) callback(err);
2844
+ });
2845
+ return deferred;
2605
2846
  }
2606
- }
2607
-
2608
- const usePrevious = (value, ignore) => {
2609
- const ref = useRef();
2610
- useEffect(() => {
2611
- ref.current = ignore ? ref.current : value;
2612
- }, [value, ignore]);
2613
- return ref.current;
2614
- };
2615
- function useTranslation(ns) {
2616
- let props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
2617
- const {
2618
- i18n: i18nFromProps
2619
- } = props;
2620
- const {
2621
- i18n: i18nFromContext,
2622
- defaultNS: defaultNSFromContext
2623
- } = useContext(I18nContext) || {};
2624
- const i18n = i18nFromProps || i18nFromContext || getI18n();
2625
- if (i18n && !i18n.reportNamespaces) i18n.reportNamespaces = new ReportNamespaces();
2626
- if (!i18n) {
2627
- warnOnce('You will need to pass in an i18next instance by using initReactI18next');
2628
- const notReadyT = (k, optsOrDefaultValue) => {
2629
- if (typeof optsOrDefaultValue === 'string') return optsOrDefaultValue;
2630
- if (optsOrDefaultValue && typeof optsOrDefaultValue === 'object' && typeof optsOrDefaultValue.defaultValue === 'string') return optsOrDefaultValue.defaultValue;
2631
- return Array.isArray(k) ? k[k.length - 1] : k;
2632
- };
2633
- const retNotReady = [notReadyT, {}, false];
2634
- retNotReady.t = notReadyT;
2635
- retNotReady.i18n = {};
2636
- retNotReady.ready = false;
2637
- return retNotReady;
2847
+ dir(lng) {
2848
+ if (!lng) lng = this.resolvedLanguage || (this.languages && this.languages.length > 0 ? this.languages[0] : this.language);
2849
+ if (!lng) return 'rtl';
2850
+ 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'];
2851
+ const languageUtils = this.services && this.services.languageUtils || new LanguageUtil(get());
2852
+ return rtlLngs.indexOf(languageUtils.getLanguagePartFromCode(lng)) > -1 || lng.toLowerCase().indexOf('-arab') > 1 ? 'rtl' : 'ltr';
2638
2853
  }
2639
- if (i18n.options.react && i18n.options.react.wait !== undefined) warnOnce('It seems you are still using the old wait option, you may migrate to the new useSuspense behaviour.');
2640
- const i18nOptions = {
2641
- ...getDefaults(),
2642
- ...i18n.options.react,
2643
- ...props
2644
- };
2645
- const {
2646
- useSuspense,
2647
- keyPrefix
2648
- } = i18nOptions;
2649
- let namespaces = ns || defaultNSFromContext || i18n.options && i18n.options.defaultNS;
2650
- namespaces = typeof namespaces === 'string' ? [namespaces] : namespaces || ['translation'];
2651
- if (i18n.reportNamespaces.addUsedNamespaces) i18n.reportNamespaces.addUsedNamespaces(namespaces);
2652
- const ready = (i18n.isInitialized || i18n.initializedStoreOnce) && namespaces.every(n => hasLoadedNamespace(n, i18n, i18nOptions));
2653
- function getT() {
2654
- return i18n.getFixedT(props.lng || null, i18nOptions.nsMode === 'fallback' ? namespaces : namespaces[0], keyPrefix);
2854
+ static createInstance() {
2855
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2856
+ let callback = arguments.length > 1 ? arguments[1] : undefined;
2857
+ return new I18n(options, callback);
2655
2858
  }
2656
- const [t, setT] = useState(getT);
2657
- let joinedNS = namespaces.join();
2658
- if (props.lng) joinedNS = `${props.lng}${joinedNS}`;
2659
- const previousJoinedNS = usePrevious(joinedNS);
2660
- const isMounted = useRef(true);
2661
- useEffect(() => {
2662
- const {
2663
- bindI18n,
2664
- bindI18nStore
2665
- } = i18nOptions;
2666
- isMounted.current = true;
2667
- if (!ready && !useSuspense) {
2668
- if (props.lng) {
2669
- loadLanguages(i18n, props.lng, namespaces, () => {
2670
- if (isMounted.current) setT(getT);
2671
- });
2672
- } else {
2673
- loadNamespaces(i18n, namespaces, () => {
2674
- if (isMounted.current) setT(getT);
2675
- });
2859
+ cloneInstance() {
2860
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2861
+ let callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop;
2862
+ const forkResourceStore = options.forkResourceStore;
2863
+ if (forkResourceStore) delete options.forkResourceStore;
2864
+ const mergedOptions = {
2865
+ ...this.options,
2866
+ ...options,
2867
+ ...{
2868
+ isClone: true
2676
2869
  }
2677
- }
2678
- if (ready && previousJoinedNS && previousJoinedNS !== joinedNS && isMounted.current) {
2679
- setT(getT);
2680
- }
2681
- function boundReset() {
2682
- if (isMounted.current) setT(getT);
2683
- }
2684
- if (bindI18n && i18n) i18n.on(bindI18n, boundReset);
2685
- if (bindI18nStore && i18n) i18n.store.on(bindI18nStore, boundReset);
2686
- return () => {
2687
- isMounted.current = false;
2688
- if (bindI18n && i18n) bindI18n.split(' ').forEach(e => i18n.off(e, boundReset));
2689
- if (bindI18nStore && i18n) bindI18nStore.split(' ').forEach(e => i18n.store.off(e, boundReset));
2690
2870
  };
2691
- }, [i18n, joinedNS]);
2692
- const isInitial = useRef(true);
2693
- useEffect(() => {
2694
- if (isMounted.current && !isInitial.current) {
2695
- setT(getT);
2871
+ const clone = new I18n(mergedOptions);
2872
+ if (options.debug !== undefined || options.prefix !== undefined) {
2873
+ clone.logger = clone.logger.clone(options);
2696
2874
  }
2697
- isInitial.current = false;
2698
- }, [i18n, keyPrefix]);
2699
- const ret = [t, i18n, ready];
2700
- ret.t = t;
2701
- ret.i18n = i18n;
2702
- ret.ready = ready;
2703
- if (ready) return ret;
2704
- if (!ready && !useSuspense) return ret;
2705
- throw new Promise(resolve => {
2706
- if (props.lng) {
2707
- loadLanguages(i18n, props.lng, namespaces, () => resolve());
2708
- } else {
2709
- loadNamespaces(i18n, namespaces, () => resolve());
2875
+ const membersToCopy = ['store', 'services', 'language'];
2876
+ membersToCopy.forEach(m => {
2877
+ clone[m] = this[m];
2878
+ });
2879
+ clone.services = {
2880
+ ...this.services
2881
+ };
2882
+ clone.services.utils = {
2883
+ hasLoadedNamespace: clone.hasLoadedNamespace.bind(clone)
2884
+ };
2885
+ if (forkResourceStore) {
2886
+ clone.store = new ResourceStore(this.store.data, mergedOptions);
2887
+ clone.services.resourceStore = clone.store;
2710
2888
  }
2711
- });
2889
+ clone.translator = new Translator(clone.services, mergedOptions);
2890
+ clone.translator.on('*', function (event) {
2891
+ for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
2892
+ args[_key4 - 1] = arguments[_key4];
2893
+ }
2894
+ clone.emit(event, ...args);
2895
+ });
2896
+ clone.init(mergedOptions, callback);
2897
+ clone.translator.options = mergedOptions;
2898
+ clone.translator.backendConnector.services.utils = {
2899
+ hasLoadedNamespace: clone.hasLoadedNamespace.bind(clone)
2900
+ };
2901
+ return clone;
2902
+ }
2903
+ toJSON() {
2904
+ return {
2905
+ options: this.options,
2906
+ store: this.store,
2907
+ language: this.language,
2908
+ languages: this.languages,
2909
+ resolvedLanguage: this.resolvedLanguage
2910
+ };
2911
+ }
2712
2912
  }
2913
+ const instance = I18n.createInstance();
2914
+ instance.createInstance = I18n.createInstance;
2915
+
2916
+ instance.createInstance;
2917
+ instance.dir;
2918
+ instance.init;
2919
+ instance.loadResources;
2920
+ instance.reloadResources;
2921
+ instance.use;
2922
+ instance.changeLanguage;
2923
+ instance.getFixedT;
2924
+ instance.t;
2925
+ instance.exists;
2926
+ instance.setDefaultNamespace;
2927
+ instance.hasLoadedNamespace;
2928
+ instance.loadNamespaces;
2929
+ instance.loadLanguages;
2713
2930
 
2714
2931
  var locations$1 = {
2715
2932
  label: "Location",
@@ -2851,70 +3068,30 @@ var fiCommon = {
2851
3068
  errors: errors
2852
3069
  };
2853
3070
 
2854
- var urlParams = typeof window !== 'undefined'
2855
- ? new URLSearchParams(window.location.search)
2856
- : null;
2857
- var localeFromUrl = (urlParams === null || urlParams === void 0 ? void 0 : urlParams.get('locale')) || 'fi';
2858
- instance.use(initReactI18next).init({
2859
- resources: {
2860
- en: { filterBar: enFilterBar, common: enCommon },
2861
- fi: { filterBar: fiFilterBar, common: fiCommon },
2862
- },
2863
- lng: localeFromUrl,
2864
- fallbackLng: 'fi',
2865
- interpolation: {
2866
- escapeValue: false,
2867
- },
2868
- });
2869
-
2870
- var useUpdateTranslations = function (_a) {
2871
- var language = _a.language;
2872
- var _b = __read(useState(0), 2); _b[0]; var setRerenderKey = _b[1];
2873
- useEffect(function () {
2874
- instance.changeLanguage(language);
2875
- setRerenderKey(function (prevKey) { return prevKey + 1; });
2876
- }, [language]);
3071
+ var resources = {
3072
+ en: { filterBar: enFilterBar, common: enCommon },
3073
+ fi: { filterBar: fiFilterBar, common: fiCommon },
2877
3074
  };
2878
-
2879
- // TODO - Refactor and rename this hook
2880
- var useCloseFilterSection = function (_a) {
2881
- var handleSelectedFilter = _a.handleSelectedFilter;
2882
- var filterSectionRef = useRef(null);
2883
- useEffect(function () {
2884
- var handleClickOutside = function (event) {
2885
- if (filterSectionRef.current &&
2886
- !filterSectionRef.current.contains(event.target)) {
2887
- handleSelectedFilter(false);
2888
- }
2889
- };
2890
- document.addEventListener('mousedown', handleClickOutside);
2891
- return function () {
2892
- document.removeEventListener('mousedown', handleClickOutside);
2893
- };
2894
- }, [filterSectionRef]);
2895
- return { filterSectionRef: filterSectionRef };
3075
+ var readLocaleFromUrl = function () {
3076
+ if (typeof window === 'undefined')
3077
+ return null;
3078
+ return new URLSearchParams(window.location.search).get('locale');
3079
+ };
3080
+ var createI18nInstance = function (language) {
3081
+ var instance$1 = instance.createInstance();
3082
+ instance$1.use(initReactI18next).init({
3083
+ resources: resources,
3084
+ lng: language || readLocaleFromUrl() || 'fi',
3085
+ fallbackLng: 'fi',
3086
+ interpolation: { escapeValue: false },
3087
+ });
3088
+ return instance$1;
2896
3089
  };
2897
3090
 
2898
- var useAutoFocus = function (autoFocus) {
2899
- var ref = useRef(null);
2900
- useEffect(function () {
2901
- if (!autoFocus || !ref.current)
2902
- return;
2903
- var attemptFocus = function (attempts) {
2904
- if (attempts === void 0) { attempts = 0; }
2905
- if (attempts > 20 || !ref.current)
2906
- return;
2907
- var focusable = ref.current.querySelector('button:not([disabled]), [tabindex]:not([tabindex="-1"])');
2908
- if (focusable) {
2909
- focusable.focus();
2910
- }
2911
- else {
2912
- requestAnimationFrame(function () { return attemptFocus(attempts + 1); });
2913
- }
2914
- };
2915
- requestAnimationFrame(function () { return attemptFocus(); });
2916
- }, [autoFocus]);
2917
- return ref;
3091
+ var I18nProvider = function (_a) {
3092
+ var language = _a.language, children = _a.children;
3093
+ var i18n = useMemo(function () { return createI18nInstance(language); }, []);
3094
+ return React__default.createElement(I18nextProvider, { i18n: i18n }, children);
2918
3095
  };
2919
3096
 
2920
3097
  var css_248z$j = ".will-filter-bar-select-button {\n width: 100%;\n height: auto;\n background-color: transparent;\n border: none;\n padding: 0 20px;\n border-radius: 20px;\n cursor: pointer;\n font-size: 14px;\n text-align: initial;\n user-select: none;\n}\n\n.will-filter-bar-select-button.disabled {\n cursor: not-allowed;\n}\n\n.will-filter-bar-select-button .select-button-wrapper {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 10px;\n}\n\n.will-filter-bar-select-button .select-button-wrapper > div {\n display: grid;\n}\n\n.will-filter-bar-select-button .select-button-label {\n color: var(--will-black);\n font-weight: 600;\n}\n\n.will-filter-bar-select-button .select-button-description {\n color: var(--will-black);\n font-weight: 400;\n opacity: 0.5;\n white-space: nowrap;\n min-height: 19px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.will-filter-bar-select-button .select-button-description span {\n font: inherit;\n}\n\n.will-filter-bar-select-button .select-button-label.active,\n.will-filter-bar-select-button .select-button-description.active {\n font-weight: 700;\n font-size: 15px;\n opacity: 1;\n}\n\n@media (max-width: 960px) {\n .will-filter-bar-select-button {\n padding: 15px 0;\n }\n\n .will-filter-bar-select-button:first-child {\n padding: 0 0 15px 0;\n }\n\n .will-filter-bar-select-button .select-button-wrapper {\n justify-content: center;\n text-align: center;\n }\n\n .will-filter-bar-select-button .select-button-description {\n white-space: wrap;\n }\n\n .will-filter-bar-select-button .select-button-divider {\n display: none;\n }\n}\n";
@@ -12257,12 +12434,12 @@ styleInject(css_248z$2);
12257
12434
  var css_248z$1 = ".will-root {\n z-index: 999;\n width: fit-content;\n min-width: 796px;\n max-height: 100vh;\n position: relative;\n}\n\n.will-root.is-full-width {\n width: 100%;\n}\n\n.will-filter-bar {\n box-sizing: border-box;\n position: relative;\n}\n\n@media (max-width: 960px) {\n .will-root {\n width: 100%;\n min-width: auto;\n }\n}\n\n/* Common */\n\n.will-filter-bar-controls.dark,\n.will-filter-bar-panels.dark {\n box-shadow: var(--will-box-shadow-dark);\n}\n\n.will-filter-bar-controls.light,\n.will-filter-bar-panels.light {\n box-shadow: var(--will-box-shadow-light);\n}\n";
12258
12435
  styleInject(css_248z$1);
12259
12436
 
12260
- var FilterBar = function (_a) {
12437
+ var FilterBar = function (props) { return (React__default.createElement(I18nProvider, { language: props.language },
12438
+ React__default.createElement(FilterBarInner, __assign$2({}, props)))); };
12439
+ var FilterBarInner = function (_a) {
12261
12440
  var language = _a.language, ageCategories = _a.ageCategories, _b = _a.redirectUrl, redirectUrl = _b === void 0 ? REDIRECT_URL_FALLBACK : _b, palette = _a.palette, onSubmit = _a.onSubmit, fullWidth = _a.fullWidth, disableCalendarDates = _a.disableCalendarDates, mode = _a.mode, tabs = _a.tabs, outerLoading = _a.outerLoading, locations = _a.locations;
12262
12441
  var themePalette = useTheme({ palette: palette });
12263
- // Translations
12264
12442
  useUpdateTranslations({ language: language });
12265
- // Display component after fully loaded
12266
12443
  useAwaitRender();
12267
12444
  return (React__default.createElement(FilterBarProvider, { language: language, ageCategories: ageCategories, redirectUrl: redirectUrl, palette: palette, onSubmit: onSubmit, fullWidth: fullWidth, disableCalendarDates: disableCalendarDates, mode: mode, tabs: tabs, outerLoading: outerLoading, locations: locations },
12268
12445
  React__default.createElement("div", { className: "will-root ".concat(fullWidth ? 'is-full-width' : ''), style: themePalette },
@@ -12429,7 +12606,11 @@ var renderCalendarErrorMessage = function (_a) {
12429
12606
  var css_248z = ".will-root .will-calendar-wrapper {\n box-shadow: var(--will-box-shadow-dark);\n border-radius: 20px;\n background-color: var(--will-white);\n position: absolute;\n top: 0;\n left: 0;\n \n}\n\n.will-root .will-calendar-wrapper .will-calendar-header,\n.will-root .will-calendar-wrapper .will-calendar-main,\n.will-root .will-calendar-wrapper .will-calendar-footer {\n padding: 20px;\n}\n\n/* Header */\n\n.will-root .will-calendar-wrapper .will-calendar-header {\n display: flex;\n justify-content: space-between;\n border-bottom: 1px solid var(--will-grey);\n align-items: center;\n}\n\n/* Footer */\n\n.will-root .will-calendar-wrapper .will-calendar-footer {\n border-top: 1px solid var(--will-grey);\n}\n\n/* Footer actions */\n\n.will-root .will-calendar-wrapper .will-calendar-footer-actions-wrapper {\n display: flex;\n justify-content: space-between;\n}\n\n.will-root .will-calendar-wrapper .will-calendar-footer-dates > div {\n margin-bottom: 5px;\n}\n\n.will-root .will-calendar-wrapper .will-calendar-footer-dates-separator {\n margin: 0 15px;\n}\n\n.will-root .will-calendar-wrapper .will-calendar-footer-dates .will-calendar-footer-booked {\n display: flex;\n min-height: 20.5px;\n margin-top: 10px;\n}\n\n.will-root .will-calendar-wrapper .will-calendar-footer-error {\n display: flex;\n max-width: 80%;\n}\n\n.will-root .will-calendar-wrapper .will-calendar-footer-error span {\n display: inline-block;\n margin-left: 10px;\n}\n\n@media (max-width: 960px) {\n .will-root .will-calendar-wrapper {\n width: -webkit-fill-available;\n margin: 0 -6%;\n }\n\n .will-root .will-calendar-wrapper .will-calendar-header,\n .will-root .will-calendar-wrapper .will-calendar-main,\n .will-root .will-calendar-wrapper .will-calendar-footer {\n padding: 20px 10px;\n }\n\n .will-root .will-calendar-wrapper .will-calendar-footer-actions-wrapper {\n flex-direction: column;\n }\n\n .will-root .will-calendar-wrapper .will-calendar-footer-dates {\n text-align: center;\n }\n\n .will-root .will-calendar-wrapper .will-calendar-footer-dates .will-calendar-footer-booked {\n justify-content: center;\n }\n\n .will-root .will-calendar-wrapper .will-calendar-footer-actions {\n flex-direction: column;\n width: 100%;\n }\n\n .will-root .will-calendar-wrapper .will-calendar-footer-actions button{\n width: 100%;\n margin-top: 10px;\n }\n\n .will-root .will-calendar-wrapper .will-calendar-footer-error {\n max-width: 100%;\n }\n\n .will-root .will-calendar-wrapper .will-calendar-footer-error span {\n text-align: center;\n margin-left: 5px;\n }\n }\n\n.will-root .will-calendar-wrapper .will-calendar-header .will-filter-bar-close-button {\n position: initial;\n}";
12430
12607
  styleInject(css_248z);
12431
12608
 
12432
- function FilterCalendar(_a) {
12609
+ function FilterCalendar(props) {
12610
+ return (React__default.createElement(I18nProvider, { language: props.language },
12611
+ React__default.createElement(FilterCalendarInner, __assign$2({}, props))));
12612
+ }
12613
+ function FilterCalendarInner(_a) {
12433
12614
  var calendarOffset = _a.calendarOffset, language = _a.language, palette = _a.palette, onSubmit = _a.onSubmit, outerDisableCalendarDates = _a.disableCalendarDates, toggleCalendar = _a.toggleCalendar, loadingData = _a.loadingData, setToggleCalendar = _a.setToggleCalendar, requestDates = _a.requestDates, showFeedback = _a.showFeedback, noActiveSelection = _a.noActiveSelection, outerRangeContext = _a.rangeContext;
12434
12615
  var themePalette = useTheme({ palette: palette });
12435
12616
  // Translations