@bleedingdev/modern-js-plugin-i18n 3.9.0-ultramodern.2 → 3.9.0-ultramodern.21
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 +10 -21
- package/dist/cjs/cli/localisedRoutes.js +47 -0
- package/dist/cjs/runtime/Link.js +19 -32
- package/dist/cjs/runtime/context.js +30 -73
- package/dist/cjs/runtime/contextHelpers.js +5 -5
- package/dist/cjs/runtime/contexts.js +49 -0
- package/dist/cjs/runtime/core.js +27 -14
- package/dist/cjs/runtime/hooks.js +7 -8
- package/dist/cjs/runtime/localizedPaths.js +11 -9
- package/dist/cjs/runtime/navigation.js +48 -0
- package/dist/cjs/runtime/providerComposition.js +37 -13
- package/dist/cjs/runtime/routerAdapter.js +33 -140
- package/dist/cjs/runtime/sharedContexts.js +43 -0
- package/dist/cjs/runtime/utils.js +21 -19
- package/dist/cjs/server/defaultUrlStrategy.js +48 -0
- package/dist/cjs/server/index.js +11 -7
- package/dist/cjs/server/mappedUrlStrategy.js +43 -0
- package/dist/cjs/server/redirectPolicy.js +33 -24
- package/dist/cjs/shared/mappedUrlStrategy.js +63 -0
- package/dist/cjs/shared/urlStrategy.js +48 -0
- package/dist/esm/cli/index.mjs +10 -21
- package/dist/esm/cli/localisedRoutes.mjs +9 -0
- package/dist/esm/runtime/Link.mjs +19 -32
- package/dist/esm/runtime/context.mjs +20 -72
- package/dist/esm/runtime/contextHelpers.mjs +5 -5
- package/dist/esm/runtime/contexts.mjs +5 -0
- package/dist/esm/runtime/core.mjs +13 -6
- package/dist/esm/runtime/hooks.mjs +7 -8
- package/dist/esm/runtime/localizedPaths.mjs +11 -9
- package/dist/esm/runtime/navigation.mjs +7 -0
- package/dist/esm/runtime/providerComposition.mjs +38 -14
- package/dist/esm/runtime/routerAdapter.mjs +28 -141
- package/dist/esm/runtime/sharedContexts.mjs +1 -0
- package/dist/esm/runtime/utils.mjs +19 -17
- package/dist/esm/server/defaultUrlStrategy.mjs +7 -0
- package/dist/esm/server/index.mjs +11 -7
- package/dist/esm/server/mappedUrlStrategy.mjs +1 -0
- package/dist/esm/server/redirectPolicy.mjs +33 -24
- package/dist/esm/shared/mappedUrlStrategy.mjs +19 -0
- package/dist/esm/shared/urlStrategy.mjs +7 -0
- package/dist/esm-node/cli/index.mjs +10 -21
- package/dist/esm-node/cli/localisedRoutes.mjs +10 -0
- package/dist/esm-node/runtime/Link.mjs +19 -32
- package/dist/esm-node/runtime/context.mjs +20 -72
- package/dist/esm-node/runtime/contextHelpers.mjs +5 -5
- package/dist/esm-node/runtime/contexts.mjs +6 -0
- package/dist/esm-node/runtime/core.mjs +13 -6
- package/dist/esm-node/runtime/hooks.mjs +7 -8
- package/dist/esm-node/runtime/localizedPaths.mjs +11 -9
- package/dist/esm-node/runtime/navigation.mjs +8 -0
- package/dist/esm-node/runtime/providerComposition.mjs +38 -14
- package/dist/esm-node/runtime/routerAdapter.mjs +28 -141
- package/dist/esm-node/runtime/sharedContexts.mjs +2 -0
- package/dist/esm-node/runtime/utils.mjs +19 -17
- package/dist/esm-node/server/defaultUrlStrategy.mjs +8 -0
- package/dist/esm-node/server/index.mjs +11 -7
- package/dist/esm-node/server/mappedUrlStrategy.mjs +2 -0
- package/dist/esm-node/server/redirectPolicy.mjs +33 -24
- package/dist/esm-node/shared/mappedUrlStrategy.mjs +20 -0
- package/dist/esm-node/shared/urlStrategy.mjs +8 -0
- package/dist/types/cli/localisedRoutes.d.ts +19 -0
- package/dist/types/runtime/context.d.ts +8 -11
- package/dist/types/runtime/contextHelpers.d.ts +2 -2
- package/dist/types/runtime/contexts.d.ts +6 -0
- package/dist/types/runtime/core.d.ts +12 -2
- package/dist/types/runtime/hooks.d.ts +4 -5
- package/dist/types/runtime/localizedPaths.d.ts +4 -4
- package/dist/types/runtime/navigation.d.ts +10 -0
- package/dist/types/runtime/providerComposition.d.ts +13 -1
- package/dist/types/runtime/routerAdapter.d.ts +23 -6
- package/dist/types/runtime/sharedContexts.d.ts +1 -0
- package/dist/types/runtime/utils.d.ts +4 -12
- package/dist/types/server/defaultUrlStrategy.d.ts +11 -0
- package/dist/types/server/index.d.ts +2 -0
- package/dist/types/server/mappedUrlStrategy.d.ts +7 -0
- package/dist/types/server/redirectPolicy.d.ts +5 -13
- package/dist/types/shared/mappedUrlStrategy.d.ts +27 -0
- package/dist/types/shared/type.d.ts +7 -11
- package/dist/types/shared/urlStrategy.d.ts +18 -0
- package/package.json +42 -19
- package/rslib.config.mts +8 -1
- package/rstest.config.mts +6 -5
- package/src/cli/index.ts +42 -42
- package/src/cli/localisedRoutes.ts +53 -0
- package/src/runtime/Link.tsx +20 -40
- package/src/runtime/context.tsx +33 -157
- package/src/runtime/contextHelpers.ts +7 -5
- package/src/runtime/contexts.ts +16 -0
- package/src/runtime/core.tsx +53 -6
- package/src/runtime/hooks.ts +14 -9
- package/src/runtime/i18n/instance.ts +1 -2
- package/src/runtime/localizedPaths.ts +24 -19
- package/src/runtime/navigation.tsx +20 -0
- package/src/runtime/providerComposition.tsx +71 -23
- package/src/runtime/routerAdapter.tsx +65 -339
- package/src/runtime/sharedContexts.ts +8 -0
- package/src/runtime/utils.ts +49 -31
- package/src/server/defaultUrlStrategy.ts +27 -0
- package/src/server/index.ts +39 -9
- package/src/server/mappedUrlStrategy.ts +10 -0
- package/src/server/redirectPolicy.ts +85 -70
- package/src/shared/mappedUrlStrategy.ts +59 -0
- package/src/shared/type.ts +7 -11
- package/src/shared/urlStrategy.ts +38 -0
- package/tests/backendDefaults.test.ts +2 -23
- package/tests/defaultUrlStrategy.test.ts +107 -0
- package/tests/federatedI18nBoundaryResolver.test.tsx +65 -0
- package/tests/i18nUtils.test.ts +31 -65
- package/tests/link.test.tsx +13 -511
- package/tests/localisedRouteGeneration.test.ts +200 -0
- package/tests/localisedUrls.test.ts +16 -208
- package/tests/mappedUrlStrategyDerivation.test.ts +62 -0
- package/tests/navigation.test.tsx +403 -0
- package/tests/reactI18nextRuntimeBoundary.test.ts +8 -83
- package/tests/redirectPolicy.test.ts +89 -27
- package/tests/routerAdapter.test.tsx +98 -1171
- package/tests/urlStrategySerialization.test.ts +122 -0
- package/tsconfig.json +4 -2
- package/tests/federatedI18nBoundary.client.test.tsx +0 -129
- package/tests/federatedI18nBoundary.test.tsx +0 -132
- package/tests/linkTypes.test.ts +0 -59
- package/tests/localisedUrlRewriteMatrix.fork.test.ts +0 -147
- package/tests/peerCohort.test.ts +0 -25
- package/tests/type-fixture/fixture-globals.d.ts +0 -11
- package/tests/type-fixture/i18nInstanceTypes.fixture.ts +0 -29
- package/tests/type-fixture/linkTypes.fixture.tsx +0 -51
- package/tests/type-fixture/tsconfig.json +0 -16
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, getters, values)=>{
|
|
5
|
+
var define = (defs, kind)=>{
|
|
6
|
+
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
[kind]: defs[key]
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
define(getters, "get");
|
|
12
|
+
define(values, "value");
|
|
13
|
+
};
|
|
14
|
+
})();
|
|
15
|
+
(()=>{
|
|
16
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
17
|
+
})();
|
|
18
|
+
(()=>{
|
|
19
|
+
__webpack_require__.r = (exports1)=>{
|
|
20
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
21
|
+
value: 'Module'
|
|
22
|
+
});
|
|
23
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
24
|
+
value: true
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
})();
|
|
28
|
+
var __webpack_exports__ = {};
|
|
29
|
+
__webpack_require__.r(__webpack_exports__);
|
|
30
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
31
|
+
createMappedUrlStrategy: ()=>mappedUrlStrategy_js_namespaceObject.createMappedUrlStrategy,
|
|
32
|
+
resolveMappedUrlStrategy: ()=>mappedUrlStrategy_js_namespaceObject.resolveMappedUrlStrategy
|
|
33
|
+
});
|
|
34
|
+
const mappedUrlStrategy_js_namespaceObject = require("../shared/mappedUrlStrategy.js");
|
|
35
|
+
exports.createMappedUrlStrategy = __webpack_exports__.createMappedUrlStrategy;
|
|
36
|
+
exports.resolveMappedUrlStrategy = __webpack_exports__.resolveMappedUrlStrategy;
|
|
37
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
38
|
+
"createMappedUrlStrategy",
|
|
39
|
+
"resolveMappedUrlStrategy"
|
|
40
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
41
|
+
Object.defineProperty(exports, '__esModule', {
|
|
42
|
+
value: true
|
|
43
|
+
});
|
|
@@ -34,42 +34,51 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
34
34
|
isStaticResourceRequest: ()=>isStaticResourceRequest,
|
|
35
35
|
shouldIgnoreRedirect: ()=>shouldIgnoreRedirect
|
|
36
36
|
});
|
|
37
|
-
const
|
|
37
|
+
const mappedUrlStrategy_js_namespaceObject = require("../shared/mappedUrlStrategy.js");
|
|
38
|
+
const urlStrategy_js_namespaceObject = require("../shared/urlStrategy.js");
|
|
38
39
|
const stripUrlPathPrefix = (pathname, urlPath)=>{
|
|
39
40
|
const basePath = urlPath.replace('/*', '');
|
|
40
41
|
if (!basePath || '/' === basePath) return pathname;
|
|
41
|
-
|
|
42
|
-
return remainingPath || '/';
|
|
42
|
+
return pathname === basePath || pathname.startsWith(`${basePath}/`) ? pathname.slice(basePath.length) || '/' : pathname;
|
|
43
43
|
};
|
|
44
|
-
const shouldIgnoreRedirect = (pathname, urlPath, ignoreRedirectRoutes)=>{
|
|
44
|
+
const shouldIgnoreRedirect = (pathname, urlPath, ignoreRedirectRoutes, urlStrategy, languages = [])=>{
|
|
45
45
|
const remainingPath = stripUrlPathPrefix(pathname, urlPath);
|
|
46
|
-
|
|
46
|
+
if ((0, mappedUrlStrategy_js_namespaceObject.isDefaultLocaleRedirectSkipPath)(remainingPath, languages)) return true;
|
|
47
|
+
if ((0, urlStrategy_js_namespaceObject.asI18nUrlStrategy)(urlStrategy)?.shouldSkipRedirect?.(remainingPath, languages)) return true;
|
|
48
|
+
if (!ignoreRedirectRoutes) return false;
|
|
49
|
+
const segments = remainingPath.split('/').filter(Boolean);
|
|
50
|
+
if (segments[0] && languages.some((language)=>language.toLowerCase() === segments[0].toLowerCase())) segments.shift();
|
|
51
|
+
const normalizedPath = `/${segments.join('/')}`;
|
|
52
|
+
return 'function' == typeof ignoreRedirectRoutes ? ignoreRedirectRoutes(normalizedPath) : ignoreRedirectRoutes.some((pattern)=>normalizedPath === pattern || normalizedPath.startsWith(`${pattern}/`));
|
|
47
53
|
};
|
|
48
54
|
const isStaticResourceRequest = (pathname, staticRoutePrefixes, languages = [])=>{
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
const prefixes = [
|
|
56
|
+
...staticRoutePrefixes,
|
|
57
|
+
'/static',
|
|
58
|
+
'/upload'
|
|
59
|
+
];
|
|
60
|
+
const matches = (target)=>prefixes.some((prefix)=>target === prefix || target.startsWith(`${prefix}/`));
|
|
61
|
+
if (matches(pathname)) return true;
|
|
62
|
+
const segments = pathname.split('/').filter(Boolean);
|
|
63
|
+
if (segments[0] && languages.some((language)=>language.toLowerCase() === segments[0].toLowerCase())) return matches(`/${segments.slice(1).join('/')}`);
|
|
64
|
+
return false;
|
|
54
65
|
};
|
|
55
66
|
const getLanguageFromPath = (req, urlPath, languages)=>{
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
const firstSegment = segments[0];
|
|
61
|
-
if (languages.includes(firstSegment)) return firstSegment;
|
|
62
|
-
return null;
|
|
67
|
+
const host = req.header?.().host;
|
|
68
|
+
const url = new URL(req.url, host ? `http://${host}` : void 0);
|
|
69
|
+
const firstSegment = stripUrlPathPrefix(url.pathname, urlPath).split('/').filter(Boolean)[0];
|
|
70
|
+
return languages.find((language)=>language.toLowerCase() === firstSegment?.toLowerCase()) ?? null;
|
|
63
71
|
};
|
|
64
|
-
const buildLocalizedUrl = (req, urlPath, language, languages,
|
|
72
|
+
const buildLocalizedUrl = (req, urlPath, language, languages, urlStrategy)=>{
|
|
65
73
|
const url = new URL(req.url);
|
|
66
|
-
const pathname = url.pathname;
|
|
67
74
|
const basePath = urlPath.replace('/*', '');
|
|
68
|
-
const remainingPath = stripUrlPathPrefix(pathname, urlPath);
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
75
|
+
const remainingPath = stripUrlPathPrefix(url.pathname, urlPath);
|
|
76
|
+
const segments = remainingPath.split('/').filter(Boolean);
|
|
77
|
+
if (segments[0] && languages.some((item)=>item.toLowerCase() === segments[0].toLowerCase())) segments[0] = language;
|
|
78
|
+
else segments.unshift(language);
|
|
79
|
+
const strategy = (0, urlStrategy_js_namespaceObject.asI18nUrlStrategy)(urlStrategy);
|
|
80
|
+
const pathname = strategy ? strategy.localizePathname(remainingPath, language, languages) : `/${segments.join('/')}`;
|
|
81
|
+
return `${'/' === basePath ? '' : basePath}${pathname}${url.search}${url.hash}`;
|
|
73
82
|
};
|
|
74
83
|
const createLocaleRedirectResponse = (location)=>new Response(null, {
|
|
75
84
|
status: 302,
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, getters, values)=>{
|
|
5
|
+
var define = (defs, kind)=>{
|
|
6
|
+
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
[kind]: defs[key]
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
define(getters, "get");
|
|
12
|
+
define(values, "value");
|
|
13
|
+
};
|
|
14
|
+
})();
|
|
15
|
+
(()=>{
|
|
16
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
17
|
+
})();
|
|
18
|
+
(()=>{
|
|
19
|
+
__webpack_require__.r = (exports1)=>{
|
|
20
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
21
|
+
value: 'Module'
|
|
22
|
+
});
|
|
23
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
24
|
+
value: true
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
})();
|
|
28
|
+
var __webpack_exports__ = {};
|
|
29
|
+
__webpack_require__.r(__webpack_exports__);
|
|
30
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
31
|
+
createMappedUrlStrategy: ()=>createMappedUrlStrategy,
|
|
32
|
+
isDefaultLocaleRedirectSkipPath: ()=>i18n_runtime_extensions_namespaceObject.isDefaultLocaleRedirectSkipPath,
|
|
33
|
+
resolveMappedUrlStrategy: ()=>resolveMappedUrlStrategy
|
|
34
|
+
});
|
|
35
|
+
const i18n_runtime_extensions_namespaceObject = require("@modern-js/i18n-runtime-extensions");
|
|
36
|
+
const createMappedUrlStrategy = (localisedUrls)=>({
|
|
37
|
+
localizePathname: (pathname, language, languages)=>(0, i18n_runtime_extensions_namespaceObject.localiseTargetPathname)(pathname, language, [
|
|
38
|
+
...languages
|
|
39
|
+
], localisedUrls),
|
|
40
|
+
canonicalPathname: (pathname, languages)=>(0, i18n_runtime_extensions_namespaceObject.canonicalTargetPathname)(pathname, [
|
|
41
|
+
...languages
|
|
42
|
+
], localisedUrls),
|
|
43
|
+
shouldSkipRedirect: (pathname, languages)=>(0, i18n_runtime_extensions_namespaceObject.isDefaultLocaleRedirectSkipPath)(pathname, [
|
|
44
|
+
...languages
|
|
45
|
+
])
|
|
46
|
+
});
|
|
47
|
+
const resolveMappedUrlStrategy = (localeDetection)=>{
|
|
48
|
+
if (!localeDetection || 'object' != typeof localeDetection) return;
|
|
49
|
+
const localisedUrls = Reflect.get(localeDetection, 'localisedUrls');
|
|
50
|
+
if (!localisedUrls || 'object' != typeof localisedUrls || 0 === Object.keys(localisedUrls).length) return;
|
|
51
|
+
return createMappedUrlStrategy(localisedUrls);
|
|
52
|
+
};
|
|
53
|
+
exports.createMappedUrlStrategy = __webpack_exports__.createMappedUrlStrategy;
|
|
54
|
+
exports.isDefaultLocaleRedirectSkipPath = __webpack_exports__.isDefaultLocaleRedirectSkipPath;
|
|
55
|
+
exports.resolveMappedUrlStrategy = __webpack_exports__.resolveMappedUrlStrategy;
|
|
56
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
57
|
+
"createMappedUrlStrategy",
|
|
58
|
+
"isDefaultLocaleRedirectSkipPath",
|
|
59
|
+
"resolveMappedUrlStrategy"
|
|
60
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
61
|
+
Object.defineProperty(exports, '__esModule', {
|
|
62
|
+
value: true
|
|
63
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, getters, values)=>{
|
|
5
|
+
var define = (defs, kind)=>{
|
|
6
|
+
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
[kind]: defs[key]
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
define(getters, "get");
|
|
12
|
+
define(values, "value");
|
|
13
|
+
};
|
|
14
|
+
})();
|
|
15
|
+
(()=>{
|
|
16
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
17
|
+
})();
|
|
18
|
+
(()=>{
|
|
19
|
+
__webpack_require__.r = (exports1)=>{
|
|
20
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
21
|
+
value: 'Module'
|
|
22
|
+
});
|
|
23
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
24
|
+
value: true
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
})();
|
|
28
|
+
var __webpack_exports__ = {};
|
|
29
|
+
__webpack_require__.r(__webpack_exports__);
|
|
30
|
+
const asI18nUrlStrategy = (candidate)=>{
|
|
31
|
+
if (!candidate || 'object' != typeof candidate) return;
|
|
32
|
+
const strategy = candidate;
|
|
33
|
+
return 'function' == typeof strategy.localizePathname && 'function' == typeof strategy.canonicalPathname ? strategy : void 0;
|
|
34
|
+
};
|
|
35
|
+
const isUnusableI18nUrlStrategy = (candidate)=>Boolean(candidate) && 'object' == typeof candidate && void 0 === asI18nUrlStrategy(candidate);
|
|
36
|
+
__webpack_require__.d(__webpack_exports__, {}, {
|
|
37
|
+
asI18nUrlStrategy: asI18nUrlStrategy,
|
|
38
|
+
isUnusableI18nUrlStrategy: isUnusableI18nUrlStrategy
|
|
39
|
+
});
|
|
40
|
+
exports.asI18nUrlStrategy = __webpack_exports__.asI18nUrlStrategy;
|
|
41
|
+
exports.isUnusableI18nUrlStrategy = __webpack_exports__.isUnusableI18nUrlStrategy;
|
|
42
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
43
|
+
"asI18nUrlStrategy",
|
|
44
|
+
"isUnusableI18nUrlStrategy"
|
|
45
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
46
|
+
Object.defineProperty(exports, '__esModule', {
|
|
47
|
+
value: true
|
|
48
|
+
});
|
package/dist/esm/cli/index.mjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { applyLocalisedUrlsToRoutes, resolveLocalisedUrlsConfig } from "@modern-js/i18n-runtime-extensions";
|
|
2
1
|
import { getPublicDirRoutePrefixes } from "@modern-js/server-core";
|
|
2
|
+
import { logger } from "@modern-js/utils";
|
|
3
|
+
import { isUnusableI18nUrlStrategy } from "../shared/urlStrategy.mjs";
|
|
3
4
|
import { getBackendOptions, getLocaleDetectionOptions } from "../shared/utils.mjs";
|
|
4
5
|
import { applyDetectedBackendPaths, detectLocalesDirectory } from "./locales.mjs";
|
|
6
|
+
import { applyLocalisedRoutes } from "./localisedRoutes.mjs";
|
|
5
7
|
import "../runtime/types.mjs";
|
|
6
8
|
const i18nPlugin = (options = {})=>({
|
|
7
9
|
name: '@modern-js/plugin-i18n',
|
|
@@ -31,6 +33,10 @@ const i18nPlugin = (options = {})=>({
|
|
|
31
33
|
backend: backendOptions,
|
|
32
34
|
...extendedConfig
|
|
33
35
|
};
|
|
36
|
+
if (isUnusableI18nUrlStrategy(config.urlStrategy)) {
|
|
37
|
+
delete config.urlStrategy;
|
|
38
|
+
logger.warn("[i18n] `urlStrategy` cannot be passed through `modern.config.ts`: the generated runtime registration carries plugin options as JSON, which drops its methods. Configure `localeDetection.localisedUrls` instead — the runtime and the server both derive the URL policy from it — or register a runtime plugin that supplies the strategy directly.");
|
|
39
|
+
}
|
|
34
40
|
const { reactI18next } = extendedConfig;
|
|
35
41
|
const runtimePluginPath = customPlugin?.runtime?.path || (false === reactI18next ? `@${metaName}/plugin-i18n/runtime/no-react-i18next` : `@${metaName}/plugin-i18n/runtime`);
|
|
36
42
|
plugins.push({
|
|
@@ -43,27 +49,10 @@ const i18nPlugin = (options = {})=>({
|
|
|
43
49
|
plugins
|
|
44
50
|
};
|
|
45
51
|
});
|
|
46
|
-
api.modifyFileSystemRoutes(({ entrypoint, routes })=>{
|
|
47
|
-
if (!localeDetection) return {
|
|
52
|
+
api.modifyFileSystemRoutes(({ entrypoint, routes })=>({
|
|
48
53
|
entrypoint,
|
|
49
|
-
routes
|
|
50
|
-
};
|
|
51
|
-
const localeDetectionOptions = getLocaleDetectionOptions(entrypoint.entryName, localeDetection);
|
|
52
|
-
const { localePathRedirect, languages = [], localisedUrls } = localeDetectionOptions;
|
|
53
|
-
if (!localePathRedirect || 0 === languages.length) return {
|
|
54
|
-
entrypoint,
|
|
55
|
-
routes
|
|
56
|
-
};
|
|
57
|
-
const localisedUrlsConfig = resolveLocalisedUrlsConfig(localisedUrls);
|
|
58
|
-
if (!localisedUrlsConfig.enabled) return {
|
|
59
|
-
entrypoint,
|
|
60
|
-
routes
|
|
61
|
-
};
|
|
62
|
-
return {
|
|
63
|
-
entrypoint,
|
|
64
|
-
routes: applyLocalisedUrlsToRoutes(routes, languages, localisedUrlsConfig.map)
|
|
65
|
-
};
|
|
66
|
-
});
|
|
54
|
+
routes: applyLocalisedRoutes(routes, localeDetection ? getLocaleDetectionOptions(entrypoint.entryName, localeDetection) : void 0, entrypoint)
|
|
55
|
+
}));
|
|
67
56
|
api._internalServerPlugins(({ plugins })=>{
|
|
68
57
|
const { serverRoutes, metaName } = api.getAppContext();
|
|
69
58
|
const normalizedConfig = api.getNormalizedConfig();
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { applyLocalisedUrlsToRoutes, resolveLocalisedUrlsConfig } from "@modern-js/i18n-runtime-extensions";
|
|
2
|
+
import { getEntrypointRoutesOwner } from "@modern-js/runtime/cli";
|
|
3
|
+
const applyLocalisedRoutes = (routes, localeDetection, entrypoint)=>{
|
|
4
|
+
const { localePathRedirect, languages = [], localisedUrls } = localeDetection ?? {};
|
|
5
|
+
const resolved = resolveLocalisedUrlsConfig(localisedUrls);
|
|
6
|
+
if (!localePathRedirect || !languages.length || !resolved.enabled) return routes;
|
|
7
|
+
return applyLocalisedUrlsToRoutes(routes, languages, resolved.map, entrypoint && '@modern-js/plugin-tanstack' === getEntrypointRoutesOwner(entrypoint) ? 'canonical' : 'physical');
|
|
8
|
+
};
|
|
9
|
+
export { applyLocalisedRoutes };
|
|
@@ -9,10 +9,10 @@ const EXTERNAL_TARGET_RE = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
|
|
|
9
9
|
const Link = (props)=>{
|
|
10
10
|
const { to, params, children, hash: hashProp, search: searchProp, hashScrollIntoView, activeOptions, activeProps, prefetch, preload, ...rest } = props;
|
|
11
11
|
const adapter = useI18nRouterAdapter();
|
|
12
|
-
const { language, supportedLanguages,
|
|
12
|
+
const { language, supportedLanguages, urlStrategy } = useModernI18n();
|
|
13
13
|
const config = {
|
|
14
14
|
languages: supportedLanguages,
|
|
15
|
-
|
|
15
|
+
urlStrategy
|
|
16
16
|
};
|
|
17
17
|
const isExternal = EXTERNAL_TARGET_RE.test(to);
|
|
18
18
|
const isBareHash = to.startsWith('#');
|
|
@@ -22,7 +22,7 @@ const Link = (props)=>{
|
|
|
22
22
|
const interpolated = interpolateRouteParams(pathname || '/', params);
|
|
23
23
|
const firstSegment = interpolated.split('/').filter(Boolean)[0];
|
|
24
24
|
if (firstSegment && supportedLanguages.includes(firstSegment)) warnOnce(`lang-prefix:${to}`, `[plugin-i18n] <Link to="${to}"> starts with a language prefix. Write language-agnostic canonical paths; the Link localizes them automatically.`);
|
|
25
|
-
const localizedPathname = buildLocalizedUrl(interpolated, language, supportedLanguages,
|
|
25
|
+
const localizedPathname = buildLocalizedUrl(interpolated, language, supportedLanguages, urlStrategy);
|
|
26
26
|
const hash = hashProp ?? (hashFromTo ? hashFromTo.slice(1) : '');
|
|
27
27
|
const { searchString, searchObject } = normalizeSearch(searchProp, searchFromTo);
|
|
28
28
|
return {
|
|
@@ -42,7 +42,7 @@ const Link = (props)=>{
|
|
|
42
42
|
isBareHash,
|
|
43
43
|
language,
|
|
44
44
|
supportedLanguages,
|
|
45
|
-
|
|
45
|
+
urlStrategy
|
|
46
46
|
]);
|
|
47
47
|
const isActive = useMemo(()=>{
|
|
48
48
|
if (!target || !adapter.location) return false;
|
|
@@ -57,7 +57,7 @@ const Link = (props)=>{
|
|
|
57
57
|
adapter.location,
|
|
58
58
|
activeOptions?.exact,
|
|
59
59
|
supportedLanguages,
|
|
60
|
-
|
|
60
|
+
urlStrategy
|
|
61
61
|
]);
|
|
62
62
|
const resolvedActiveProps = splitActiveProps(isActive, activeProps);
|
|
63
63
|
const activeAttributes = isActive ? {
|
|
@@ -72,7 +72,7 @@ const Link = (props)=>{
|
|
|
72
72
|
children: children
|
|
73
73
|
});
|
|
74
74
|
}
|
|
75
|
-
const { Link: RouterLink, hasRouter
|
|
75
|
+
const { Link: RouterLink, hasRouter } = adapter;
|
|
76
76
|
if (!hasRouter || !RouterLink) {
|
|
77
77
|
const { replace: _replace, ...anchorProps } = rest;
|
|
78
78
|
const { className: activeClassName, style: activeStyle, ...activeRest } = resolvedActiveProps;
|
|
@@ -95,38 +95,25 @@ const Link = (props)=>{
|
|
|
95
95
|
...rest.style,
|
|
96
96
|
...activeStyle
|
|
97
97
|
};
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
} : {},
|
|
108
|
-
...void 0 === hashScrollIntoView ? {} : {
|
|
109
|
-
hashScrollIntoView
|
|
110
|
-
},
|
|
111
|
-
...void 0 === tanstackPreload ? {} : {
|
|
112
|
-
preload: tanstackPreload
|
|
113
|
-
},
|
|
114
|
-
...rest,
|
|
115
|
-
...activeRest,
|
|
116
|
-
...activeAttributes,
|
|
117
|
-
className: mergedClassName,
|
|
118
|
-
style: mergedStyle,
|
|
119
|
-
children: children
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
return /*#__PURE__*/ jsx(RouterLink, {
|
|
98
|
+
const routerProps = adapter.createLinkProps?.({
|
|
99
|
+
pathname: target.localizedPathname,
|
|
100
|
+
href: target.href,
|
|
101
|
+
search: target.searchObject,
|
|
102
|
+
hash: target.hash,
|
|
103
|
+
hashScrollIntoView,
|
|
104
|
+
prefetch,
|
|
105
|
+
preload
|
|
106
|
+
}) ?? {
|
|
123
107
|
to: target.href,
|
|
124
108
|
...void 0 === prefetch ? {} : {
|
|
125
109
|
prefetch
|
|
126
110
|
},
|
|
127
111
|
...void 0 === preload ? {} : {
|
|
128
112
|
preload
|
|
129
|
-
}
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
return /*#__PURE__*/ jsx(RouterLink, {
|
|
116
|
+
...routerProps,
|
|
130
117
|
...rest,
|
|
131
118
|
...activeRest,
|
|
132
119
|
...activeAttributes,
|
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { RuntimeComponentResolverContext } from "@modern-js/runtime/context";
|
|
3
|
+
import { useCallback, useContext, useEffect, useMemo } from "react";
|
|
3
4
|
import { changeModernI18nLanguage, getPathLanguage, isI18nLanguageSupported, isI18nResourcesReady, translateI18n } from "./contextHelpers.mjs";
|
|
4
|
-
import { getActualI18nextInstance } from "./i18n/instance.mjs";
|
|
5
5
|
import { useI18nRouterAdapter } from "./routerAdapter.mjs";
|
|
6
|
-
|
|
7
|
-
const reactI18nextProviderContextKey = Symbol.for('@modern-js/plugin-i18n/runtime/ReactI18nextProviderContext');
|
|
8
|
-
const getGlobalContext = (key, defaultValue)=>{
|
|
9
|
-
const globalStore = globalThis;
|
|
10
|
-
globalStore[key] ??= /*#__PURE__*/ createContext(defaultValue);
|
|
11
|
-
return globalStore[key];
|
|
12
|
-
};
|
|
13
|
-
const ModernI18nContext = getGlobalContext(modernI18nContextKey, null);
|
|
14
|
-
const ReactI18nextProviderContext = getGlobalContext(reactI18nextProviderContextKey, null);
|
|
6
|
+
import { ModernI18nContext, ReactI18nextProviderContext } from "./sharedContexts.mjs";
|
|
15
7
|
const ModernI18nProvider = ({ children, i18nextProvider, value })=>{
|
|
16
8
|
const content = /*#__PURE__*/ jsx(ModernI18nContext.Provider, {
|
|
17
9
|
value: value,
|
|
@@ -22,68 +14,23 @@ const ModernI18nProvider = ({ children, i18nextProvider, value })=>{
|
|
|
22
14
|
children: content
|
|
23
15
|
});
|
|
24
16
|
};
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
initImmediate: false,
|
|
37
|
-
lng: parent.language,
|
|
38
|
-
ns: [
|
|
39
|
-
defaultNamespace
|
|
40
|
-
],
|
|
41
|
-
resources,
|
|
42
|
-
supportedLngs: languages
|
|
43
|
-
});
|
|
44
|
-
if (!clone) throw new Error('FederatedI18nBoundary requires an i18n instance with cloneInstance support');
|
|
45
|
-
const resourceStore = clone.store;
|
|
46
|
-
const parentResourceStore = parentInstance.store;
|
|
47
|
-
const sharesNestedResourceState = Object.entries(resourceStore?.data ?? {}).some(([language, namespaces])=>{
|
|
48
|
-
const parentNamespaces = parentResourceStore?.data?.[language];
|
|
49
|
-
return namespaces === parentNamespaces || Object.entries(namespaces).some(([namespace, resource])=>null !== resource && 'object' == typeof resource && resource === parentNamespaces?.[namespace]);
|
|
50
|
-
});
|
|
51
|
-
if (clone === parentInstance || resourceStore === parentResourceStore || resourceStore?.data === parentResourceStore?.data || sharesNestedResourceState) throw new Error('FederatedI18nBoundary cloneInstance did not isolate the host resource store');
|
|
52
|
-
if (!resourceStore?.addResourceBundle || !clone.removeResourceBundle || !resourceStore.data) throw new Error('FederatedI18nBoundary requires an isolated mutable i18n resource store');
|
|
53
|
-
for (const [language, namespaces] of Object.entries(resourceStore.data))for (const namespace of Object.keys(namespaces))clone.removeResourceBundle(language, namespace);
|
|
54
|
-
for (const [language, namespaces] of Object.entries(resources))for (const [namespace, resource] of Object.entries(namespaces))resourceStore.addResourceBundle(language, namespace, resource, true, true);
|
|
55
|
-
return clone;
|
|
56
|
-
}, [
|
|
57
|
-
defaultNamespace,
|
|
58
|
-
fallbackLanguage,
|
|
59
|
-
languages,
|
|
60
|
-
parent.i18nInstance,
|
|
61
|
-
parent.language,
|
|
62
|
-
resources
|
|
63
|
-
]);
|
|
64
|
-
const value = useMemo(()=>({
|
|
65
|
-
...parent,
|
|
66
|
-
i18nInstance: scopedInstance,
|
|
67
|
-
language: parent.language,
|
|
68
|
-
languages
|
|
69
|
-
}), [
|
|
70
|
-
languages,
|
|
71
|
-
parent,
|
|
72
|
-
scopedInstance
|
|
73
|
-
]);
|
|
74
|
-
const scopedContent = /*#__PURE__*/ jsx(ModernI18nProvider, {
|
|
75
|
-
value: value,
|
|
76
|
-
children: children
|
|
17
|
+
const MissingFederatedI18nBoundary = ()=>{
|
|
18
|
+
throw new Error('FederatedI18nBoundary requires the @modern-js/i18n-integration runtime plugin');
|
|
19
|
+
};
|
|
20
|
+
const FederatedI18nBoundary = (props)=>{
|
|
21
|
+
const resolveComponent = useContext(RuntimeComponentResolverContext);
|
|
22
|
+
const Boundary = resolveComponent?.(MissingFederatedI18nBoundary, {
|
|
23
|
+
name: 'i18n.FederatedI18nBoundary'
|
|
24
|
+
}) ?? MissingFederatedI18nBoundary;
|
|
25
|
+
if (Boundary === FederatedI18nBoundary) throw new Error('FederatedI18nBoundary resolver returned its own wrapper');
|
|
26
|
+
return /*#__PURE__*/ jsx(Boundary, {
|
|
27
|
+
...props
|
|
77
28
|
});
|
|
78
|
-
return I18nextProvider ? /*#__PURE__*/ jsx(I18nextProvider, {
|
|
79
|
-
i18n: scopedInstance,
|
|
80
|
-
children: scopedContent
|
|
81
|
-
}) : scopedContent;
|
|
82
29
|
};
|
|
83
30
|
const useModernI18n = ()=>{
|
|
84
31
|
const context = useContext(ModernI18nContext);
|
|
85
32
|
if (!context) throw new Error('useModernI18n must be used within ModernI18nProvider');
|
|
86
|
-
const { language: contextLanguage, i18nInstance, languages, localePathRedirect, ignoreRedirectRoutes,
|
|
33
|
+
const { language: contextLanguage, i18nInstance, languages, localePathRedirect, ignoreRedirectRoutes, urlStrategy, updateLanguage, synchronizeLanguage } = context;
|
|
87
34
|
const { navigate, location, hasRouter } = useI18nRouterAdapter();
|
|
88
35
|
const pathLanguage = useMemo(()=>getPathLanguage(location?.pathname, languages, localePathRedirect), [
|
|
89
36
|
languages,
|
|
@@ -102,7 +49,7 @@ const useModernI18n = ()=>{
|
|
|
102
49
|
updateLanguage,
|
|
103
50
|
localePathRedirect,
|
|
104
51
|
ignoreRedirectRoutes,
|
|
105
|
-
|
|
52
|
+
urlStrategy,
|
|
106
53
|
languages,
|
|
107
54
|
hasRouter,
|
|
108
55
|
navigate,
|
|
@@ -112,7 +59,7 @@ const useModernI18n = ()=>{
|
|
|
112
59
|
updateLanguage,
|
|
113
60
|
localePathRedirect,
|
|
114
61
|
ignoreRedirectRoutes,
|
|
115
|
-
|
|
62
|
+
urlStrategy,
|
|
116
63
|
languages,
|
|
117
64
|
hasRouter,
|
|
118
65
|
navigate,
|
|
@@ -135,9 +82,10 @@ const useModernI18n = ()=>{
|
|
|
135
82
|
t,
|
|
136
83
|
i18nInstance: i18nInstance,
|
|
137
84
|
supportedLanguages: languages || [],
|
|
138
|
-
|
|
85
|
+
urlStrategy,
|
|
139
86
|
isLanguageSupported,
|
|
140
87
|
isResourcesReady
|
|
141
88
|
};
|
|
142
89
|
};
|
|
143
|
-
export {
|
|
90
|
+
export { getActualI18nextInstance } from "./i18n/instance.mjs";
|
|
91
|
+
export { FederatedI18nBoundary, ModernI18nContext, ModernI18nProvider, ReactI18nextProviderContext, useModernI18n };
|
|
@@ -17,7 +17,7 @@ async function changeI18nInstanceLanguage(i18nInstance, language) {
|
|
|
17
17
|
else await i18nInstance.changeLanguage?.(language);
|
|
18
18
|
}
|
|
19
19
|
async function changeModernI18nLanguage(newLang, options) {
|
|
20
|
-
const { i18nInstance, updateLanguage, localePathRedirect, ignoreRedirectRoutes,
|
|
20
|
+
const { i18nInstance, updateLanguage, localePathRedirect, ignoreRedirectRoutes, urlStrategy, languages, hasRouter, navigate, location } = options;
|
|
21
21
|
try {
|
|
22
22
|
if (!newLang || 'string' != typeof newLang) throw new Error('Language must be non-empty string');
|
|
23
23
|
await changeI18nInstanceLanguage(i18nInstance, newLang);
|
|
@@ -28,8 +28,8 @@ async function changeModernI18nLanguage(newLang, options) {
|
|
|
28
28
|
const relativePath = currentPath.replace(entryPath, '');
|
|
29
29
|
const pathLanguage = detectLanguageFromPath(currentPath, languages || [], localePathRedirect);
|
|
30
30
|
if (pathLanguage.detected && pathLanguage.language === newLang) return void updateLanguage?.(newLang);
|
|
31
|
-
if (!shouldIgnoreRedirect(relativePath, languages || [], ignoreRedirectRoutes)) {
|
|
32
|
-
const newPath = buildLocalizedUrl(relativePath, newLang, languages || [],
|
|
31
|
+
if (!shouldIgnoreRedirect(relativePath, languages || [], ignoreRedirectRoutes, urlStrategy)) {
|
|
32
|
+
const newPath = buildLocalizedUrl(relativePath, newLang, languages || [], urlStrategy);
|
|
33
33
|
const newUrl = entryPath + newPath + location.search + location.hash;
|
|
34
34
|
await navigate(newUrl, {
|
|
35
35
|
replace: true
|
|
@@ -41,8 +41,8 @@ async function changeModernI18nLanguage(newLang, options) {
|
|
|
41
41
|
const relativePath = currentPath.replace(entryPath, '');
|
|
42
42
|
const pathLanguage = detectLanguageFromPath(currentPath, languages || [], localePathRedirect);
|
|
43
43
|
if (pathLanguage.detected && pathLanguage.language === newLang) return void updateLanguage?.(newLang);
|
|
44
|
-
if (!shouldIgnoreRedirect(relativePath, languages || [], ignoreRedirectRoutes)) {
|
|
45
|
-
const newPath = buildLocalizedUrl(relativePath, newLang, languages || [],
|
|
44
|
+
if (!shouldIgnoreRedirect(relativePath, languages || [], ignoreRedirectRoutes, urlStrategy)) {
|
|
45
|
+
const newPath = buildLocalizedUrl(relativePath, newLang, languages || [], urlStrategy);
|
|
46
46
|
const newUrl = entryPath + newPath + window.location.search + window.location.hash;
|
|
47
47
|
window.history.pushState(null, '', newUrl);
|
|
48
48
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { createContext } from "react";
|
|
2
|
+
const ModernI18nContext = createContext(null);
|
|
3
|
+
const ReactI18nextProviderContext = createContext(null);
|
|
4
|
+
const I18nNavigationContext = createContext(null);
|
|
5
|
+
export { I18nNavigationContext, ModernI18nContext, ReactI18nextProviderContext };
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { resolveMappedUrlStrategy } from "../shared/mappedUrlStrategy.mjs";
|
|
2
|
+
import { asI18nUrlStrategy } from "../shared/urlStrategy.mjs";
|
|
3
|
+
import { I18nRouterNavigationProvider, useIntegratedRouterAdapter } from "./navigation.mjs";
|
|
1
4
|
import { setupI18nBeforeRender } from "./pluginSetup.mjs";
|
|
2
5
|
import { createI18nRootWrapper } from "./providerComposition.mjs";
|
|
3
6
|
import { resolveReactI18nextIntegration } from "./reactI18next.mjs";
|
|
@@ -5,9 +8,10 @@ import "./types.mjs";
|
|
|
5
8
|
const createI18nPlugin = (loadReactI18nextIntegration)=>(options)=>({
|
|
6
9
|
name: '@modern-js/plugin-i18n',
|
|
7
10
|
setup: (api)=>{
|
|
8
|
-
const { entryName, i18nInstance: userI18nInstance, initOptions, localeDetection, backend, htmlLangAttr = false, reactI18next = true } = options;
|
|
9
|
-
const { localePathRedirect = false, i18nextDetector = true, languages = [], fallbackLanguage = 'en', detection, ignoreRedirectRoutes
|
|
11
|
+
const { entryName, i18nInstance: userI18nInstance, initOptions, localeDetection, backend, htmlLangAttr = false, reactI18next = true, urlStrategy, NavigationProvider, LanguageSynchronization } = options;
|
|
12
|
+
const { localePathRedirect = false, i18nextDetector = true, languages = [], fallbackLanguage = 'en', detection, ignoreRedirectRoutes } = localeDetection || {};
|
|
10
13
|
const { enabled: backendEnabled = false } = backend || {};
|
|
14
|
+
const resolvedUrlStrategy = asI18nUrlStrategy(urlStrategy) ?? resolveMappedUrlStrategy(localeDetection);
|
|
11
15
|
let latestI18nInstance;
|
|
12
16
|
let I18nextProvider;
|
|
13
17
|
api.onBeforeRender(async (context)=>{
|
|
@@ -35,15 +39,18 @@ const createI18nPlugin = (loadReactI18nextIntegration)=>(options)=>({
|
|
|
35
39
|
languages,
|
|
36
40
|
fallbackLanguage,
|
|
37
41
|
ignoreRedirectRoutes,
|
|
38
|
-
|
|
42
|
+
urlStrategy: resolvedUrlStrategy,
|
|
43
|
+
NavigationProvider: NavigationProvider ?? I18nRouterNavigationProvider,
|
|
44
|
+
LanguageSynchronization,
|
|
39
45
|
getLatestI18nInstance: ()=>latestI18nInstance,
|
|
40
46
|
getI18nextProvider: ()=>I18nextProvider
|
|
41
47
|
}));
|
|
42
48
|
}
|
|
43
49
|
});
|
|
50
|
+
export { I18nNavigationProvider, useI18nRouterAdapter, useNativeI18nRouterAdapter } from "./routerAdapter.mjs";
|
|
44
51
|
export { FederatedI18nBoundary, useModernI18n } from "./context.mjs";
|
|
45
52
|
export { I18nLink } from "./I18nLink.mjs";
|
|
46
53
|
export { Link } from "./Link.mjs";
|
|
47
|
-
export {
|
|
48
|
-
export {
|
|
49
|
-
export { createI18nPlugin };
|
|
54
|
+
export { useLocalizedLocation, useLocalizedPaths } from "./localizedPaths.mjs";
|
|
55
|
+
export { splitUrlTarget } from "./utils.mjs";
|
|
56
|
+
export { I18nRouterNavigationProvider, createI18nPlugin, useIntegratedRouterAdapter };
|