@modern-js/plugin-i18n 2.69.7 → 3.0.0-alpha.1
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/README.md +6 -0
- package/dist/cjs/cli/index.cjs +154 -0
- package/dist/cjs/runtime/I18nLink.cjs +68 -0
- package/dist/cjs/runtime/context.cjs +138 -0
- package/dist/cjs/runtime/hooks.cjs +189 -0
- package/dist/cjs/runtime/i18n/backend/config.cjs +39 -0
- package/dist/cjs/runtime/i18n/backend/defaults.cjs +56 -0
- package/dist/cjs/runtime/i18n/backend/defaults.node.cjs +56 -0
- package/dist/cjs/runtime/i18n/backend/index.cjs +108 -0
- package/dist/cjs/runtime/i18n/backend/middleware.cjs +54 -0
- package/dist/cjs/runtime/i18n/backend/middleware.common.cjs +105 -0
- package/dist/cjs/runtime/i18n/backend/middleware.node.cjs +58 -0
- package/dist/cjs/runtime/i18n/backend/sdk-backend.cjs +171 -0
- package/dist/cjs/runtime/i18n/detection/config.cjs +63 -0
- package/dist/cjs/runtime/i18n/detection/index.cjs +309 -0
- package/dist/cjs/runtime/i18n/detection/middleware.cjs +185 -0
- package/dist/cjs/runtime/i18n/detection/middleware.node.cjs +74 -0
- package/dist/cjs/runtime/i18n/index.cjs +43 -0
- package/dist/cjs/runtime/i18n/instance.cjs +132 -0
- package/dist/cjs/runtime/i18n/utils.cjs +185 -0
- package/dist/cjs/runtime/index.cjs +172 -0
- package/dist/cjs/runtime/types.cjs +18 -0
- package/dist/cjs/runtime/utils.cjs +134 -0
- package/dist/cjs/server/index.cjs +178 -0
- package/dist/cjs/shared/deepMerge.cjs +54 -0
- package/dist/cjs/shared/detection.cjs +105 -0
- package/dist/cjs/shared/type.cjs +18 -0
- package/dist/cjs/shared/utils.cjs +78 -0
- package/dist/esm/cli/index.js +106 -0
- package/dist/esm/runtime/I18nLink.js +31 -0
- package/dist/esm/runtime/context.js +101 -0
- package/dist/esm/runtime/hooks.js +146 -0
- package/dist/esm/runtime/i18n/backend/config.js +5 -0
- package/dist/esm/runtime/i18n/backend/defaults.js +19 -0
- package/dist/esm/runtime/i18n/backend/defaults.node.js +19 -0
- package/dist/esm/runtime/i18n/backend/index.js +74 -0
- package/dist/esm/runtime/i18n/backend/middleware.common.js +61 -0
- package/dist/esm/runtime/i18n/backend/middleware.js +7 -0
- package/dist/esm/runtime/i18n/backend/middleware.node.js +8 -0
- package/dist/esm/runtime/i18n/backend/sdk-backend.js +137 -0
- package/dist/esm/runtime/i18n/detection/config.js +26 -0
- package/dist/esm/runtime/i18n/detection/index.js +260 -0
- package/dist/esm/runtime/i18n/detection/middleware.js +132 -0
- package/dist/esm/runtime/i18n/detection/middleware.node.js +31 -0
- package/dist/esm/runtime/i18n/index.js +3 -0
- package/dist/esm/runtime/i18n/instance.js +77 -0
- package/dist/esm/runtime/i18n/utils.js +136 -0
- package/dist/esm/runtime/index.js +129 -0
- package/dist/esm/runtime/types.js +0 -0
- package/dist/esm/runtime/utils.js +82 -0
- package/dist/esm/server/index.js +168 -0
- package/dist/esm/shared/deepMerge.js +20 -0
- package/dist/esm/shared/detection.js +71 -0
- package/dist/esm/shared/type.js +0 -0
- package/dist/esm/shared/utils.js +35 -0
- package/dist/esm-node/cli/index.js +106 -0
- package/dist/esm-node/runtime/I18nLink.js +31 -0
- package/dist/esm-node/runtime/context.js +101 -0
- package/dist/esm-node/runtime/hooks.js +146 -0
- package/dist/esm-node/runtime/i18n/backend/config.js +5 -0
- package/dist/esm-node/runtime/i18n/backend/defaults.js +19 -0
- package/dist/esm-node/runtime/i18n/backend/defaults.node.js +19 -0
- package/dist/esm-node/runtime/i18n/backend/index.js +74 -0
- package/dist/esm-node/runtime/i18n/backend/middleware.common.js +61 -0
- package/dist/esm-node/runtime/i18n/backend/middleware.js +7 -0
- package/dist/esm-node/runtime/i18n/backend/middleware.node.js +8 -0
- package/dist/esm-node/runtime/i18n/backend/sdk-backend.js +137 -0
- package/dist/esm-node/runtime/i18n/detection/config.js +26 -0
- package/dist/esm-node/runtime/i18n/detection/index.js +260 -0
- package/dist/esm-node/runtime/i18n/detection/middleware.js +132 -0
- package/dist/esm-node/runtime/i18n/detection/middleware.node.js +31 -0
- package/dist/esm-node/runtime/i18n/index.js +3 -0
- package/dist/esm-node/runtime/i18n/instance.js +77 -0
- package/dist/esm-node/runtime/i18n/utils.js +136 -0
- package/dist/esm-node/runtime/index.js +129 -0
- package/dist/esm-node/runtime/types.js +0 -0
- package/dist/esm-node/runtime/utils.js +82 -0
- package/dist/esm-node/server/index.js +168 -0
- package/dist/esm-node/shared/deepMerge.js +20 -0
- package/dist/esm-node/shared/detection.js +71 -0
- package/dist/esm-node/shared/type.js +0 -0
- package/dist/esm-node/shared/utils.js +35 -0
- package/dist/types/cli/index.d.ts +21 -0
- package/dist/types/runtime/I18nLink.d.ts +8 -0
- package/dist/types/runtime/context.d.ts +38 -0
- package/dist/types/runtime/hooks.d.ts +28 -0
- package/dist/types/runtime/i18n/backend/config.d.ts +2 -0
- package/dist/types/runtime/i18n/backend/defaults.d.ts +13 -0
- package/dist/types/runtime/i18n/backend/defaults.node.d.ts +8 -0
- package/dist/types/runtime/i18n/backend/index.d.ts +3 -0
- package/dist/types/runtime/i18n/backend/middleware.common.d.ts +14 -0
- package/dist/types/runtime/i18n/backend/middleware.d.ts +12 -0
- package/dist/types/runtime/i18n/backend/middleware.node.d.ts +13 -0
- package/dist/types/runtime/i18n/backend/sdk-backend.d.ts +52 -0
- package/dist/types/runtime/i18n/detection/config.d.ts +11 -0
- package/dist/types/runtime/i18n/detection/index.d.ts +50 -0
- package/dist/types/runtime/i18n/detection/middleware.d.ts +24 -0
- package/dist/types/runtime/i18n/detection/middleware.node.d.ts +17 -0
- package/dist/types/runtime/i18n/index.d.ts +3 -0
- package/dist/types/runtime/i18n/instance.d.ts +93 -0
- package/dist/types/runtime/i18n/utils.d.ts +29 -0
- package/dist/types/runtime/index.d.ts +20 -0
- package/dist/types/runtime/types.d.ts +15 -0
- package/dist/types/runtime/utils.d.ts +33 -0
- package/dist/types/server/index.d.ts +8 -0
- package/dist/types/shared/deepMerge.d.ts +1 -0
- package/dist/types/shared/detection.d.ts +11 -0
- package/dist/types/shared/type.d.ts +156 -0
- package/dist/types/shared/utils.d.ts +5 -0
- package/package.json +100 -34
- package/rslib.config.mts +4 -0
- package/src/cli/index.ts +245 -0
- package/src/runtime/I18nLink.tsx +76 -0
- package/src/runtime/context.tsx +256 -0
- package/src/runtime/hooks.ts +274 -0
- package/src/runtime/i18n/backend/config.ts +10 -0
- package/src/runtime/i18n/backend/defaults.node.ts +31 -0
- package/src/runtime/i18n/backend/defaults.ts +37 -0
- package/src/runtime/i18n/backend/index.ts +181 -0
- package/src/runtime/i18n/backend/middleware.common.ts +116 -0
- package/src/runtime/i18n/backend/middleware.node.ts +32 -0
- package/src/runtime/i18n/backend/middleware.ts +28 -0
- package/src/runtime/i18n/backend/sdk-backend.ts +292 -0
- package/src/runtime/i18n/detection/config.ts +32 -0
- package/src/runtime/i18n/detection/index.ts +641 -0
- package/src/runtime/i18n/detection/middleware.node.ts +84 -0
- package/src/runtime/i18n/detection/middleware.ts +251 -0
- package/src/runtime/i18n/index.ts +8 -0
- package/src/runtime/i18n/instance.ts +227 -0
- package/src/runtime/i18n/utils.ts +333 -0
- package/src/runtime/index.tsx +281 -0
- package/src/runtime/types.ts +17 -0
- package/src/runtime/utils.ts +151 -0
- package/src/server/index.ts +336 -0
- package/src/shared/deepMerge.ts +38 -0
- package/src/shared/detection.ts +131 -0
- package/src/shared/type.ts +170 -0
- package/src/shared/utils.ts +82 -0
- package/tsconfig.json +12 -0
- package/dist/cjs/index.js +0 -73
- package/dist/cjs/languageDetector.js +0 -51
- package/dist/cjs/utils/index.js +0 -39
- package/dist/esm/index.js +0 -61
- package/dist/esm/languageDetector.js +0 -33
- package/dist/esm/utils/index.js +0 -16
- package/dist/esm-node/index.js +0 -49
- package/dist/esm-node/languageDetector.js +0 -26
- package/dist/esm-node/utils/index.js +0 -15
- package/dist/types/index.d.ts +0 -34
- package/dist/types/languageDetector.d.ts +0 -6
- package/dist/types/utils/index.d.ts +0 -5
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import { isBrowser } from "@modern-js/runtime";
|
|
2
|
+
import { detectLanguageFromPath } from "../../utils.js";
|
|
3
|
+
import { isI18nWrapperInstance } from "../instance.js";
|
|
4
|
+
import { mergeDetectionOptions } from "./config.js";
|
|
5
|
+
import { cacheUserLanguage, detectLanguage, readLanguageFromStorage, useI18nextLanguageDetector } from "./middleware.js";
|
|
6
|
+
const detectorInstanceCache = new WeakMap();
|
|
7
|
+
const DETECTOR_SAFE_OPTION_KEYS = [
|
|
8
|
+
'lowerCaseLng',
|
|
9
|
+
'nonExplicitSupportedLngs',
|
|
10
|
+
'load',
|
|
11
|
+
'partialBundledLanguages',
|
|
12
|
+
'returnNull',
|
|
13
|
+
'returnEmptyString',
|
|
14
|
+
'returnObjects',
|
|
15
|
+
'joinArrays',
|
|
16
|
+
'keySeparator',
|
|
17
|
+
'nsSeparator',
|
|
18
|
+
'pluralSeparator',
|
|
19
|
+
'contextSeparator',
|
|
20
|
+
'fallbackNS',
|
|
21
|
+
'ns',
|
|
22
|
+
'defaultNS',
|
|
23
|
+
'debug'
|
|
24
|
+
];
|
|
25
|
+
const stableStringify = (value)=>{
|
|
26
|
+
if (null == value) return JSON.stringify(value);
|
|
27
|
+
if ('object' != typeof value) return JSON.stringify(value);
|
|
28
|
+
if (Array.isArray(value)) return `[${value.map((item)=>stableStringify(item)).join(',')}]`;
|
|
29
|
+
const sortedKeys = Object.keys(value).sort();
|
|
30
|
+
const sortedEntries = sortedKeys.map((key)=>{
|
|
31
|
+
const stringifiedValue = stableStringify(value[key]);
|
|
32
|
+
return `${JSON.stringify(key)}:${stringifiedValue}`;
|
|
33
|
+
});
|
|
34
|
+
return `{${sortedEntries.join(',')}}`;
|
|
35
|
+
};
|
|
36
|
+
const buildDetectorConfigKey = (languages, fallbackLanguage, mergedDetection)=>stableStringify({
|
|
37
|
+
languages,
|
|
38
|
+
fallbackLanguage,
|
|
39
|
+
detection: mergedDetection
|
|
40
|
+
});
|
|
41
|
+
const pickSafeDetectionOptions = (userInitOptions)=>{
|
|
42
|
+
if (!userInitOptions) return {};
|
|
43
|
+
const safeOptions = {};
|
|
44
|
+
for (const key of DETECTOR_SAFE_OPTION_KEYS){
|
|
45
|
+
const value = userInitOptions[key];
|
|
46
|
+
if (void 0 !== value) safeOptions[key] = value;
|
|
47
|
+
}
|
|
48
|
+
if (userInitOptions.interpolation) safeOptions.interpolation = {
|
|
49
|
+
...userInitOptions.interpolation
|
|
50
|
+
};
|
|
51
|
+
return safeOptions;
|
|
52
|
+
};
|
|
53
|
+
const cleanupDetectorCacheEntry = (entry)=>{
|
|
54
|
+
if (!entry || !entry.isTemporary) return;
|
|
55
|
+
const instance = entry.instance;
|
|
56
|
+
try {
|
|
57
|
+
instance?.removeAllListeners?.();
|
|
58
|
+
} catch (error) {}
|
|
59
|
+
try {
|
|
60
|
+
instance?.off?.('*');
|
|
61
|
+
} catch (error) {}
|
|
62
|
+
try {
|
|
63
|
+
instance?.services?.backendConnector?.backend?.stop?.();
|
|
64
|
+
} catch (error) {}
|
|
65
|
+
try {
|
|
66
|
+
instance?.services?.backendConnector?.backend?.close?.();
|
|
67
|
+
} catch (error) {}
|
|
68
|
+
};
|
|
69
|
+
function exportServerLngToWindow(context, lng) {
|
|
70
|
+
context.__i18nData__ = {
|
|
71
|
+
lng
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
const getLanguageFromSSRData = (window1)=>{
|
|
75
|
+
try {
|
|
76
|
+
const ssrData = window1._SSR_DATA;
|
|
77
|
+
if (!ssrData || !ssrData.data || !ssrData.data.i18nData) return;
|
|
78
|
+
const lng = ssrData.data.i18nData.lng;
|
|
79
|
+
return 'string' == typeof lng && '' !== lng.trim() ? lng : void 0;
|
|
80
|
+
} catch (error) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
const normalizeLanguageCode = (language)=>{
|
|
85
|
+
if (!language) return language;
|
|
86
|
+
const baseLang = language.split('-')[0];
|
|
87
|
+
return baseLang;
|
|
88
|
+
};
|
|
89
|
+
const isLanguageSupported = (language, supportedLanguages)=>{
|
|
90
|
+
if (!language) return false;
|
|
91
|
+
if (0 === supportedLanguages.length) return true;
|
|
92
|
+
if (supportedLanguages.includes(language)) return true;
|
|
93
|
+
const baseLang = normalizeLanguageCode(language);
|
|
94
|
+
if (baseLang !== language && supportedLanguages.includes(baseLang)) return true;
|
|
95
|
+
return false;
|
|
96
|
+
};
|
|
97
|
+
const getSupportedLanguage = (language, supportedLanguages)=>{
|
|
98
|
+
if (!language) return;
|
|
99
|
+
if (0 === supportedLanguages.length) return language;
|
|
100
|
+
if (supportedLanguages.includes(language)) return language;
|
|
101
|
+
const baseLang = normalizeLanguageCode(language);
|
|
102
|
+
if (baseLang !== language && supportedLanguages.includes(baseLang)) return baseLang;
|
|
103
|
+
};
|
|
104
|
+
const detectLanguageFromSSR = (languages)=>{
|
|
105
|
+
if (!isBrowser()) return;
|
|
106
|
+
try {
|
|
107
|
+
const ssrLanguage = getLanguageFromSSRData(window);
|
|
108
|
+
if (ssrLanguage && isLanguageSupported(ssrLanguage, languages)) return ssrLanguage;
|
|
109
|
+
} catch (error) {}
|
|
110
|
+
};
|
|
111
|
+
const detectLanguageFromPathPriority = (pathname, languages, localePathRedirect)=>{
|
|
112
|
+
if (!localePathRedirect) return;
|
|
113
|
+
if (!languages || 0 === languages.length) return;
|
|
114
|
+
if (!pathname || '' === pathname.trim()) return;
|
|
115
|
+
try {
|
|
116
|
+
const pathDetection = detectLanguageFromPath(pathname, languages, localePathRedirect);
|
|
117
|
+
if (true === pathDetection.detected && pathDetection.language) return pathDetection.language;
|
|
118
|
+
} catch (error) {}
|
|
119
|
+
};
|
|
120
|
+
const createDetectorInstance = (baseInstance, configKey)=>{
|
|
121
|
+
const cached = detectorInstanceCache.get(baseInstance);
|
|
122
|
+
if (cached && cached.configKey === configKey) return {
|
|
123
|
+
instance: cached.instance,
|
|
124
|
+
isTemporary: cached.isTemporary
|
|
125
|
+
};
|
|
126
|
+
if (cached) {
|
|
127
|
+
cleanupDetectorCacheEntry(cached);
|
|
128
|
+
detectorInstanceCache.delete(baseInstance);
|
|
129
|
+
}
|
|
130
|
+
const createNewInstance = ()=>{
|
|
131
|
+
if ('function' == typeof baseInstance.createInstance) try {
|
|
132
|
+
const created = baseInstance.createInstance();
|
|
133
|
+
if (created) return {
|
|
134
|
+
instance: created,
|
|
135
|
+
isTemporary: true
|
|
136
|
+
};
|
|
137
|
+
} catch (error) {}
|
|
138
|
+
if ('function' == typeof baseInstance.cloneInstance) try {
|
|
139
|
+
const cloned = baseInstance.cloneInstance();
|
|
140
|
+
if (cloned) return {
|
|
141
|
+
instance: cloned,
|
|
142
|
+
isTemporary: true
|
|
143
|
+
};
|
|
144
|
+
} catch (error) {}
|
|
145
|
+
return {
|
|
146
|
+
instance: baseInstance,
|
|
147
|
+
isTemporary: false
|
|
148
|
+
};
|
|
149
|
+
};
|
|
150
|
+
const created = createNewInstance();
|
|
151
|
+
if (created.isTemporary) detectorInstanceCache.set(baseInstance, {
|
|
152
|
+
instance: created.instance,
|
|
153
|
+
isTemporary: true,
|
|
154
|
+
configKey
|
|
155
|
+
});
|
|
156
|
+
return created;
|
|
157
|
+
};
|
|
158
|
+
const initializeI18nForDetector = async (i18nInstance, options)=>{
|
|
159
|
+
const mergedDetection = detection_mergeDetectionOptions(options.i18nextDetector, options.detection, options.localePathRedirect, options.userInitOptions);
|
|
160
|
+
const configKey = buildDetectorConfigKey(options.languages, options.fallbackLanguage, mergedDetection);
|
|
161
|
+
const { instance, isTemporary } = createDetectorInstance(i18nInstance, configKey);
|
|
162
|
+
const safeUserOptions = pickSafeDetectionOptions(options.userInitOptions);
|
|
163
|
+
const initOptions = {
|
|
164
|
+
...safeUserOptions,
|
|
165
|
+
fallbackLng: options.fallbackLanguage,
|
|
166
|
+
supportedLngs: options.languages,
|
|
167
|
+
detection: mergedDetection,
|
|
168
|
+
initImmediate: true,
|
|
169
|
+
interpolation: {
|
|
170
|
+
...safeUserOptions?.interpolation || {},
|
|
171
|
+
escapeValue: safeUserOptions?.interpolation?.escapeValue ?? false
|
|
172
|
+
},
|
|
173
|
+
react: {
|
|
174
|
+
useSuspense: false
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
useI18nextLanguageDetector(instance);
|
|
178
|
+
if (instance.isInitialized) {
|
|
179
|
+
if (isTemporary) await instance.init(initOptions);
|
|
180
|
+
} else await instance.init(initOptions);
|
|
181
|
+
return {
|
|
182
|
+
detectorInstance: instance,
|
|
183
|
+
isTemporary
|
|
184
|
+
};
|
|
185
|
+
};
|
|
186
|
+
const detectLanguageFromI18nextDetector = async (i18nInstance, options)=>{
|
|
187
|
+
if (!options.i18nextDetector) return;
|
|
188
|
+
const mergedDetection = detection_mergeDetectionOptions(options.i18nextDetector, options.detection, options.localePathRedirect, options.userInitOptions);
|
|
189
|
+
const { detectorInstance, isTemporary } = await initializeI18nForDetector(i18nInstance, options);
|
|
190
|
+
try {
|
|
191
|
+
const request = options.ssrContext?.request;
|
|
192
|
+
if (!isBrowser() && !request) return;
|
|
193
|
+
const detectorLang = detectLanguage(detectorInstance, request, mergedDetection);
|
|
194
|
+
if (detectorLang) {
|
|
195
|
+
const supportedLang = getSupportedLanguage(detectorLang, options.languages);
|
|
196
|
+
if (supportedLang) return supportedLang;
|
|
197
|
+
}
|
|
198
|
+
if (detectorInstance.isInitialized && detectorInstance.language) {
|
|
199
|
+
const currentLang = detectorInstance.language;
|
|
200
|
+
if (isLanguageSupported(currentLang, options.languages)) return currentLang;
|
|
201
|
+
}
|
|
202
|
+
} catch (error) {} finally{
|
|
203
|
+
if (isTemporary && detectorInstance !== i18nInstance) detectorInstanceCache.set(i18nInstance, {
|
|
204
|
+
instance: detectorInstance,
|
|
205
|
+
isTemporary: true,
|
|
206
|
+
configKey: buildDetectorConfigKey(options.languages, options.fallbackLanguage, mergedDetection)
|
|
207
|
+
});
|
|
208
|
+
else if (detectorInstance === i18nInstance) {
|
|
209
|
+
i18nInstance.isInitialized = false;
|
|
210
|
+
delete i18nInstance.language;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
const detectLanguageWithPriority = async (i18nInstance, options)=>{
|
|
215
|
+
const { languages, fallbackLanguage, localePathRedirect, i18nextDetector, detection, userInitOptions, pathname, ssrContext } = options;
|
|
216
|
+
let detectedLanguage;
|
|
217
|
+
detectedLanguage = detectLanguageFromSSR(languages);
|
|
218
|
+
if (!detectedLanguage) detectedLanguage = detectLanguageFromPathPriority(pathname, languages, localePathRedirect);
|
|
219
|
+
if (!detectedLanguage && i18nextDetector) detectedLanguage = isI18nWrapperInstance(i18nInstance) ? readLanguageFromStorage(detection_mergeDetectionOptions(i18nextDetector, detection, localePathRedirect, userInitOptions)) : await detectLanguageFromI18nextDetector(i18nInstance, {
|
|
220
|
+
languages,
|
|
221
|
+
fallbackLanguage,
|
|
222
|
+
localePathRedirect,
|
|
223
|
+
i18nextDetector,
|
|
224
|
+
detection,
|
|
225
|
+
userInitOptions,
|
|
226
|
+
mergedBackend: options.mergedBackend,
|
|
227
|
+
ssrContext
|
|
228
|
+
});
|
|
229
|
+
const finalLanguage = detectedLanguage || userInitOptions?.lng || fallbackLanguage;
|
|
230
|
+
return {
|
|
231
|
+
detectedLanguage,
|
|
232
|
+
finalLanguage
|
|
233
|
+
};
|
|
234
|
+
};
|
|
235
|
+
const buildInitOptions = (params)=>{
|
|
236
|
+
const { finalLanguage, fallbackLanguage, languages, userInitOptions, mergedDetection, mergeBackend } = params;
|
|
237
|
+
return {
|
|
238
|
+
...userInitOptions || {},
|
|
239
|
+
lng: finalLanguage,
|
|
240
|
+
fallbackLng: fallbackLanguage,
|
|
241
|
+
supportedLngs: languages,
|
|
242
|
+
detection: mergedDetection,
|
|
243
|
+
backend: mergeBackend,
|
|
244
|
+
interpolation: {
|
|
245
|
+
...userInitOptions?.interpolation || {},
|
|
246
|
+
escapeValue: userInitOptions?.interpolation?.escapeValue ?? false
|
|
247
|
+
},
|
|
248
|
+
react: {
|
|
249
|
+
useSuspense: isBrowser()
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
};
|
|
253
|
+
const detection_mergeDetectionOptions = (i18nextDetector, detection, localePathRedirect, userInitOptions)=>{
|
|
254
|
+
let mergedDetection;
|
|
255
|
+
mergedDetection = i18nextDetector ? mergeDetectionOptions(detection, userInitOptions?.detection) : userInitOptions?.detection || {};
|
|
256
|
+
if (!mergedDetection || 'object' != typeof mergedDetection) mergedDetection = {};
|
|
257
|
+
if (localePathRedirect && mergedDetection.order) mergedDetection.order = mergedDetection.order.filter((item)=>'path' !== item);
|
|
258
|
+
return mergedDetection;
|
|
259
|
+
};
|
|
260
|
+
export { buildInitOptions, cacheUserLanguage, detectLanguageWithPriority, exportServerLngToWindow, getLanguageFromSSRData, detection_mergeDetectionOptions as mergeDetectionOptions };
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { isBrowser } from "@modern-js/runtime";
|
|
2
|
+
import i18next_browser_languagedetector from "i18next-browser-languagedetector";
|
|
3
|
+
import { getActualI18nextInstance, isI18nWrapperInstance } from "../instance.js";
|
|
4
|
+
const useI18nextLanguageDetector = (i18nInstance)=>{
|
|
5
|
+
if (!i18nInstance.isInitialized) {
|
|
6
|
+
if (isI18nWrapperInstance(i18nInstance)) {
|
|
7
|
+
const actualInstance = getActualI18nextInstance(i18nInstance);
|
|
8
|
+
if (actualInstance && !actualInstance.isInitialized) actualInstance.use(i18next_browser_languagedetector);
|
|
9
|
+
}
|
|
10
|
+
return i18nInstance.use(i18next_browser_languagedetector);
|
|
11
|
+
}
|
|
12
|
+
return i18nInstance;
|
|
13
|
+
};
|
|
14
|
+
const readLanguageFromStorage = (detectionOptions)=>{
|
|
15
|
+
try {
|
|
16
|
+
const options = detectionOptions || {};
|
|
17
|
+
const order = options.order || [
|
|
18
|
+
'querystring',
|
|
19
|
+
'cookie',
|
|
20
|
+
'localStorage',
|
|
21
|
+
'navigator',
|
|
22
|
+
'htmlTag',
|
|
23
|
+
'path',
|
|
24
|
+
'subdomain'
|
|
25
|
+
];
|
|
26
|
+
for (const method of order)switch(method){
|
|
27
|
+
case 'querystring':
|
|
28
|
+
{
|
|
29
|
+
const lookupKey = options.lookupQuerystring || 'lng';
|
|
30
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
31
|
+
const lang = urlParams.get(lookupKey);
|
|
32
|
+
if (lang) return lang;
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
case 'cookie':
|
|
36
|
+
{
|
|
37
|
+
const lookupKey = options.lookupCookie || 'i18next';
|
|
38
|
+
const cookies = document.cookie.split(';').reduce((acc, item)=>{
|
|
39
|
+
const [key, value] = item.trim().split('=');
|
|
40
|
+
if (key && value) acc[key] = decodeURIComponent(value);
|
|
41
|
+
return acc;
|
|
42
|
+
}, {});
|
|
43
|
+
if (cookies[lookupKey]) return cookies[lookupKey];
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
case 'localStorage':
|
|
47
|
+
{
|
|
48
|
+
const lookupKey = options.lookupLocalStorage || 'i18nextLng';
|
|
49
|
+
const keysToCheck = [
|
|
50
|
+
lookupKey
|
|
51
|
+
];
|
|
52
|
+
if ('i18nextLng' === lookupKey) keysToCheck.push('i18next');
|
|
53
|
+
for (const key of keysToCheck){
|
|
54
|
+
const stored = localStorage.getItem(key);
|
|
55
|
+
if (stored) return stored;
|
|
56
|
+
}
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
case 'navigator':
|
|
60
|
+
if (navigator.language) return navigator.language.split('-')[0];
|
|
61
|
+
break;
|
|
62
|
+
case 'htmlTag':
|
|
63
|
+
{
|
|
64
|
+
const htmlLang = document.documentElement.lang;
|
|
65
|
+
if (htmlLang) return htmlLang.split('-')[0];
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
} catch (error) {}
|
|
70
|
+
};
|
|
71
|
+
const detectLanguage = (i18nInstance, _request, detectionOptions)=>{
|
|
72
|
+
try {
|
|
73
|
+
const actualInstance = isI18nWrapperInstance(i18nInstance) ? getActualI18nextInstance(i18nInstance) : i18nInstance;
|
|
74
|
+
const isInitialized = i18nInstance.isInitialized || actualInstance?.isInitialized;
|
|
75
|
+
const detector = actualInstance?.services?.languageDetector || i18nInstance.services?.languageDetector;
|
|
76
|
+
if (detector && 'function' == typeof detector.detect) {
|
|
77
|
+
const result = detector.detect();
|
|
78
|
+
if ('string' == typeof result) return result;
|
|
79
|
+
if (Array.isArray(result) && result.length > 0) return result[0];
|
|
80
|
+
}
|
|
81
|
+
if (isBrowser()) {
|
|
82
|
+
const directRead = readLanguageFromStorage(detectionOptions);
|
|
83
|
+
if (directRead) return directRead;
|
|
84
|
+
}
|
|
85
|
+
if (isInitialized) {
|
|
86
|
+
const servicesToUse = actualInstance?.services || i18nInstance.services;
|
|
87
|
+
const optionsToUse = actualInstance?.options || i18nInstance.options;
|
|
88
|
+
if (servicesToUse && optionsToUse) {
|
|
89
|
+
const manualDetector = new i18next_browser_languagedetector();
|
|
90
|
+
const mergedOptions = detectionOptions ? {
|
|
91
|
+
...optionsToUse,
|
|
92
|
+
detection: detectionOptions
|
|
93
|
+
} : optionsToUse;
|
|
94
|
+
manualDetector.init(servicesToUse, mergedOptions);
|
|
95
|
+
const result = manualDetector.detect();
|
|
96
|
+
if ('string' == typeof result) return result;
|
|
97
|
+
if (Array.isArray(result) && result.length > 0) return result[0];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
} catch (error) {}
|
|
101
|
+
};
|
|
102
|
+
const cacheUserLanguage = (i18nInstance, language, detectionOptions)=>{
|
|
103
|
+
if ("u" < typeof window) return;
|
|
104
|
+
try {
|
|
105
|
+
const actualInstance = isI18nWrapperInstance(i18nInstance) ? getActualI18nextInstance(i18nInstance) : i18nInstance;
|
|
106
|
+
const detector = actualInstance?.services?.languageDetector || i18nInstance.services?.languageDetector;
|
|
107
|
+
if (detector && 'function' == typeof detector.cacheUserLanguage) try {
|
|
108
|
+
detector.cacheUserLanguage(language);
|
|
109
|
+
return;
|
|
110
|
+
} catch (error) {
|
|
111
|
+
if ('development' === process.env.NODE_ENV) console.warn('[i18n] Failed to cache via detector, falling back to manual cache:', error);
|
|
112
|
+
}
|
|
113
|
+
const isInitialized = i18nInstance.isInitialized || actualInstance?.isInitialized;
|
|
114
|
+
const servicesToUse = actualInstance?.services || i18nInstance.services;
|
|
115
|
+
const optionsToUse = actualInstance?.options || i18nInstance.options;
|
|
116
|
+
if (isInitialized && servicesToUse && optionsToUse) try {
|
|
117
|
+
const userOptions = detectionOptions || optionsToUse?.detection;
|
|
118
|
+
const mergedOptions = userOptions ? {
|
|
119
|
+
...optionsToUse,
|
|
120
|
+
detection: userOptions
|
|
121
|
+
} : optionsToUse;
|
|
122
|
+
const manualDetector = new i18next_browser_languagedetector();
|
|
123
|
+
manualDetector.init(servicesToUse, mergedOptions);
|
|
124
|
+
if ('function' == typeof manualDetector.cacheUserLanguage) return void manualDetector.cacheUserLanguage(language);
|
|
125
|
+
} catch (error) {
|
|
126
|
+
if ('development' === process.env.NODE_ENV) console.warn('[i18n] Failed to create manual detector:', error);
|
|
127
|
+
}
|
|
128
|
+
} catch (error) {
|
|
129
|
+
if ('development' === process.env.NODE_ENV) console.error('Failed to cache user language:', error);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
export { cacheUserLanguage, detectLanguage, readLanguageFromStorage, useI18nextLanguageDetector };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { LanguageDetector } from "i18next-http-middleware";
|
|
2
|
+
const cacheUserLanguage = (_i18nInstance, _language, _detectionOptions)=>{};
|
|
3
|
+
const readLanguageFromStorage = (_detectionOptions)=>{};
|
|
4
|
+
const useI18nextLanguageDetector = (i18nInstance)=>{
|
|
5
|
+
if (!i18nInstance.isInitialized) return i18nInstance.use(LanguageDetector);
|
|
6
|
+
return i18nInstance;
|
|
7
|
+
};
|
|
8
|
+
const detectLanguage = (i18nInstance, request, detectionOptions)=>{
|
|
9
|
+
if (!request) return;
|
|
10
|
+
try {
|
|
11
|
+
const detector = i18nInstance.services?.languageDetector;
|
|
12
|
+
if (detector && 'function' == typeof detector.detect) {
|
|
13
|
+
const result = detector.detect(request, {});
|
|
14
|
+
if ('string' == typeof result) return result;
|
|
15
|
+
if (Array.isArray(result) && result.length > 0) return result[0];
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (i18nInstance.isInitialized && i18nInstance.services && i18nInstance.options) {
|
|
19
|
+
const manualDetector = new LanguageDetector();
|
|
20
|
+
const optionsToUse = detectionOptions ? {
|
|
21
|
+
...i18nInstance.options,
|
|
22
|
+
detection: detectionOptions
|
|
23
|
+
} : i18nInstance.options;
|
|
24
|
+
manualDetector.init(i18nInstance.services, optionsToUse);
|
|
25
|
+
const result = manualDetector.detect(request, {}, void 0);
|
|
26
|
+
if ('string' == typeof result) return result;
|
|
27
|
+
if (Array.isArray(result) && result.length > 0) return result[0];
|
|
28
|
+
}
|
|
29
|
+
} catch (error) {}
|
|
30
|
+
};
|
|
31
|
+
export { cacheUserLanguage, detectLanguage, readLanguageFromStorage, useI18nextLanguageDetector };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
function isI18nWrapperInstance(obj) {
|
|
2
|
+
if (!obj || 'object' != typeof obj) return false;
|
|
3
|
+
if (!obj.i18nInstance || 'object' != typeof obj.i18nInstance) return false;
|
|
4
|
+
if (!obj.i18nInstance.instance) return false;
|
|
5
|
+
if ('function' != typeof obj.init || 'function' != typeof obj.use) return false;
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
function getI18nWrapperI18nextInstance(wrapperInstance) {
|
|
9
|
+
if (isI18nWrapperInstance(wrapperInstance)) return wrapperInstance.i18nInstance?.instance;
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
function getActualI18nextInstance(instance) {
|
|
13
|
+
if (isI18nWrapperInstance(instance)) {
|
|
14
|
+
const i18nextInstance = getI18nWrapperI18nextInstance(instance);
|
|
15
|
+
return i18nextInstance || instance;
|
|
16
|
+
}
|
|
17
|
+
return instance;
|
|
18
|
+
}
|
|
19
|
+
function isI18nInstance(obj) {
|
|
20
|
+
if (!obj || 'object' != typeof obj) return false;
|
|
21
|
+
if (isI18nWrapperInstance(obj)) return true;
|
|
22
|
+
return 'function' == typeof obj.init && 'function' == typeof obj.use;
|
|
23
|
+
}
|
|
24
|
+
async function tryImportI18next() {
|
|
25
|
+
try {
|
|
26
|
+
const i18next = await import("i18next");
|
|
27
|
+
return i18next.default;
|
|
28
|
+
} catch (error) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async function createI18nextInstance() {
|
|
33
|
+
try {
|
|
34
|
+
const i18next = await tryImportI18next();
|
|
35
|
+
if (!i18next) return null;
|
|
36
|
+
return i18next.createInstance({
|
|
37
|
+
initImmediate: false
|
|
38
|
+
});
|
|
39
|
+
} catch (error) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async function tryImportReactI18next() {
|
|
44
|
+
try {
|
|
45
|
+
const reactI18next = await import("react-i18next");
|
|
46
|
+
return reactI18next;
|
|
47
|
+
} catch (error) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function getI18nextInstanceForProvider(instance) {
|
|
52
|
+
if (isI18nWrapperInstance(instance)) {
|
|
53
|
+
const i18nextInstance = getI18nWrapperI18nextInstance(instance);
|
|
54
|
+
if (i18nextInstance) return i18nextInstance;
|
|
55
|
+
}
|
|
56
|
+
return instance;
|
|
57
|
+
}
|
|
58
|
+
async function getI18nInstance(userInstance) {
|
|
59
|
+
if (userInstance) {
|
|
60
|
+
if (isI18nWrapperInstance(userInstance)) return userInstance;
|
|
61
|
+
if (isI18nInstance(userInstance)) return userInstance;
|
|
62
|
+
}
|
|
63
|
+
const i18nextInstance = await createI18nextInstance();
|
|
64
|
+
if (i18nextInstance) return i18nextInstance;
|
|
65
|
+
throw new Error('No i18n instance found');
|
|
66
|
+
}
|
|
67
|
+
async function getInitReactI18next() {
|
|
68
|
+
const reactI18nextModule = await tryImportReactI18next();
|
|
69
|
+
if (reactI18nextModule) return reactI18nextModule.initReactI18next;
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
async function getI18nextProvider() {
|
|
73
|
+
const reactI18nextModule = await tryImportReactI18next();
|
|
74
|
+
if (reactI18nextModule) return reactI18nextModule.I18nextProvider;
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
export { getActualI18nextInstance, getI18nInstance, getI18nWrapperI18nextInstance, getI18nextInstanceForProvider, getI18nextProvider, getInitReactI18next, isI18nInstance, isI18nWrapperInstance };
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { isBrowser } from "@modern-js/runtime";
|
|
2
|
+
import { mergeBackendOptions } from "./backend/index.js";
|
|
3
|
+
import { HttpBackendWithSave, useI18nextBackend } from "./backend/middleware.js";
|
|
4
|
+
import { SdkBackend } from "./backend/sdk-backend.js";
|
|
5
|
+
import { cacheUserLanguage, mergeDetectionOptions } from "./detection/index.js";
|
|
6
|
+
import { getActualI18nextInstance, isI18nInstance, isI18nWrapperInstance } from "./instance.js";
|
|
7
|
+
function assertI18nInstance(obj) {
|
|
8
|
+
if (!isI18nInstance(obj)) throw new Error('Object does not implement I18nInstance interface');
|
|
9
|
+
}
|
|
10
|
+
const buildInitOptions = async (finalLanguage, fallbackLanguage, languages, mergedDetection, mergedBackend, userInitOptions, useSuspense, i18nInstance)=>{
|
|
11
|
+
const defaultUseSuspense = void 0 !== useSuspense ? useSuspense : isBrowser() ? userInitOptions?.react?.useSuspense ?? true : false;
|
|
12
|
+
const isChainedBackend = !!mergedBackend?._useChainedBackend;
|
|
13
|
+
const sanitizedUserInitOptions = userInitOptions ? {
|
|
14
|
+
...userInitOptions,
|
|
15
|
+
backend: void 0
|
|
16
|
+
} : void 0;
|
|
17
|
+
const { backend: _removedBackend, ...userOptionsWithoutBackend } = sanitizedUserInitOptions || {};
|
|
18
|
+
const initOptions = {
|
|
19
|
+
lng: finalLanguage,
|
|
20
|
+
fallbackLng: fallbackLanguage,
|
|
21
|
+
supportedLngs: languages,
|
|
22
|
+
detection: mergedDetection,
|
|
23
|
+
initImmediate: sanitizedUserInitOptions?.initImmediate ?? true,
|
|
24
|
+
interpolation: {
|
|
25
|
+
...sanitizedUserInitOptions?.interpolation || {},
|
|
26
|
+
escapeValue: sanitizedUserInitOptions?.interpolation?.escapeValue ?? false
|
|
27
|
+
},
|
|
28
|
+
react: {
|
|
29
|
+
...sanitizedUserInitOptions?.react || {},
|
|
30
|
+
useSuspense: defaultUseSuspense
|
|
31
|
+
},
|
|
32
|
+
...userOptionsWithoutBackend
|
|
33
|
+
};
|
|
34
|
+
if (mergedBackend) if (isChainedBackend && mergedBackend._chainedBackendConfig) {
|
|
35
|
+
let HttpBackend;
|
|
36
|
+
let SdkBackendClass;
|
|
37
|
+
if (i18nInstance?.options?.backend?.backends && Array.isArray(i18nInstance.options.backend.backends) && i18nInstance.options.backend.backends.length >= 2) {
|
|
38
|
+
HttpBackend = i18nInstance.options.backend.backends[0];
|
|
39
|
+
SdkBackendClass = i18nInstance.options.backend.backends[1];
|
|
40
|
+
} else {
|
|
41
|
+
HttpBackend = HttpBackendWithSave;
|
|
42
|
+
SdkBackendClass = SdkBackend;
|
|
43
|
+
}
|
|
44
|
+
initOptions.backend = {
|
|
45
|
+
backends: [
|
|
46
|
+
HttpBackend,
|
|
47
|
+
SdkBackendClass
|
|
48
|
+
],
|
|
49
|
+
backendOptions: mergedBackend._chainedBackendConfig.backendOptions,
|
|
50
|
+
cacheHitMode: mergedBackend.cacheHitMode || 'refreshAndUpdateStore'
|
|
51
|
+
};
|
|
52
|
+
} else {
|
|
53
|
+
const { _useChainedBackend, _chainedBackendConfig, ...cleanBackend } = mergedBackend || {};
|
|
54
|
+
initOptions.backend = cleanBackend;
|
|
55
|
+
}
|
|
56
|
+
return initOptions;
|
|
57
|
+
};
|
|
58
|
+
const ensureLanguageMatch = async (i18nInstance, finalLanguage)=>{
|
|
59
|
+
if (i18nInstance.language !== finalLanguage) {
|
|
60
|
+
await i18nInstance.setLang?.(finalLanguage);
|
|
61
|
+
await i18nInstance.changeLanguage?.(finalLanguage);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
const changeI18nLanguage = async (i18nInstance, newLang, options)=>{
|
|
65
|
+
if (!newLang || 'string' != typeof newLang) throw new Error('Language must be a non-empty string');
|
|
66
|
+
if (!i18nInstance) throw new Error('i18nInstance is required');
|
|
67
|
+
await i18nInstance.setLang?.(newLang);
|
|
68
|
+
await i18nInstance.changeLanguage?.(newLang);
|
|
69
|
+
if (isBrowser()) {
|
|
70
|
+
const detectionOptions = options?.detectionOptions || i18nInstance.options?.detection;
|
|
71
|
+
cacheUserLanguage(i18nInstance, newLang, detectionOptions);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
const initializeI18nInstance = async (i18nInstance, finalLanguage, fallbackLanguage, languages, mergedDetection, mergedBackend, userInitOptions, useSuspense)=>{
|
|
75
|
+
if (!i18nInstance.isInitialized) {
|
|
76
|
+
const initOptions = await buildInitOptions(finalLanguage, fallbackLanguage, languages, mergedDetection, mergedBackend, userInitOptions, useSuspense, i18nInstance);
|
|
77
|
+
const actualInstance = getActualI18nextInstance(i18nInstance);
|
|
78
|
+
const savedBackendConfig = actualInstance?.options?.backend || i18nInstance.options?.backend;
|
|
79
|
+
const isChainedBackendFromSaved = savedBackendConfig?.backends && Array.isArray(savedBackendConfig.backends);
|
|
80
|
+
await i18nInstance.init(initOptions);
|
|
81
|
+
if (mergedBackend) {
|
|
82
|
+
if (isI18nWrapperInstance(i18nInstance) && actualInstance?.options) {
|
|
83
|
+
if (isChainedBackendFromSaved && initOptions.backend) actualInstance.options.backend = {
|
|
84
|
+
...initOptions.backend,
|
|
85
|
+
backends: savedBackendConfig.backends
|
|
86
|
+
};
|
|
87
|
+
else if (initOptions.backend) actualInstance.options.backend = {
|
|
88
|
+
...actualInstance.options.backend,
|
|
89
|
+
...initOptions.backend
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
if (hasOptions(i18nInstance)) {
|
|
93
|
+
if (isChainedBackendFromSaved && initOptions.backend) i18nInstance.options.backend = {
|
|
94
|
+
...initOptions.backend,
|
|
95
|
+
backends: savedBackendConfig.backends
|
|
96
|
+
};
|
|
97
|
+
else if (initOptions.backend) i18nInstance.options.backend = {
|
|
98
|
+
...i18nInstance.options.backend,
|
|
99
|
+
...initOptions.backend
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (mergedBackend && hasOptions(i18nInstance)) {
|
|
104
|
+
const defaultNS = initOptions.defaultNS || initOptions.ns || 'translation';
|
|
105
|
+
const ns = Array.isArray(defaultNS) ? defaultNS[0] : defaultNS;
|
|
106
|
+
let retries = 20;
|
|
107
|
+
while(retries > 0){
|
|
108
|
+
const actualInstance = getActualI18nextInstance(i18nInstance);
|
|
109
|
+
const store = actualInstance.store;
|
|
110
|
+
if (store?.data?.[finalLanguage]?.[ns]) break;
|
|
111
|
+
await new Promise((resolve)=>setTimeout(resolve, 100));
|
|
112
|
+
retries--;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
function hasOptions(instance) {
|
|
118
|
+
return void 0 !== instance.options && null !== instance.options;
|
|
119
|
+
}
|
|
120
|
+
const setupClonedInstance = async (i18nInstance, finalLanguage, fallbackLanguage, languages, backendEnabled, backend, i18nextDetector, detection, localePathRedirect, userInitOptions)=>{
|
|
121
|
+
const mergedBackend = mergeBackendOptions(backend, userInitOptions);
|
|
122
|
+
const hasSdkConfig = 'function' == typeof userInitOptions?.backend?.sdk || mergedBackend?.sdk && 'function' == typeof mergedBackend.sdk;
|
|
123
|
+
if (backendEnabled || hasSdkConfig) {
|
|
124
|
+
useI18nextBackend(i18nInstance, mergedBackend);
|
|
125
|
+
if (mergedBackend && hasOptions(i18nInstance)) i18nInstance.options.backend = {
|
|
126
|
+
...i18nInstance.options.backend,
|
|
127
|
+
...mergedBackend
|
|
128
|
+
};
|
|
129
|
+
if (i18nInstance.isInitialized) await ensureLanguageMatch(i18nInstance, finalLanguage);
|
|
130
|
+
else {
|
|
131
|
+
const mergedDetection = mergeDetectionOptions(i18nextDetector, detection, localePathRedirect, userInitOptions);
|
|
132
|
+
await initializeI18nInstance(i18nInstance, finalLanguage, fallbackLanguage, languages, mergedDetection, mergedBackend, userInitOptions, false);
|
|
133
|
+
}
|
|
134
|
+
} else await ensureLanguageMatch(i18nInstance, finalLanguage);
|
|
135
|
+
};
|
|
136
|
+
export { assertI18nInstance, buildInitOptions, changeI18nLanguage, ensureLanguageMatch, initializeI18nInstance, setupClonedInstance };
|