@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.
Files changed (58) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cjs/cli.js +97 -0
  3. package/dist/cjs/federation/boundary.js +100 -0
  4. package/dist/cjs/federation/registration.js +43 -0
  5. package/dist/cjs/languageSynchronization.js +44 -0
  6. package/dist/cjs/navigation.js +220 -0
  7. package/dist/cjs/options.js +18 -0
  8. package/dist/cjs/runtime-no-react-i18next.js +46 -0
  9. package/dist/cjs/runtime.js +46 -0
  10. package/dist/cjs/runtimeComposition.js +60 -0
  11. package/dist/cjs/server.js +50 -0
  12. package/dist/cjs/urlStrategy.js +51 -0
  13. package/dist/esm/cli.mjs +57 -0
  14. package/dist/esm/federation/boundary.mjs +62 -0
  15. package/dist/esm/federation/registration.mjs +5 -0
  16. package/dist/esm/languageSynchronization.mjs +6 -0
  17. package/dist/esm/navigation.mjs +182 -0
  18. package/dist/esm/options.mjs +0 -0
  19. package/dist/esm/runtime-no-react-i18next.mjs +6 -0
  20. package/dist/esm/runtime.mjs +6 -0
  21. package/dist/esm/runtimeComposition.mjs +22 -0
  22. package/dist/esm/server.mjs +10 -0
  23. package/dist/esm/urlStrategy.mjs +13 -0
  24. package/dist/esm-node/cli.mjs +58 -0
  25. package/dist/esm-node/federation/boundary.mjs +63 -0
  26. package/dist/esm-node/federation/registration.mjs +6 -0
  27. package/dist/esm-node/languageSynchronization.mjs +7 -0
  28. package/dist/esm-node/navigation.mjs +183 -0
  29. package/dist/esm-node/options.mjs +1 -0
  30. package/dist/esm-node/runtime-no-react-i18next.mjs +7 -0
  31. package/dist/esm-node/runtime.mjs +7 -0
  32. package/dist/esm-node/runtimeComposition.mjs +23 -0
  33. package/dist/esm-node/server.mjs +11 -0
  34. package/dist/esm-node/urlStrategy.mjs +14 -0
  35. package/dist/types/cli.d.ts +4 -0
  36. package/dist/types/federation/boundary.d.ts +9 -0
  37. package/dist/types/federation/registration.d.ts +2 -0
  38. package/dist/types/languageSynchronization.d.ts +3 -0
  39. package/dist/types/navigation.d.ts +3 -0
  40. package/dist/types/options.d.ts +13 -0
  41. package/dist/types/runtime-no-react-i18next.d.ts +2 -0
  42. package/dist/types/runtime.d.ts +2 -0
  43. package/dist/types/runtimeComposition.d.ts +4 -0
  44. package/dist/types/server.d.ts +3 -0
  45. package/dist/types/urlStrategy.d.ts +4 -0
  46. package/package.json +139 -5
  47. package/src/cli.ts +72 -0
  48. package/src/federation/boundary.tsx +129 -0
  49. package/src/federation/registration.ts +8 -0
  50. package/src/languageSynchronization.tsx +23 -0
  51. package/src/navigation.tsx +399 -0
  52. package/src/options.ts +18 -0
  53. package/src/runtime-no-react-i18next.ts +5 -0
  54. package/src/runtime.ts +5 -0
  55. package/src/runtimeComposition.ts +33 -0
  56. package/src/server.ts +27 -0
  57. package/src/urlStrategy.ts +19 -0
  58. 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
+ });
@@ -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 };