@bleedingdev/modern-js-plugin-i18n 3.5.0-ultramodern.3 → 3.5.0-ultramodern.31

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 (168) hide show
  1. package/dist/cjs/cli/index.js +2 -1
  2. package/dist/cjs/runtime/Link.js +8 -89
  3. package/dist/cjs/runtime/context.js +18 -82
  4. package/dist/cjs/runtime/contextHelpers.js +137 -0
  5. package/dist/cjs/runtime/core.js +29 -132
  6. package/dist/cjs/runtime/i18n/detection/cache.js +149 -0
  7. package/dist/cjs/runtime/i18n/detection/detector.js +100 -0
  8. package/dist/cjs/runtime/i18n/detection/index.js +8 -263
  9. package/dist/cjs/runtime/i18n/detection/initOptions.js +69 -0
  10. package/dist/cjs/runtime/i18n/detection/language.js +62 -0
  11. package/dist/cjs/runtime/i18n/detection/path.js +49 -0
  12. package/dist/cjs/runtime/i18n/detection/priority.js +66 -0
  13. package/dist/cjs/runtime/i18n/detection/ssr.js +70 -0
  14. package/dist/cjs/runtime/i18n/detection/types.js +18 -0
  15. package/dist/cjs/runtime/linkHelpers.js +148 -0
  16. package/dist/cjs/runtime/pluginSetup.js +102 -0
  17. package/dist/cjs/runtime/providerComposition.js +113 -0
  18. package/dist/cjs/runtime/reactI18next.js +43 -0
  19. package/dist/cjs/server/apiPrefix.js +72 -0
  20. package/dist/cjs/server/detectorOptions.js +97 -0
  21. package/dist/cjs/server/index.js +17 -144
  22. package/dist/cjs/server/redirectPolicy.js +102 -0
  23. package/dist/cjs/shared/localisedUrls/config.js +49 -0
  24. package/dist/cjs/shared/localisedUrls/index.js +75 -0
  25. package/dist/cjs/shared/localisedUrls/normalise.js +87 -0
  26. package/dist/cjs/shared/localisedUrls/pathname.js +65 -0
  27. package/dist/cjs/shared/localisedUrls/patterns.js +130 -0
  28. package/dist/cjs/shared/localisedUrls/resolve.js +91 -0
  29. package/dist/cjs/shared/localisedUrls/routes.js +129 -0
  30. package/dist/cjs/shared/localisedUrls/types.js +18 -0
  31. package/dist/cjs/shared/localisedUrls.js +13 -294
  32. package/dist/esm/cli/index.mjs +2 -1
  33. package/dist/esm/runtime/Link.mjs +1 -82
  34. package/dist/esm/runtime/context.mjs +18 -82
  35. package/dist/esm/runtime/contextHelpers.mjs +84 -0
  36. package/dist/esm/runtime/core.mjs +30 -133
  37. package/dist/esm/runtime/i18n/detection/cache.mjs +102 -0
  38. package/dist/esm/runtime/i18n/detection/detector.mjs +62 -0
  39. package/dist/esm/runtime/i18n/detection/index.mjs +4 -260
  40. package/dist/esm/runtime/i18n/detection/initOptions.mjs +28 -0
  41. package/dist/esm/runtime/i18n/detection/language.mjs +21 -0
  42. package/dist/esm/runtime/i18n/detection/path.mjs +11 -0
  43. package/dist/esm/runtime/i18n/detection/priority.mjs +28 -0
  44. package/dist/esm/runtime/i18n/detection/ssr.mjs +26 -0
  45. package/dist/esm/runtime/i18n/detection/types.mjs +0 -0
  46. package/dist/esm/runtime/linkHelpers.mjs +98 -0
  47. package/dist/esm/runtime/pluginSetup.mjs +64 -0
  48. package/dist/esm/runtime/providerComposition.mjs +75 -0
  49. package/dist/esm/runtime/reactI18next.mjs +5 -0
  50. package/dist/esm/server/apiPrefix.mjs +31 -0
  51. package/dist/esm/server/detectorOptions.mjs +59 -0
  52. package/dist/esm/server/index.mjs +6 -133
  53. package/dist/esm/server/redirectPolicy.mjs +52 -0
  54. package/dist/esm/shared/localisedUrls/config.mjs +11 -0
  55. package/dist/esm/shared/localisedUrls/index.mjs +6 -0
  56. package/dist/esm/shared/localisedUrls/normalise.mjs +37 -0
  57. package/dist/esm/shared/localisedUrls/pathname.mjs +24 -0
  58. package/dist/esm/shared/localisedUrls/patterns.mjs +86 -0
  59. package/dist/esm/shared/localisedUrls/resolve.mjs +50 -0
  60. package/dist/esm/shared/localisedUrls/routes.mjs +88 -0
  61. package/dist/esm/shared/localisedUrls/types.mjs +0 -0
  62. package/dist/esm/shared/localisedUrls.mjs +1 -283
  63. package/dist/esm-node/cli/index.mjs +2 -1
  64. package/dist/esm-node/runtime/Link.mjs +1 -82
  65. package/dist/esm-node/runtime/context.mjs +18 -82
  66. package/dist/esm-node/runtime/contextHelpers.mjs +85 -0
  67. package/dist/esm-node/runtime/core.mjs +30 -133
  68. package/dist/esm-node/runtime/i18n/detection/cache.mjs +103 -0
  69. package/dist/esm-node/runtime/i18n/detection/detector.mjs +63 -0
  70. package/dist/esm-node/runtime/i18n/detection/index.mjs +4 -260
  71. package/dist/esm-node/runtime/i18n/detection/initOptions.mjs +29 -0
  72. package/dist/esm-node/runtime/i18n/detection/language.mjs +22 -0
  73. package/dist/esm-node/runtime/i18n/detection/path.mjs +12 -0
  74. package/dist/esm-node/runtime/i18n/detection/priority.mjs +29 -0
  75. package/dist/esm-node/runtime/i18n/detection/ssr.mjs +27 -0
  76. package/dist/esm-node/runtime/i18n/detection/types.mjs +1 -0
  77. package/dist/esm-node/runtime/linkHelpers.mjs +99 -0
  78. package/dist/esm-node/runtime/pluginSetup.mjs +65 -0
  79. package/dist/esm-node/runtime/providerComposition.mjs +76 -0
  80. package/dist/esm-node/runtime/reactI18next.mjs +6 -0
  81. package/dist/esm-node/server/apiPrefix.mjs +32 -0
  82. package/dist/esm-node/server/detectorOptions.mjs +60 -0
  83. package/dist/esm-node/server/index.mjs +6 -133
  84. package/dist/esm-node/server/redirectPolicy.mjs +53 -0
  85. package/dist/esm-node/shared/localisedUrls/config.mjs +12 -0
  86. package/dist/esm-node/shared/localisedUrls/index.mjs +7 -0
  87. package/dist/esm-node/shared/localisedUrls/normalise.mjs +38 -0
  88. package/dist/esm-node/shared/localisedUrls/pathname.mjs +25 -0
  89. package/dist/esm-node/shared/localisedUrls/patterns.mjs +87 -0
  90. package/dist/esm-node/shared/localisedUrls/resolve.mjs +51 -0
  91. package/dist/esm-node/shared/localisedUrls/routes.mjs +89 -0
  92. package/dist/esm-node/shared/localisedUrls/types.mjs +1 -0
  93. package/dist/esm-node/shared/localisedUrls.mjs +1 -283
  94. package/dist/types/runtime/Link.d.ts +3 -7
  95. package/dist/types/runtime/context.d.ts +2 -2
  96. package/dist/types/runtime/contextHelpers.d.ts +28 -0
  97. package/dist/types/runtime/core.d.ts +3 -7
  98. package/dist/types/runtime/hooks.d.ts +5 -0
  99. package/dist/types/runtime/i18n/detection/cache.d.ts +14 -0
  100. package/dist/types/runtime/i18n/detection/detector.d.ts +8 -0
  101. package/dist/types/runtime/i18n/detection/index.d.ts +5 -50
  102. package/dist/types/runtime/i18n/detection/initOptions.d.ts +10 -0
  103. package/dist/types/runtime/i18n/detection/language.d.ts +11 -0
  104. package/dist/types/runtime/i18n/detection/path.d.ts +5 -0
  105. package/dist/types/runtime/i18n/detection/priority.d.ts +10 -0
  106. package/dist/types/runtime/i18n/detection/ssr.d.ts +9 -0
  107. package/dist/types/runtime/i18n/detection/types.d.ts +29 -0
  108. package/dist/types/runtime/i18n/react-i18next.d.ts +1 -6
  109. package/dist/types/runtime/linkHelpers.d.ts +17 -0
  110. package/dist/types/runtime/pluginSetup.d.ts +32 -0
  111. package/dist/types/runtime/providerComposition.d.ts +15 -0
  112. package/dist/types/runtime/reactI18next.d.ts +7 -0
  113. package/dist/types/runtime/utils.d.ts +7 -2
  114. package/dist/types/server/apiPrefix.d.ts +7 -0
  115. package/dist/types/server/detectorOptions.d.ts +21 -0
  116. package/dist/types/server/index.d.ts +1 -6
  117. package/dist/types/server/redirectPolicy.d.ts +16 -0
  118. package/dist/types/shared/localisedUrls/config.d.ts +9 -0
  119. package/dist/types/shared/localisedUrls/index.d.ts +7 -0
  120. package/dist/types/shared/localisedUrls/normalise.d.ts +10 -0
  121. package/dist/types/shared/localisedUrls/pathname.d.ts +3 -0
  122. package/dist/types/shared/localisedUrls/patterns.d.ts +5 -0
  123. package/dist/types/shared/localisedUrls/resolve.d.ts +8 -0
  124. package/dist/types/shared/localisedUrls/routes.d.ts +3 -0
  125. package/dist/types/shared/localisedUrls/types.d.ts +14 -0
  126. package/dist/types/shared/localisedUrls.d.ts +2 -36
  127. package/package.json +10 -10
  128. package/src/cli/index.ts +3 -2
  129. package/src/runtime/Link.tsx +11 -138
  130. package/src/runtime/context.tsx +42 -196
  131. package/src/runtime/contextHelpers.ts +232 -0
  132. package/src/runtime/core.tsx +43 -274
  133. package/src/runtime/hooks.ts +3 -0
  134. package/src/runtime/i18n/detection/cache.ts +175 -0
  135. package/src/runtime/i18n/detection/detector.ts +157 -0
  136. package/src/runtime/i18n/detection/index.ts +10 -641
  137. package/src/runtime/i18n/detection/initOptions.ts +74 -0
  138. package/src/runtime/i18n/detection/language.ts +64 -0
  139. package/src/runtime/i18n/detection/path.ts +41 -0
  140. package/src/runtime/i18n/detection/priority.ts +82 -0
  141. package/src/runtime/i18n/detection/ssr.ts +47 -0
  142. package/src/runtime/i18n/detection/types.ts +33 -0
  143. package/src/runtime/i18n/react-i18next.ts +1 -6
  144. package/src/runtime/linkHelpers.ts +174 -0
  145. package/src/runtime/pluginSetup.ts +189 -0
  146. package/src/runtime/providerComposition.tsx +142 -0
  147. package/src/runtime/reactI18next.ts +20 -0
  148. package/src/runtime/utils.ts +7 -5
  149. package/src/server/apiPrefix.ts +67 -0
  150. package/src/server/detectorOptions.ts +105 -0
  151. package/src/server/index.ts +14 -319
  152. package/src/server/redirectPolicy.ts +152 -0
  153. package/src/shared/localisedUrls/config.ts +18 -0
  154. package/src/shared/localisedUrls/index.ts +13 -0
  155. package/src/shared/localisedUrls/normalise.ts +67 -0
  156. package/src/shared/localisedUrls/pathname.ts +57 -0
  157. package/src/shared/localisedUrls/patterns.ts +160 -0
  158. package/src/shared/localisedUrls/resolve.ts +118 -0
  159. package/src/shared/localisedUrls/routes.ts +226 -0
  160. package/src/shared/localisedUrls/types.ts +18 -0
  161. package/src/shared/localisedUrls.ts +20 -623
  162. package/tests/link.test.tsx +111 -0
  163. package/tests/linkTypes.test.ts +15 -4
  164. package/tests/localisedUrls.test.ts +54 -2
  165. package/tests/reactI18nextRuntimeBoundary.test.ts +6 -3
  166. package/tests/routerAdapter.test.tsx +56 -0
  167. package/tests/type-fixture/fixture-globals.d.ts +11 -0
  168. package/tests/type-fixture/tsconfig.json +1 -0
@@ -64,7 +64,8 @@ const i18nPlugin = (options = {})=>({
64
64
  backend: backendOptions,
65
65
  ...extendedConfig
66
66
  };
67
- const runtimePluginPath = customPlugin?.runtime?.path || (false === config.reactI18next ? `@${metaName}/plugin-i18n/runtime/no-react-i18next` : `@${metaName}/plugin-i18n/runtime`);
67
+ const { reactI18next } = extendedConfig;
68
+ const runtimePluginPath = customPlugin?.runtime?.path || (false === reactI18next ? `@${metaName}/plugin-i18n/runtime/no-react-i18next` : `@${metaName}/plugin-i18n/runtime`);
68
69
  plugins.push({
69
70
  name: customPlugin?.runtime?.name || 'i18n',
70
71
  path: runtimePluginPath,
@@ -30,97 +30,16 @@ __webpack_require__.r(__webpack_exports__);
30
30
  __webpack_require__.d(__webpack_exports__, {
31
31
  Link: ()=>Link,
32
32
  default: ()=>runtime_Link,
33
- interpolateRouteParams: ()=>interpolateRouteParams
33
+ interpolateRouteParams: ()=>external_linkHelpers_js_namespaceObject.interpolateRouteParams
34
34
  });
35
35
  const jsx_runtime_namespaceObject = require("react/jsx-runtime");
36
36
  const external_react_namespaceObject = require("react");
37
37
  const external_context_js_namespaceObject = require("./context.js");
38
+ const external_linkHelpers_js_namespaceObject = require("./linkHelpers.js");
38
39
  const external_localizedPaths_js_namespaceObject = require("./localizedPaths.js");
39
40
  const external_routerAdapter_js_namespaceObject = require("./routerAdapter.js");
40
41
  const external_utils_js_namespaceObject = require("./utils.js");
41
42
  const EXTERNAL_TARGET_RE = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
42
- const warnedTargets = new Set();
43
- const warnOnce = (key, message)=>{
44
- if ('development' !== process.env.NODE_ENV || warnedTargets.has(key)) return;
45
- warnedTargets.add(key);
46
- console.warn(message);
47
- };
48
- const interpolateRouteParams = (pathname, params)=>{
49
- if (!/[$:*{]/.test(pathname)) return pathname;
50
- const resolveParam = (name)=>{
51
- const value = params?.[name];
52
- return void 0 === value ? void 0 : String(value);
53
- };
54
- const segments = pathname.split('/').map((segment)=>{
55
- if (!segment) return segment;
56
- if (segment.startsWith('{-$') && segment.endsWith('}')) {
57
- const value = resolveParam(segment.slice(3, -1));
58
- return void 0 === value ? null : encodeURIComponent(value);
59
- }
60
- if ('$' === segment || '*' === segment) {
61
- const value = resolveParam('_splat') ?? resolveParam('*');
62
- return void 0 === value ? null : value.split('/').map(encodeURIComponent).join('/');
63
- }
64
- if (segment.startsWith('$')) {
65
- const value = resolveParam(segment.slice(1));
66
- if (void 0 === value) {
67
- warnOnce(`missing-param:${pathname}:${segment}`, `[plugin-i18n] <Link to="${pathname}"> is missing required param "${segment.slice(1)}".`);
68
- return segment;
69
- }
70
- return encodeURIComponent(value);
71
- }
72
- if (segment.startsWith(':')) {
73
- const optional = segment.endsWith('?');
74
- const name = segment.slice(1, optional ? -1 : void 0);
75
- const value = resolveParam(name);
76
- if (void 0 === value) {
77
- if (optional) return null;
78
- warnOnce(`missing-param:${pathname}:${segment}`, `[plugin-i18n] <Link to="${pathname}"> is missing required param "${name}".`);
79
- return segment;
80
- }
81
- return encodeURIComponent(value);
82
- }
83
- return segment;
84
- }).filter((segment)=>null !== segment);
85
- return segments.join('/') || '/';
86
- };
87
- const normalizeSearch = (search, searchFromTo)=>{
88
- if (search && 'object' == typeof search) {
89
- const entries = Object.entries(search).filter(([, value])=>null != value);
90
- const searchObject = Object.fromEntries(entries.map(([key, value])=>[
91
- key,
92
- String(value)
93
- ]));
94
- const params = new URLSearchParams(searchObject);
95
- const serialized = params.toString();
96
- return {
97
- searchString: serialized ? `?${serialized}` : '',
98
- searchObject
99
- };
100
- }
101
- const raw = 'string' == typeof search && search ? search : searchFromTo;
102
- if (!raw) return {
103
- searchString: '',
104
- searchObject: void 0
105
- };
106
- const searchString = raw.startsWith('?') ? raw : `?${raw}`;
107
- const searchObject = {};
108
- new URLSearchParams(searchString).forEach((value, key)=>{
109
- searchObject[key] = value;
110
- });
111
- return {
112
- searchString,
113
- searchObject
114
- };
115
- };
116
- const splitActiveProps = (active, activeProps)=>{
117
- if (!active || !activeProps) return {};
118
- return activeProps;
119
- };
120
- const mergeClassNames = (...values)=>{
121
- const classNames = values.filter((value)=>'string' == typeof value && value.length > 0);
122
- return classNames.length > 0 ? classNames.join(' ') : void 0;
123
- };
124
43
  const Link = (props)=>{
125
44
  const { to, params, children, hash: hashProp, search: searchProp, hashScrollIntoView, activeOptions, activeProps, prefetch, preload, ...rest } = props;
126
45
  const adapter = (0, external_routerAdapter_js_namespaceObject.useI18nRouterAdapter)();
@@ -134,12 +53,12 @@ const Link = (props)=>{
134
53
  const target = (0, external_react_namespaceObject.useMemo)(()=>{
135
54
  if (isExternal || isBareHash) return null;
136
55
  const { pathname, search: searchFromTo, hash: hashFromTo } = (0, external_utils_js_namespaceObject.splitUrlTarget)(to);
137
- const interpolated = interpolateRouteParams(pathname || '/', params);
56
+ const interpolated = (0, external_linkHelpers_js_namespaceObject.interpolateRouteParams)(pathname || '/', params);
138
57
  const firstSegment = interpolated.split('/').filter(Boolean)[0];
139
- if (firstSegment && supportedLanguages.includes(firstSegment)) warnOnce(`lang-prefix:${to}`, `[plugin-i18n] <Link to="${to}"> starts with a language prefix. Write language-agnostic canonical paths; the Link localizes them automatically.`);
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.`);
140
59
  const localizedPathname = (0, external_utils_js_namespaceObject.buildLocalizedUrl)(interpolated, language, supportedLanguages, localisedUrls);
141
60
  const hash = hashProp ?? (hashFromTo ? hashFromTo.slice(1) : '');
142
- const { searchString, searchObject } = normalizeSearch(searchProp, searchFromTo);
61
+ const { searchString, searchObject } = (0, external_linkHelpers_js_namespaceObject.normalizeSearch)(searchProp, searchFromTo);
143
62
  return {
144
63
  canonicalPathname: interpolated,
145
64
  localizedPathname,
@@ -174,7 +93,7 @@ const Link = (props)=>{
174
93
  supportedLanguages,
175
94
  localisedUrls
176
95
  ]);
177
- const resolvedActiveProps = splitActiveProps(isActive, activeProps);
96
+ const resolvedActiveProps = (0, external_linkHelpers_js_namespaceObject.splitActiveProps)(isActive, activeProps);
178
97
  const activeAttributes = isActive ? {
179
98
  'data-status': 'active',
180
99
  'aria-current': rest['aria-current'] ?? resolvedActiveProps['aria-current'] ?? 'page'
@@ -196,7 +115,7 @@ const Link = (props)=>{
196
115
  ...anchorProps,
197
116
  ...activeRest,
198
117
  ...activeAttributes,
199
- className: mergeClassNames(rest.className, activeClassName),
118
+ className: (0, external_linkHelpers_js_namespaceObject.mergeClassNames)(rest.className, activeClassName),
200
119
  style: {
201
120
  ...rest.style,
202
121
  ...activeStyle
@@ -205,7 +124,7 @@ const Link = (props)=>{
205
124
  });
206
125
  }
207
126
  const { className: activeClassName, style: activeStyle, ...activeRest } = resolvedActiveProps;
208
- const mergedClassName = mergeClassNames(rest.className, activeClassName);
127
+ const mergedClassName = (0, external_linkHelpers_js_namespaceObject.mergeClassNames)(rest.className, activeClassName);
209
128
  const mergedStyle = {
210
129
  ...rest.style,
211
130
  ...activeStyle
@@ -32,11 +32,9 @@ __webpack_require__.d(__webpack_exports__, {
32
32
  useModernI18n: ()=>useModernI18n
33
33
  });
34
34
  const jsx_runtime_namespaceObject = require("react/jsx-runtime");
35
- const runtime_namespaceObject = require("@modern-js/runtime");
36
35
  const external_react_namespaceObject = require("react");
37
- const index_js_namespaceObject = require("./i18n/detection/index.js");
36
+ const external_contextHelpers_js_namespaceObject = require("./contextHelpers.js");
38
37
  const external_routerAdapter_js_namespaceObject = require("./routerAdapter.js");
39
- const external_utils_js_namespaceObject = require("./utils.js");
40
38
  const modernI18nContextKey = Symbol.for('@modern-js/plugin-i18n/runtime/ModernI18nContext');
41
39
  const getModernI18nContext = ()=>{
42
40
  const globalStore = globalThis;
@@ -50,14 +48,10 @@ const ModernI18nProvider = ({ children, value })=>/*#__PURE__*/ (0, jsx_runtime_
50
48
  });
51
49
  const useModernI18n = ()=>{
52
50
  const context = (0, external_react_namespaceObject.useContext)(ModernI18nContext);
53
- if (!context) throw new Error('useModernI18n must be used within a ModernI18nProvider');
51
+ if (!context) throw new Error('useModernI18n must be used within ModernI18nProvider');
54
52
  const { language: contextLanguage, i18nInstance, languages, localePathRedirect, ignoreRedirectRoutes, localisedUrls, updateLanguage } = context;
55
53
  const { navigate, location, hasRouter } = (0, external_routerAdapter_js_namespaceObject.useI18nRouterAdapter)();
56
- const pathLanguage = (0, external_react_namespaceObject.useMemo)(()=>{
57
- if (!localePathRedirect || !location?.pathname) return;
58
- const detected = (0, external_utils_js_namespaceObject.detectLanguageFromPath)(location.pathname, languages || [], localePathRedirect);
59
- return detected.detected ? detected.language : void 0;
60
- }, [
54
+ const pathLanguage = (0, external_react_namespaceObject.useMemo)(()=>(0, external_contextHelpers_js_namespaceObject.getPathLanguage)(location?.pathname, languages, localePathRedirect), [
61
55
  languages,
62
56
  localePathRedirect,
63
57
  location?.pathname
@@ -68,56 +62,24 @@ const useModernI18n = ()=>{
68
62
  updateLanguage?.(pathLanguage);
69
63
  i18nInstance?.setLang?.(pathLanguage);
70
64
  i18nInstance?.changeLanguage?.(pathLanguage);
71
- if ((0, runtime_namespaceObject.isBrowser)()) {
72
- const detectionOptions = i18nInstance.options?.detection;
73
- (0, index_js_namespaceObject.cacheUserLanguage)(i18nInstance, pathLanguage, detectionOptions);
74
- }
65
+ (0, external_contextHelpers_js_namespaceObject.cacheI18nLanguage)(i18nInstance, pathLanguage);
75
66
  }, [
76
67
  contextLanguage,
77
68
  i18nInstance,
78
69
  pathLanguage,
79
70
  updateLanguage
80
71
  ]);
81
- const changeLanguage = (0, external_react_namespaceObject.useCallback)(async (newLang)=>{
82
- try {
83
- if (!newLang || 'string' != typeof newLang) throw new Error('Language must be a non-empty string');
84
- await i18nInstance?.setLang?.(newLang);
85
- await i18nInstance?.changeLanguage?.(newLang);
86
- if ((0, runtime_namespaceObject.isBrowser)()) {
87
- const detectionOptions = i18nInstance.options?.detection;
88
- (0, index_js_namespaceObject.cacheUserLanguage)(i18nInstance, newLang, detectionOptions);
89
- }
90
- if (localePathRedirect && (0, runtime_namespaceObject.isBrowser)() && hasRouter && navigate && location) {
91
- const currentPath = location.pathname;
92
- const entryPath = (0, external_utils_js_namespaceObject.getEntryPath)();
93
- const relativePath = currentPath.replace(entryPath, '');
94
- const pathLanguage = (0, external_utils_js_namespaceObject.detectLanguageFromPath)(currentPath, languages || [], localePathRedirect);
95
- if (pathLanguage.detected && pathLanguage.language === newLang) return;
96
- if (!(0, external_utils_js_namespaceObject.shouldIgnoreRedirect)(relativePath, languages || [], ignoreRedirectRoutes)) {
97
- const newPath = (0, external_utils_js_namespaceObject.buildLocalizedUrl)(relativePath, newLang, languages || [], localisedUrls);
98
- const newUrl = entryPath + newPath + location.search + location.hash;
99
- await navigate(newUrl, {
100
- replace: true
101
- });
102
- }
103
- } else if (localePathRedirect && (0, runtime_namespaceObject.isBrowser)() && !hasRouter) {
104
- const currentPath = window.location.pathname;
105
- const entryPath = (0, external_utils_js_namespaceObject.getEntryPath)();
106
- const relativePath = currentPath.replace(entryPath, '');
107
- const pathLanguage = (0, external_utils_js_namespaceObject.detectLanguageFromPath)(currentPath, languages || [], localePathRedirect);
108
- if (pathLanguage.detected && pathLanguage.language === newLang) return;
109
- if (!(0, external_utils_js_namespaceObject.shouldIgnoreRedirect)(relativePath, languages || [], ignoreRedirectRoutes)) {
110
- const newPath = (0, external_utils_js_namespaceObject.buildLocalizedUrl)(relativePath, newLang, languages || [], localisedUrls);
111
- const newUrl = entryPath + newPath + window.location.search + window.location.hash;
112
- window.history.pushState(null, '', newUrl);
113
- }
114
- }
115
- if (updateLanguage) updateLanguage(newLang);
116
- } catch (error) {
117
- console.error('Failed to change language:', error);
118
- throw error;
119
- }
120
- }, [
72
+ const changeLanguage = (0, external_react_namespaceObject.useCallback)((newLang)=>(0, external_contextHelpers_js_namespaceObject.changeModernI18nLanguage)(newLang, {
73
+ i18nInstance,
74
+ updateLanguage,
75
+ localePathRedirect,
76
+ ignoreRedirectRoutes,
77
+ localisedUrls,
78
+ languages,
79
+ hasRouter,
80
+ navigate,
81
+ location
82
+ }), [
121
83
  i18nInstance,
122
84
  updateLanguage,
123
85
  localePathRedirect,
@@ -128,40 +90,14 @@ const useModernI18n = ()=>{
128
90
  navigate,
129
91
  location
130
92
  ]);
131
- const t = (0, external_react_namespaceObject.useCallback)((key, ...args)=>{
132
- if ('function' != typeof i18nInstance.t) throw new Error('i18nInstance.t is required');
133
- return i18nInstance.t(key, ...args);
134
- }, [
93
+ const t = (0, external_react_namespaceObject.useCallback)((key, ...args)=>(0, external_contextHelpers_js_namespaceObject.translateI18n)(i18nInstance, key, ...args), [
135
94
  currentLanguage,
136
95
  i18nInstance
137
96
  ]);
138
- const isLanguageSupported = (0, external_react_namespaceObject.useCallback)((lang)=>languages?.includes(lang) || false, [
97
+ const isLanguageSupported = (0, external_react_namespaceObject.useCallback)((lang)=>(0, external_contextHelpers_js_namespaceObject.isI18nLanguageSupported)(languages, lang), [
139
98
  languages
140
99
  ]);
141
- const isResourcesReady = (0, external_react_namespaceObject.useMemo)(()=>{
142
- if (!i18nInstance?.isInitialized) return false;
143
- const backend = i18nInstance?.services?.backend;
144
- if (backend && 'function' == typeof backend.isLoading) {
145
- const loadingResources = backend.getLoadingResources();
146
- const isCurrentLanguageLoading = loadingResources.some(({ language })=>language === currentLanguage);
147
- if (isCurrentLanguageLoading) return false;
148
- }
149
- const store = i18nInstance.store;
150
- if (!store?.data) return false;
151
- const langData = store.data[currentLanguage];
152
- if (!langData || 'object' != typeof langData) return false;
153
- const options = i18nInstance.options;
154
- const namespaces = options?.ns || options?.defaultNS || [
155
- 'translation'
156
- ];
157
- const requiredNamespaces = Array.isArray(namespaces) ? namespaces : [
158
- namespaces
159
- ];
160
- return requiredNamespaces.every((ns)=>{
161
- const nsData = langData[ns];
162
- return nsData && 'object' == typeof nsData && Object.keys(nsData).length > 0;
163
- });
164
- }, [
100
+ const isResourcesReady = (0, external_react_namespaceObject.useMemo)(()=>(0, external_contextHelpers_js_namespaceObject.isI18nResourcesReady)(i18nInstance, currentLanguage), [
165
101
  currentLanguage,
166
102
  i18nInstance
167
103
  ]);
@@ -0,0 +1,137 @@
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
+ cacheI18nLanguage: ()=>cacheI18nLanguage,
32
+ changeModernI18nLanguage: ()=>changeModernI18nLanguage,
33
+ getPathLanguage: ()=>getPathLanguage,
34
+ isI18nLanguageSupported: ()=>isI18nLanguageSupported,
35
+ isI18nResourcesReady: ()=>isI18nResourcesReady,
36
+ translateI18n: ()=>translateI18n
37
+ });
38
+ const runtime_namespaceObject = require("@modern-js/runtime");
39
+ const index_js_namespaceObject = require("./i18n/detection/index.js");
40
+ const external_utils_js_namespaceObject = require("./utils.js");
41
+ function getPathLanguage(pathname, languages, localePathRedirect) {
42
+ if (!localePathRedirect || !pathname) return;
43
+ const detected = (0, external_utils_js_namespaceObject.detectLanguageFromPath)(pathname, languages || [], localePathRedirect);
44
+ return detected.detected ? detected.language : void 0;
45
+ }
46
+ function cacheI18nLanguage(i18nInstance, language) {
47
+ if ((0, runtime_namespaceObject.isBrowser)()) {
48
+ const detectionOptions = i18nInstance.options?.detection;
49
+ (0, index_js_namespaceObject.cacheUserLanguage)(i18nInstance, language, detectionOptions);
50
+ }
51
+ }
52
+ async function changeModernI18nLanguage(newLang, options) {
53
+ const { i18nInstance, updateLanguage, localePathRedirect, ignoreRedirectRoutes, localisedUrls, languages, hasRouter, navigate, location } = options;
54
+ try {
55
+ if (!newLang || 'string' != typeof newLang) throw new Error('Language must be non-empty string');
56
+ await i18nInstance?.setLang?.(newLang);
57
+ await i18nInstance?.changeLanguage?.(newLang);
58
+ cacheI18nLanguage(i18nInstance, newLang);
59
+ if (localePathRedirect && (0, runtime_namespaceObject.isBrowser)() && hasRouter && navigate && location) {
60
+ const currentPath = location.pathname;
61
+ const entryPath = (0, external_utils_js_namespaceObject.getEntryPath)();
62
+ const relativePath = currentPath.replace(entryPath, '');
63
+ const pathLanguage = (0, external_utils_js_namespaceObject.detectLanguageFromPath)(currentPath, languages || [], localePathRedirect);
64
+ if (pathLanguage.detected && pathLanguage.language === newLang) return void updateLanguage?.(newLang);
65
+ if (!(0, external_utils_js_namespaceObject.shouldIgnoreRedirect)(relativePath, languages || [], ignoreRedirectRoutes)) {
66
+ const newPath = (0, external_utils_js_namespaceObject.buildLocalizedUrl)(relativePath, newLang, languages || [], localisedUrls);
67
+ const newUrl = entryPath + newPath + location.search + location.hash;
68
+ await navigate(newUrl, {
69
+ replace: true
70
+ });
71
+ }
72
+ } else if (localePathRedirect && (0, runtime_namespaceObject.isBrowser)() && !hasRouter) {
73
+ const currentPath = window.location.pathname;
74
+ const entryPath = (0, external_utils_js_namespaceObject.getEntryPath)();
75
+ const relativePath = currentPath.replace(entryPath, '');
76
+ const pathLanguage = (0, external_utils_js_namespaceObject.detectLanguageFromPath)(currentPath, languages || [], localePathRedirect);
77
+ if (pathLanguage.detected && pathLanguage.language === newLang) return void updateLanguage?.(newLang);
78
+ if (!(0, external_utils_js_namespaceObject.shouldIgnoreRedirect)(relativePath, languages || [], ignoreRedirectRoutes)) {
79
+ const newPath = (0, external_utils_js_namespaceObject.buildLocalizedUrl)(relativePath, newLang, languages || [], localisedUrls);
80
+ const newUrl = entryPath + newPath + window.location.search + window.location.hash;
81
+ window.history.pushState(null, '', newUrl);
82
+ }
83
+ }
84
+ if (updateLanguage) updateLanguage(newLang);
85
+ } catch (error) {
86
+ console.error('Failed change language:', error);
87
+ throw error;
88
+ }
89
+ }
90
+ function translateI18n(i18nInstance, key, ...args) {
91
+ if ('function' != typeof i18nInstance.t) throw new Error('i18nInstance.t required');
92
+ return i18nInstance.t(key, ...args);
93
+ }
94
+ function isI18nLanguageSupported(languages, lang) {
95
+ return languages?.includes(lang) || false;
96
+ }
97
+ function isI18nResourcesReady(i18nInstance, currentLanguage) {
98
+ if (!i18nInstance?.isInitialized) return false;
99
+ const backend = i18nInstance?.services?.backend;
100
+ if (backend && 'function' == typeof backend.isLoading) {
101
+ const loadingResources = backend.getLoadingResources();
102
+ const isCurrentLanguageLoading = loadingResources.some(({ language })=>language === currentLanguage);
103
+ if (isCurrentLanguageLoading) return false;
104
+ }
105
+ const store = i18nInstance.store;
106
+ if (!store?.data) return false;
107
+ const langData = store.data[currentLanguage];
108
+ if (!langData || 'object' != typeof langData) return false;
109
+ const options = i18nInstance.options;
110
+ const namespaces = options?.ns || options?.defaultNS || [
111
+ 'translation'
112
+ ];
113
+ const requiredNamespaces = Array.isArray(namespaces) ? namespaces : [
114
+ namespaces
115
+ ];
116
+ return requiredNamespaces.every((ns)=>{
117
+ const nsData = langData[ns];
118
+ return nsData && 'object' == typeof nsData && Object.keys(nsData).length > 0;
119
+ });
120
+ }
121
+ exports.cacheI18nLanguage = __webpack_exports__.cacheI18nLanguage;
122
+ exports.changeModernI18nLanguage = __webpack_exports__.changeModernI18nLanguage;
123
+ exports.getPathLanguage = __webpack_exports__.getPathLanguage;
124
+ exports.isI18nLanguageSupported = __webpack_exports__.isI18nLanguageSupported;
125
+ exports.isI18nResourcesReady = __webpack_exports__.isI18nResourcesReady;
126
+ exports.translateI18n = __webpack_exports__.translateI18n;
127
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
128
+ "cacheI18nLanguage",
129
+ "changeModernI18nLanguage",
130
+ "getPathLanguage",
131
+ "isI18nLanguageSupported",
132
+ "isI18nResourcesReady",
133
+ "translateI18n"
134
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
135
+ Object.defineProperty(exports, '__esModule', {
136
+ value: true
137
+ });
@@ -39,37 +39,15 @@ __webpack_require__.d(__webpack_exports__, {
39
39
  useLocalizedPaths: ()=>external_localizedPaths_js_namespaceObject.useLocalizedPaths,
40
40
  useModernI18n: ()=>external_context_js_namespaceObject.useModernI18n
41
41
  });
42
- const jsx_runtime_namespaceObject = require("react/jsx-runtime");
43
- const runtime_namespaceObject = require("@modern-js/runtime");
44
- const head_namespaceObject = require("@modern-js/runtime/head");
45
- const merge_namespaceObject = require("@modern-js/runtime-utils/merge");
46
- const external_react_namespaceObject = require("react");
47
- const external_context_js_namespaceObject = require("./context.js");
48
- const external_hooks_js_namespaceObject = require("./hooks.js");
49
- const index_js_namespaceObject = require("./i18n/index.js");
50
- const backend_index_js_namespaceObject = require("./i18n/backend/index.js");
51
- const detection_index_js_namespaceObject = require("./i18n/detection/index.js");
52
- const middleware_js_namespaceObject = require("./i18n/detection/middleware.js");
53
- const instance_js_namespaceObject = require("./i18n/instance.js");
54
- const external_utils_js_namespaceObject = require("./utils.js");
42
+ const external_pluginSetup_js_namespaceObject = require("./pluginSetup.js");
43
+ const external_providerComposition_js_namespaceObject = require("./providerComposition.js");
44
+ const external_reactI18next_js_namespaceObject = require("./reactI18next.js");
55
45
  require("./types.js");
46
+ const external_context_js_namespaceObject = require("./context.js");
56
47
  const external_I18nLink_js_namespaceObject = require("./I18nLink.js");
57
48
  const external_Link_js_namespaceObject = require("./Link.js");
58
49
  const external_localizedPaths_js_namespaceObject = require("./localizedPaths.js");
59
- let i18nLifecycleHelpersPromise;
60
- function loadI18nLifecycleHelpers() {
61
- i18nLifecycleHelpersPromise ??= Promise.all([
62
- import("./i18n/backend/middleware.js"),
63
- import("./i18n/utils.js")
64
- ]).then(([backendMiddleware, utils])=>({
65
- useI18nextBackend: backendMiddleware.useI18nextBackend,
66
- changeI18nLanguage: utils.changeI18nLanguage,
67
- ensureLanguageMatch: utils.ensureLanguageMatch,
68
- initializeI18nInstance: utils.initializeI18nInstance,
69
- setupClonedInstance: utils.setupClonedInstance
70
- }));
71
- return i18nLifecycleHelpersPromise;
72
- }
50
+ const external_utils_js_namespaceObject = require("./utils.js");
73
51
  const createI18nPlugin = (loadReactI18nextIntegration)=>(options)=>({
74
52
  name: '@modern-js/plugin-i18n',
75
53
  setup: (api)=>{
@@ -78,116 +56,35 @@ const createI18nPlugin = (loadReactI18nextIntegration)=>(options)=>({
78
56
  const { enabled: backendEnabled = false } = backend || {};
79
57
  let latestI18nInstance;
80
58
  let I18nextProvider;
81
- const resolveReactI18nextIntegration = async ()=>{
82
- if (!reactI18next) return null;
83
- return loadReactI18nextIntegration?.() ?? null;
84
- };
85
59
  api.onBeforeRender(async (context)=>{
86
- const { useI18nextBackend, changeI18nLanguage, ensureLanguageMatch, initializeI18nInstance, setupClonedInstance } = await loadI18nLifecycleHelpers();
87
- let i18nInstance = await (0, index_js_namespaceObject.getI18nInstance)(userI18nInstance);
88
- const { i18n: otherConfig } = api.getRuntimeConfig();
89
- const { initOptions: otherInitOptions } = otherConfig || {};
90
- const userInitOptions = (0, merge_namespaceObject.merge)(otherInitOptions || {}, initOptions || {});
91
- const reactI18nextIntegration = await resolveReactI18nextIntegration();
92
- I18nextProvider = reactI18nextIntegration?.I18nextProvider ?? null;
93
- if (reactI18nextIntegration?.initReactI18next) i18nInstance.use(reactI18nextIntegration.initReactI18next);
94
- const pathname = (0, external_utils_js_namespaceObject.getPathname)(context);
95
- if (i18nextDetector) (0, middleware_js_namespaceObject.useI18nextLanguageDetector)(i18nInstance);
96
- const mergedDetection = (0, detection_index_js_namespaceObject.mergeDetectionOptions)(i18nextDetector, detection, localePathRedirect, userInitOptions);
97
- const mergedBackend = (0, backend_index_js_namespaceObject.mergeBackendOptions)(backend, userInitOptions);
98
- const hasSdkConfig = 'function' == typeof userInitOptions?.backend?.sdk || mergedBackend?.sdk && 'function' == typeof mergedBackend.sdk;
99
- if (mergedBackend && (backendEnabled || hasSdkConfig)) useI18nextBackend(i18nInstance, mergedBackend);
100
- const { finalLanguage } = await (0, detection_index_js_namespaceObject.detectLanguageWithPriority)(i18nInstance, {
101
- languages,
102
- fallbackLanguage,
103
- localePathRedirect,
60
+ latestI18nInstance = await (0, external_pluginSetup_js_namespaceObject.setupI18nBeforeRender)(context, {
61
+ api,
62
+ userI18nInstance,
63
+ initOptions,
64
+ backend,
65
+ backendEnabled,
104
66
  i18nextDetector,
105
67
  detection,
106
- userInitOptions,
107
- mergedBackend,
108
- pathname,
109
- ssrContext: context.ssrContext
110
- });
111
- await initializeI18nInstance(i18nInstance, finalLanguage, fallbackLanguage, languages, mergedDetection, mergedBackend, userInitOptions);
112
- if (!(0, runtime_namespaceObject.isBrowser)() && i18nInstance.cloneInstance) {
113
- i18nInstance = i18nInstance.cloneInstance();
114
- await setupClonedInstance(i18nInstance, finalLanguage, fallbackLanguage, languages, backendEnabled, backend, i18nextDetector, detection, localePathRedirect, userInitOptions);
115
- }
116
- if (localePathRedirect) await ensureLanguageMatch(i18nInstance, finalLanguage);
117
- if (!(0, runtime_namespaceObject.isBrowser)()) (0, detection_index_js_namespaceObject.exportServerLngToWindow)(context, finalLanguage);
118
- context.i18nInstance = i18nInstance;
119
- latestI18nInstance = i18nInstance;
120
- context.changeLanguage = async (newLang)=>{
121
- await changeI18nLanguage(i18nInstance, newLang, {
122
- detectionOptions: mergedDetection
123
- });
124
- };
125
- });
126
- api.wrapRoot((App)=>(props)=>{
127
- const runtimeContext = (0, external_react_namespaceObject.useContext)(runtime_namespaceObject.RuntimeContext);
128
- const i18nInstance = runtimeContext.i18nInstance || latestI18nInstance;
129
- const initialLang = (0, external_react_namespaceObject.useMemo)(()=>i18nInstance?.language || (localeDetection?.fallbackLanguage ?? 'en'), [
130
- i18nInstance?.language,
131
- localeDetection?.fallbackLanguage
132
- ]);
133
- const [lang, setLang] = (0, external_react_namespaceObject.useState)(initialLang);
134
- const [forceUpdate, setForceUpdate] = (0, external_react_namespaceObject.useState)(0);
135
- const prevLangRef = (0, external_react_namespaceObject.useRef)(lang);
136
- const runtimeContextRef = (0, external_react_namespaceObject.useRef)(runtimeContext);
137
- runtimeContextRef.current = runtimeContext;
138
- (0, external_react_namespaceObject.useEffect)(()=>{
139
- if (i18nInstance?.language) {
140
- const translator = i18nInstance.translator;
141
- if (translator) translator.language = i18nInstance.language;
142
- }
143
- }, [
144
- i18nInstance?.language
145
- ]);
146
- (0, external_react_namespaceObject.useEffect)(()=>{
147
- prevLangRef.current = lang;
148
- }, [
149
- lang
150
- ]);
151
- (0, external_hooks_js_namespaceObject.useSdkResourcesLoader)(i18nInstance, setForceUpdate);
152
- (0, external_hooks_js_namespaceObject.useLanguageSync)(i18nInstance, localePathRedirect, languages, runtimeContextRef, prevLangRef, setLang);
153
- (0, external_hooks_js_namespaceObject.useClientSideRedirect)(i18nInstance, localePathRedirect, languages, fallbackLanguage, ignoreRedirectRoutes, localisedUrls);
154
- const contextValue = (0, external_react_namespaceObject.useMemo)(()=>(0, external_hooks_js_namespaceObject.createContextValue)(lang, i18nInstance, entryName, languages, localePathRedirect, ignoreRedirectRoutes, localisedUrls, setLang), [
155
- lang,
156
- i18nInstance,
157
- entryName,
158
- languages,
159
- localePathRedirect,
160
- ignoreRedirectRoutes,
161
- localisedUrls,
162
- forceUpdate
163
- ]);
164
- const children = props.children;
165
- const appContent = /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)(jsx_runtime_namespaceObject.Fragment, {
166
- children: [
167
- Boolean(htmlLangAttr) && /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(head_namespaceObject.Helmet, {
168
- htmlAttributes: {
169
- lang
170
- }
171
- }),
172
- /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_context_js_namespaceObject.ModernI18nProvider, {
173
- value: contextValue,
174
- children: App ? /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(App, {
175
- ...props,
176
- children: children
177
- }) : children
178
- })
179
- ]
180
- });
181
- if (!i18nInstance) return appContent;
182
- if (I18nextProvider) {
183
- const i18nextInstanceForProvider = (0, instance_js_namespaceObject.getI18nextInstanceForProvider)(i18nInstance);
184
- return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(I18nextProvider, {
185
- i18n: i18nextInstanceForProvider,
186
- children: appContent
187
- });
68
+ localePathRedirect,
69
+ languages,
70
+ fallbackLanguage,
71
+ resolveReactI18nextIntegration: ()=>(0, external_reactI18next_js_namespaceObject.resolveReactI18nextIntegration)(reactI18next, loadReactI18nextIntegration),
72
+ setI18nextProvider: (provider)=>{
73
+ I18nextProvider = provider;
188
74
  }
189
- return appContent;
190
75
  });
76
+ });
77
+ api.wrapRoot((0, external_providerComposition_js_namespaceObject.createI18nRootWrapper)({
78
+ entryName,
79
+ htmlLangAttr,
80
+ localePathRedirect,
81
+ languages,
82
+ fallbackLanguage,
83
+ ignoreRedirectRoutes,
84
+ localisedUrls,
85
+ getLatestI18nInstance: ()=>latestI18nInstance,
86
+ getI18nextProvider: ()=>I18nextProvider
87
+ }));
191
88
  }
192
89
  });
193
90
  exports.I18nLink = __webpack_exports__.I18nLink;