@bleedingdev/modern-js-plugin-i18n 3.4.0-ultramodern.1 → 3.4.0-ultramodern.2
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/dist/cjs/cli/index.js +2 -1
- package/dist/cjs/runtime/core.js +204 -0
- package/dist/cjs/runtime/index.js +44 -173
- package/dist/cjs/runtime/no-react-i18next.js +76 -0
- package/dist/esm/cli/index.mjs +2 -1
- package/dist/esm/runtime/core.mjs +139 -0
- package/dist/esm/runtime/index.mjs +5 -140
- package/dist/esm/runtime/no-react-i18next.mjs +6 -0
- package/dist/esm-node/cli/index.mjs +2 -1
- package/dist/esm-node/runtime/core.mjs +140 -0
- package/dist/esm-node/runtime/index.mjs +5 -140
- package/dist/esm-node/runtime/no-react-i18next.mjs +7 -0
- package/dist/types/runtime/core.d.ts +30 -0
- package/dist/types/runtime/index.d.ts +2 -24
- package/dist/types/runtime/no-react-i18next.d.ts +3 -0
- package/package.json +21 -11
- package/rstest.config.mts +1 -0
- package/src/cli/index.ts +6 -1
- package/src/runtime/core.tsx +335 -0
- package/src/runtime/index.tsx +4 -316
- package/src/runtime/no-react-i18next.tsx +7 -0
- package/tests/localisedUrls.test.ts +35 -0
- package/tests/reactI18nextRuntimeBoundary.test.ts +27 -0
|
@@ -1,25 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import type { I18nInitOptions, I18nInstance } from './i18n';
|
|
4
|
-
import './types';
|
|
5
|
-
export type { I18nSdkLoader, I18nSdkLoadOptions } from '../shared/type';
|
|
6
|
-
export type { Resources } from './i18n/instance';
|
|
7
|
-
export interface I18nPluginOptions {
|
|
8
|
-
entryName?: string;
|
|
9
|
-
localeDetection?: BaseLocaleDetectionOptions;
|
|
10
|
-
backend?: BaseBackendOptions;
|
|
11
|
-
i18nInstance?: I18nInstance;
|
|
12
|
-
changeLanguage?: (lang: string) => void;
|
|
13
|
-
initOptions?: I18nInitOptions;
|
|
14
|
-
htmlLangAttr?: boolean;
|
|
15
|
-
reactI18next?: boolean;
|
|
16
|
-
[key: string]: any;
|
|
17
|
-
}
|
|
18
|
-
export declare const i18nPlugin: (options: I18nPluginOptions) => RuntimePlugin;
|
|
19
|
-
export type { AllowedLinkTarget, CanonicalRoutePath, UltramodernCanonicalRoutes, } from './canonicalRoutes';
|
|
20
|
-
export { useModernI18n } from './context';
|
|
21
|
-
export { I18nLink, type I18nLinkProps } from './I18nLink';
|
|
22
|
-
export { Link, type LinkActiveOptions, type LinkBaseProps, type LinkParams, type LinkProps, } from './Link';
|
|
23
|
-
export { canonicalPath, type LocalizedPathsConfig, localizePath, type UseLocalizedLocationReturn, type UseLocalizedPathsReturn, useLocalizedLocation, useLocalizedPaths, } from './localizedPaths';
|
|
24
|
-
export { buildLocalizedUrl, splitUrlTarget } from './utils';
|
|
1
|
+
export * from './core';
|
|
2
|
+
export declare const i18nPlugin: (options: import("./core").I18nPluginOptions) => import("@modern-js/runtime").RuntimePlugin;
|
|
25
3
|
export default i18nPlugin;
|
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"modern",
|
|
18
18
|
"modern.js"
|
|
19
19
|
],
|
|
20
|
-
"version": "3.4.0-ultramodern.
|
|
20
|
+
"version": "3.4.0-ultramodern.2",
|
|
21
21
|
"engines": {
|
|
22
22
|
"node": ">=20"
|
|
23
23
|
},
|
|
@@ -48,6 +48,13 @@
|
|
|
48
48
|
},
|
|
49
49
|
"default": "./dist/esm/runtime/index.mjs"
|
|
50
50
|
},
|
|
51
|
+
"./runtime/no-react-i18next": {
|
|
52
|
+
"types": "./dist/types/runtime/no-react-i18next.d.ts",
|
|
53
|
+
"node": {
|
|
54
|
+
"module": "./dist/esm/runtime/no-react-i18next.mjs"
|
|
55
|
+
},
|
|
56
|
+
"default": "./dist/esm/runtime/no-react-i18next.mjs"
|
|
57
|
+
},
|
|
51
58
|
"./server": {
|
|
52
59
|
"types": "./dist/types/server/index.d.ts",
|
|
53
60
|
"node": {
|
|
@@ -72,6 +79,9 @@
|
|
|
72
79
|
"runtime": [
|
|
73
80
|
"./dist/types/runtime/index.d.ts"
|
|
74
81
|
],
|
|
82
|
+
"runtime/no-react-i18next": [
|
|
83
|
+
"./dist/types/runtime/no-react-i18next.d.ts"
|
|
84
|
+
],
|
|
75
85
|
"server": [
|
|
76
86
|
"./dist/types/server/index.d.ts"
|
|
77
87
|
],
|
|
@@ -87,15 +97,15 @@
|
|
|
87
97
|
"i18next-fs-backend": "^2.6.6",
|
|
88
98
|
"i18next-http-backend": "^4.0.0",
|
|
89
99
|
"i18next-http-middleware": "^3.9.7",
|
|
90
|
-
"@modern-js/
|
|
91
|
-
"@modern-js/
|
|
92
|
-
"@modern-js/
|
|
93
|
-
"@modern-js/
|
|
94
|
-
"@modern-js/
|
|
95
|
-
"@modern-js/
|
|
100
|
+
"@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.4.0-ultramodern.2",
|
|
101
|
+
"@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.4.0-ultramodern.2",
|
|
102
|
+
"@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.4.0-ultramodern.2",
|
|
103
|
+
"@modern-js/types": "npm:@bleedingdev/modern-js-types@3.4.0-ultramodern.2",
|
|
104
|
+
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.4.0-ultramodern.2",
|
|
105
|
+
"@modern-js/server-runtime": "npm:@bleedingdev/modern-js-server-runtime@3.4.0-ultramodern.2"
|
|
96
106
|
},
|
|
97
107
|
"peerDependencies": {
|
|
98
|
-
"@modern-js/runtime": "3.4.0-ultramodern.
|
|
108
|
+
"@modern-js/runtime": "3.4.0-ultramodern.2",
|
|
99
109
|
"i18next": ">=26.3.1",
|
|
100
110
|
"react": "^19.2.7",
|
|
101
111
|
"react-dom": "^19.2.7",
|
|
@@ -111,7 +121,7 @@
|
|
|
111
121
|
},
|
|
112
122
|
"devDependencies": {
|
|
113
123
|
"@rslib/core": "0.23.0",
|
|
114
|
-
"@types/node": "^26.0.
|
|
124
|
+
"@types/node": "^26.0.1",
|
|
115
125
|
"@typescript/native-preview": "7.0.0-dev.20260624.1",
|
|
116
126
|
"i18next": "26.3.2",
|
|
117
127
|
"react": "^19.2.7",
|
|
@@ -119,8 +129,8 @@
|
|
|
119
129
|
"react-i18next": "17.0.8",
|
|
120
130
|
"ts-node": "^10.9.2",
|
|
121
131
|
"typescript": "^6.0.3",
|
|
122
|
-
"@modern-js/
|
|
123
|
-
"@modern-js/
|
|
132
|
+
"@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.4.0-ultramodern.2",
|
|
133
|
+
"@modern-js/runtime": "npm:@bleedingdev/modern-js-runtime@3.4.0-ultramodern.2"
|
|
124
134
|
},
|
|
125
135
|
"sideEffects": false,
|
|
126
136
|
"publishConfig": {
|
package/rstest.config.mts
CHANGED
package/src/cli/index.ts
CHANGED
|
@@ -126,10 +126,15 @@ export const i18nPlugin = (
|
|
|
126
126
|
backend: backendOptions,
|
|
127
127
|
...extendedConfig,
|
|
128
128
|
};
|
|
129
|
+
const runtimePluginPath =
|
|
130
|
+
customPlugin?.runtime?.path ||
|
|
131
|
+
(config.reactI18next === false
|
|
132
|
+
? `@${metaName}/plugin-i18n/runtime/no-react-i18next`
|
|
133
|
+
: `@${metaName}/plugin-i18n/runtime`);
|
|
129
134
|
|
|
130
135
|
plugins.push({
|
|
131
136
|
name: customPlugin?.runtime?.name || 'i18n',
|
|
132
|
-
path:
|
|
137
|
+
path: runtimePluginPath,
|
|
133
138
|
config,
|
|
134
139
|
});
|
|
135
140
|
return {
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isBrowser,
|
|
3
|
+
RuntimeContext,
|
|
4
|
+
type RuntimePlugin,
|
|
5
|
+
} from '@modern-js/runtime';
|
|
6
|
+
import { Helmet } from '@modern-js/runtime/head';
|
|
7
|
+
import type { TInternalRuntimeContext } from '@modern-js/runtime/internal';
|
|
8
|
+
import { merge } from '@modern-js/runtime-utils/merge';
|
|
9
|
+
import type React from 'react';
|
|
10
|
+
import { useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
11
|
+
import type {
|
|
12
|
+
BaseBackendOptions,
|
|
13
|
+
BaseLocaleDetectionOptions,
|
|
14
|
+
} from '../shared/type';
|
|
15
|
+
import { ModernI18nProvider } from './context';
|
|
16
|
+
import {
|
|
17
|
+
createContextValue,
|
|
18
|
+
useClientSideRedirect,
|
|
19
|
+
useLanguageSync,
|
|
20
|
+
useSdkResourcesLoader,
|
|
21
|
+
} from './hooks';
|
|
22
|
+
import type { I18nInitOptions, I18nInstance } from './i18n';
|
|
23
|
+
import { getI18nInstance } from './i18n';
|
|
24
|
+
import { mergeBackendOptions } from './i18n/backend';
|
|
25
|
+
import { useI18nextBackend } from './i18n/backend/middleware';
|
|
26
|
+
import {
|
|
27
|
+
detectLanguageWithPriority,
|
|
28
|
+
exportServerLngToWindow,
|
|
29
|
+
mergeDetectionOptions,
|
|
30
|
+
} from './i18n/detection';
|
|
31
|
+
import { useI18nextLanguageDetector } from './i18n/detection/middleware';
|
|
32
|
+
import { getI18nextInstanceForProvider } from './i18n/instance';
|
|
33
|
+
import {
|
|
34
|
+
changeI18nLanguage,
|
|
35
|
+
ensureLanguageMatch,
|
|
36
|
+
initializeI18nInstance,
|
|
37
|
+
setupClonedInstance,
|
|
38
|
+
} from './i18n/utils';
|
|
39
|
+
import { getPathname } from './utils';
|
|
40
|
+
import './types';
|
|
41
|
+
|
|
42
|
+
export type { I18nSdkLoader, I18nSdkLoadOptions } from '../shared/type';
|
|
43
|
+
export type { Resources } from './i18n/instance';
|
|
44
|
+
|
|
45
|
+
export interface I18nPluginOptions {
|
|
46
|
+
entryName?: string;
|
|
47
|
+
localeDetection?: BaseLocaleDetectionOptions;
|
|
48
|
+
backend?: BaseBackendOptions;
|
|
49
|
+
i18nInstance?: I18nInstance;
|
|
50
|
+
changeLanguage?: (lang: string) => void;
|
|
51
|
+
initOptions?: I18nInitOptions;
|
|
52
|
+
htmlLangAttr?: boolean;
|
|
53
|
+
reactI18next?: boolean;
|
|
54
|
+
[key: string]: any;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
interface RuntimeContextWithI18n extends TInternalRuntimeContext {
|
|
58
|
+
i18nInstance?: I18nInstance;
|
|
59
|
+
changeLanguage?: (lang: string) => Promise<void>;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface ReactI18nextIntegration {
|
|
63
|
+
I18nextProvider: React.ComponentType<any> | null;
|
|
64
|
+
initReactI18next: any | null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export type LoadReactI18nextIntegration =
|
|
68
|
+
() => Promise<ReactI18nextIntegration | null>;
|
|
69
|
+
|
|
70
|
+
export const createI18nPlugin =
|
|
71
|
+
(
|
|
72
|
+
loadReactI18nextIntegration?: LoadReactI18nextIntegration,
|
|
73
|
+
): ((options: I18nPluginOptions) => RuntimePlugin) =>
|
|
74
|
+
(options: I18nPluginOptions): RuntimePlugin => ({
|
|
75
|
+
name: '@modern-js/plugin-i18n',
|
|
76
|
+
setup: api => {
|
|
77
|
+
const {
|
|
78
|
+
entryName,
|
|
79
|
+
i18nInstance: userI18nInstance,
|
|
80
|
+
initOptions,
|
|
81
|
+
localeDetection,
|
|
82
|
+
backend,
|
|
83
|
+
htmlLangAttr = false,
|
|
84
|
+
reactI18next = true,
|
|
85
|
+
} = options;
|
|
86
|
+
const {
|
|
87
|
+
localePathRedirect = false,
|
|
88
|
+
i18nextDetector = true,
|
|
89
|
+
languages = [],
|
|
90
|
+
fallbackLanguage = 'en',
|
|
91
|
+
detection,
|
|
92
|
+
ignoreRedirectRoutes,
|
|
93
|
+
localisedUrls,
|
|
94
|
+
} = localeDetection || {};
|
|
95
|
+
const { enabled: backendEnabled = false } = backend || {};
|
|
96
|
+
let latestI18nInstance: I18nInstance | undefined;
|
|
97
|
+
let I18nextProvider: React.ComponentType<any> | null;
|
|
98
|
+
|
|
99
|
+
const resolveReactI18nextIntegration = async () => {
|
|
100
|
+
if (!reactI18next) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
return loadReactI18nextIntegration?.() ?? null;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
api.onBeforeRender(async context => {
|
|
107
|
+
let i18nInstance = await getI18nInstance(userI18nInstance);
|
|
108
|
+
const { i18n: otherConfig } = api.getRuntimeConfig();
|
|
109
|
+
const { initOptions: otherInitOptions } = otherConfig || {};
|
|
110
|
+
const userInitOptions = merge(
|
|
111
|
+
otherInitOptions || {},
|
|
112
|
+
initOptions || {},
|
|
113
|
+
);
|
|
114
|
+
const reactI18nextIntegration = await resolveReactI18nextIntegration();
|
|
115
|
+
I18nextProvider = reactI18nextIntegration?.I18nextProvider ?? null;
|
|
116
|
+
if (reactI18nextIntegration?.initReactI18next) {
|
|
117
|
+
i18nInstance.use(reactI18nextIntegration.initReactI18next);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const pathname = getPathname(context);
|
|
121
|
+
|
|
122
|
+
if (i18nextDetector) {
|
|
123
|
+
useI18nextLanguageDetector(i18nInstance);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const mergedDetection = mergeDetectionOptions(
|
|
127
|
+
i18nextDetector,
|
|
128
|
+
detection,
|
|
129
|
+
localePathRedirect,
|
|
130
|
+
userInitOptions,
|
|
131
|
+
);
|
|
132
|
+
const mergedBackend = mergeBackendOptions(backend, userInitOptions);
|
|
133
|
+
|
|
134
|
+
// Register Backend BEFORE detectLanguageWithPriority
|
|
135
|
+
// This is critical because detectLanguageWithPriority may trigger init()
|
|
136
|
+
// through i18next detector, and backend must be registered before init()
|
|
137
|
+
// Register backend if:
|
|
138
|
+
// 1. enabled is true (explicitly or auto-detected), OR
|
|
139
|
+
// 2. SDK is configured (allows standalone SDK usage even without locales directory)
|
|
140
|
+
const hasSdkConfig =
|
|
141
|
+
typeof userInitOptions?.backend?.sdk === 'function' ||
|
|
142
|
+
(mergedBackend?.sdk && typeof mergedBackend.sdk === 'function');
|
|
143
|
+
if (mergedBackend && (backendEnabled || hasSdkConfig)) {
|
|
144
|
+
useI18nextBackend(i18nInstance, mergedBackend);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const { finalLanguage } = await detectLanguageWithPriority(
|
|
148
|
+
i18nInstance,
|
|
149
|
+
{
|
|
150
|
+
languages,
|
|
151
|
+
fallbackLanguage,
|
|
152
|
+
localePathRedirect,
|
|
153
|
+
i18nextDetector,
|
|
154
|
+
detection,
|
|
155
|
+
userInitOptions,
|
|
156
|
+
mergedBackend,
|
|
157
|
+
pathname,
|
|
158
|
+
ssrContext: context.ssrContext,
|
|
159
|
+
},
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
await initializeI18nInstance(
|
|
163
|
+
i18nInstance,
|
|
164
|
+
finalLanguage,
|
|
165
|
+
fallbackLanguage,
|
|
166
|
+
languages,
|
|
167
|
+
mergedDetection,
|
|
168
|
+
mergedBackend,
|
|
169
|
+
userInitOptions,
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
if (!isBrowser() && i18nInstance.cloneInstance) {
|
|
173
|
+
i18nInstance = i18nInstance.cloneInstance();
|
|
174
|
+
await setupClonedInstance(
|
|
175
|
+
i18nInstance,
|
|
176
|
+
finalLanguage,
|
|
177
|
+
fallbackLanguage,
|
|
178
|
+
languages,
|
|
179
|
+
backendEnabled,
|
|
180
|
+
backend,
|
|
181
|
+
i18nextDetector,
|
|
182
|
+
detection,
|
|
183
|
+
localePathRedirect,
|
|
184
|
+
userInitOptions,
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (localePathRedirect) {
|
|
189
|
+
await ensureLanguageMatch(i18nInstance, finalLanguage);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (!isBrowser()) {
|
|
193
|
+
exportServerLngToWindow(context, finalLanguage);
|
|
194
|
+
}
|
|
195
|
+
context.i18nInstance = i18nInstance;
|
|
196
|
+
latestI18nInstance = i18nInstance;
|
|
197
|
+
|
|
198
|
+
// Add changeLanguage method to context for other runtime plugins to use
|
|
199
|
+
context.changeLanguage = async (newLang: string) => {
|
|
200
|
+
await changeI18nLanguage(i18nInstance, newLang, {
|
|
201
|
+
detectionOptions: mergedDetection,
|
|
202
|
+
});
|
|
203
|
+
};
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
api.wrapRoot(App => {
|
|
207
|
+
return props => {
|
|
208
|
+
const runtimeContext = useContext(
|
|
209
|
+
RuntimeContext,
|
|
210
|
+
) as RuntimeContextWithI18n;
|
|
211
|
+
const i18nInstance =
|
|
212
|
+
runtimeContext.i18nInstance || latestI18nInstance;
|
|
213
|
+
const initialLang = useMemo(
|
|
214
|
+
() =>
|
|
215
|
+
i18nInstance?.language ||
|
|
216
|
+
(localeDetection?.fallbackLanguage ?? 'en'),
|
|
217
|
+
[i18nInstance?.language, localeDetection?.fallbackLanguage],
|
|
218
|
+
);
|
|
219
|
+
const [lang, setLang] = useState(initialLang);
|
|
220
|
+
const [forceUpdate, setForceUpdate] = useState(0);
|
|
221
|
+
const prevLangRef = useRef(lang);
|
|
222
|
+
const runtimeContextRef = useRef(runtimeContext);
|
|
223
|
+
runtimeContextRef.current = runtimeContext;
|
|
224
|
+
|
|
225
|
+
useEffect(() => {
|
|
226
|
+
if (i18nInstance?.language) {
|
|
227
|
+
const translator = (i18nInstance as any).translator;
|
|
228
|
+
if (translator) {
|
|
229
|
+
translator.language = i18nInstance.language;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}, [i18nInstance?.language]);
|
|
233
|
+
|
|
234
|
+
useEffect(() => {
|
|
235
|
+
prevLangRef.current = lang;
|
|
236
|
+
}, [lang]);
|
|
237
|
+
|
|
238
|
+
useSdkResourcesLoader(i18nInstance, setForceUpdate);
|
|
239
|
+
useLanguageSync(
|
|
240
|
+
i18nInstance,
|
|
241
|
+
localePathRedirect,
|
|
242
|
+
languages,
|
|
243
|
+
runtimeContextRef,
|
|
244
|
+
prevLangRef,
|
|
245
|
+
setLang,
|
|
246
|
+
);
|
|
247
|
+
// Handle client-side redirect for static deployments
|
|
248
|
+
// Note: This hook only executes in browser environment and skips SSR scenarios
|
|
249
|
+
useClientSideRedirect(
|
|
250
|
+
i18nInstance,
|
|
251
|
+
localePathRedirect,
|
|
252
|
+
languages,
|
|
253
|
+
fallbackLanguage,
|
|
254
|
+
ignoreRedirectRoutes,
|
|
255
|
+
localisedUrls,
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
const contextValue = useMemo(
|
|
259
|
+
() =>
|
|
260
|
+
createContextValue(
|
|
261
|
+
lang,
|
|
262
|
+
i18nInstance,
|
|
263
|
+
entryName,
|
|
264
|
+
languages,
|
|
265
|
+
localePathRedirect,
|
|
266
|
+
ignoreRedirectRoutes,
|
|
267
|
+
localisedUrls,
|
|
268
|
+
setLang,
|
|
269
|
+
),
|
|
270
|
+
[
|
|
271
|
+
lang,
|
|
272
|
+
i18nInstance,
|
|
273
|
+
entryName,
|
|
274
|
+
languages,
|
|
275
|
+
localePathRedirect,
|
|
276
|
+
ignoreRedirectRoutes,
|
|
277
|
+
localisedUrls,
|
|
278
|
+
forceUpdate,
|
|
279
|
+
],
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
const children = (props as React.PropsWithChildren).children;
|
|
283
|
+
const appContent = (
|
|
284
|
+
<>
|
|
285
|
+
{Boolean(htmlLangAttr) && <Helmet htmlAttributes={{ lang }} />}
|
|
286
|
+
<ModernI18nProvider value={contextValue}>
|
|
287
|
+
{App ? <App {...props}>{children}</App> : children}
|
|
288
|
+
</ModernI18nProvider>
|
|
289
|
+
</>
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
if (!i18nInstance) {
|
|
293
|
+
return appContent;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (I18nextProvider) {
|
|
297
|
+
const i18nextInstanceForProvider =
|
|
298
|
+
getI18nextInstanceForProvider(i18nInstance);
|
|
299
|
+
return (
|
|
300
|
+
<I18nextProvider i18n={i18nextInstanceForProvider}>
|
|
301
|
+
{appContent}
|
|
302
|
+
</I18nextProvider>
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return appContent;
|
|
307
|
+
};
|
|
308
|
+
});
|
|
309
|
+
},
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
export type {
|
|
313
|
+
AllowedLinkTarget,
|
|
314
|
+
CanonicalRoutePath,
|
|
315
|
+
UltramodernCanonicalRoutes,
|
|
316
|
+
} from './canonicalRoutes';
|
|
317
|
+
export { useModernI18n } from './context';
|
|
318
|
+
export { I18nLink, type I18nLinkProps } from './I18nLink';
|
|
319
|
+
export {
|
|
320
|
+
Link,
|
|
321
|
+
type LinkActiveOptions,
|
|
322
|
+
type LinkBaseProps,
|
|
323
|
+
type LinkParams,
|
|
324
|
+
type LinkProps,
|
|
325
|
+
} from './Link';
|
|
326
|
+
export {
|
|
327
|
+
canonicalPath,
|
|
328
|
+
type LocalizedPathsConfig,
|
|
329
|
+
localizePath,
|
|
330
|
+
type UseLocalizedLocationReturn,
|
|
331
|
+
type UseLocalizedPathsReturn,
|
|
332
|
+
useLocalizedLocation,
|
|
333
|
+
useLocalizedPaths,
|
|
334
|
+
} from './localizedPaths';
|
|
335
|
+
export { buildLocalizedUrl, splitUrlTarget } from './utils';
|