@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.
Files changed (127) hide show
  1. package/dist/cjs/cli/index.js +10 -21
  2. package/dist/cjs/cli/localisedRoutes.js +47 -0
  3. package/dist/cjs/runtime/Link.js +19 -32
  4. package/dist/cjs/runtime/context.js +30 -73
  5. package/dist/cjs/runtime/contextHelpers.js +5 -5
  6. package/dist/cjs/runtime/contexts.js +49 -0
  7. package/dist/cjs/runtime/core.js +27 -14
  8. package/dist/cjs/runtime/hooks.js +7 -8
  9. package/dist/cjs/runtime/localizedPaths.js +11 -9
  10. package/dist/cjs/runtime/navigation.js +48 -0
  11. package/dist/cjs/runtime/providerComposition.js +37 -13
  12. package/dist/cjs/runtime/routerAdapter.js +33 -140
  13. package/dist/cjs/runtime/sharedContexts.js +43 -0
  14. package/dist/cjs/runtime/utils.js +21 -19
  15. package/dist/cjs/server/defaultUrlStrategy.js +48 -0
  16. package/dist/cjs/server/index.js +11 -7
  17. package/dist/cjs/server/mappedUrlStrategy.js +43 -0
  18. package/dist/cjs/server/redirectPolicy.js +33 -24
  19. package/dist/cjs/shared/mappedUrlStrategy.js +63 -0
  20. package/dist/cjs/shared/urlStrategy.js +48 -0
  21. package/dist/esm/cli/index.mjs +10 -21
  22. package/dist/esm/cli/localisedRoutes.mjs +9 -0
  23. package/dist/esm/runtime/Link.mjs +19 -32
  24. package/dist/esm/runtime/context.mjs +20 -72
  25. package/dist/esm/runtime/contextHelpers.mjs +5 -5
  26. package/dist/esm/runtime/contexts.mjs +5 -0
  27. package/dist/esm/runtime/core.mjs +13 -6
  28. package/dist/esm/runtime/hooks.mjs +7 -8
  29. package/dist/esm/runtime/localizedPaths.mjs +11 -9
  30. package/dist/esm/runtime/navigation.mjs +7 -0
  31. package/dist/esm/runtime/providerComposition.mjs +38 -14
  32. package/dist/esm/runtime/routerAdapter.mjs +28 -141
  33. package/dist/esm/runtime/sharedContexts.mjs +1 -0
  34. package/dist/esm/runtime/utils.mjs +19 -17
  35. package/dist/esm/server/defaultUrlStrategy.mjs +7 -0
  36. package/dist/esm/server/index.mjs +11 -7
  37. package/dist/esm/server/mappedUrlStrategy.mjs +1 -0
  38. package/dist/esm/server/redirectPolicy.mjs +33 -24
  39. package/dist/esm/shared/mappedUrlStrategy.mjs +19 -0
  40. package/dist/esm/shared/urlStrategy.mjs +7 -0
  41. package/dist/esm-node/cli/index.mjs +10 -21
  42. package/dist/esm-node/cli/localisedRoutes.mjs +10 -0
  43. package/dist/esm-node/runtime/Link.mjs +19 -32
  44. package/dist/esm-node/runtime/context.mjs +20 -72
  45. package/dist/esm-node/runtime/contextHelpers.mjs +5 -5
  46. package/dist/esm-node/runtime/contexts.mjs +6 -0
  47. package/dist/esm-node/runtime/core.mjs +13 -6
  48. package/dist/esm-node/runtime/hooks.mjs +7 -8
  49. package/dist/esm-node/runtime/localizedPaths.mjs +11 -9
  50. package/dist/esm-node/runtime/navigation.mjs +8 -0
  51. package/dist/esm-node/runtime/providerComposition.mjs +38 -14
  52. package/dist/esm-node/runtime/routerAdapter.mjs +28 -141
  53. package/dist/esm-node/runtime/sharedContexts.mjs +2 -0
  54. package/dist/esm-node/runtime/utils.mjs +19 -17
  55. package/dist/esm-node/server/defaultUrlStrategy.mjs +8 -0
  56. package/dist/esm-node/server/index.mjs +11 -7
  57. package/dist/esm-node/server/mappedUrlStrategy.mjs +2 -0
  58. package/dist/esm-node/server/redirectPolicy.mjs +33 -24
  59. package/dist/esm-node/shared/mappedUrlStrategy.mjs +20 -0
  60. package/dist/esm-node/shared/urlStrategy.mjs +8 -0
  61. package/dist/types/cli/localisedRoutes.d.ts +19 -0
  62. package/dist/types/runtime/context.d.ts +8 -11
  63. package/dist/types/runtime/contextHelpers.d.ts +2 -2
  64. package/dist/types/runtime/contexts.d.ts +6 -0
  65. package/dist/types/runtime/core.d.ts +12 -2
  66. package/dist/types/runtime/hooks.d.ts +4 -5
  67. package/dist/types/runtime/localizedPaths.d.ts +4 -4
  68. package/dist/types/runtime/navigation.d.ts +10 -0
  69. package/dist/types/runtime/providerComposition.d.ts +13 -1
  70. package/dist/types/runtime/routerAdapter.d.ts +23 -6
  71. package/dist/types/runtime/sharedContexts.d.ts +1 -0
  72. package/dist/types/runtime/utils.d.ts +4 -12
  73. package/dist/types/server/defaultUrlStrategy.d.ts +11 -0
  74. package/dist/types/server/index.d.ts +2 -0
  75. package/dist/types/server/mappedUrlStrategy.d.ts +7 -0
  76. package/dist/types/server/redirectPolicy.d.ts +5 -13
  77. package/dist/types/shared/mappedUrlStrategy.d.ts +27 -0
  78. package/dist/types/shared/type.d.ts +7 -11
  79. package/dist/types/shared/urlStrategy.d.ts +18 -0
  80. package/package.json +42 -19
  81. package/rslib.config.mts +8 -1
  82. package/rstest.config.mts +6 -5
  83. package/src/cli/index.ts +42 -42
  84. package/src/cli/localisedRoutes.ts +53 -0
  85. package/src/runtime/Link.tsx +20 -40
  86. package/src/runtime/context.tsx +33 -157
  87. package/src/runtime/contextHelpers.ts +7 -5
  88. package/src/runtime/contexts.ts +16 -0
  89. package/src/runtime/core.tsx +53 -6
  90. package/src/runtime/hooks.ts +14 -9
  91. package/src/runtime/i18n/instance.ts +1 -2
  92. package/src/runtime/localizedPaths.ts +24 -19
  93. package/src/runtime/navigation.tsx +20 -0
  94. package/src/runtime/providerComposition.tsx +71 -23
  95. package/src/runtime/routerAdapter.tsx +65 -339
  96. package/src/runtime/sharedContexts.ts +8 -0
  97. package/src/runtime/utils.ts +49 -31
  98. package/src/server/defaultUrlStrategy.ts +27 -0
  99. package/src/server/index.ts +39 -9
  100. package/src/server/mappedUrlStrategy.ts +10 -0
  101. package/src/server/redirectPolicy.ts +85 -70
  102. package/src/shared/mappedUrlStrategy.ts +59 -0
  103. package/src/shared/type.ts +7 -11
  104. package/src/shared/urlStrategy.ts +38 -0
  105. package/tests/backendDefaults.test.ts +2 -23
  106. package/tests/defaultUrlStrategy.test.ts +107 -0
  107. package/tests/federatedI18nBoundaryResolver.test.tsx +65 -0
  108. package/tests/i18nUtils.test.ts +31 -65
  109. package/tests/link.test.tsx +13 -511
  110. package/tests/localisedRouteGeneration.test.ts +200 -0
  111. package/tests/localisedUrls.test.ts +16 -208
  112. package/tests/mappedUrlStrategyDerivation.test.ts +62 -0
  113. package/tests/navigation.test.tsx +403 -0
  114. package/tests/reactI18nextRuntimeBoundary.test.ts +8 -83
  115. package/tests/redirectPolicy.test.ts +89 -27
  116. package/tests/routerAdapter.test.tsx +98 -1171
  117. package/tests/urlStrategySerialization.test.ts +122 -0
  118. package/tsconfig.json +4 -2
  119. package/tests/federatedI18nBoundary.client.test.tsx +0 -129
  120. package/tests/federatedI18nBoundary.test.tsx +0 -132
  121. package/tests/linkTypes.test.ts +0 -59
  122. package/tests/localisedUrlRewriteMatrix.fork.test.ts +0 -147
  123. package/tests/peerCohort.test.ts +0 -25
  124. package/tests/type-fixture/fixture-globals.d.ts +0 -11
  125. package/tests/type-fixture/i18nInstanceTypes.fixture.ts +0 -29
  126. package/tests/type-fixture/linkTypes.fixture.tsx +0 -51
  127. package/tests/type-fixture/tsconfig.json +0 -16
@@ -31,10 +31,12 @@ __webpack_require__.d(__webpack_exports__, {
31
31
  default: ()=>cli,
32
32
  i18nPlugin: ()=>i18nPlugin
33
33
  });
34
- const i18n_runtime_extensions_namespaceObject = require("@modern-js/i18n-runtime-extensions");
35
34
  const server_core_namespaceObject = require("@modern-js/server-core");
35
+ const utils_namespaceObject = require("@modern-js/utils");
36
+ const urlStrategy_js_namespaceObject = require("../shared/urlStrategy.js");
36
37
  const utils_js_namespaceObject = require("../shared/utils.js");
37
38
  const external_locales_js_namespaceObject = require("./locales.js");
39
+ const external_localisedRoutes_js_namespaceObject = require("./localisedRoutes.js");
38
40
  require("../runtime/types.js");
39
41
  const i18nPlugin = (options = {})=>({
40
42
  name: '@modern-js/plugin-i18n',
@@ -64,6 +66,10 @@ const i18nPlugin = (options = {})=>({
64
66
  backend: backendOptions,
65
67
  ...extendedConfig
66
68
  };
69
+ if ((0, urlStrategy_js_namespaceObject.isUnusableI18nUrlStrategy)(config.urlStrategy)) {
70
+ delete config.urlStrategy;
71
+ utils_namespaceObject.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.");
72
+ }
67
73
  const { reactI18next } = extendedConfig;
68
74
  const runtimePluginPath = customPlugin?.runtime?.path || (false === reactI18next ? `@${metaName}/plugin-i18n/runtime/no-react-i18next` : `@${metaName}/plugin-i18n/runtime`);
69
75
  plugins.push({
@@ -76,27 +82,10 @@ const i18nPlugin = (options = {})=>({
76
82
  plugins
77
83
  };
78
84
  });
79
- api.modifyFileSystemRoutes(({ entrypoint, routes })=>{
80
- if (!localeDetection) return {
85
+ api.modifyFileSystemRoutes(({ entrypoint, routes })=>({
81
86
  entrypoint,
82
- routes
83
- };
84
- const localeDetectionOptions = (0, utils_js_namespaceObject.getLocaleDetectionOptions)(entrypoint.entryName, localeDetection);
85
- const { localePathRedirect, languages = [], localisedUrls } = localeDetectionOptions;
86
- if (!localePathRedirect || 0 === languages.length) return {
87
- entrypoint,
88
- routes
89
- };
90
- const localisedUrlsConfig = (0, i18n_runtime_extensions_namespaceObject.resolveLocalisedUrlsConfig)(localisedUrls);
91
- if (!localisedUrlsConfig.enabled) return {
92
- entrypoint,
93
- routes
94
- };
95
- return {
96
- entrypoint,
97
- routes: (0, i18n_runtime_extensions_namespaceObject.applyLocalisedUrlsToRoutes)(routes, languages, localisedUrlsConfig.map)
98
- };
99
- });
87
+ routes: (0, external_localisedRoutes_js_namespaceObject.applyLocalisedRoutes)(routes, localeDetection ? (0, utils_js_namespaceObject.getLocaleDetectionOptions)(entrypoint.entryName, localeDetection) : void 0, entrypoint)
88
+ }));
100
89
  api._internalServerPlugins(({ plugins })=>{
101
90
  const { serverRoutes, metaName } = api.getAppContext();
102
91
  const normalizedConfig = api.getNormalizedConfig();
@@ -0,0 +1,47 @@
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
+ applyLocalisedRoutes: ()=>applyLocalisedRoutes
32
+ });
33
+ const i18n_runtime_extensions_namespaceObject = require("@modern-js/i18n-runtime-extensions");
34
+ const cli_namespaceObject = require("@modern-js/runtime/cli");
35
+ const applyLocalisedRoutes = (routes, localeDetection, entrypoint)=>{
36
+ const { localePathRedirect, languages = [], localisedUrls } = localeDetection ?? {};
37
+ const resolved = (0, i18n_runtime_extensions_namespaceObject.resolveLocalisedUrlsConfig)(localisedUrls);
38
+ if (!localePathRedirect || !languages.length || !resolved.enabled) return routes;
39
+ return (0, i18n_runtime_extensions_namespaceObject.applyLocalisedUrlsToRoutes)(routes, languages, resolved.map, entrypoint && '@modern-js/plugin-tanstack' === (0, cli_namespaceObject.getEntrypointRoutesOwner)(entrypoint) ? 'canonical' : 'physical');
40
+ };
41
+ exports.applyLocalisedRoutes = __webpack_exports__.applyLocalisedRoutes;
42
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
43
+ "applyLocalisedRoutes"
44
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
45
+ Object.defineProperty(exports, '__esModule', {
46
+ value: true
47
+ });
@@ -43,10 +43,10 @@ const EXTERNAL_TARGET_RE = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
43
43
  const Link = (props)=>{
44
44
  const { to, params, children, hash: hashProp, search: searchProp, hashScrollIntoView, activeOptions, activeProps, prefetch, preload, ...rest } = props;
45
45
  const adapter = (0, external_routerAdapter_js_namespaceObject.useI18nRouterAdapter)();
46
- const { language, supportedLanguages, localisedUrls } = (0, external_context_js_namespaceObject.useModernI18n)();
46
+ const { language, supportedLanguages, urlStrategy } = (0, external_context_js_namespaceObject.useModernI18n)();
47
47
  const config = {
48
48
  languages: supportedLanguages,
49
- localisedUrls
49
+ urlStrategy
50
50
  };
51
51
  const isExternal = EXTERNAL_TARGET_RE.test(to);
52
52
  const isBareHash = to.startsWith('#');
@@ -56,7 +56,7 @@ const Link = (props)=>{
56
56
  const interpolated = (0, external_linkHelpers_js_namespaceObject.interpolateRouteParams)(pathname || '/', params);
57
57
  const firstSegment = interpolated.split('/').filter(Boolean)[0];
58
58
  if (firstSegment && supportedLanguages.includes(firstSegment)) (0, external_linkHelpers_js_namespaceObject.warnOnce)(`lang-prefix:${to}`, `[plugin-i18n] <Link to="${to}"> starts with a language prefix. Write language-agnostic canonical paths; the Link localizes them automatically.`);
59
- const localizedPathname = (0, external_utils_js_namespaceObject.buildLocalizedUrl)(interpolated, language, supportedLanguages, localisedUrls);
59
+ const localizedPathname = (0, external_utils_js_namespaceObject.buildLocalizedUrl)(interpolated, language, supportedLanguages, urlStrategy);
60
60
  const hash = hashProp ?? (hashFromTo ? hashFromTo.slice(1) : '');
61
61
  const { searchString, searchObject } = (0, external_linkHelpers_js_namespaceObject.normalizeSearch)(searchProp, searchFromTo);
62
62
  return {
@@ -76,7 +76,7 @@ const Link = (props)=>{
76
76
  isBareHash,
77
77
  language,
78
78
  supportedLanguages,
79
- localisedUrls
79
+ urlStrategy
80
80
  ]);
81
81
  const isActive = (0, external_react_namespaceObject.useMemo)(()=>{
82
82
  if (!target || !adapter.location) return false;
@@ -91,7 +91,7 @@ const Link = (props)=>{
91
91
  adapter.location,
92
92
  activeOptions?.exact,
93
93
  supportedLanguages,
94
- localisedUrls
94
+ urlStrategy
95
95
  ]);
96
96
  const resolvedActiveProps = (0, external_linkHelpers_js_namespaceObject.splitActiveProps)(isActive, activeProps);
97
97
  const activeAttributes = isActive ? {
@@ -106,7 +106,7 @@ const Link = (props)=>{
106
106
  children: children
107
107
  });
108
108
  }
109
- const { Link: RouterLink, hasRouter, framework } = adapter;
109
+ const { Link: RouterLink, hasRouter } = adapter;
110
110
  if (!hasRouter || !RouterLink) {
111
111
  const { replace: _replace, ...anchorProps } = rest;
112
112
  const { className: activeClassName, style: activeStyle, ...activeRest } = resolvedActiveProps;
@@ -129,38 +129,25 @@ const Link = (props)=>{
129
129
  ...rest.style,
130
130
  ...activeStyle
131
131
  };
132
- if ('tanstack' === framework) {
133
- const tanstackPreload = void 0 !== preload ? preload : void 0 === prefetch ? void 0 : 'none' === prefetch ? false : prefetch;
134
- return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(RouterLink, {
135
- to: target.localizedPathname,
136
- ...target.searchObject ? {
137
- search: target.searchObject
138
- } : {},
139
- ...target.hash ? {
140
- hash: target.hash
141
- } : {},
142
- ...void 0 === hashScrollIntoView ? {} : {
143
- hashScrollIntoView
144
- },
145
- ...void 0 === tanstackPreload ? {} : {
146
- preload: tanstackPreload
147
- },
148
- ...rest,
149
- ...activeRest,
150
- ...activeAttributes,
151
- className: mergedClassName,
152
- style: mergedStyle,
153
- children: children
154
- });
155
- }
156
- return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(RouterLink, {
132
+ const routerProps = adapter.createLinkProps?.({
133
+ pathname: target.localizedPathname,
134
+ href: target.href,
135
+ search: target.searchObject,
136
+ hash: target.hash,
137
+ hashScrollIntoView,
138
+ prefetch,
139
+ preload
140
+ }) ?? {
157
141
  to: target.href,
158
142
  ...void 0 === prefetch ? {} : {
159
143
  prefetch
160
144
  },
161
145
  ...void 0 === preload ? {} : {
162
146
  preload
163
- },
147
+ }
148
+ };
149
+ return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(RouterLink, {
150
+ ...routerProps,
164
151
  ...rest,
165
152
  ...activeRest,
166
153
  ...activeAttributes,
@@ -29,95 +29,46 @@ var __webpack_exports__ = {};
29
29
  __webpack_require__.r(__webpack_exports__);
30
30
  __webpack_require__.d(__webpack_exports__, {
31
31
  FederatedI18nBoundary: ()=>FederatedI18nBoundary,
32
+ ModernI18nContext: ()=>external_sharedContexts_js_namespaceObject.ModernI18nContext,
32
33
  ModernI18nProvider: ()=>ModernI18nProvider,
34
+ ReactI18nextProviderContext: ()=>external_sharedContexts_js_namespaceObject.ReactI18nextProviderContext,
35
+ getActualI18nextInstance: ()=>instance_js_namespaceObject.getActualI18nextInstance,
33
36
  useModernI18n: ()=>useModernI18n
34
37
  });
35
38
  const jsx_runtime_namespaceObject = require("react/jsx-runtime");
39
+ const context_namespaceObject = require("@modern-js/runtime/context");
36
40
  const external_react_namespaceObject = require("react");
37
41
  const external_contextHelpers_js_namespaceObject = require("./contextHelpers.js");
38
- const instance_js_namespaceObject = require("./i18n/instance.js");
39
42
  const external_routerAdapter_js_namespaceObject = require("./routerAdapter.js");
40
- const modernI18nContextKey = Symbol.for('@modern-js/plugin-i18n/runtime/ModernI18nContext');
41
- const reactI18nextProviderContextKey = Symbol.for('@modern-js/plugin-i18n/runtime/ReactI18nextProviderContext');
42
- const getGlobalContext = (key, defaultValue)=>{
43
- const globalStore = globalThis;
44
- globalStore[key] ??= /*#__PURE__*/ (0, external_react_namespaceObject.createContext)(defaultValue);
45
- return globalStore[key];
46
- };
47
- const ModernI18nContext = getGlobalContext(modernI18nContextKey, null);
48
- const ReactI18nextProviderContext = getGlobalContext(reactI18nextProviderContextKey, null);
43
+ const external_sharedContexts_js_namespaceObject = require("./sharedContexts.js");
44
+ const instance_js_namespaceObject = require("./i18n/instance.js");
49
45
  const ModernI18nProvider = ({ children, i18nextProvider, value })=>{
50
- const content = /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(ModernI18nContext.Provider, {
46
+ const content = /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_sharedContexts_js_namespaceObject.ModernI18nContext.Provider, {
51
47
  value: value,
52
48
  children: children
53
49
  });
54
- return void 0 === i18nextProvider ? content : /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(ReactI18nextProviderContext.Provider, {
50
+ return void 0 === i18nextProvider ? content : /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_sharedContexts_js_namespaceObject.ReactI18nextProviderContext.Provider, {
55
51
  value: i18nextProvider,
56
52
  children: content
57
53
  });
58
54
  };
59
- const FederatedI18nBoundary = ({ children, defaultNamespace, fallbackLanguage, resources, supportedLanguages })=>{
60
- const parent = (0, external_react_namespaceObject.useContext)(ModernI18nContext);
61
- const I18nextProvider = (0, external_react_namespaceObject.useContext)(ReactI18nextProviderContext);
62
- if (!parent) throw new Error('FederatedI18nBoundary must be used within ModernI18nProvider');
63
- const languages = supportedLanguages ?? parent.languages ?? Object.keys(resources);
64
- const scopedInstance = (0, external_react_namespaceObject.useMemo)(()=>{
65
- const parentInstance = (0, instance_js_namespaceObject.getActualI18nextInstance)(parent.i18nInstance);
66
- const clone = parentInstance.cloneInstance?.({
67
- defaultNS: defaultNamespace,
68
- fallbackLng: fallbackLanguage ?? languages[0] ?? parent.language,
69
- forkResourceStore: true,
70
- initImmediate: false,
71
- lng: parent.language,
72
- ns: [
73
- defaultNamespace
74
- ],
75
- resources,
76
- supportedLngs: languages
77
- });
78
- if (!clone) throw new Error('FederatedI18nBoundary requires an i18n instance with cloneInstance support');
79
- const resourceStore = clone.store;
80
- const parentResourceStore = parentInstance.store;
81
- const sharesNestedResourceState = Object.entries(resourceStore?.data ?? {}).some(([language, namespaces])=>{
82
- const parentNamespaces = parentResourceStore?.data?.[language];
83
- return namespaces === parentNamespaces || Object.entries(namespaces).some(([namespace, resource])=>null !== resource && 'object' == typeof resource && resource === parentNamespaces?.[namespace]);
84
- });
85
- if (clone === parentInstance || resourceStore === parentResourceStore || resourceStore?.data === parentResourceStore?.data || sharesNestedResourceState) throw new Error('FederatedI18nBoundary cloneInstance did not isolate the host resource store');
86
- if (!resourceStore?.addResourceBundle || !clone.removeResourceBundle || !resourceStore.data) throw new Error('FederatedI18nBoundary requires an isolated mutable i18n resource store');
87
- for (const [language, namespaces] of Object.entries(resourceStore.data))for (const namespace of Object.keys(namespaces))clone.removeResourceBundle(language, namespace);
88
- for (const [language, namespaces] of Object.entries(resources))for (const [namespace, resource] of Object.entries(namespaces))resourceStore.addResourceBundle(language, namespace, resource, true, true);
89
- return clone;
90
- }, [
91
- defaultNamespace,
92
- fallbackLanguage,
93
- languages,
94
- parent.i18nInstance,
95
- parent.language,
96
- resources
97
- ]);
98
- const value = (0, external_react_namespaceObject.useMemo)(()=>({
99
- ...parent,
100
- i18nInstance: scopedInstance,
101
- language: parent.language,
102
- languages
103
- }), [
104
- languages,
105
- parent,
106
- scopedInstance
107
- ]);
108
- const scopedContent = /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(ModernI18nProvider, {
109
- value: value,
110
- children: children
55
+ const MissingFederatedI18nBoundary = ()=>{
56
+ throw new Error('FederatedI18nBoundary requires the @modern-js/i18n-integration runtime plugin');
57
+ };
58
+ const FederatedI18nBoundary = (props)=>{
59
+ const resolveComponent = (0, external_react_namespaceObject.useContext)(context_namespaceObject.RuntimeComponentResolverContext);
60
+ const Boundary = resolveComponent?.(MissingFederatedI18nBoundary, {
61
+ name: 'i18n.FederatedI18nBoundary'
62
+ }) ?? MissingFederatedI18nBoundary;
63
+ if (Boundary === FederatedI18nBoundary) throw new Error('FederatedI18nBoundary resolver returned its own wrapper');
64
+ return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(Boundary, {
65
+ ...props
111
66
  });
112
- return I18nextProvider ? /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(I18nextProvider, {
113
- i18n: scopedInstance,
114
- children: scopedContent
115
- }) : scopedContent;
116
67
  };
117
68
  const useModernI18n = ()=>{
118
- const context = (0, external_react_namespaceObject.useContext)(ModernI18nContext);
69
+ const context = (0, external_react_namespaceObject.useContext)(external_sharedContexts_js_namespaceObject.ModernI18nContext);
119
70
  if (!context) throw new Error('useModernI18n must be used within ModernI18nProvider');
120
- const { language: contextLanguage, i18nInstance, languages, localePathRedirect, ignoreRedirectRoutes, localisedUrls, updateLanguage, synchronizeLanguage } = context;
71
+ const { language: contextLanguage, i18nInstance, languages, localePathRedirect, ignoreRedirectRoutes, urlStrategy, updateLanguage, synchronizeLanguage } = context;
121
72
  const { navigate, location, hasRouter } = (0, external_routerAdapter_js_namespaceObject.useI18nRouterAdapter)();
122
73
  const pathLanguage = (0, external_react_namespaceObject.useMemo)(()=>(0, external_contextHelpers_js_namespaceObject.getPathLanguage)(location?.pathname, languages, localePathRedirect), [
123
74
  languages,
@@ -136,7 +87,7 @@ const useModernI18n = ()=>{
136
87
  updateLanguage,
137
88
  localePathRedirect,
138
89
  ignoreRedirectRoutes,
139
- localisedUrls,
90
+ urlStrategy,
140
91
  languages,
141
92
  hasRouter,
142
93
  navigate,
@@ -146,7 +97,7 @@ const useModernI18n = ()=>{
146
97
  updateLanguage,
147
98
  localePathRedirect,
148
99
  ignoreRedirectRoutes,
149
- localisedUrls,
100
+ urlStrategy,
150
101
  languages,
151
102
  hasRouter,
152
103
  navigate,
@@ -169,17 +120,23 @@ const useModernI18n = ()=>{
169
120
  t,
170
121
  i18nInstance: i18nInstance,
171
122
  supportedLanguages: languages || [],
172
- localisedUrls,
123
+ urlStrategy,
173
124
  isLanguageSupported,
174
125
  isResourcesReady
175
126
  };
176
127
  };
177
128
  exports.FederatedI18nBoundary = __webpack_exports__.FederatedI18nBoundary;
129
+ exports.ModernI18nContext = __webpack_exports__.ModernI18nContext;
178
130
  exports.ModernI18nProvider = __webpack_exports__.ModernI18nProvider;
131
+ exports.ReactI18nextProviderContext = __webpack_exports__.ReactI18nextProviderContext;
132
+ exports.getActualI18nextInstance = __webpack_exports__.getActualI18nextInstance;
179
133
  exports.useModernI18n = __webpack_exports__.useModernI18n;
180
134
  for(var __rspack_i in __webpack_exports__)if (-1 === [
181
135
  "FederatedI18nBoundary",
136
+ "ModernI18nContext",
182
137
  "ModernI18nProvider",
138
+ "ReactI18nextProviderContext",
139
+ "getActualI18nextInstance",
183
140
  "useModernI18n"
184
141
  ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
185
142
  Object.defineProperty(exports, '__esModule', {
@@ -55,7 +55,7 @@ async function changeI18nInstanceLanguage(i18nInstance, language) {
55
55
  else await i18nInstance.changeLanguage?.(language);
56
56
  }
57
57
  async function changeModernI18nLanguage(newLang, options) {
58
- const { i18nInstance, updateLanguage, localePathRedirect, ignoreRedirectRoutes, localisedUrls, languages, hasRouter, navigate, location } = options;
58
+ const { i18nInstance, updateLanguage, localePathRedirect, ignoreRedirectRoutes, urlStrategy, languages, hasRouter, navigate, location } = options;
59
59
  try {
60
60
  if (!newLang || 'string' != typeof newLang) throw new Error('Language must be non-empty string');
61
61
  await changeI18nInstanceLanguage(i18nInstance, newLang);
@@ -66,8 +66,8 @@ async function changeModernI18nLanguage(newLang, options) {
66
66
  const relativePath = currentPath.replace(entryPath, '');
67
67
  const pathLanguage = (0, external_utils_js_namespaceObject.detectLanguageFromPath)(currentPath, languages || [], localePathRedirect);
68
68
  if (pathLanguage.detected && pathLanguage.language === newLang) return void updateLanguage?.(newLang);
69
- if (!(0, external_utils_js_namespaceObject.shouldIgnoreRedirect)(relativePath, languages || [], ignoreRedirectRoutes)) {
70
- const newPath = (0, external_utils_js_namespaceObject.buildLocalizedUrl)(relativePath, newLang, languages || [], localisedUrls);
69
+ if (!(0, external_utils_js_namespaceObject.shouldIgnoreRedirect)(relativePath, languages || [], ignoreRedirectRoutes, urlStrategy)) {
70
+ const newPath = (0, external_utils_js_namespaceObject.buildLocalizedUrl)(relativePath, newLang, languages || [], urlStrategy);
71
71
  const newUrl = entryPath + newPath + location.search + location.hash;
72
72
  await navigate(newUrl, {
73
73
  replace: true
@@ -79,8 +79,8 @@ async function changeModernI18nLanguage(newLang, options) {
79
79
  const relativePath = currentPath.replace(entryPath, '');
80
80
  const pathLanguage = (0, external_utils_js_namespaceObject.detectLanguageFromPath)(currentPath, languages || [], localePathRedirect);
81
81
  if (pathLanguage.detected && pathLanguage.language === newLang) return void updateLanguage?.(newLang);
82
- if (!(0, external_utils_js_namespaceObject.shouldIgnoreRedirect)(relativePath, languages || [], ignoreRedirectRoutes)) {
83
- const newPath = (0, external_utils_js_namespaceObject.buildLocalizedUrl)(relativePath, newLang, languages || [], localisedUrls);
82
+ if (!(0, external_utils_js_namespaceObject.shouldIgnoreRedirect)(relativePath, languages || [], ignoreRedirectRoutes, urlStrategy)) {
83
+ const newPath = (0, external_utils_js_namespaceObject.buildLocalizedUrl)(relativePath, newLang, languages || [], urlStrategy);
84
84
  const newUrl = entryPath + newPath + window.location.search + window.location.hash;
85
85
  window.history.pushState(null, '', newUrl);
86
86
  }
@@ -0,0 +1,49 @@
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
+ I18nNavigationContext: ()=>I18nNavigationContext,
32
+ ModernI18nContext: ()=>ModernI18nContext,
33
+ ReactI18nextProviderContext: ()=>ReactI18nextProviderContext
34
+ });
35
+ const external_react_namespaceObject = require("react");
36
+ const ModernI18nContext = (0, external_react_namespaceObject.createContext)(null);
37
+ const ReactI18nextProviderContext = (0, external_react_namespaceObject.createContext)(null);
38
+ const I18nNavigationContext = (0, external_react_namespaceObject.createContext)(null);
39
+ exports.I18nNavigationContext = __webpack_exports__.I18nNavigationContext;
40
+ exports.ModernI18nContext = __webpack_exports__.ModernI18nContext;
41
+ exports.ReactI18nextProviderContext = __webpack_exports__.ReactI18nextProviderContext;
42
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
43
+ "I18nNavigationContext",
44
+ "ModernI18nContext",
45
+ "ReactI18nextProviderContext"
46
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
47
+ Object.defineProperty(exports, '__esModule', {
48
+ value: true
49
+ });
@@ -30,20 +30,26 @@ __webpack_require__.r(__webpack_exports__);
30
30
  __webpack_require__.d(__webpack_exports__, {
31
31
  FederatedI18nBoundary: ()=>external_context_js_namespaceObject.FederatedI18nBoundary,
32
32
  I18nLink: ()=>external_I18nLink_js_namespaceObject.I18nLink,
33
+ I18nNavigationProvider: ()=>external_routerAdapter_js_namespaceObject.I18nNavigationProvider,
34
+ I18nRouterNavigationProvider: ()=>external_navigation_js_namespaceObject.I18nRouterNavigationProvider,
33
35
  Link: ()=>external_Link_js_namespaceObject.Link,
34
- buildLocalizedUrl: ()=>external_utils_js_namespaceObject.buildLocalizedUrl,
35
- canonicalPath: ()=>external_localizedPaths_js_namespaceObject.canonicalPath,
36
36
  createI18nPlugin: ()=>createI18nPlugin,
37
- localizePath: ()=>external_localizedPaths_js_namespaceObject.localizePath,
38
37
  splitUrlTarget: ()=>external_utils_js_namespaceObject.splitUrlTarget,
38
+ useI18nRouterAdapter: ()=>external_routerAdapter_js_namespaceObject.useI18nRouterAdapter,
39
+ useIntegratedRouterAdapter: ()=>external_navigation_js_namespaceObject.useIntegratedRouterAdapter,
39
40
  useLocalizedLocation: ()=>external_localizedPaths_js_namespaceObject.useLocalizedLocation,
40
41
  useLocalizedPaths: ()=>external_localizedPaths_js_namespaceObject.useLocalizedPaths,
41
- useModernI18n: ()=>external_context_js_namespaceObject.useModernI18n
42
+ useModernI18n: ()=>external_context_js_namespaceObject.useModernI18n,
43
+ useNativeI18nRouterAdapter: ()=>external_routerAdapter_js_namespaceObject.useNativeI18nRouterAdapter
42
44
  });
45
+ const mappedUrlStrategy_js_namespaceObject = require("../shared/mappedUrlStrategy.js");
46
+ const urlStrategy_js_namespaceObject = require("../shared/urlStrategy.js");
47
+ const external_navigation_js_namespaceObject = require("./navigation.js");
43
48
  const external_pluginSetup_js_namespaceObject = require("./pluginSetup.js");
44
49
  const external_providerComposition_js_namespaceObject = require("./providerComposition.js");
45
50
  const external_reactI18next_js_namespaceObject = require("./reactI18next.js");
46
51
  require("./types.js");
52
+ const external_routerAdapter_js_namespaceObject = require("./routerAdapter.js");
47
53
  const external_context_js_namespaceObject = require("./context.js");
48
54
  const external_I18nLink_js_namespaceObject = require("./I18nLink.js");
49
55
  const external_Link_js_namespaceObject = require("./Link.js");
@@ -52,9 +58,10 @@ const external_utils_js_namespaceObject = require("./utils.js");
52
58
  const createI18nPlugin = (loadReactI18nextIntegration)=>(options)=>({
53
59
  name: '@modern-js/plugin-i18n',
54
60
  setup: (api)=>{
55
- const { entryName, i18nInstance: userI18nInstance, initOptions, localeDetection, backend, htmlLangAttr = false, reactI18next = true } = options;
56
- const { localePathRedirect = false, i18nextDetector = true, languages = [], fallbackLanguage = 'en', detection, ignoreRedirectRoutes, localisedUrls } = localeDetection || {};
61
+ const { entryName, i18nInstance: userI18nInstance, initOptions, localeDetection, backend, htmlLangAttr = false, reactI18next = true, urlStrategy, NavigationProvider, LanguageSynchronization } = options;
62
+ const { localePathRedirect = false, i18nextDetector = true, languages = [], fallbackLanguage = 'en', detection, ignoreRedirectRoutes } = localeDetection || {};
57
63
  const { enabled: backendEnabled = false } = backend || {};
64
+ const resolvedUrlStrategy = (0, urlStrategy_js_namespaceObject.asI18nUrlStrategy)(urlStrategy) ?? (0, mappedUrlStrategy_js_namespaceObject.resolveMappedUrlStrategy)(localeDetection);
58
65
  let latestI18nInstance;
59
66
  let I18nextProvider;
60
67
  api.onBeforeRender(async (context)=>{
@@ -82,7 +89,9 @@ const createI18nPlugin = (loadReactI18nextIntegration)=>(options)=>({
82
89
  languages,
83
90
  fallbackLanguage,
84
91
  ignoreRedirectRoutes,
85
- localisedUrls,
92
+ urlStrategy: resolvedUrlStrategy,
93
+ NavigationProvider: NavigationProvider ?? external_navigation_js_namespaceObject.I18nRouterNavigationProvider,
94
+ LanguageSynchronization,
86
95
  getLatestI18nInstance: ()=>latestI18nInstance,
87
96
  getI18nextProvider: ()=>I18nextProvider
88
97
  }));
@@ -90,27 +99,31 @@ const createI18nPlugin = (loadReactI18nextIntegration)=>(options)=>({
90
99
  });
91
100
  exports.FederatedI18nBoundary = __webpack_exports__.FederatedI18nBoundary;
92
101
  exports.I18nLink = __webpack_exports__.I18nLink;
102
+ exports.I18nNavigationProvider = __webpack_exports__.I18nNavigationProvider;
103
+ exports.I18nRouterNavigationProvider = __webpack_exports__.I18nRouterNavigationProvider;
93
104
  exports.Link = __webpack_exports__.Link;
94
- exports.buildLocalizedUrl = __webpack_exports__.buildLocalizedUrl;
95
- exports.canonicalPath = __webpack_exports__.canonicalPath;
96
105
  exports.createI18nPlugin = __webpack_exports__.createI18nPlugin;
97
- exports.localizePath = __webpack_exports__.localizePath;
98
106
  exports.splitUrlTarget = __webpack_exports__.splitUrlTarget;
107
+ exports.useI18nRouterAdapter = __webpack_exports__.useI18nRouterAdapter;
108
+ exports.useIntegratedRouterAdapter = __webpack_exports__.useIntegratedRouterAdapter;
99
109
  exports.useLocalizedLocation = __webpack_exports__.useLocalizedLocation;
100
110
  exports.useLocalizedPaths = __webpack_exports__.useLocalizedPaths;
101
111
  exports.useModernI18n = __webpack_exports__.useModernI18n;
112
+ exports.useNativeI18nRouterAdapter = __webpack_exports__.useNativeI18nRouterAdapter;
102
113
  for(var __rspack_i in __webpack_exports__)if (-1 === [
103
114
  "FederatedI18nBoundary",
104
115
  "I18nLink",
116
+ "I18nNavigationProvider",
117
+ "I18nRouterNavigationProvider",
105
118
  "Link",
106
- "buildLocalizedUrl",
107
- "canonicalPath",
108
119
  "createI18nPlugin",
109
- "localizePath",
110
120
  "splitUrlTarget",
121
+ "useI18nRouterAdapter",
122
+ "useIntegratedRouterAdapter",
111
123
  "useLocalizedLocation",
112
124
  "useLocalizedPaths",
113
- "useModernI18n"
125
+ "useModernI18n",
126
+ "useNativeI18nRouterAdapter"
114
127
  ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
115
128
  Object.defineProperty(exports, '__esModule', {
116
129
  value: true
@@ -53,7 +53,7 @@ function createMinimalI18nInstance(language) {
53
53
  };
54
54
  return minimalInstance;
55
55
  }
56
- function createContextValue(lang, i18nInstance, entryName, languages, localePathRedirect, ignoreRedirectRoutes, localisedUrls, setLang, synchronizeLanguage) {
56
+ function createContextValue(lang, i18nInstance, entryName, languages, localePathRedirect, ignoreRedirectRoutes, setLang, urlStrategy) {
57
57
  const instance = i18nInstance || createMinimalI18nInstance(lang);
58
58
  return {
59
59
  language: lang,
@@ -62,9 +62,8 @@ function createContextValue(lang, i18nInstance, entryName, languages, localePath
62
62
  languages,
63
63
  localePathRedirect,
64
64
  ignoreRedirectRoutes,
65
- localisedUrls,
66
- updateLanguage: setLang,
67
- synchronizeLanguage
65
+ urlStrategy,
66
+ updateLanguage: setLang
68
67
  };
69
68
  }
70
69
  function useSdkResourcesLoader(i18nInstance, setForceUpdate) {
@@ -113,7 +112,7 @@ function useSdkResourcesLoader(i18nInstance, setForceUpdate) {
113
112
  setForceUpdate
114
113
  ]);
115
114
  }
116
- function useClientSideRedirect(i18nInstance, localePathRedirect, languages, fallbackLanguage, ignoreRedirectRoutes, localisedUrls) {
115
+ function useClientSideRedirect(i18nInstance, localePathRedirect, languages, fallbackLanguage, ignoreRedirectRoutes, urlStrategy) {
117
116
  const urlRef = (0, external_react_namespaceObject.useRef)('');
118
117
  const { navigate, location, hasRouter } = (0, external_routerAdapter_js_namespaceObject.useI18nRouterAdapter)();
119
118
  (0, external_react_namespaceObject.useEffect)(()=>{
@@ -130,10 +129,10 @@ function useClientSideRedirect(i18nInstance, localePathRedirect, languages, fall
130
129
  const currentHash = hasRouter && location ? location.hash : window.location.hash;
131
130
  const entryPath = (0, external_utils_js_namespaceObject.getEntryPath)();
132
131
  const relativePath = currentPathname.replace(entryPath, '');
133
- if ((0, external_utils_js_namespaceObject.shouldIgnoreRedirect)(relativePath, languages, ignoreRedirectRoutes)) return;
132
+ if ((0, external_utils_js_namespaceObject.shouldIgnoreRedirect)(relativePath, languages, ignoreRedirectRoutes, urlStrategy)) return;
134
133
  const pathDetection = (0, external_utils_js_namespaceObject.detectLanguageFromPath)(currentPathname, languages, localePathRedirect);
135
134
  const targetLanguage = pathDetection.language || i18nInstance.language || fallbackLanguage || languages[0] || 'en';
136
- const newPath = (0, external_utils_js_namespaceObject.buildLocalizedUrl)(relativePath, targetLanguage, languages, localisedUrls);
135
+ const newPath = (0, external_utils_js_namespaceObject.buildLocalizedUrl)(relativePath, targetLanguage, languages, urlStrategy);
137
136
  const newUrl = entryPath + newPath + currentSearch + currentHash;
138
137
  urlRef.current = currentPathname;
139
138
  if (newUrl !== currentPathname + currentSearch + currentHash) if (hasRouter && navigate && location) navigate(newUrl, {
@@ -149,7 +148,7 @@ function useClientSideRedirect(i18nInstance, localePathRedirect, languages, fall
149
148
  languages,
150
149
  fallbackLanguage,
151
150
  ignoreRedirectRoutes,
152
- localisedUrls
151
+ urlStrategy
153
152
  ]);
154
153
  }
155
154
  function useLanguageSync(i18nInstance, localePathRedirect, languages, pathname, prevLangRef, setLang) {