react-i18next 16.1.6 → 16.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/dist/amd/react-i18next.js +169 -77
- package/dist/amd/react-i18next.min.js +1 -1
- package/dist/commonjs/useTranslation.js +76 -74
- package/dist/es/package.json +1 -1
- package/dist/es/useTranslation.js +77 -75
- package/dist/umd/react-i18next.js +169 -77
- package/dist/umd/react-i18next.min.js +1 -1
- package/package.json +4 -3
- package/react-i18next.js +169 -77
- package/react-i18next.min.js +1 -1
- package/src/useTranslation.js +91 -126
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useContext, useCallback, useMemo, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { useSyncExternalStore } from 'use-sync-external-store/shim';
|
|
2
3
|
import { getI18n, getDefaults, ReportNamespaces, I18nContext } from './context.js';
|
|
3
4
|
import { warnOnce, loadNamespaces, loadLanguages, hasLoadedNamespace, isString, isObject } from './utils.js';
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
const notReadyT = (k, optsOrDefaultValue) => {
|
|
6
|
+
if (isString(optsOrDefaultValue)) return optsOrDefaultValue;
|
|
7
|
+
if (isObject(optsOrDefaultValue) && isString(optsOrDefaultValue.defaultValue)) return optsOrDefaultValue.defaultValue;
|
|
8
|
+
return Array.isArray(k) ? k[k.length - 1] : k;
|
|
9
|
+
};
|
|
10
|
+
const notReadySnapshot = {
|
|
11
|
+
t: notReadyT,
|
|
12
|
+
ready: false
|
|
10
13
|
};
|
|
11
|
-
const
|
|
12
|
-
const useMemoizedT = (i18n, language, namespace, keyPrefix) => useCallback(alwaysNewT(i18n, language, namespace, keyPrefix), [i18n, language, namespace, keyPrefix]);
|
|
14
|
+
const dummySubscribe = () => () => {};
|
|
13
15
|
export const useTranslation = (ns, props = {}) => {
|
|
14
16
|
const {
|
|
15
17
|
i18n: i18nFromProps
|
|
@@ -22,86 +24,86 @@ export const useTranslation = (ns, props = {}) => {
|
|
|
22
24
|
if (i18n && !i18n.reportNamespaces) i18n.reportNamespaces = new ReportNamespaces();
|
|
23
25
|
if (!i18n) {
|
|
24
26
|
warnOnce(i18n, 'NO_I18NEXT_INSTANCE', 'useTranslation: You will need to pass in an i18next instance by using initReactI18next');
|
|
25
|
-
const notReadyT = (k, optsOrDefaultValue) => {
|
|
26
|
-
if (isString(optsOrDefaultValue)) return optsOrDefaultValue;
|
|
27
|
-
if (isObject(optsOrDefaultValue) && isString(optsOrDefaultValue.defaultValue)) return optsOrDefaultValue.defaultValue;
|
|
28
|
-
return Array.isArray(k) ? k[k.length - 1] : k;
|
|
29
|
-
};
|
|
30
|
-
const retNotReady = [notReadyT, {}, false];
|
|
31
|
-
retNotReady.t = notReadyT;
|
|
32
|
-
retNotReady.i18n = {};
|
|
33
|
-
retNotReady.ready = false;
|
|
34
|
-
return retNotReady;
|
|
35
27
|
}
|
|
36
|
-
|
|
37
|
-
const i18nOptions = {
|
|
28
|
+
const i18nOptions = useMemo(() => ({
|
|
38
29
|
...getDefaults(),
|
|
39
|
-
...i18n
|
|
30
|
+
...i18n?.options?.react,
|
|
40
31
|
...props
|
|
41
|
-
};
|
|
32
|
+
}), [i18n, props]);
|
|
42
33
|
const {
|
|
43
34
|
useSuspense,
|
|
44
35
|
keyPrefix
|
|
45
36
|
} = i18nOptions;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
const [t, setT] = useState(getT);
|
|
54
|
-
let joinedNS = namespaces.join();
|
|
55
|
-
if (props.lng) joinedNS = `${props.lng}${joinedNS}`;
|
|
56
|
-
const previousJoinedNS = usePrevious(joinedNS);
|
|
57
|
-
const isMounted = useRef(true);
|
|
58
|
-
useEffect(() => {
|
|
37
|
+
const namespaces = useMemo(() => {
|
|
38
|
+
const nsOrContext = ns || defaultNSFromContext || i18n?.options?.defaultNS;
|
|
39
|
+
return isString(nsOrContext) ? [nsOrContext] : nsOrContext || ['translation'];
|
|
40
|
+
}, [ns, defaultNSFromContext, i18n]);
|
|
41
|
+
i18n?.reportNamespaces?.addUsedNamespaces?.(namespaces);
|
|
42
|
+
const subscribe = useCallback(callback => {
|
|
43
|
+
if (!i18n) return dummySubscribe;
|
|
59
44
|
const {
|
|
60
45
|
bindI18n,
|
|
61
46
|
bindI18nStore
|
|
62
47
|
} = i18nOptions;
|
|
63
|
-
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
48
|
+
if (bindI18n) i18n.on(bindI18n, callback);
|
|
49
|
+
if (bindI18nStore) i18n.store.on(bindI18nStore, callback);
|
|
50
|
+
return () => {
|
|
51
|
+
if (bindI18n) bindI18n.split(' ').forEach(e => i18n.off(e, callback));
|
|
52
|
+
if (bindI18nStore) bindI18nStore.split(' ').forEach(e => i18n.store.off(e, callback));
|
|
53
|
+
};
|
|
54
|
+
}, [i18n, i18nOptions]);
|
|
55
|
+
const snapshotRef = useRef();
|
|
56
|
+
const getSnapshot = useCallback(() => {
|
|
57
|
+
if (!i18n) {
|
|
58
|
+
return notReadySnapshot;
|
|
74
59
|
}
|
|
75
|
-
|
|
76
|
-
|
|
60
|
+
const calculatedReady = !!(i18n.isInitialized || i18n.initializedStoreOnce) && namespaces.every(n => hasLoadedNamespace(n, i18n, i18nOptions));
|
|
61
|
+
const calculatedT = i18n.getFixedT(props.lng || i18n.language, i18nOptions.nsMode === 'fallback' ? namespaces : namespaces[0], keyPrefix);
|
|
62
|
+
const lastSnapshot = snapshotRef.current;
|
|
63
|
+
if (lastSnapshot && lastSnapshot.ready === calculatedReady && lastSnapshot.lng === (props.lng || i18n.language) && lastSnapshot.keyPrefix === keyPrefix) {
|
|
64
|
+
return lastSnapshot;
|
|
77
65
|
}
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
return () => {
|
|
84
|
-
isMounted.current = false;
|
|
85
|
-
if (i18n && bindI18n) bindI18n?.split(' ').forEach(e => i18n.off(e, boundReset));
|
|
86
|
-
if (bindI18nStore && i18n) bindI18nStore.split(' ').forEach(e => i18n.store.off(e, boundReset));
|
|
66
|
+
const newSnapshot = {
|
|
67
|
+
t: calculatedT,
|
|
68
|
+
ready: calculatedReady,
|
|
69
|
+
lng: props.lng || i18n.language,
|
|
70
|
+
keyPrefix
|
|
87
71
|
};
|
|
88
|
-
|
|
72
|
+
snapshotRef.current = newSnapshot;
|
|
73
|
+
return newSnapshot;
|
|
74
|
+
}, [i18n, namespaces, keyPrefix, i18nOptions, props.lng]);
|
|
75
|
+
const [loadCount, setLoadCount] = useState(0);
|
|
76
|
+
const {
|
|
77
|
+
t,
|
|
78
|
+
ready
|
|
79
|
+
} = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
89
80
|
useEffect(() => {
|
|
90
|
-
if (
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
ret.ready = ready;
|
|
98
|
-
if (ready) return ret;
|
|
99
|
-
if (!ready && !useSuspense) return ret;
|
|
100
|
-
throw new Promise(resolve => {
|
|
101
|
-
if (props.lng) {
|
|
102
|
-
loadLanguages(i18n, props.lng, namespaces, () => resolve());
|
|
103
|
-
} else {
|
|
104
|
-
loadNamespaces(i18n, namespaces, () => resolve());
|
|
81
|
+
if (i18n && !ready && !useSuspense) {
|
|
82
|
+
const onLoaded = () => setLoadCount(c => c + 1);
|
|
83
|
+
if (props.lng) {
|
|
84
|
+
loadLanguages(i18n, props.lng, namespaces, onLoaded);
|
|
85
|
+
} else {
|
|
86
|
+
loadNamespaces(i18n, namespaces, onLoaded);
|
|
87
|
+
}
|
|
105
88
|
}
|
|
106
|
-
});
|
|
89
|
+
}, [i18n, props.lng, namespaces, ready, useSuspense, loadCount]);
|
|
90
|
+
const finalI18n = i18n || {};
|
|
91
|
+
const ret = useMemo(() => {
|
|
92
|
+
const arr = [t, finalI18n, ready];
|
|
93
|
+
arr.t = t;
|
|
94
|
+
arr.i18n = finalI18n;
|
|
95
|
+
arr.ready = ready;
|
|
96
|
+
return arr;
|
|
97
|
+
}, [t, finalI18n, ready]);
|
|
98
|
+
if (i18n && useSuspense && !ready) {
|
|
99
|
+
throw new Promise(resolve => {
|
|
100
|
+
const onLoaded = () => resolve();
|
|
101
|
+
if (props.lng) {
|
|
102
|
+
loadLanguages(i18n, props.lng, namespaces, onLoaded);
|
|
103
|
+
} else {
|
|
104
|
+
loadNamespaces(i18n, namespaces, onLoaded);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return ret;
|
|
107
109
|
};
|
|
@@ -475,7 +475,12 @@
|
|
|
475
475
|
};
|
|
476
476
|
if (key == null) return false;
|
|
477
477
|
const resolved = this.resolve(key, opt);
|
|
478
|
-
|
|
478
|
+
if (resolved?.res === undefined) return false;
|
|
479
|
+
const isObject = shouldHandleAsObject(resolved.res);
|
|
480
|
+
if (opt.returnObjects === false && isObject) {
|
|
481
|
+
return false;
|
|
482
|
+
}
|
|
483
|
+
return true;
|
|
479
484
|
}
|
|
480
485
|
extractFromKey(key, opt) {
|
|
481
486
|
let nsSeparator = opt.nsSeparator !== undefined ? opt.nsSeparator : this.options.nsSeparator;
|
|
@@ -3270,15 +3275,102 @@
|
|
|
3270
3275
|
}
|
|
3271
3276
|
IcuTrans.displayName = 'IcuTrans';
|
|
3272
3277
|
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3278
|
+
var shim = {exports: {}};
|
|
3279
|
+
|
|
3280
|
+
var useSyncExternalStoreShim_development = {};
|
|
3281
|
+
|
|
3282
|
+
/**
|
|
3283
|
+
* @license React
|
|
3284
|
+
* use-sync-external-store-shim.development.js
|
|
3285
|
+
*
|
|
3286
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3287
|
+
*
|
|
3288
|
+
* This source code is licensed under the MIT license found in the
|
|
3289
|
+
* LICENSE file in the root directory of this source tree.
|
|
3290
|
+
*/
|
|
3291
|
+
|
|
3292
|
+
(function () {
|
|
3293
|
+
function is(x, y) {
|
|
3294
|
+
return x === y && (0 !== x || 1 / x === 1 / y) || x !== x && y !== y;
|
|
3295
|
+
}
|
|
3296
|
+
function useSyncExternalStore$2(subscribe, getSnapshot) {
|
|
3297
|
+
didWarnOld18Alpha || void 0 === React$1.startTransition || (didWarnOld18Alpha = true, console.error("You are using an outdated, pre-release alpha of React 18 that does not support useSyncExternalStore. The use-sync-external-store shim will not work correctly. Upgrade to a newer pre-release."));
|
|
3298
|
+
var value = getSnapshot();
|
|
3299
|
+
if (!didWarnUncachedGetSnapshot) {
|
|
3300
|
+
var cachedValue = getSnapshot();
|
|
3301
|
+
objectIs(value, cachedValue) || (console.error("The result of getSnapshot should be cached to avoid an infinite loop"), didWarnUncachedGetSnapshot = true);
|
|
3302
|
+
}
|
|
3303
|
+
cachedValue = useState({
|
|
3304
|
+
inst: {
|
|
3305
|
+
value: value,
|
|
3306
|
+
getSnapshot: getSnapshot
|
|
3307
|
+
}
|
|
3308
|
+
});
|
|
3309
|
+
var inst = cachedValue[0].inst,
|
|
3310
|
+
forceUpdate = cachedValue[1];
|
|
3311
|
+
useLayoutEffect(function () {
|
|
3312
|
+
inst.value = value;
|
|
3313
|
+
inst.getSnapshot = getSnapshot;
|
|
3314
|
+
checkIfSnapshotChanged(inst) && forceUpdate({
|
|
3315
|
+
inst: inst
|
|
3316
|
+
});
|
|
3317
|
+
}, [subscribe, value, getSnapshot]);
|
|
3318
|
+
useEffect(function () {
|
|
3319
|
+
checkIfSnapshotChanged(inst) && forceUpdate({
|
|
3320
|
+
inst: inst
|
|
3321
|
+
});
|
|
3322
|
+
return subscribe(function () {
|
|
3323
|
+
checkIfSnapshotChanged(inst) && forceUpdate({
|
|
3324
|
+
inst: inst
|
|
3325
|
+
});
|
|
3326
|
+
});
|
|
3327
|
+
}, [subscribe]);
|
|
3328
|
+
useDebugValue(value);
|
|
3329
|
+
return value;
|
|
3330
|
+
}
|
|
3331
|
+
function checkIfSnapshotChanged(inst) {
|
|
3332
|
+
var latestGetSnapshot = inst.getSnapshot;
|
|
3333
|
+
inst = inst.value;
|
|
3334
|
+
try {
|
|
3335
|
+
var nextValue = latestGetSnapshot();
|
|
3336
|
+
return !objectIs(inst, nextValue);
|
|
3337
|
+
} catch (error) {
|
|
3338
|
+
return true;
|
|
3339
|
+
}
|
|
3340
|
+
}
|
|
3341
|
+
function useSyncExternalStore$1(subscribe, getSnapshot) {
|
|
3342
|
+
return getSnapshot();
|
|
3343
|
+
}
|
|
3344
|
+
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
|
|
3345
|
+
var React$1 = React,
|
|
3346
|
+
objectIs = "function" === typeof Object.is ? Object.is : is,
|
|
3347
|
+
useState = React$1.useState,
|
|
3348
|
+
useEffect = React$1.useEffect,
|
|
3349
|
+
useLayoutEffect = React$1.useLayoutEffect,
|
|
3350
|
+
useDebugValue = React$1.useDebugValue,
|
|
3351
|
+
didWarnOld18Alpha = false,
|
|
3352
|
+
didWarnUncachedGetSnapshot = false,
|
|
3353
|
+
shim = "undefined" === typeof window || "undefined" === typeof window.document || "undefined" === typeof window.document.createElement ? useSyncExternalStore$1 : useSyncExternalStore$2;
|
|
3354
|
+
useSyncExternalStoreShim_development.useSyncExternalStore = void 0 !== React$1.useSyncExternalStore ? React$1.useSyncExternalStore : shim;
|
|
3355
|
+
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
|
|
3356
|
+
})();
|
|
3357
|
+
|
|
3358
|
+
{
|
|
3359
|
+
shim.exports = useSyncExternalStoreShim_development;
|
|
3360
|
+
}
|
|
3361
|
+
|
|
3362
|
+
var shimExports = shim.exports;
|
|
3363
|
+
|
|
3364
|
+
const notReadyT = (k, optsOrDefaultValue) => {
|
|
3365
|
+
if (isString(optsOrDefaultValue)) return optsOrDefaultValue;
|
|
3366
|
+
if (isObject(optsOrDefaultValue) && isString(optsOrDefaultValue.defaultValue)) return optsOrDefaultValue.defaultValue;
|
|
3367
|
+
return Array.isArray(k) ? k[k.length - 1] : k;
|
|
3368
|
+
};
|
|
3369
|
+
const notReadySnapshot = {
|
|
3370
|
+
t: notReadyT,
|
|
3371
|
+
ready: false
|
|
3279
3372
|
};
|
|
3280
|
-
const
|
|
3281
|
-
const useMemoizedT = (i18n, language, namespace, keyPrefix) => React.useCallback(alwaysNewT(i18n, language, namespace, keyPrefix), [i18n, language, namespace, keyPrefix]);
|
|
3373
|
+
const dummySubscribe = () => () => {};
|
|
3282
3374
|
const useTranslation = (ns, props = {}) => {
|
|
3283
3375
|
const {
|
|
3284
3376
|
i18n: i18nFromProps
|
|
@@ -3291,88 +3383,88 @@
|
|
|
3291
3383
|
if (i18n && !i18n.reportNamespaces) i18n.reportNamespaces = new ReportNamespaces();
|
|
3292
3384
|
if (!i18n) {
|
|
3293
3385
|
warnOnce(i18n, 'NO_I18NEXT_INSTANCE', 'useTranslation: You will need to pass in an i18next instance by using initReactI18next');
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
if (isObject(optsOrDefaultValue) && isString(optsOrDefaultValue.defaultValue)) return optsOrDefaultValue.defaultValue;
|
|
3297
|
-
return Array.isArray(k) ? k[k.length - 1] : k;
|
|
3298
|
-
};
|
|
3299
|
-
const retNotReady = [notReadyT, {}, false];
|
|
3300
|
-
retNotReady.t = notReadyT;
|
|
3301
|
-
retNotReady.i18n = {};
|
|
3302
|
-
retNotReady.ready = false;
|
|
3303
|
-
return retNotReady;
|
|
3304
|
-
}
|
|
3305
|
-
if (i18n.options.react?.wait) warnOnce(i18n, 'DEPRECATED_OPTION', 'useTranslation: It seems you are still using the old wait option, you may migrate to the new useSuspense behaviour.');
|
|
3306
|
-
const i18nOptions = {
|
|
3386
|
+
}
|
|
3387
|
+
const i18nOptions = React.useMemo(() => ({
|
|
3307
3388
|
...getDefaults(),
|
|
3308
|
-
...i18n
|
|
3389
|
+
...i18n?.options?.react,
|
|
3309
3390
|
...props
|
|
3310
|
-
};
|
|
3391
|
+
}), [i18n, props]);
|
|
3311
3392
|
const {
|
|
3312
3393
|
useSuspense,
|
|
3313
3394
|
keyPrefix
|
|
3314
3395
|
} = i18nOptions;
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
const
|
|
3321
|
-
|
|
3322
|
-
const [t, setT] = React.useState(getT);
|
|
3323
|
-
let joinedNS = namespaces.join();
|
|
3324
|
-
if (props.lng) joinedNS = `${props.lng}${joinedNS}`;
|
|
3325
|
-
const previousJoinedNS = usePrevious(joinedNS);
|
|
3326
|
-
const isMounted = React.useRef(true);
|
|
3327
|
-
React.useEffect(() => {
|
|
3396
|
+
const namespaces = React.useMemo(() => {
|
|
3397
|
+
const nsOrContext = ns || defaultNSFromContext || i18n?.options?.defaultNS;
|
|
3398
|
+
return isString(nsOrContext) ? [nsOrContext] : nsOrContext || ['translation'];
|
|
3399
|
+
}, [ns, defaultNSFromContext, i18n]);
|
|
3400
|
+
i18n?.reportNamespaces?.addUsedNamespaces?.(namespaces);
|
|
3401
|
+
const subscribe = React.useCallback(callback => {
|
|
3402
|
+
if (!i18n) return dummySubscribe;
|
|
3328
3403
|
const {
|
|
3329
3404
|
bindI18n,
|
|
3330
3405
|
bindI18nStore
|
|
3331
3406
|
} = i18nOptions;
|
|
3332
|
-
|
|
3333
|
-
if (
|
|
3334
|
-
if (props.lng) {
|
|
3335
|
-
loadLanguages(i18n, props.lng, namespaces, () => {
|
|
3336
|
-
if (isMounted.current) setT(getNewT);
|
|
3337
|
-
});
|
|
3338
|
-
} else {
|
|
3339
|
-
loadNamespaces(i18n, namespaces, () => {
|
|
3340
|
-
if (isMounted.current) setT(getNewT);
|
|
3341
|
-
});
|
|
3342
|
-
}
|
|
3343
|
-
}
|
|
3344
|
-
if (ready && previousJoinedNS && previousJoinedNS !== joinedNS && isMounted.current) {
|
|
3345
|
-
setT(getNewT);
|
|
3346
|
-
}
|
|
3347
|
-
const boundReset = () => {
|
|
3348
|
-
if (isMounted.current) setT(getNewT);
|
|
3349
|
-
};
|
|
3350
|
-
if (bindI18n) i18n?.on(bindI18n, boundReset);
|
|
3351
|
-
if (bindI18nStore) i18n?.store.on(bindI18nStore, boundReset);
|
|
3407
|
+
if (bindI18n) i18n.on(bindI18n, callback);
|
|
3408
|
+
if (bindI18nStore) i18n.store.on(bindI18nStore, callback);
|
|
3352
3409
|
return () => {
|
|
3353
|
-
|
|
3354
|
-
if (
|
|
3355
|
-
|
|
3410
|
+
if (bindI18n) bindI18n.split(' ').forEach(e => i18n.off(e, callback));
|
|
3411
|
+
if (bindI18nStore) bindI18nStore.split(' ').forEach(e => i18n.store.off(e, callback));
|
|
3412
|
+
};
|
|
3413
|
+
}, [i18n, i18nOptions]);
|
|
3414
|
+
const snapshotRef = React.useRef();
|
|
3415
|
+
const getSnapshot = React.useCallback(() => {
|
|
3416
|
+
if (!i18n) {
|
|
3417
|
+
return notReadySnapshot;
|
|
3418
|
+
}
|
|
3419
|
+
const calculatedReady = !!(i18n.isInitialized || i18n.initializedStoreOnce) && namespaces.every(n => hasLoadedNamespace(n, i18n, i18nOptions));
|
|
3420
|
+
const calculatedT = i18n.getFixedT(props.lng || i18n.language, i18nOptions.nsMode === 'fallback' ? namespaces : namespaces[0], keyPrefix);
|
|
3421
|
+
const lastSnapshot = snapshotRef.current;
|
|
3422
|
+
if (lastSnapshot && lastSnapshot.ready === calculatedReady && lastSnapshot.lng === (props.lng || i18n.language) && lastSnapshot.keyPrefix === keyPrefix) {
|
|
3423
|
+
return lastSnapshot;
|
|
3424
|
+
}
|
|
3425
|
+
const newSnapshot = {
|
|
3426
|
+
t: calculatedT,
|
|
3427
|
+
ready: calculatedReady,
|
|
3428
|
+
lng: props.lng || i18n.language,
|
|
3429
|
+
keyPrefix
|
|
3356
3430
|
};
|
|
3357
|
-
|
|
3431
|
+
snapshotRef.current = newSnapshot;
|
|
3432
|
+
return newSnapshot;
|
|
3433
|
+
}, [i18n, namespaces, keyPrefix, i18nOptions, props.lng]);
|
|
3434
|
+
const [loadCount, setLoadCount] = React.useState(0);
|
|
3435
|
+
const {
|
|
3436
|
+
t,
|
|
3437
|
+
ready
|
|
3438
|
+
} = shimExports.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
3358
3439
|
React.useEffect(() => {
|
|
3359
|
-
if (
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
ret.ready = ready;
|
|
3367
|
-
if (ready) return ret;
|
|
3368
|
-
if (!ready && !useSuspense) return ret;
|
|
3369
|
-
throw new Promise(resolve => {
|
|
3370
|
-
if (props.lng) {
|
|
3371
|
-
loadLanguages(i18n, props.lng, namespaces, () => resolve());
|
|
3372
|
-
} else {
|
|
3373
|
-
loadNamespaces(i18n, namespaces, () => resolve());
|
|
3440
|
+
if (i18n && !ready && !useSuspense) {
|
|
3441
|
+
const onLoaded = () => setLoadCount(c => c + 1);
|
|
3442
|
+
if (props.lng) {
|
|
3443
|
+
loadLanguages(i18n, props.lng, namespaces, onLoaded);
|
|
3444
|
+
} else {
|
|
3445
|
+
loadNamespaces(i18n, namespaces, onLoaded);
|
|
3446
|
+
}
|
|
3374
3447
|
}
|
|
3375
|
-
});
|
|
3448
|
+
}, [i18n, props.lng, namespaces, ready, useSuspense, loadCount]);
|
|
3449
|
+
const finalI18n = i18n || {};
|
|
3450
|
+
const ret = React.useMemo(() => {
|
|
3451
|
+
const arr = [t, finalI18n, ready];
|
|
3452
|
+
arr.t = t;
|
|
3453
|
+
arr.i18n = finalI18n;
|
|
3454
|
+
arr.ready = ready;
|
|
3455
|
+
return arr;
|
|
3456
|
+
}, [t, finalI18n, ready]);
|
|
3457
|
+
if (i18n && useSuspense && !ready) {
|
|
3458
|
+
throw new Promise(resolve => {
|
|
3459
|
+
const onLoaded = () => resolve();
|
|
3460
|
+
if (props.lng) {
|
|
3461
|
+
loadLanguages(i18n, props.lng, namespaces, onLoaded);
|
|
3462
|
+
} else {
|
|
3463
|
+
loadNamespaces(i18n, namespaces, onLoaded);
|
|
3464
|
+
}
|
|
3465
|
+
});
|
|
3466
|
+
}
|
|
3467
|
+
return ret;
|
|
3376
3468
|
};
|
|
3377
3469
|
|
|
3378
3470
|
const withTranslation = (ns, options = {}) => function Extend(WrappedComponent) {
|