@modern-js/plugin-i18n 3.1.1 → 3.1.3-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/runtime/hooks.js +8 -3
- package/dist/cjs/runtime/i18n/backend/sdk-backend.js +6 -2
- package/dist/cjs/runtime/i18n/backend/sdk-event.js +64 -0
- package/dist/esm/rslib-runtime.mjs +0 -21
- package/dist/esm/runtime/hooks.mjs +8 -3
- package/dist/esm/runtime/i18n/backend/sdk-backend.mjs +6 -2
- package/dist/esm/runtime/i18n/backend/sdk-event.mjs +21 -0
- package/dist/esm/runtime/utils.mjs +2 -2
- package/dist/esm/server/index.mjs +3 -9
- package/dist/esm-node/rslib-runtime.mjs +0 -21
- package/dist/esm-node/runtime/hooks.mjs +8 -3
- package/dist/esm-node/runtime/i18n/backend/sdk-backend.mjs +6 -2
- package/dist/esm-node/runtime/i18n/backend/sdk-event.mjs +22 -0
- package/dist/esm-node/runtime/utils.mjs +2 -2
- package/dist/esm-node/server/index.mjs +3 -9
- package/dist/types/runtime/i18n/backend/sdk-backend.d.ts +1 -0
- package/dist/types/runtime/i18n/backend/sdk-event.d.ts +9 -0
- package/log/app/app.access.log +0 -0
- package/log/app.call.log +0 -0
- package/log/app.log +0 -0
- package/log/rpc/app.call.log +3 -0
- package/package.json +13 -16
- package/src/runtime/hooks.ts +31 -7
- package/src/runtime/i18n/backend/sdk-backend.ts +16 -2
- package/src/runtime/i18n/backend/sdk-event.ts +39 -0
|
@@ -32,6 +32,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
32
32
|
const runtime_namespaceObject = require("@modern-js/runtime");
|
|
33
33
|
const external_react_namespaceObject = require("react");
|
|
34
34
|
const index_js_namespaceObject = require("./i18n/detection/index.js");
|
|
35
|
+
const sdk_event_js_namespaceObject = require("./i18n/backend/sdk-event.js");
|
|
35
36
|
const external_utils_js_namespaceObject = require("./utils.js");
|
|
36
37
|
function createMinimalI18nInstance(language) {
|
|
37
38
|
const minimalInstance = {
|
|
@@ -59,9 +60,13 @@ function createContextValue(lang, i18nInstance, entryName, languages, localePath
|
|
|
59
60
|
function useSdkResourcesLoader(i18nInstance, setForceUpdate) {
|
|
60
61
|
(0, external_react_namespaceObject.useEffect)(()=>{
|
|
61
62
|
if (!i18nInstance || !(0, runtime_namespaceObject.isBrowser)()) return;
|
|
63
|
+
const backendId = (0, sdk_event_js_namespaceObject.getI18nSdkBackendId)(i18nInstance.services?.resourceStore) || (0, sdk_event_js_namespaceObject.getI18nSdkBackendId)(i18nInstance.services?.store) || (0, sdk_event_js_namespaceObject.getI18nSdkBackendId)(i18nInstance.store);
|
|
64
|
+
if (!backendId) return;
|
|
62
65
|
const handleSdkResourcesLoaded = (event)=>{
|
|
63
66
|
const customEvent = event;
|
|
64
|
-
const { language, namespace } = customEvent.detail;
|
|
67
|
+
const { language, namespace, backendId: eventBackendId } = customEvent.detail || {};
|
|
68
|
+
if (!language || !namespace) return;
|
|
69
|
+
if (eventBackendId && eventBackendId !== backendId) return;
|
|
65
70
|
const triggerUpdate = (retryCount = 0)=>{
|
|
66
71
|
const store = i18nInstance.store;
|
|
67
72
|
const hasResource = store?.data?.[language]?.[namespace];
|
|
@@ -89,9 +94,9 @@ function useSdkResourcesLoader(i18nInstance, setForceUpdate) {
|
|
|
89
94
|
};
|
|
90
95
|
triggerUpdate();
|
|
91
96
|
};
|
|
92
|
-
window.addEventListener(
|
|
97
|
+
window.addEventListener(sdk_event_js_namespaceObject.I18N_SDK_RESOURCES_LOADED_EVENT, handleSdkResourcesLoaded);
|
|
93
98
|
return ()=>{
|
|
94
|
-
window.removeEventListener(
|
|
99
|
+
window.removeEventListener(sdk_event_js_namespaceObject.I18N_SDK_RESOURCES_LOADED_EVENT, handleSdkResourcesLoaded);
|
|
95
100
|
};
|
|
96
101
|
}, [
|
|
97
102
|
i18nInstance,
|
|
@@ -26,10 +26,12 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
26
26
|
__webpack_require__.d(__webpack_exports__, {
|
|
27
27
|
SdkBackend: ()=>SdkBackend
|
|
28
28
|
});
|
|
29
|
+
const external_sdk_event_js_namespaceObject = require("./sdk-event.js");
|
|
29
30
|
class SdkBackend {
|
|
30
31
|
init(services, backendOptions, _i18nextOptions) {
|
|
31
32
|
this.services = services;
|
|
32
33
|
this.sdk = backendOptions?.sdk;
|
|
34
|
+
(0, external_sdk_event_js_namespaceObject.setI18nSdkBackendId)(services.resourceStore || services.store, this.backendId);
|
|
33
35
|
if (!this.sdk) throw new Error('SdkBackend requires an SDK function to be provided in backend options');
|
|
34
36
|
}
|
|
35
37
|
read(language, namespace, callback) {
|
|
@@ -146,10 +148,11 @@ class SdkBackend {
|
|
|
146
148
|
}
|
|
147
149
|
triggerI18nextUpdate(language, namespace) {
|
|
148
150
|
if ("u" > typeof window) {
|
|
149
|
-
const event = new CustomEvent(
|
|
151
|
+
const event = new CustomEvent(external_sdk_event_js_namespaceObject.I18N_SDK_RESOURCES_LOADED_EVENT, {
|
|
150
152
|
detail: {
|
|
151
153
|
language,
|
|
152
|
-
namespace
|
|
154
|
+
namespace,
|
|
155
|
+
backendId: this.backendId
|
|
153
156
|
}
|
|
154
157
|
});
|
|
155
158
|
window.dispatchEvent(event);
|
|
@@ -158,6 +161,7 @@ class SdkBackend {
|
|
|
158
161
|
constructor(_services, _options){
|
|
159
162
|
this.type = 'backend';
|
|
160
163
|
this.allResourcesCache = null;
|
|
164
|
+
this.backendId = (0, external_sdk_event_js_namespaceObject.createI18nSdkBackendId)();
|
|
161
165
|
this.loadingPromises = new Map();
|
|
162
166
|
}
|
|
163
167
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
5
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: definition[key]
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
})();
|
|
11
|
+
(()=>{
|
|
12
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
13
|
+
})();
|
|
14
|
+
(()=>{
|
|
15
|
+
__webpack_require__.r = (exports1)=>{
|
|
16
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
17
|
+
value: 'Module'
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
20
|
+
value: true
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
var __webpack_exports__ = {};
|
|
25
|
+
__webpack_require__.r(__webpack_exports__);
|
|
26
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
I18N_SDK_RESOURCES_LOADED_EVENT: ()=>I18N_SDK_RESOURCES_LOADED_EVENT,
|
|
28
|
+
createI18nSdkBackendId: ()=>createI18nSdkBackendId,
|
|
29
|
+
getI18nSdkBackendId: ()=>getI18nSdkBackendId,
|
|
30
|
+
setI18nSdkBackendId: ()=>setI18nSdkBackendId
|
|
31
|
+
});
|
|
32
|
+
const I18N_SDK_RESOURCES_LOADED_EVENT = 'i18n-sdk-resources-loaded';
|
|
33
|
+
const I18N_SDK_BACKEND_ID_KEY = '__modern_i18n_sdk_backend_id__';
|
|
34
|
+
let sdkBackendInstanceCount = 0;
|
|
35
|
+
function createI18nSdkBackendId() {
|
|
36
|
+
sdkBackendInstanceCount += 1;
|
|
37
|
+
return `modern-i18n-sdk-backend-${sdkBackendInstanceCount}`;
|
|
38
|
+
}
|
|
39
|
+
function setI18nSdkBackendId(target, backendId) {
|
|
40
|
+
if (!target || 'object' != typeof target) return;
|
|
41
|
+
Object.defineProperty(target, I18N_SDK_BACKEND_ID_KEY, {
|
|
42
|
+
configurable: true,
|
|
43
|
+
enumerable: false,
|
|
44
|
+
value: backendId,
|
|
45
|
+
writable: true
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function getI18nSdkBackendId(target) {
|
|
49
|
+
if (!target || 'object' != typeof target) return;
|
|
50
|
+
return target[I18N_SDK_BACKEND_ID_KEY];
|
|
51
|
+
}
|
|
52
|
+
exports.I18N_SDK_RESOURCES_LOADED_EVENT = __webpack_exports__.I18N_SDK_RESOURCES_LOADED_EVENT;
|
|
53
|
+
exports.createI18nSdkBackendId = __webpack_exports__.createI18nSdkBackendId;
|
|
54
|
+
exports.getI18nSdkBackendId = __webpack_exports__.getI18nSdkBackendId;
|
|
55
|
+
exports.setI18nSdkBackendId = __webpack_exports__.setI18nSdkBackendId;
|
|
56
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
57
|
+
"I18N_SDK_RESOURCES_LOADED_EVENT",
|
|
58
|
+
"createI18nSdkBackendId",
|
|
59
|
+
"getI18nSdkBackendId",
|
|
60
|
+
"setI18nSdkBackendId"
|
|
61
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
62
|
+
Object.defineProperty(exports, '__esModule', {
|
|
63
|
+
value: true
|
|
64
|
+
});
|
|
@@ -10,30 +10,9 @@ function __webpack_require__(moduleId) {
|
|
|
10
10
|
return module.exports;
|
|
11
11
|
}
|
|
12
12
|
__webpack_require__.m = __webpack_modules__;
|
|
13
|
-
(()=>{
|
|
14
|
-
__webpack_require__.d = (exports, definition)=>{
|
|
15
|
-
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) Object.defineProperty(exports, key, {
|
|
16
|
-
enumerable: true,
|
|
17
|
-
get: definition[key]
|
|
18
|
-
});
|
|
19
|
-
};
|
|
20
|
-
})();
|
|
21
13
|
(()=>{
|
|
22
14
|
__webpack_require__.add = function(modules) {
|
|
23
15
|
Object.assign(__webpack_require__.m, modules);
|
|
24
16
|
};
|
|
25
17
|
})();
|
|
26
|
-
(()=>{
|
|
27
|
-
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
28
|
-
})();
|
|
29
|
-
(()=>{
|
|
30
|
-
__webpack_require__.r = (exports)=>{
|
|
31
|
-
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports, Symbol.toStringTag, {
|
|
32
|
-
value: 'Module'
|
|
33
|
-
});
|
|
34
|
-
Object.defineProperty(exports, '__esModule', {
|
|
35
|
-
value: true
|
|
36
|
-
});
|
|
37
|
-
};
|
|
38
|
-
})();
|
|
39
18
|
export { __webpack_require__ };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isBrowser } from "@modern-js/runtime";
|
|
2
2
|
import { useEffect, useRef } from "react";
|
|
3
3
|
import { cacheUserLanguage } from "./i18n/detection/index.mjs";
|
|
4
|
+
import { I18N_SDK_RESOURCES_LOADED_EVENT, getI18nSdkBackendId } from "./i18n/backend/sdk-event.mjs";
|
|
4
5
|
import { buildLocalizedUrl, detectLanguageFromPath, getEntryPath, getPathname, shouldIgnoreRedirect, useRouterHooks } from "./utils.mjs";
|
|
5
6
|
function createMinimalI18nInstance(language) {
|
|
6
7
|
const minimalInstance = {
|
|
@@ -28,9 +29,13 @@ function createContextValue(lang, i18nInstance, entryName, languages, localePath
|
|
|
28
29
|
function useSdkResourcesLoader(i18nInstance, setForceUpdate) {
|
|
29
30
|
useEffect(()=>{
|
|
30
31
|
if (!i18nInstance || !isBrowser()) return;
|
|
32
|
+
const backendId = getI18nSdkBackendId(i18nInstance.services?.resourceStore) || getI18nSdkBackendId(i18nInstance.services?.store) || getI18nSdkBackendId(i18nInstance.store);
|
|
33
|
+
if (!backendId) return;
|
|
31
34
|
const handleSdkResourcesLoaded = (event)=>{
|
|
32
35
|
const customEvent = event;
|
|
33
|
-
const { language, namespace } = customEvent.detail;
|
|
36
|
+
const { language, namespace, backendId: eventBackendId } = customEvent.detail || {};
|
|
37
|
+
if (!language || !namespace) return;
|
|
38
|
+
if (eventBackendId && eventBackendId !== backendId) return;
|
|
34
39
|
const triggerUpdate = (retryCount = 0)=>{
|
|
35
40
|
const store = i18nInstance.store;
|
|
36
41
|
const hasResource = store?.data?.[language]?.[namespace];
|
|
@@ -58,9 +63,9 @@ function useSdkResourcesLoader(i18nInstance, setForceUpdate) {
|
|
|
58
63
|
};
|
|
59
64
|
triggerUpdate();
|
|
60
65
|
};
|
|
61
|
-
window.addEventListener(
|
|
66
|
+
window.addEventListener(I18N_SDK_RESOURCES_LOADED_EVENT, handleSdkResourcesLoaded);
|
|
62
67
|
return ()=>{
|
|
63
|
-
window.removeEventListener(
|
|
68
|
+
window.removeEventListener(I18N_SDK_RESOURCES_LOADED_EVENT, handleSdkResourcesLoaded);
|
|
64
69
|
};
|
|
65
70
|
}, [
|
|
66
71
|
i18nInstance,
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { I18N_SDK_RESOURCES_LOADED_EVENT, createI18nSdkBackendId, setI18nSdkBackendId } from "./sdk-event.mjs";
|
|
1
2
|
class SdkBackend {
|
|
2
3
|
init(services, backendOptions, _i18nextOptions) {
|
|
3
4
|
this.services = services;
|
|
4
5
|
this.sdk = backendOptions?.sdk;
|
|
6
|
+
setI18nSdkBackendId(services.resourceStore || services.store, this.backendId);
|
|
5
7
|
if (!this.sdk) throw new Error('SdkBackend requires an SDK function to be provided in backend options');
|
|
6
8
|
}
|
|
7
9
|
read(language, namespace, callback) {
|
|
@@ -118,10 +120,11 @@ class SdkBackend {
|
|
|
118
120
|
}
|
|
119
121
|
triggerI18nextUpdate(language, namespace) {
|
|
120
122
|
if ("u" > typeof window) {
|
|
121
|
-
const event = new CustomEvent(
|
|
123
|
+
const event = new CustomEvent(I18N_SDK_RESOURCES_LOADED_EVENT, {
|
|
122
124
|
detail: {
|
|
123
125
|
language,
|
|
124
|
-
namespace
|
|
126
|
+
namespace,
|
|
127
|
+
backendId: this.backendId
|
|
125
128
|
}
|
|
126
129
|
});
|
|
127
130
|
window.dispatchEvent(event);
|
|
@@ -130,6 +133,7 @@ class SdkBackend {
|
|
|
130
133
|
constructor(_services, _options){
|
|
131
134
|
this.type = 'backend';
|
|
132
135
|
this.allResourcesCache = null;
|
|
136
|
+
this.backendId = createI18nSdkBackendId();
|
|
133
137
|
this.loadingPromises = new Map();
|
|
134
138
|
}
|
|
135
139
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const I18N_SDK_RESOURCES_LOADED_EVENT = 'i18n-sdk-resources-loaded';
|
|
2
|
+
const I18N_SDK_BACKEND_ID_KEY = '__modern_i18n_sdk_backend_id__';
|
|
3
|
+
let sdkBackendInstanceCount = 0;
|
|
4
|
+
function createI18nSdkBackendId() {
|
|
5
|
+
sdkBackendInstanceCount += 1;
|
|
6
|
+
return `modern-i18n-sdk-backend-${sdkBackendInstanceCount}`;
|
|
7
|
+
}
|
|
8
|
+
function setI18nSdkBackendId(target, backendId) {
|
|
9
|
+
if (!target || 'object' != typeof target) return;
|
|
10
|
+
Object.defineProperty(target, I18N_SDK_BACKEND_ID_KEY, {
|
|
11
|
+
configurable: true,
|
|
12
|
+
enumerable: false,
|
|
13
|
+
value: backendId,
|
|
14
|
+
writable: true
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
function getI18nSdkBackendId(target) {
|
|
18
|
+
if (!target || 'object' != typeof target) return;
|
|
19
|
+
return target[I18N_SDK_BACKEND_ID_KEY];
|
|
20
|
+
}
|
|
21
|
+
export { I18N_SDK_RESOURCES_LOADED_EVENT, createI18nSdkBackendId, getI18nSdkBackendId, setI18nSdkBackendId };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as __rspack_external__modern_js_runtime_router_2dfd0c78 from "@modern-js/runtime/router";
|
|
2
|
-
import { __webpack_require__ } from "../rslib-runtime.mjs";
|
|
3
1
|
import { isBrowser } from "@modern-js/runtime";
|
|
4
2
|
import { getGlobalBasename } from "@modern-js/runtime/context";
|
|
3
|
+
import { __webpack_require__ } from "../rslib-runtime.mjs";
|
|
4
|
+
import * as __rspack_external__modern_js_runtime_router_2dfd0c78 from "@modern-js/runtime/router";
|
|
5
5
|
__webpack_require__.add({
|
|
6
6
|
"@modern-js/runtime/router?f1fa" (module) {
|
|
7
7
|
module.exports = __rspack_external__modern_js_runtime_router_2dfd0c78;
|
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
import { __webpack_require__ } from "../rslib-runtime.mjs";
|
|
2
|
-
import { languageDetector } from "@modern-js/server-core/hono";
|
|
3
1
|
import { DEFAULT_I18NEXT_DETECTION_OPTIONS, mergeDetectionOptions } from "../runtime/i18n/detection/config.mjs";
|
|
4
2
|
import { getLocaleDetectionOptions } from "../shared/utils.mjs";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
__webpack_require__.d(hono_namespaceObject, {
|
|
8
|
-
languageDetector: ()=>languageDetector
|
|
9
|
-
});
|
|
10
|
-
const { languageDetector: server_languageDetector } = hono_namespaceObject;
|
|
3
|
+
import * as __rspack_external__modern_js_server_core_hono_a76ca254 from "@modern-js/server-core/hono";
|
|
4
|
+
const { languageDetector: languageDetector } = __rspack_external__modern_js_server_core_hono_a76ca254;
|
|
11
5
|
const convertToHonoLanguageDetectorOptions = (languages, fallbackLanguage, detectionOptions)=>{
|
|
12
6
|
const mergedDetection = detectionOptions ? mergeDetectionOptions(detectionOptions) : DEFAULT_I18NEXT_DETECTION_OPTIONS;
|
|
13
7
|
const order = (mergedDetection.order || []).filter((item)=>![
|
|
@@ -114,7 +108,7 @@ const i18nServerPlugin = (options)=>({
|
|
|
114
108
|
if (localePathRedirect) {
|
|
115
109
|
if (i18nextDetector) {
|
|
116
110
|
const detectorOptions = convertToHonoLanguageDetectorOptions(languages, fallbackLanguage, detection);
|
|
117
|
-
const detectorHandler =
|
|
111
|
+
const detectorHandler = languageDetector(detectorOptions);
|
|
118
112
|
middlewares.push({
|
|
119
113
|
name: 'i18n-language-detector',
|
|
120
114
|
path: urlPath,
|
|
@@ -11,30 +11,9 @@ function __webpack_require__(moduleId) {
|
|
|
11
11
|
return module.exports;
|
|
12
12
|
}
|
|
13
13
|
__webpack_require__.m = __webpack_modules__;
|
|
14
|
-
(()=>{
|
|
15
|
-
__webpack_require__.d = (exports, definition)=>{
|
|
16
|
-
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) Object.defineProperty(exports, key, {
|
|
17
|
-
enumerable: true,
|
|
18
|
-
get: definition[key]
|
|
19
|
-
});
|
|
20
|
-
};
|
|
21
|
-
})();
|
|
22
14
|
(()=>{
|
|
23
15
|
__webpack_require__.add = function(modules) {
|
|
24
16
|
Object.assign(__webpack_require__.m, modules);
|
|
25
17
|
};
|
|
26
18
|
})();
|
|
27
|
-
(()=>{
|
|
28
|
-
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
29
|
-
})();
|
|
30
|
-
(()=>{
|
|
31
|
-
__webpack_require__.r = (exports)=>{
|
|
32
|
-
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports, Symbol.toStringTag, {
|
|
33
|
-
value: 'Module'
|
|
34
|
-
});
|
|
35
|
-
Object.defineProperty(exports, '__esModule', {
|
|
36
|
-
value: true
|
|
37
|
-
});
|
|
38
|
-
};
|
|
39
|
-
})();
|
|
40
19
|
export { __webpack_require__ };
|
|
@@ -2,6 +2,7 @@ import "node:module";
|
|
|
2
2
|
import { isBrowser } from "@modern-js/runtime";
|
|
3
3
|
import { useEffect, useRef } from "react";
|
|
4
4
|
import { cacheUserLanguage } from "./i18n/detection/index.mjs";
|
|
5
|
+
import { I18N_SDK_RESOURCES_LOADED_EVENT, getI18nSdkBackendId } from "./i18n/backend/sdk-event.mjs";
|
|
5
6
|
import { buildLocalizedUrl, detectLanguageFromPath, getEntryPath, getPathname, shouldIgnoreRedirect, useRouterHooks } from "./utils.mjs";
|
|
6
7
|
function createMinimalI18nInstance(language) {
|
|
7
8
|
const minimalInstance = {
|
|
@@ -29,9 +30,13 @@ function createContextValue(lang, i18nInstance, entryName, languages, localePath
|
|
|
29
30
|
function useSdkResourcesLoader(i18nInstance, setForceUpdate) {
|
|
30
31
|
useEffect(()=>{
|
|
31
32
|
if (!i18nInstance || !isBrowser()) return;
|
|
33
|
+
const backendId = getI18nSdkBackendId(i18nInstance.services?.resourceStore) || getI18nSdkBackendId(i18nInstance.services?.store) || getI18nSdkBackendId(i18nInstance.store);
|
|
34
|
+
if (!backendId) return;
|
|
32
35
|
const handleSdkResourcesLoaded = (event)=>{
|
|
33
36
|
const customEvent = event;
|
|
34
|
-
const { language, namespace } = customEvent.detail;
|
|
37
|
+
const { language, namespace, backendId: eventBackendId } = customEvent.detail || {};
|
|
38
|
+
if (!language || !namespace) return;
|
|
39
|
+
if (eventBackendId && eventBackendId !== backendId) return;
|
|
35
40
|
const triggerUpdate = (retryCount = 0)=>{
|
|
36
41
|
const store = i18nInstance.store;
|
|
37
42
|
const hasResource = store?.data?.[language]?.[namespace];
|
|
@@ -59,9 +64,9 @@ function useSdkResourcesLoader(i18nInstance, setForceUpdate) {
|
|
|
59
64
|
};
|
|
60
65
|
triggerUpdate();
|
|
61
66
|
};
|
|
62
|
-
window.addEventListener(
|
|
67
|
+
window.addEventListener(I18N_SDK_RESOURCES_LOADED_EVENT, handleSdkResourcesLoaded);
|
|
63
68
|
return ()=>{
|
|
64
|
-
window.removeEventListener(
|
|
69
|
+
window.removeEventListener(I18N_SDK_RESOURCES_LOADED_EVENT, handleSdkResourcesLoaded);
|
|
65
70
|
};
|
|
66
71
|
}, [
|
|
67
72
|
i18nInstance,
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import "node:module";
|
|
2
|
+
import { I18N_SDK_RESOURCES_LOADED_EVENT, createI18nSdkBackendId, setI18nSdkBackendId } from "./sdk-event.mjs";
|
|
2
3
|
class SdkBackend {
|
|
3
4
|
init(services, backendOptions, _i18nextOptions) {
|
|
4
5
|
this.services = services;
|
|
5
6
|
this.sdk = backendOptions?.sdk;
|
|
7
|
+
setI18nSdkBackendId(services.resourceStore || services.store, this.backendId);
|
|
6
8
|
if (!this.sdk) throw new Error('SdkBackend requires an SDK function to be provided in backend options');
|
|
7
9
|
}
|
|
8
10
|
read(language, namespace, callback) {
|
|
@@ -119,10 +121,11 @@ class SdkBackend {
|
|
|
119
121
|
}
|
|
120
122
|
triggerI18nextUpdate(language, namespace) {
|
|
121
123
|
if ("u" > typeof window) {
|
|
122
|
-
const event = new CustomEvent(
|
|
124
|
+
const event = new CustomEvent(I18N_SDK_RESOURCES_LOADED_EVENT, {
|
|
123
125
|
detail: {
|
|
124
126
|
language,
|
|
125
|
-
namespace
|
|
127
|
+
namespace,
|
|
128
|
+
backendId: this.backendId
|
|
126
129
|
}
|
|
127
130
|
});
|
|
128
131
|
window.dispatchEvent(event);
|
|
@@ -131,6 +134,7 @@ class SdkBackend {
|
|
|
131
134
|
constructor(_services, _options){
|
|
132
135
|
this.type = 'backend';
|
|
133
136
|
this.allResourcesCache = null;
|
|
137
|
+
this.backendId = createI18nSdkBackendId();
|
|
134
138
|
this.loadingPromises = new Map();
|
|
135
139
|
}
|
|
136
140
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
const I18N_SDK_RESOURCES_LOADED_EVENT = 'i18n-sdk-resources-loaded';
|
|
3
|
+
const I18N_SDK_BACKEND_ID_KEY = '__modern_i18n_sdk_backend_id__';
|
|
4
|
+
let sdkBackendInstanceCount = 0;
|
|
5
|
+
function createI18nSdkBackendId() {
|
|
6
|
+
sdkBackendInstanceCount += 1;
|
|
7
|
+
return `modern-i18n-sdk-backend-${sdkBackendInstanceCount}`;
|
|
8
|
+
}
|
|
9
|
+
function setI18nSdkBackendId(target, backendId) {
|
|
10
|
+
if (!target || 'object' != typeof target) return;
|
|
11
|
+
Object.defineProperty(target, I18N_SDK_BACKEND_ID_KEY, {
|
|
12
|
+
configurable: true,
|
|
13
|
+
enumerable: false,
|
|
14
|
+
value: backendId,
|
|
15
|
+
writable: true
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
function getI18nSdkBackendId(target) {
|
|
19
|
+
if (!target || 'object' != typeof target) return;
|
|
20
|
+
return target[I18N_SDK_BACKEND_ID_KEY];
|
|
21
|
+
}
|
|
22
|
+
export { I18N_SDK_RESOURCES_LOADED_EVENT, createI18nSdkBackendId, getI18nSdkBackendId, setI18nSdkBackendId };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "node:module";
|
|
2
|
-
import * as __rspack_external__modern_js_runtime_router_2dfd0c78 from "@modern-js/runtime/router";
|
|
3
|
-
import { __webpack_require__ } from "../rslib-runtime.mjs";
|
|
4
2
|
import { isBrowser } from "@modern-js/runtime";
|
|
5
3
|
import { getGlobalBasename } from "@modern-js/runtime/context";
|
|
4
|
+
import { __webpack_require__ } from "../rslib-runtime.mjs";
|
|
5
|
+
import * as __rspack_external__modern_js_runtime_router_2dfd0c78 from "@modern-js/runtime/router";
|
|
6
6
|
__webpack_require__.add({
|
|
7
7
|
"@modern-js/runtime/router?f1fa" (module) {
|
|
8
8
|
module.exports = __rspack_external__modern_js_runtime_router_2dfd0c78;
|
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
import "node:module";
|
|
2
|
-
import { __webpack_require__ } from "../rslib-runtime.mjs";
|
|
3
|
-
import { languageDetector } from "@modern-js/server-core/hono";
|
|
4
2
|
import { DEFAULT_I18NEXT_DETECTION_OPTIONS, mergeDetectionOptions } from "../runtime/i18n/detection/config.mjs";
|
|
5
3
|
import { getLocaleDetectionOptions } from "../shared/utils.mjs";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
__webpack_require__.d(hono_namespaceObject, {
|
|
9
|
-
languageDetector: ()=>languageDetector
|
|
10
|
-
});
|
|
11
|
-
const { languageDetector: server_languageDetector } = hono_namespaceObject;
|
|
4
|
+
import * as __rspack_external__modern_js_server_core_hono_a76ca254 from "@modern-js/server-core/hono";
|
|
5
|
+
const { languageDetector: languageDetector } = __rspack_external__modern_js_server_core_hono_a76ca254;
|
|
12
6
|
const convertToHonoLanguageDetectorOptions = (languages, fallbackLanguage, detectionOptions)=>{
|
|
13
7
|
const mergedDetection = detectionOptions ? mergeDetectionOptions(detectionOptions) : DEFAULT_I18NEXT_DETECTION_OPTIONS;
|
|
14
8
|
const order = (mergedDetection.order || []).filter((item)=>![
|
|
@@ -115,7 +109,7 @@ const i18nServerPlugin = (options)=>({
|
|
|
115
109
|
if (localePathRedirect) {
|
|
116
110
|
if (i18nextDetector) {
|
|
117
111
|
const detectorOptions = convertToHonoLanguageDetectorOptions(languages, fallbackLanguage, detection);
|
|
118
|
-
const detectorHandler =
|
|
112
|
+
const detectorHandler = languageDetector(detectorOptions);
|
|
119
113
|
middlewares.push({
|
|
120
114
|
name: 'i18n-language-detector',
|
|
121
115
|
path: urlPath,
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const I18N_SDK_RESOURCES_LOADED_EVENT = "i18n-sdk-resources-loaded";
|
|
2
|
+
export interface I18nSdkResourcesLoadedEventDetail {
|
|
3
|
+
language: string;
|
|
4
|
+
namespace: string;
|
|
5
|
+
backendId?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function createI18nSdkBackendId(): string;
|
|
8
|
+
export declare function setI18nSdkBackendId(target: unknown, backendId: string): void;
|
|
9
|
+
export declare function getI18nSdkBackendId(target: unknown): string | undefined;
|
|
File without changes
|
package/log/app.call.log
ADDED
|
File without changes
|
package/log/app.log
ADDED
|
File without changes
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
TRACE 2025-11-11 14:57:06,552 v1(7) call.js:0 10.91.112.88 - 021762844226351fe800000000000000cf9cee0d62d65ddb132e8 default - - psm=- spanId=311573918650071 parentSpanId=0 costInUs=177889 remoteMethod=byted_service_fetch_unknown_to_method remoteCluster=default remoteService=galaxy-api.bytedance.net remoteAddress=- statusCode=200 startAt=1762844226373111 env=prod stress_tag=- to=galaxy-api.bytedance.net to_cluster=default to_idc=- retry=0 http.method=GET http.url=/auth/api/v1/jwt http.host=galaxy-api.bytedance.net http.status_code=200 http.param= mesh=0 to_env=prod remote_protocol=https sampled=true localMethod=byted_service_fetch_unknown_to_method type=rpcCall
|
|
2
|
+
TRACE 2025-11-11 14:57:40,453 v1(7) call.js:0 10.91.112.88 - 021762844260256fe800000000000000cf9cee0d62d65dd47eac7 default - - psm=- spanId=911184692546025 parentSpanId=0 costInUs=175395 remoteMethod=byted_service_fetch_unknown_to_method remoteCluster=default remoteService=galaxy-api.bytedance.net remoteAddress=- statusCode=200 startAt=1762844260276605 env=prod stress_tag=- to=galaxy-api.bytedance.net to_cluster=default to_idc=- retry=0 http.method=GET http.url=/auth/api/v1/jwt http.host=galaxy-api.bytedance.net http.status_code=200 http.param= mesh=0 to_env=prod remote_protocol=https sampled=true localMethod=byted_service_fetch_unknown_to_method type=rpcCall
|
|
3
|
+
TRACE 2025-11-11 14:58:01,872 v1(7) call.js:0 10.91.112.88 - 021762844281704fe800000000000000cf9cee0d62d65ddc5dbdc default - - psm=- spanId=1584335362867424 parentSpanId=0 costInUs=146941 remoteMethod=byted_service_fetch_unknown_to_method remoteCluster=default remoteService=galaxy-api.bytedance.net remoteAddress=- statusCode=200 startAt=1762844281724059 env=prod stress_tag=- to=galaxy-api.bytedance.net to_cluster=default to_idc=- retry=0 http.method=GET http.url=/auth/api/v1/jwt http.host=galaxy-api.bytedance.net http.status_code=200 http.param= mesh=0 to_env=prod remote_protocol=https sampled=true localMethod=byted_service_fetch_unknown_to_method type=rpcCall
|
package/package.json
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"modern",
|
|
16
16
|
"modern.js"
|
|
17
17
|
],
|
|
18
|
-
"version": "3.1.
|
|
18
|
+
"version": "3.1.3-alpha.0",
|
|
19
19
|
"engines": {
|
|
20
20
|
"node": ">=20"
|
|
21
21
|
},
|
|
@@ -82,22 +82,22 @@
|
|
|
82
82
|
"@swc/helpers": "^0.5.17",
|
|
83
83
|
"i18next-browser-languagedetector": "^8.2.1",
|
|
84
84
|
"i18next-chained-backend": "^4.6.3",
|
|
85
|
-
"i18next-fs-backend": "^2.6.
|
|
85
|
+
"i18next-fs-backend": "^2.6.3",
|
|
86
86
|
"i18next-http-backend": "^3.0.2",
|
|
87
87
|
"i18next-http-middleware": "^3.9.2",
|
|
88
|
-
"@modern-js/plugin": "3.1.
|
|
89
|
-
"@modern-js/runtime-utils": "3.1.
|
|
90
|
-
"@modern-js/server-core": "3.1.
|
|
91
|
-
"@modern-js/server-runtime": "3.1.
|
|
92
|
-
"@modern-js/types": "3.1.
|
|
93
|
-
"@modern-js/utils": "3.1.
|
|
88
|
+
"@modern-js/plugin": "3.1.2",
|
|
89
|
+
"@modern-js/runtime-utils": "3.1.2",
|
|
90
|
+
"@modern-js/server-core": "3.1.2",
|
|
91
|
+
"@modern-js/server-runtime": "3.1.2",
|
|
92
|
+
"@modern-js/types": "3.1.2",
|
|
93
|
+
"@modern-js/utils": "3.1.2"
|
|
94
94
|
},
|
|
95
95
|
"peerDependencies": {
|
|
96
96
|
"react": ">=17.0.2",
|
|
97
97
|
"react-dom": ">=17.0.2",
|
|
98
98
|
"i18next": ">=25.7.4",
|
|
99
99
|
"react-i18next": ">=15.7.4",
|
|
100
|
-
"@modern-js/runtime": "^3.1.
|
|
100
|
+
"@modern-js/runtime": "^3.1.2"
|
|
101
101
|
},
|
|
102
102
|
"peerDependenciesMeta": {
|
|
103
103
|
"i18next": {
|
|
@@ -108,20 +108,17 @@
|
|
|
108
108
|
}
|
|
109
109
|
},
|
|
110
110
|
"devDependencies": {
|
|
111
|
-
"@rslib/core": "0.20.
|
|
112
|
-
"@types/jest": "^29.5.14",
|
|
111
|
+
"@rslib/core": "0.20.3",
|
|
113
112
|
"@types/node": "^20",
|
|
114
113
|
"i18next": "25.7.4",
|
|
115
|
-
"jest": "^29.7.0",
|
|
116
114
|
"react": "^19.2.4",
|
|
117
115
|
"react-dom": "^19.2.4",
|
|
118
116
|
"react-i18next": "15.7.4",
|
|
119
|
-
"ts-jest": "^29.4.6",
|
|
120
117
|
"ts-node": "^10.9.2",
|
|
121
118
|
"typescript": "^5",
|
|
122
|
-
"@modern-js/app-tools": "3.1.
|
|
123
|
-
"@modern-js/
|
|
124
|
-
"@modern-js/
|
|
119
|
+
"@modern-js/app-tools": "3.1.2",
|
|
120
|
+
"@modern-js/runtime": "3.1.2",
|
|
121
|
+
"@modern-js/rslib": "2.68.10"
|
|
125
122
|
},
|
|
126
123
|
"sideEffects": false,
|
|
127
124
|
"publishConfig": {
|
package/src/runtime/hooks.ts
CHANGED
|
@@ -3,6 +3,11 @@ import type { TRuntimeContext } from '@modern-js/runtime';
|
|
|
3
3
|
import type React from 'react';
|
|
4
4
|
import { useEffect, useRef } from 'react';
|
|
5
5
|
import type { I18nInstance } from './i18n';
|
|
6
|
+
import {
|
|
7
|
+
I18N_SDK_RESOURCES_LOADED_EVENT,
|
|
8
|
+
type I18nSdkResourcesLoadedEventDetail,
|
|
9
|
+
getI18nSdkBackendId,
|
|
10
|
+
} from './i18n/backend/sdk-event';
|
|
6
11
|
import { cacheUserLanguage } from './i18n/detection';
|
|
7
12
|
import {
|
|
8
13
|
buildLocalizedUrl,
|
|
@@ -59,12 +64,31 @@ export function useSdkResourcesLoader(
|
|
|
59
64
|
return;
|
|
60
65
|
}
|
|
61
66
|
|
|
67
|
+
const backendId =
|
|
68
|
+
getI18nSdkBackendId(i18nInstance.services?.resourceStore) ||
|
|
69
|
+
getI18nSdkBackendId(i18nInstance.services?.store) ||
|
|
70
|
+
getI18nSdkBackendId(i18nInstance.store);
|
|
71
|
+
|
|
72
|
+
if (!backendId) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
62
76
|
const handleSdkResourcesLoaded = (event: Event) => {
|
|
63
|
-
const customEvent =
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
77
|
+
const customEvent =
|
|
78
|
+
event as CustomEvent<I18nSdkResourcesLoadedEventDetail>;
|
|
79
|
+
const {
|
|
80
|
+
language,
|
|
81
|
+
namespace,
|
|
82
|
+
backendId: eventBackendId,
|
|
83
|
+
} = customEvent.detail || {};
|
|
84
|
+
|
|
85
|
+
if (!language || !namespace) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (eventBackendId && eventBackendId !== backendId) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
68
92
|
|
|
69
93
|
const triggerUpdate = (retryCount = 0) => {
|
|
70
94
|
const store = (i18nInstance as any).store;
|
|
@@ -110,13 +134,13 @@ export function useSdkResourcesLoader(
|
|
|
110
134
|
};
|
|
111
135
|
|
|
112
136
|
window.addEventListener(
|
|
113
|
-
|
|
137
|
+
I18N_SDK_RESOURCES_LOADED_EVENT,
|
|
114
138
|
handleSdkResourcesLoaded,
|
|
115
139
|
);
|
|
116
140
|
|
|
117
141
|
return () => {
|
|
118
142
|
window.removeEventListener(
|
|
119
|
-
|
|
143
|
+
I18N_SDK_RESOURCES_LOADED_EVENT,
|
|
120
144
|
handleSdkResourcesLoaded,
|
|
121
145
|
);
|
|
122
146
|
};
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { I18nSdkLoadOptions, I18nSdkLoader } from '../../../shared/type';
|
|
2
2
|
import type { Resources } from '../instance';
|
|
3
|
+
import {
|
|
4
|
+
I18N_SDK_RESOURCES_LOADED_EVENT,
|
|
5
|
+
createI18nSdkBackendId,
|
|
6
|
+
setI18nSdkBackendId,
|
|
7
|
+
} from './sdk-event';
|
|
3
8
|
|
|
4
9
|
interface BackendOptions {
|
|
5
10
|
sdk?: I18nSdkLoader;
|
|
@@ -29,6 +34,7 @@ export class SdkBackend {
|
|
|
29
34
|
type = 'backend' as const;
|
|
30
35
|
sdk?: I18nSdkLoader;
|
|
31
36
|
private allResourcesCache: Resources | null = null;
|
|
37
|
+
private backendId = createI18nSdkBackendId();
|
|
32
38
|
private loadingPromises = new Map<string, Promise<unknown>>();
|
|
33
39
|
private services?: I18nextServices;
|
|
34
40
|
|
|
@@ -45,6 +51,10 @@ export class SdkBackend {
|
|
|
45
51
|
this.services = services;
|
|
46
52
|
void _i18nextOptions;
|
|
47
53
|
this.sdk = backendOptions?.sdk;
|
|
54
|
+
setI18nSdkBackendId(
|
|
55
|
+
services.resourceStore || services.store,
|
|
56
|
+
this.backendId,
|
|
57
|
+
);
|
|
48
58
|
if (!this.sdk) {
|
|
49
59
|
throw new Error(
|
|
50
60
|
'SdkBackend requires an SDK function to be provided in backend options',
|
|
@@ -283,8 +293,12 @@ export class SdkBackend {
|
|
|
283
293
|
|
|
284
294
|
private triggerI18nextUpdate(language: string, namespace: string): void {
|
|
285
295
|
if (typeof window !== 'undefined') {
|
|
286
|
-
const event = new CustomEvent(
|
|
287
|
-
detail: {
|
|
296
|
+
const event = new CustomEvent(I18N_SDK_RESOURCES_LOADED_EVENT, {
|
|
297
|
+
detail: {
|
|
298
|
+
language,
|
|
299
|
+
namespace,
|
|
300
|
+
backendId: this.backendId,
|
|
301
|
+
},
|
|
288
302
|
});
|
|
289
303
|
window.dispatchEvent(event);
|
|
290
304
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export const I18N_SDK_RESOURCES_LOADED_EVENT = 'i18n-sdk-resources-loaded';
|
|
2
|
+
|
|
3
|
+
const I18N_SDK_BACKEND_ID_KEY = '__modern_i18n_sdk_backend_id__';
|
|
4
|
+
|
|
5
|
+
let sdkBackendInstanceCount = 0;
|
|
6
|
+
|
|
7
|
+
export interface I18nSdkResourcesLoadedEventDetail {
|
|
8
|
+
language: string;
|
|
9
|
+
namespace: string;
|
|
10
|
+
backendId?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function createI18nSdkBackendId(): string {
|
|
14
|
+
sdkBackendInstanceCount += 1;
|
|
15
|
+
return `modern-i18n-sdk-backend-${sdkBackendInstanceCount}`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function setI18nSdkBackendId(target: unknown, backendId: string): void {
|
|
19
|
+
if (!target || typeof target !== 'object') {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
Object.defineProperty(target, I18N_SDK_BACKEND_ID_KEY, {
|
|
24
|
+
configurable: true,
|
|
25
|
+
enumerable: false,
|
|
26
|
+
value: backendId,
|
|
27
|
+
writable: true,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function getI18nSdkBackendId(target: unknown): string | undefined {
|
|
32
|
+
if (!target || typeof target !== 'object') {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return (target as Record<string, unknown>)[I18N_SDK_BACKEND_ID_KEY] as
|
|
37
|
+
| string
|
|
38
|
+
| undefined;
|
|
39
|
+
}
|