@bleedingdev/modern-js-plugin-i18n 3.4.0-ultramodern.7 → 3.4.0-ultramodern.9

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.
@@ -48,16 +48,28 @@ const external_context_js_namespaceObject = require("./context.js");
48
48
  const external_hooks_js_namespaceObject = require("./hooks.js");
49
49
  const index_js_namespaceObject = require("./i18n/index.js");
50
50
  const backend_index_js_namespaceObject = require("./i18n/backend/index.js");
51
- const middleware_js_namespaceObject = require("./i18n/backend/middleware.js");
52
51
  const detection_index_js_namespaceObject = require("./i18n/detection/index.js");
53
- const detection_middleware_js_namespaceObject = require("./i18n/detection/middleware.js");
52
+ const middleware_js_namespaceObject = require("./i18n/detection/middleware.js");
54
53
  const instance_js_namespaceObject = require("./i18n/instance.js");
55
- const utils_js_namespaceObject = require("./i18n/utils.js");
56
54
  const external_utils_js_namespaceObject = require("./utils.js");
57
55
  require("./types.js");
58
56
  const external_I18nLink_js_namespaceObject = require("./I18nLink.js");
59
57
  const external_Link_js_namespaceObject = require("./Link.js");
60
58
  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
+ }
61
73
  const createI18nPlugin = (loadReactI18nextIntegration)=>(options)=>({
62
74
  name: '@modern-js/plugin-i18n',
63
75
  setup: (api)=>{
@@ -71,6 +83,7 @@ const createI18nPlugin = (loadReactI18nextIntegration)=>(options)=>({
71
83
  return loadReactI18nextIntegration?.() ?? null;
72
84
  };
73
85
  api.onBeforeRender(async (context)=>{
86
+ const { useI18nextBackend, changeI18nLanguage, ensureLanguageMatch, initializeI18nInstance, setupClonedInstance } = await loadI18nLifecycleHelpers();
74
87
  let i18nInstance = await (0, index_js_namespaceObject.getI18nInstance)(userI18nInstance);
75
88
  const { i18n: otherConfig } = api.getRuntimeConfig();
76
89
  const { initOptions: otherInitOptions } = otherConfig || {};
@@ -79,11 +92,11 @@ const createI18nPlugin = (loadReactI18nextIntegration)=>(options)=>({
79
92
  I18nextProvider = reactI18nextIntegration?.I18nextProvider ?? null;
80
93
  if (reactI18nextIntegration?.initReactI18next) i18nInstance.use(reactI18nextIntegration.initReactI18next);
81
94
  const pathname = (0, external_utils_js_namespaceObject.getPathname)(context);
82
- if (i18nextDetector) (0, detection_middleware_js_namespaceObject.useI18nextLanguageDetector)(i18nInstance);
95
+ if (i18nextDetector) (0, middleware_js_namespaceObject.useI18nextLanguageDetector)(i18nInstance);
83
96
  const mergedDetection = (0, detection_index_js_namespaceObject.mergeDetectionOptions)(i18nextDetector, detection, localePathRedirect, userInitOptions);
84
97
  const mergedBackend = (0, backend_index_js_namespaceObject.mergeBackendOptions)(backend, userInitOptions);
85
98
  const hasSdkConfig = 'function' == typeof userInitOptions?.backend?.sdk || mergedBackend?.sdk && 'function' == typeof mergedBackend.sdk;
86
- if (mergedBackend && (backendEnabled || hasSdkConfig)) (0, middleware_js_namespaceObject.useI18nextBackend)(i18nInstance, mergedBackend);
99
+ if (mergedBackend && (backendEnabled || hasSdkConfig)) useI18nextBackend(i18nInstance, mergedBackend);
87
100
  const { finalLanguage } = await (0, detection_index_js_namespaceObject.detectLanguageWithPriority)(i18nInstance, {
88
101
  languages,
89
102
  fallbackLanguage,
@@ -95,17 +108,17 @@ const createI18nPlugin = (loadReactI18nextIntegration)=>(options)=>({
95
108
  pathname,
96
109
  ssrContext: context.ssrContext
97
110
  });
98
- await (0, utils_js_namespaceObject.initializeI18nInstance)(i18nInstance, finalLanguage, fallbackLanguage, languages, mergedDetection, mergedBackend, userInitOptions);
111
+ await initializeI18nInstance(i18nInstance, finalLanguage, fallbackLanguage, languages, mergedDetection, mergedBackend, userInitOptions);
99
112
  if (!(0, runtime_namespaceObject.isBrowser)() && i18nInstance.cloneInstance) {
100
113
  i18nInstance = i18nInstance.cloneInstance();
101
- await (0, utils_js_namespaceObject.setupClonedInstance)(i18nInstance, finalLanguage, fallbackLanguage, languages, backendEnabled, backend, i18nextDetector, detection, localePathRedirect, userInitOptions);
114
+ await setupClonedInstance(i18nInstance, finalLanguage, fallbackLanguage, languages, backendEnabled, backend, i18nextDetector, detection, localePathRedirect, userInitOptions);
102
115
  }
103
- if (localePathRedirect) await (0, utils_js_namespaceObject.ensureLanguageMatch)(i18nInstance, finalLanguage);
116
+ if (localePathRedirect) await ensureLanguageMatch(i18nInstance, finalLanguage);
104
117
  if (!(0, runtime_namespaceObject.isBrowser)()) (0, detection_index_js_namespaceObject.exportServerLngToWindow)(context, finalLanguage);
105
118
  context.i18nInstance = i18nInstance;
106
119
  latestI18nInstance = i18nInstance;
107
120
  context.changeLanguage = async (newLang)=>{
108
- await (0, utils_js_namespaceObject.changeI18nLanguage)(i18nInstance, newLang, {
121
+ await changeI18nLanguage(i18nInstance, newLang, {
109
122
  detectionOptions: mergedDetection
110
123
  });
111
124
  };
@@ -7,13 +7,25 @@ import { ModernI18nProvider, useModernI18n } from "./context.mjs";
7
7
  import { createContextValue, useClientSideRedirect, useLanguageSync, useSdkResourcesLoader } from "./hooks.mjs";
8
8
  import { getI18nInstance } from "./i18n/index.mjs";
9
9
  import { mergeBackendOptions } from "./i18n/backend/index.mjs";
10
- import { useI18nextBackend } from "./i18n/backend/middleware.mjs";
11
10
  import { detectLanguageWithPriority, exportServerLngToWindow, mergeDetectionOptions } from "./i18n/detection/index.mjs";
12
11
  import { useI18nextLanguageDetector } from "./i18n/detection/middleware.mjs";
13
12
  import { getI18nextInstanceForProvider } from "./i18n/instance.mjs";
14
- import { changeI18nLanguage, ensureLanguageMatch, initializeI18nInstance, setupClonedInstance } from "./i18n/utils.mjs";
15
13
  import { buildLocalizedUrl, getPathname, splitUrlTarget } from "./utils.mjs";
16
14
  import "./types.mjs";
15
+ let i18nLifecycleHelpersPromise;
16
+ function loadI18nLifecycleHelpers() {
17
+ i18nLifecycleHelpersPromise ??= Promise.all([
18
+ import("./i18n/backend/middleware.mjs"),
19
+ import("./i18n/utils.mjs")
20
+ ]).then(([backendMiddleware, utils])=>({
21
+ useI18nextBackend: backendMiddleware.useI18nextBackend,
22
+ changeI18nLanguage: utils.changeI18nLanguage,
23
+ ensureLanguageMatch: utils.ensureLanguageMatch,
24
+ initializeI18nInstance: utils.initializeI18nInstance,
25
+ setupClonedInstance: utils.setupClonedInstance
26
+ }));
27
+ return i18nLifecycleHelpersPromise;
28
+ }
17
29
  const createI18nPlugin = (loadReactI18nextIntegration)=>(options)=>({
18
30
  name: '@modern-js/plugin-i18n',
19
31
  setup: (api)=>{
@@ -27,6 +39,7 @@ const createI18nPlugin = (loadReactI18nextIntegration)=>(options)=>({
27
39
  return loadReactI18nextIntegration?.() ?? null;
28
40
  };
29
41
  api.onBeforeRender(async (context)=>{
42
+ const { useI18nextBackend, changeI18nLanguage, ensureLanguageMatch, initializeI18nInstance, setupClonedInstance } = await loadI18nLifecycleHelpers();
30
43
  let i18nInstance = await getI18nInstance(userI18nInstance);
31
44
  const { i18n: otherConfig } = api.getRuntimeConfig();
32
45
  const { initOptions: otherInitOptions } = otherConfig || {};
@@ -8,13 +8,25 @@ import { ModernI18nProvider, useModernI18n } from "./context.mjs";
8
8
  import { createContextValue, useClientSideRedirect, useLanguageSync, useSdkResourcesLoader } from "./hooks.mjs";
9
9
  import { getI18nInstance } from "./i18n/index.mjs";
10
10
  import { mergeBackendOptions } from "./i18n/backend/index.mjs";
11
- import { useI18nextBackend } from "./i18n/backend/middleware.mjs";
12
11
  import { detectLanguageWithPriority, exportServerLngToWindow, mergeDetectionOptions } from "./i18n/detection/index.mjs";
13
12
  import { useI18nextLanguageDetector } from "./i18n/detection/middleware.mjs";
14
13
  import { getI18nextInstanceForProvider } from "./i18n/instance.mjs";
15
- import { changeI18nLanguage, ensureLanguageMatch, initializeI18nInstance, setupClonedInstance } from "./i18n/utils.mjs";
16
14
  import { buildLocalizedUrl, getPathname, splitUrlTarget } from "./utils.mjs";
17
15
  import "./types.mjs";
16
+ let i18nLifecycleHelpersPromise;
17
+ function loadI18nLifecycleHelpers() {
18
+ i18nLifecycleHelpersPromise ??= Promise.all([
19
+ import("./i18n/backend/middleware.mjs"),
20
+ import("./i18n/utils.mjs")
21
+ ]).then(([backendMiddleware, utils])=>({
22
+ useI18nextBackend: backendMiddleware.useI18nextBackend,
23
+ changeI18nLanguage: utils.changeI18nLanguage,
24
+ ensureLanguageMatch: utils.ensureLanguageMatch,
25
+ initializeI18nInstance: utils.initializeI18nInstance,
26
+ setupClonedInstance: utils.setupClonedInstance
27
+ }));
28
+ return i18nLifecycleHelpersPromise;
29
+ }
18
30
  const createI18nPlugin = (loadReactI18nextIntegration)=>(options)=>({
19
31
  name: '@modern-js/plugin-i18n',
20
32
  setup: (api)=>{
@@ -28,6 +40,7 @@ const createI18nPlugin = (loadReactI18nextIntegration)=>(options)=>({
28
40
  return loadReactI18nextIntegration?.() ?? null;
29
41
  };
30
42
  api.onBeforeRender(async (context)=>{
43
+ const { useI18nextBackend, changeI18nLanguage, ensureLanguageMatch, initializeI18nInstance, setupClonedInstance } = await loadI18nLifecycleHelpers();
31
44
  let i18nInstance = await getI18nInstance(userI18nInstance);
32
45
  const { i18n: otherConfig } = api.getRuntimeConfig();
33
46
  const { initOptions: otherInitOptions } = otherConfig || {};
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "modern",
18
18
  "modern.js"
19
19
  ],
20
- "version": "3.4.0-ultramodern.7",
20
+ "version": "3.4.0-ultramodern.9",
21
21
  "engines": {
22
22
  "node": ">=20"
23
23
  },
@@ -97,15 +97,15 @@
97
97
  "i18next-fs-backend": "^2.6.6",
98
98
  "i18next-http-backend": "^4.0.0",
99
99
  "i18next-http-middleware": "^3.9.7",
100
- "@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.4.0-ultramodern.7",
101
- "@modern-js/server-runtime": "npm:@bleedingdev/modern-js-server-runtime@3.4.0-ultramodern.7",
102
- "@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.4.0-ultramodern.7",
103
- "@modern-js/types": "npm:@bleedingdev/modern-js-types@3.4.0-ultramodern.7",
104
- "@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.4.0-ultramodern.7",
105
- "@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.4.0-ultramodern.7"
100
+ "@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.4.0-ultramodern.9",
101
+ "@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.4.0-ultramodern.9",
102
+ "@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.4.0-ultramodern.9",
103
+ "@modern-js/server-runtime": "npm:@bleedingdev/modern-js-server-runtime@3.4.0-ultramodern.9",
104
+ "@modern-js/types": "npm:@bleedingdev/modern-js-types@3.4.0-ultramodern.9",
105
+ "@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.4.0-ultramodern.9"
106
106
  },
107
107
  "peerDependencies": {
108
- "@modern-js/runtime": "3.4.0-ultramodern.7",
108
+ "@modern-js/runtime": "3.4.0-ultramodern.9",
109
109
  "i18next": ">=26.3.1",
110
110
  "react": "^19.2.7",
111
111
  "react-dom": "^19.2.7",
@@ -129,8 +129,8 @@
129
129
  "react-i18next": "17.0.8",
130
130
  "ts-node": "^10.9.2",
131
131
  "typescript": "^6.0.3",
132
- "@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.4.0-ultramodern.7",
133
- "@modern-js/runtime": "npm:@bleedingdev/modern-js-runtime@3.4.0-ultramodern.7"
132
+ "@modern-js/runtime": "npm:@bleedingdev/modern-js-runtime@3.4.0-ultramodern.9",
133
+ "@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.4.0-ultramodern.9"
134
134
  },
135
135
  "sideEffects": false,
136
136
  "publishConfig": {
@@ -22,7 +22,6 @@ import {
22
22
  import type { I18nInitOptions, I18nInstance } from './i18n';
23
23
  import { getI18nInstance } from './i18n';
24
24
  import { mergeBackendOptions } from './i18n/backend';
25
- import { useI18nextBackend } from './i18n/backend/middleware';
26
25
  import {
27
26
  detectLanguageWithPriority,
28
27
  exportServerLngToWindow,
@@ -30,18 +29,37 @@ import {
30
29
  } from './i18n/detection';
31
30
  import { useI18nextLanguageDetector } from './i18n/detection/middleware';
32
31
  import { getI18nextInstanceForProvider } from './i18n/instance';
33
- import {
34
- changeI18nLanguage,
35
- ensureLanguageMatch,
36
- initializeI18nInstance,
37
- setupClonedInstance,
38
- } from './i18n/utils';
39
32
  import { getPathname } from './utils';
40
33
  import './types';
41
34
 
42
35
  export type { I18nSdkLoader, I18nSdkLoadOptions } from '../shared/type';
43
36
  export type { Resources } from './i18n/instance';
44
37
 
38
+ type I18nLifecycleHelpers = {
39
+ useI18nextBackend: typeof import('./i18n/backend/middleware')['useI18nextBackend'];
40
+ changeI18nLanguage: typeof import('./i18n/utils')['changeI18nLanguage'];
41
+ ensureLanguageMatch: typeof import('./i18n/utils')['ensureLanguageMatch'];
42
+ initializeI18nInstance: typeof import('./i18n/utils')['initializeI18nInstance'];
43
+ setupClonedInstance: typeof import('./i18n/utils')['setupClonedInstance'];
44
+ };
45
+
46
+ let i18nLifecycleHelpersPromise: Promise<I18nLifecycleHelpers> | undefined;
47
+
48
+ function loadI18nLifecycleHelpers(): Promise<I18nLifecycleHelpers> {
49
+ i18nLifecycleHelpersPromise ??= Promise.all([
50
+ import('./i18n/backend/middleware'),
51
+ import('./i18n/utils'),
52
+ ]).then(([backendMiddleware, utils]) => ({
53
+ useI18nextBackend: backendMiddleware.useI18nextBackend,
54
+ changeI18nLanguage: utils.changeI18nLanguage,
55
+ ensureLanguageMatch: utils.ensureLanguageMatch,
56
+ initializeI18nInstance: utils.initializeI18nInstance,
57
+ setupClonedInstance: utils.setupClonedInstance,
58
+ }));
59
+
60
+ return i18nLifecycleHelpersPromise;
61
+ }
62
+
45
63
  export interface I18nPluginOptions {
46
64
  entryName?: string;
47
65
  localeDetection?: BaseLocaleDetectionOptions;
@@ -104,6 +122,13 @@ export const createI18nPlugin =
104
122
  };
105
123
 
106
124
  api.onBeforeRender(async context => {
125
+ const {
126
+ useI18nextBackend,
127
+ changeI18nLanguage,
128
+ ensureLanguageMatch,
129
+ initializeI18nInstance,
130
+ setupClonedInstance,
131
+ } = await loadI18nLifecycleHelpers();
107
132
  let i18nInstance = await getI18nInstance(userI18nInstance);
108
133
  const { i18n: otherConfig } = api.getRuntimeConfig();
109
134
  const { initOptions: otherInitOptions } = otherConfig || {};
@@ -19,6 +19,15 @@ describe('react-i18next runtime boundary', () => {
19
19
  expect(core).not.toContain("import('react-i18next')");
20
20
  });
21
21
 
22
+ test('keeps the runtime plugin factory entry synchronous for federation', () => {
23
+ const core = readRuntimeSource('core.tsx');
24
+
25
+ expect(core).not.toContain("from './i18n/backend/middleware'");
26
+ expect(core).not.toContain("from './i18n/utils'");
27
+ expect(core).toContain("import('./i18n/backend/middleware')");
28
+ expect(core).toContain("import('./i18n/utils')");
29
+ });
30
+
22
31
  test('keeps the default runtime entry wired to react-i18next integration', () => {
23
32
  const defaultEntry = readRuntimeSource('index.tsx');
24
33