@bleedingdev/modern-js-i18n-integration 0.0.0 → 3.9.0-ultramodern.5
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/LICENSE +21 -0
- package/dist/cjs/cli.js +97 -0
- package/dist/cjs/federation/boundary.js +100 -0
- package/dist/cjs/federation/registration.js +43 -0
- package/dist/cjs/languageSynchronization.js +44 -0
- package/dist/cjs/navigation.js +220 -0
- package/dist/cjs/options.js +18 -0
- package/dist/cjs/runtime-no-react-i18next.js +46 -0
- package/dist/cjs/runtime.js +46 -0
- package/dist/cjs/runtimeComposition.js +60 -0
- package/dist/cjs/server.js +50 -0
- package/dist/cjs/urlStrategy.js +51 -0
- package/dist/esm/cli.mjs +57 -0
- package/dist/esm/federation/boundary.mjs +62 -0
- package/dist/esm/federation/registration.mjs +5 -0
- package/dist/esm/languageSynchronization.mjs +6 -0
- package/dist/esm/navigation.mjs +182 -0
- package/dist/esm/options.mjs +0 -0
- package/dist/esm/runtime-no-react-i18next.mjs +6 -0
- package/dist/esm/runtime.mjs +6 -0
- package/dist/esm/runtimeComposition.mjs +22 -0
- package/dist/esm/server.mjs +10 -0
- package/dist/esm/urlStrategy.mjs +13 -0
- package/dist/esm-node/cli.mjs +58 -0
- package/dist/esm-node/federation/boundary.mjs +63 -0
- package/dist/esm-node/federation/registration.mjs +6 -0
- package/dist/esm-node/languageSynchronization.mjs +7 -0
- package/dist/esm-node/navigation.mjs +183 -0
- package/dist/esm-node/options.mjs +1 -0
- package/dist/esm-node/runtime-no-react-i18next.mjs +7 -0
- package/dist/esm-node/runtime.mjs +7 -0
- package/dist/esm-node/runtimeComposition.mjs +23 -0
- package/dist/esm-node/server.mjs +11 -0
- package/dist/esm-node/urlStrategy.mjs +14 -0
- package/dist/types/cli.d.ts +4 -0
- package/dist/types/federation/boundary.d.ts +9 -0
- package/dist/types/federation/registration.d.ts +2 -0
- package/dist/types/languageSynchronization.d.ts +3 -0
- package/dist/types/navigation.d.ts +3 -0
- package/dist/types/options.d.ts +13 -0
- package/dist/types/runtime-no-react-i18next.d.ts +2 -0
- package/dist/types/runtime.d.ts +2 -0
- package/dist/types/runtimeComposition.d.ts +4 -0
- package/dist/types/server.d.ts +3 -0
- package/dist/types/urlStrategy.d.ts +4 -0
- package/package.json +139 -5
- package/src/cli.ts +72 -0
- package/src/federation/boundary.tsx +129 -0
- package/src/federation/registration.ts +8 -0
- package/src/languageSynchronization.tsx +23 -0
- package/src/navigation.tsx +399 -0
- package/src/options.ts +18 -0
- package/src/runtime-no-react-i18next.ts +5 -0
- package/src/runtime.ts +5 -0
- package/src/runtimeComposition.ts +33 -0
- package/src/server.ts +27 -0
- package/src/urlStrategy.ts +19 -0
- package/README.md +0 -3
|
@@ -0,0 +1,60 @@
|
|
|
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
|
+
composeI18nPlugin: ()=>composeI18nPlugin
|
|
32
|
+
});
|
|
33
|
+
const registration_js_namespaceObject = require("./federation/registration.js");
|
|
34
|
+
const external_languageSynchronization_js_namespaceObject = require("./languageSynchronization.js");
|
|
35
|
+
const external_navigation_js_namespaceObject = require("./navigation.js");
|
|
36
|
+
const external_urlStrategy_js_namespaceObject = require("./urlStrategy.js");
|
|
37
|
+
const composeI18nPlugin = (nativeI18nPlugin)=>(options = {})=>{
|
|
38
|
+
const { localisedUrls, localeDetectionByEntry: _entryOptions, ...nativeLocaleDetection } = options.localeDetection ?? {};
|
|
39
|
+
const native = nativeI18nPlugin({
|
|
40
|
+
...options,
|
|
41
|
+
localeDetection: nativeLocaleDetection,
|
|
42
|
+
urlStrategy: options.urlStrategy ?? (0, external_urlStrategy_js_namespaceObject.createI18nUrlStrategy)(localisedUrls),
|
|
43
|
+
NavigationProvider: options.NavigationProvider ?? external_navigation_js_namespaceObject.I18nRouterNavigationProvider,
|
|
44
|
+
LanguageSynchronization: options.LanguageSynchronization ?? external_languageSynchronization_js_namespaceObject.I18nLanguageSynchronization
|
|
45
|
+
});
|
|
46
|
+
return {
|
|
47
|
+
...native,
|
|
48
|
+
setup (api) {
|
|
49
|
+
(0, registration_js_namespaceObject.registerFederatedI18nBoundary)(api);
|
|
50
|
+
return native.setup?.(api);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
exports.composeI18nPlugin = __webpack_exports__.composeI18nPlugin;
|
|
55
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
56
|
+
"composeI18nPlugin"
|
|
57
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
58
|
+
Object.defineProperty(exports, '__esModule', {
|
|
59
|
+
value: true
|
|
60
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
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
|
+
default: ()=>server,
|
|
32
|
+
i18nServerPlugin: ()=>i18nServerPlugin
|
|
33
|
+
});
|
|
34
|
+
const config_namespaceObject = require("@modern-js/plugin-i18n/config");
|
|
35
|
+
const server_namespaceObject = require("@modern-js/plugin-i18n/server");
|
|
36
|
+
const external_urlStrategy_js_namespaceObject = require("./urlStrategy.js");
|
|
37
|
+
const i18nServerPlugin = (options)=>(0, server_namespaceObject.i18nServerPlugin)({
|
|
38
|
+
...options,
|
|
39
|
+
resolveUrlStrategy: options.resolveUrlStrategy ?? ((entryName)=>(0, external_urlStrategy_js_namespaceObject.createI18nUrlStrategy)(options.localeDetection ? (0, config_namespaceObject.getLocaleDetectionOptions)(entryName, options.localeDetection).localisedUrls : void 0))
|
|
40
|
+
});
|
|
41
|
+
const server = i18nServerPlugin;
|
|
42
|
+
exports["default"] = __webpack_exports__["default"];
|
|
43
|
+
exports.i18nServerPlugin = __webpack_exports__.i18nServerPlugin;
|
|
44
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
45
|
+
"default",
|
|
46
|
+
"i18nServerPlugin"
|
|
47
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
48
|
+
Object.defineProperty(exports, '__esModule', {
|
|
49
|
+
value: true
|
|
50
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
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
|
+
createI18nUrlStrategy: ()=>createI18nUrlStrategy
|
|
32
|
+
});
|
|
33
|
+
const i18n_runtime_extensions_namespaceObject = require("@modern-js/i18n-runtime-extensions");
|
|
34
|
+
const createI18nUrlStrategy = (localisedUrls)=>({
|
|
35
|
+
localizePathname: (pathname, language, languages)=>(0, i18n_runtime_extensions_namespaceObject.localiseTargetPathname)(pathname, language, [
|
|
36
|
+
...languages
|
|
37
|
+
], localisedUrls),
|
|
38
|
+
canonicalPathname: (pathname, languages)=>(0, i18n_runtime_extensions_namespaceObject.canonicalTargetPathname)(pathname, [
|
|
39
|
+
...languages
|
|
40
|
+
], localisedUrls),
|
|
41
|
+
shouldSkipRedirect: (pathname, languages)=>(0, i18n_runtime_extensions_namespaceObject.isDefaultLocaleRedirectSkipPath)(pathname, [
|
|
42
|
+
...languages
|
|
43
|
+
])
|
|
44
|
+
});
|
|
45
|
+
exports.createI18nUrlStrategy = __webpack_exports__.createI18nUrlStrategy;
|
|
46
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
47
|
+
"createI18nUrlStrategy"
|
|
48
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
49
|
+
Object.defineProperty(exports, '__esModule', {
|
|
50
|
+
value: true
|
|
51
|
+
});
|
package/dist/esm/cli.mjs
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { applyLocalisedUrlsToRoutes, resolveLocalisedUrlsConfig } from "@modern-js/i18n-runtime-extensions";
|
|
2
|
+
const runtimePaths = new Map([
|
|
3
|
+
[
|
|
4
|
+
'@modern-js/plugin-i18n/runtime',
|
|
5
|
+
'@modern-js/i18n-integration/runtime'
|
|
6
|
+
],
|
|
7
|
+
[
|
|
8
|
+
'@modern-js/plugin-i18n/runtime/no-react-i18next',
|
|
9
|
+
'@modern-js/i18n-integration/runtime/no-react-i18next'
|
|
10
|
+
]
|
|
11
|
+
]);
|
|
12
|
+
const integrationRuntimePaths = new Set(runtimePaths.values());
|
|
13
|
+
const ultramodernI18nIntegrationPlugin = ()=>({
|
|
14
|
+
name: '@modern-js/i18n-integration',
|
|
15
|
+
pre: [
|
|
16
|
+
'@modern-js/plugin-i18n'
|
|
17
|
+
],
|
|
18
|
+
setup (api) {
|
|
19
|
+
api._internalRuntimePlugins(({ entrypoint, plugins })=>({
|
|
20
|
+
entrypoint,
|
|
21
|
+
plugins: plugins.map((plugin)=>{
|
|
22
|
+
const path = runtimePaths.get(plugin.path);
|
|
23
|
+
return path ? {
|
|
24
|
+
...plugin,
|
|
25
|
+
path
|
|
26
|
+
} : plugin;
|
|
27
|
+
})
|
|
28
|
+
}));
|
|
29
|
+
api._internalServerPlugins(({ plugins })=>({
|
|
30
|
+
plugins: plugins.map((plugin)=>'@modern-js/plugin-i18n/server' === plugin.name ? {
|
|
31
|
+
...plugin,
|
|
32
|
+
name: '@modern-js/i18n-integration/server'
|
|
33
|
+
} : plugin)
|
|
34
|
+
}));
|
|
35
|
+
api.modifyFileSystemRoutes(async ({ entrypoint, routes })=>{
|
|
36
|
+
const { plugins } = await api.getHooks()._internalRuntimePlugins.call({
|
|
37
|
+
entrypoint,
|
|
38
|
+
plugins: []
|
|
39
|
+
});
|
|
40
|
+
const descriptor = plugins.find((plugin)=>integrationRuntimePaths.has(plugin.path));
|
|
41
|
+
const config = descriptor?.config;
|
|
42
|
+
const { localePathRedirect, languages = [], localisedUrls } = config?.localeDetection ?? {};
|
|
43
|
+
const resolved = resolveLocalisedUrlsConfig(localisedUrls);
|
|
44
|
+
if (!localePathRedirect || !languages.length || !resolved.enabled) return {
|
|
45
|
+
entrypoint,
|
|
46
|
+
routes
|
|
47
|
+
};
|
|
48
|
+
return {
|
|
49
|
+
entrypoint,
|
|
50
|
+
routes: applyLocalisedUrlsToRoutes(routes, languages, resolved.map)
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
const cli = ultramodernI18nIntegrationPlugin;
|
|
56
|
+
export default cli;
|
|
57
|
+
export { ultramodernI18nIntegrationPlugin };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { ModernI18nContext, ModernI18nProvider, ReactI18nextProviderContext, getActualI18nextInstance } from "@modern-js/plugin-i18n/runtime/consumer";
|
|
3
|
+
import { useContext, useMemo } from "react";
|
|
4
|
+
const FederatedI18nBoundary = ({ children, defaultNamespace, fallbackLanguage, resources, supportedLanguages })=>{
|
|
5
|
+
const parent = useContext(ModernI18nContext);
|
|
6
|
+
const I18nextProvider = useContext(ReactI18nextProviderContext);
|
|
7
|
+
if (!parent) throw new Error('FederatedI18nBoundary must be used within ModernI18nProvider');
|
|
8
|
+
const languages = supportedLanguages ?? parent.languages ?? Object.keys(resources);
|
|
9
|
+
const scopedInstance = useMemo(()=>{
|
|
10
|
+
const parentInstance = getActualI18nextInstance(parent.i18nInstance);
|
|
11
|
+
const clone = parentInstance.cloneInstance?.({
|
|
12
|
+
defaultNS: defaultNamespace,
|
|
13
|
+
fallbackLng: fallbackLanguage ?? languages[0] ?? parent.language,
|
|
14
|
+
forkResourceStore: true,
|
|
15
|
+
initImmediate: false,
|
|
16
|
+
lng: parent.language,
|
|
17
|
+
ns: [
|
|
18
|
+
defaultNamespace
|
|
19
|
+
],
|
|
20
|
+
resources,
|
|
21
|
+
supportedLngs: languages
|
|
22
|
+
});
|
|
23
|
+
if (!clone) throw new Error('FederatedI18nBoundary requires an i18n instance with cloneInstance support');
|
|
24
|
+
const resourceStore = clone.store;
|
|
25
|
+
const parentResourceStore = parentInstance.store;
|
|
26
|
+
const sharesNestedResourceState = Object.entries(resourceStore?.data ?? {}).some(([language, namespaces])=>{
|
|
27
|
+
const parentNamespaces = parentResourceStore?.data?.[language];
|
|
28
|
+
return namespaces === parentNamespaces || Object.entries(namespaces).some(([namespace, resource])=>null !== resource && 'object' == typeof resource && resource === parentNamespaces?.[namespace]);
|
|
29
|
+
});
|
|
30
|
+
if (clone === parentInstance || resourceStore === parentResourceStore || resourceStore?.data === parentResourceStore?.data || sharesNestedResourceState) throw new Error('FederatedI18nBoundary cloneInstance did not isolate the host resource store');
|
|
31
|
+
if (!resourceStore?.addResourceBundle || !clone.removeResourceBundle || !resourceStore.data) throw new Error('FederatedI18nBoundary requires an isolated mutable i18n resource store');
|
|
32
|
+
for (const [language, namespaces] of Object.entries(resourceStore.data))for (const namespace of Object.keys(namespaces))clone.removeResourceBundle(language, namespace);
|
|
33
|
+
for (const [language, namespaces] of Object.entries(resources))for (const [namespace, resource] of Object.entries(namespaces))resourceStore.addResourceBundle(language, namespace, resource, true, true);
|
|
34
|
+
return clone;
|
|
35
|
+
}, [
|
|
36
|
+
defaultNamespace,
|
|
37
|
+
fallbackLanguage,
|
|
38
|
+
languages,
|
|
39
|
+
parent.i18nInstance,
|
|
40
|
+
parent.language,
|
|
41
|
+
resources
|
|
42
|
+
]);
|
|
43
|
+
const value = useMemo(()=>({
|
|
44
|
+
...parent,
|
|
45
|
+
i18nInstance: scopedInstance,
|
|
46
|
+
language: parent.language,
|
|
47
|
+
languages
|
|
48
|
+
}), [
|
|
49
|
+
languages,
|
|
50
|
+
parent,
|
|
51
|
+
scopedInstance
|
|
52
|
+
]);
|
|
53
|
+
const scopedContent = /*#__PURE__*/ jsx(ModernI18nProvider, {
|
|
54
|
+
value: value,
|
|
55
|
+
children: children
|
|
56
|
+
});
|
|
57
|
+
return I18nextProvider ? /*#__PURE__*/ jsx(I18nextProvider, {
|
|
58
|
+
i18n: scopedInstance,
|
|
59
|
+
children: scopedContent
|
|
60
|
+
}) : scopedContent;
|
|
61
|
+
};
|
|
62
|
+
export { FederatedI18nBoundary };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { FederatedI18nBoundary } from "./boundary.mjs";
|
|
2
|
+
function registerFederatedI18nBoundary(api) {
|
|
3
|
+
api.resolveComponent((component, { name })=>'i18n.FederatedI18nBoundary' === name ? FederatedI18nBoundary : component);
|
|
4
|
+
}
|
|
5
|
+
export { registerFederatedI18nBoundary };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { useLanguageSync } from "@modern-js/i18n-runtime-extensions";
|
|
2
|
+
const I18nLanguageSynchronization = ({ i18nInstance, localePathRedirect, languages, pathname, prevLangRef, setLang, children })=>{
|
|
3
|
+
const synchronizeLanguage = useLanguageSync(i18nInstance, localePathRedirect, languages, pathname, prevLangRef, setLang);
|
|
4
|
+
return children(synchronizeLanguage);
|
|
5
|
+
};
|
|
6
|
+
export { I18nLanguageSynchronization };
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { I18nNavigationProvider, useNativeI18nRouterAdapter } from "@modern-js/plugin-i18n/runtime/no-react-i18next";
|
|
3
|
+
import { RuntimeContext, isBrowser } from "@modern-js/runtime";
|
|
4
|
+
import { InternalRuntimeContext } from "@modern-js/runtime/context";
|
|
5
|
+
import { getRouterRuntimeState } from "@modern-js/runtime-extensions/router-state";
|
|
6
|
+
import { useCallback, useContext, useSyncExternalStore } from "react";
|
|
7
|
+
const normalizeUrlPart = (value, prefix)=>{
|
|
8
|
+
if ('string' != typeof value || !value) return '';
|
|
9
|
+
return value.startsWith(prefix) ? value : `${prefix}${value}`;
|
|
10
|
+
};
|
|
11
|
+
const normalizeLocation = (location)=>{
|
|
12
|
+
if (!location || 'object' != typeof location) return null;
|
|
13
|
+
const locationValue = location;
|
|
14
|
+
if ('string' != typeof locationValue.pathname) return null;
|
|
15
|
+
return {
|
|
16
|
+
pathname: locationValue.pathname,
|
|
17
|
+
search: normalizeUrlPart('string' == typeof locationValue.search ? locationValue.search : locationValue.searchStr, '?'),
|
|
18
|
+
hash: normalizeUrlPart(locationValue.hash, '#')
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
const getWindowLocation = ()=>{
|
|
22
|
+
if (!isBrowser()) return null;
|
|
23
|
+
return {
|
|
24
|
+
pathname: window.location.pathname,
|
|
25
|
+
search: window.location.search,
|
|
26
|
+
hash: window.location.hash
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
const getRouterFramework = (runtimeContext, internalContext, inReactRouter)=>{
|
|
30
|
+
const framework = getRouterRuntimeState(internalContext)?.framework || getRouterRuntimeState(runtimeContext)?.framework;
|
|
31
|
+
if (framework) return framework;
|
|
32
|
+
if (internalContext.router?.useRouter || runtimeContext.router?.useRouter) return 'tanstack';
|
|
33
|
+
if (internalContext.router?.useLocation || internalContext.router?.useHref || runtimeContext.router?.useLocation || runtimeContext.router?.useHref) return 'react-router';
|
|
34
|
+
if (inReactRouter) return 'react-router';
|
|
35
|
+
};
|
|
36
|
+
const getRouterInstance = (internalContext, contextRouter)=>{
|
|
37
|
+
if (contextRouter) return contextRouter;
|
|
38
|
+
const router = getRouterRuntimeState(internalContext)?.instance;
|
|
39
|
+
if (!router || 'object' != typeof router) return null;
|
|
40
|
+
return router;
|
|
41
|
+
};
|
|
42
|
+
const getRouterStateLocation = (internalContext, contextRouter)=>{
|
|
43
|
+
const router = getRouterInstance(internalContext, contextRouter);
|
|
44
|
+
return normalizeLocation(router?.stores?.location?.get?.()) || normalizeLocation(router?.state?.location);
|
|
45
|
+
};
|
|
46
|
+
const getRouterParams = (internalContext, contextRouter)=>{
|
|
47
|
+
const router = getRouterInstance(internalContext, contextRouter);
|
|
48
|
+
const matches = router?.stores?.matches?.get?.() || router?.state?.matches;
|
|
49
|
+
if (!Array.isArray(matches)) return {};
|
|
50
|
+
return matches.reduce((params, match)=>{
|
|
51
|
+
if (match?.params) Object.assign(params, match.params);
|
|
52
|
+
return params;
|
|
53
|
+
}, {});
|
|
54
|
+
};
|
|
55
|
+
const getRouterSnapshot = (internalContext, contextRouter)=>{
|
|
56
|
+
const location = getRouterStateLocation(internalContext, contextRouter);
|
|
57
|
+
const params = getRouterParams(internalContext, contextRouter);
|
|
58
|
+
return JSON.stringify([
|
|
59
|
+
location?.pathname ?? '',
|
|
60
|
+
location?.search ?? '',
|
|
61
|
+
location?.hash ?? '',
|
|
62
|
+
Object.entries(params).sort(([left], [right])=>left.localeCompare(right))
|
|
63
|
+
]);
|
|
64
|
+
};
|
|
65
|
+
const useIntegratedRouterAdapter = ()=>{
|
|
66
|
+
const runtimeContext = useContext(RuntimeContext);
|
|
67
|
+
const internalContext = useContext(InternalRuntimeContext);
|
|
68
|
+
const routerApi = internalContext.router || runtimeContext.router;
|
|
69
|
+
const native = useNativeI18nRouterAdapter();
|
|
70
|
+
const inReactRouter = native.hasRouter;
|
|
71
|
+
const reactRouterNavigate = native.navigate;
|
|
72
|
+
const reactRouterLocation = inReactRouter ? native.location : null;
|
|
73
|
+
const reactRouterParams = native.params;
|
|
74
|
+
const framework = getRouterFramework(runtimeContext, internalContext, inReactRouter);
|
|
75
|
+
const contextUseRouter = inReactRouter || 'tanstack' !== framework ? void 0 : internalContext.router?.useRouter || runtimeContext.router?.useRouter;
|
|
76
|
+
const contextRouter = contextUseRouter ? contextUseRouter({
|
|
77
|
+
warn: false
|
|
78
|
+
}) : null;
|
|
79
|
+
const hasRouter = 'tanstack' === framework || 'react-router' === framework || Boolean(reactRouterNavigate);
|
|
80
|
+
const subscribeToRouter = useCallback((update)=>{
|
|
81
|
+
const router = getRouterInstance(internalContext, contextRouter);
|
|
82
|
+
if (!router) return ()=>void 0;
|
|
83
|
+
const unsubscribers = [];
|
|
84
|
+
if ('react-router' === framework && !inReactRouter && 'function' == typeof router.subscribe) {
|
|
85
|
+
const subscribe = router.subscribe;
|
|
86
|
+
const unsubscribe = subscribe.call(router, update);
|
|
87
|
+
if ('function' == typeof unsubscribe) unsubscribers.push(unsubscribe);
|
|
88
|
+
}
|
|
89
|
+
if ('tanstack' === framework && 'function' == typeof router.stores?.location?.subscribe) {
|
|
90
|
+
const unsubscribe = router.stores.location.subscribe(update);
|
|
91
|
+
if ('function' == typeof unsubscribe) unsubscribers.push(unsubscribe);
|
|
92
|
+
}
|
|
93
|
+
if ('tanstack' === framework && 'function' == typeof router.subscribe) {
|
|
94
|
+
const subscribe = router.subscribe;
|
|
95
|
+
for (const eventType of [
|
|
96
|
+
'onBeforeNavigate',
|
|
97
|
+
'onBeforeLoad'
|
|
98
|
+
]){
|
|
99
|
+
const unsubscribe = subscribe.call(router, eventType, update);
|
|
100
|
+
if ('function' == typeof unsubscribe) unsubscribers.push(unsubscribe);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return ()=>{
|
|
104
|
+
for (const unsubscribe of unsubscribers)unsubscribe();
|
|
105
|
+
};
|
|
106
|
+
}, [
|
|
107
|
+
contextRouter,
|
|
108
|
+
framework,
|
|
109
|
+
inReactRouter,
|
|
110
|
+
internalContext
|
|
111
|
+
]);
|
|
112
|
+
const getSnapshot = useCallback(()=>getRouterSnapshot(internalContext, contextRouter), [
|
|
113
|
+
contextRouter,
|
|
114
|
+
internalContext
|
|
115
|
+
]);
|
|
116
|
+
useSyncExternalStore(subscribeToRouter, getSnapshot, getSnapshot);
|
|
117
|
+
const navigate = useCallback((href, options)=>{
|
|
118
|
+
const router = getRouterInstance(internalContext, contextRouter);
|
|
119
|
+
const activeFramework = getRouterFramework(runtimeContext, internalContext, inReactRouter);
|
|
120
|
+
if ('tanstack' === activeFramework) {
|
|
121
|
+
if ('function' == typeof router?.navigate) return router.navigate({
|
|
122
|
+
to: href,
|
|
123
|
+
replace: options?.replace,
|
|
124
|
+
...options?.state === void 0 ? {} : {
|
|
125
|
+
state: options.state
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
throw new Error('TanStack router instance is not available.');
|
|
129
|
+
}
|
|
130
|
+
if (reactRouterNavigate) return reactRouterNavigate(href, options);
|
|
131
|
+
if ('react-router' === activeFramework) {
|
|
132
|
+
if ('function' == typeof router?.navigate) return router.navigate(href, options);
|
|
133
|
+
throw new Error('React Router instance is not available.');
|
|
134
|
+
}
|
|
135
|
+
}, [
|
|
136
|
+
contextRouter,
|
|
137
|
+
internalContext,
|
|
138
|
+
inReactRouter,
|
|
139
|
+
reactRouterNavigate,
|
|
140
|
+
runtimeContext
|
|
141
|
+
]);
|
|
142
|
+
const location = (reactRouterLocation ? normalizeLocation(reactRouterLocation) : getRouterStateLocation(internalContext, contextRouter)) || getWindowLocation();
|
|
143
|
+
const params = inReactRouter ? reactRouterParams : getRouterParams(internalContext, contextRouter);
|
|
144
|
+
const Link = 'tanstack' === framework ? internalContext.router?.Link || runtimeContext.router?.Link || null : 'react-router' === framework || inReactRouter ? routerApi?.Link ?? null : null;
|
|
145
|
+
return {
|
|
146
|
+
framework,
|
|
147
|
+
hasRouter,
|
|
148
|
+
location,
|
|
149
|
+
navigate: hasRouter ? navigate : null,
|
|
150
|
+
Link,
|
|
151
|
+
params,
|
|
152
|
+
...'tanstack' === framework ? {
|
|
153
|
+
createLinkProps: createTanstackLinkProps
|
|
154
|
+
} : {}
|
|
155
|
+
};
|
|
156
|
+
};
|
|
157
|
+
const createTanstackLinkProps = (target)=>{
|
|
158
|
+
const preload = void 0 !== target.preload ? target.preload : 'none' === target.prefetch ? false : target.prefetch;
|
|
159
|
+
return {
|
|
160
|
+
to: target.pathname,
|
|
161
|
+
...target.search ? {
|
|
162
|
+
search: target.search
|
|
163
|
+
} : {},
|
|
164
|
+
...target.hash ? {
|
|
165
|
+
hash: target.hash
|
|
166
|
+
} : {},
|
|
167
|
+
...void 0 === target.hashScrollIntoView ? {} : {
|
|
168
|
+
hashScrollIntoView: target.hashScrollIntoView
|
|
169
|
+
},
|
|
170
|
+
...void 0 === preload ? {} : {
|
|
171
|
+
preload
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
const I18nRouterNavigationProvider = ({ children })=>{
|
|
176
|
+
const value = useIntegratedRouterAdapter();
|
|
177
|
+
return /*#__PURE__*/ jsx(I18nNavigationProvider, {
|
|
178
|
+
value: value,
|
|
179
|
+
children: children
|
|
180
|
+
});
|
|
181
|
+
};
|
|
182
|
+
export { I18nRouterNavigationProvider };
|
|
File without changes
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { i18nPlugin } from "@modern-js/plugin-i18n/runtime/no-react-i18next";
|
|
2
|
+
import { composeI18nPlugin } from "./runtimeComposition.mjs";
|
|
3
|
+
const runtime_no_react_i18next_i18nPlugin = composeI18nPlugin(i18nPlugin);
|
|
4
|
+
const runtime_no_react_i18next = runtime_no_react_i18next_i18nPlugin;
|
|
5
|
+
export default runtime_no_react_i18next;
|
|
6
|
+
export { runtime_no_react_i18next_i18nPlugin as i18nPlugin };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { i18nPlugin } from "@modern-js/plugin-i18n/runtime";
|
|
2
|
+
import { composeI18nPlugin } from "./runtimeComposition.mjs";
|
|
3
|
+
const runtime_i18nPlugin = composeI18nPlugin(i18nPlugin);
|
|
4
|
+
const runtime = runtime_i18nPlugin;
|
|
5
|
+
export default runtime;
|
|
6
|
+
export { runtime_i18nPlugin as i18nPlugin };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { registerFederatedI18nBoundary } from "./federation/registration.mjs";
|
|
2
|
+
import { I18nLanguageSynchronization } from "./languageSynchronization.mjs";
|
|
3
|
+
import { I18nRouterNavigationProvider } from "./navigation.mjs";
|
|
4
|
+
import { createI18nUrlStrategy } from "./urlStrategy.mjs";
|
|
5
|
+
const composeI18nPlugin = (nativeI18nPlugin)=>(options = {})=>{
|
|
6
|
+
const { localisedUrls, localeDetectionByEntry: _entryOptions, ...nativeLocaleDetection } = options.localeDetection ?? {};
|
|
7
|
+
const native = nativeI18nPlugin({
|
|
8
|
+
...options,
|
|
9
|
+
localeDetection: nativeLocaleDetection,
|
|
10
|
+
urlStrategy: options.urlStrategy ?? createI18nUrlStrategy(localisedUrls),
|
|
11
|
+
NavigationProvider: options.NavigationProvider ?? I18nRouterNavigationProvider,
|
|
12
|
+
LanguageSynchronization: options.LanguageSynchronization ?? I18nLanguageSynchronization
|
|
13
|
+
});
|
|
14
|
+
return {
|
|
15
|
+
...native,
|
|
16
|
+
setup (api) {
|
|
17
|
+
registerFederatedI18nBoundary(api);
|
|
18
|
+
return native.setup?.(api);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
export { composeI18nPlugin };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { getLocaleDetectionOptions } from "@modern-js/plugin-i18n/config";
|
|
2
|
+
import { i18nServerPlugin } from "@modern-js/plugin-i18n/server";
|
|
3
|
+
import { createI18nUrlStrategy } from "./urlStrategy.mjs";
|
|
4
|
+
const server_i18nServerPlugin = (options)=>i18nServerPlugin({
|
|
5
|
+
...options,
|
|
6
|
+
resolveUrlStrategy: options.resolveUrlStrategy ?? ((entryName)=>createI18nUrlStrategy(options.localeDetection ? getLocaleDetectionOptions(entryName, options.localeDetection).localisedUrls : void 0))
|
|
7
|
+
});
|
|
8
|
+
const server = server_i18nServerPlugin;
|
|
9
|
+
export default server;
|
|
10
|
+
export { server_i18nServerPlugin as i18nServerPlugin };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { canonicalTargetPathname, isDefaultLocaleRedirectSkipPath, localiseTargetPathname } from "@modern-js/i18n-runtime-extensions";
|
|
2
|
+
const createI18nUrlStrategy = (localisedUrls)=>({
|
|
3
|
+
localizePathname: (pathname, language, languages)=>localiseTargetPathname(pathname, language, [
|
|
4
|
+
...languages
|
|
5
|
+
], localisedUrls),
|
|
6
|
+
canonicalPathname: (pathname, languages)=>canonicalTargetPathname(pathname, [
|
|
7
|
+
...languages
|
|
8
|
+
], localisedUrls),
|
|
9
|
+
shouldSkipRedirect: (pathname, languages)=>isDefaultLocaleRedirectSkipPath(pathname, [
|
|
10
|
+
...languages
|
|
11
|
+
])
|
|
12
|
+
});
|
|
13
|
+
export { createI18nUrlStrategy };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
import { applyLocalisedUrlsToRoutes, resolveLocalisedUrlsConfig } from "@modern-js/i18n-runtime-extensions";
|
|
3
|
+
const runtimePaths = new Map([
|
|
4
|
+
[
|
|
5
|
+
'@modern-js/plugin-i18n/runtime',
|
|
6
|
+
'@modern-js/i18n-integration/runtime'
|
|
7
|
+
],
|
|
8
|
+
[
|
|
9
|
+
'@modern-js/plugin-i18n/runtime/no-react-i18next',
|
|
10
|
+
'@modern-js/i18n-integration/runtime/no-react-i18next'
|
|
11
|
+
]
|
|
12
|
+
]);
|
|
13
|
+
const integrationRuntimePaths = new Set(runtimePaths.values());
|
|
14
|
+
const ultramodernI18nIntegrationPlugin = ()=>({
|
|
15
|
+
name: '@modern-js/i18n-integration',
|
|
16
|
+
pre: [
|
|
17
|
+
'@modern-js/plugin-i18n'
|
|
18
|
+
],
|
|
19
|
+
setup (api) {
|
|
20
|
+
api._internalRuntimePlugins(({ entrypoint, plugins })=>({
|
|
21
|
+
entrypoint,
|
|
22
|
+
plugins: plugins.map((plugin)=>{
|
|
23
|
+
const path = runtimePaths.get(plugin.path);
|
|
24
|
+
return path ? {
|
|
25
|
+
...plugin,
|
|
26
|
+
path
|
|
27
|
+
} : plugin;
|
|
28
|
+
})
|
|
29
|
+
}));
|
|
30
|
+
api._internalServerPlugins(({ plugins })=>({
|
|
31
|
+
plugins: plugins.map((plugin)=>'@modern-js/plugin-i18n/server' === plugin.name ? {
|
|
32
|
+
...plugin,
|
|
33
|
+
name: '@modern-js/i18n-integration/server'
|
|
34
|
+
} : plugin)
|
|
35
|
+
}));
|
|
36
|
+
api.modifyFileSystemRoutes(async ({ entrypoint, routes })=>{
|
|
37
|
+
const { plugins } = await api.getHooks()._internalRuntimePlugins.call({
|
|
38
|
+
entrypoint,
|
|
39
|
+
plugins: []
|
|
40
|
+
});
|
|
41
|
+
const descriptor = plugins.find((plugin)=>integrationRuntimePaths.has(plugin.path));
|
|
42
|
+
const config = descriptor?.config;
|
|
43
|
+
const { localePathRedirect, languages = [], localisedUrls } = config?.localeDetection ?? {};
|
|
44
|
+
const resolved = resolveLocalisedUrlsConfig(localisedUrls);
|
|
45
|
+
if (!localePathRedirect || !languages.length || !resolved.enabled) return {
|
|
46
|
+
entrypoint,
|
|
47
|
+
routes
|
|
48
|
+
};
|
|
49
|
+
return {
|
|
50
|
+
entrypoint,
|
|
51
|
+
routes: applyLocalisedUrlsToRoutes(routes, languages, resolved.map)
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
const cli = ultramodernI18nIntegrationPlugin;
|
|
57
|
+
export default cli;
|
|
58
|
+
export { ultramodernI18nIntegrationPlugin };
|