@modern-js/plugin-i18n 3.1.2 → 3.1.3
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/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-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/types/runtime/i18n/backend/sdk-backend.d.ts +1 -0
- package/dist/types/runtime/i18n/backend/sdk-event.d.ts +9 -0
- package/package.json +12 -15
- 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
|
@@ -31,6 +31,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
31
31
|
});
|
|
32
32
|
const runtime_namespaceObject = require("@modern-js/runtime");
|
|
33
33
|
const external_react_namespaceObject = require("react");
|
|
34
|
+
const sdk_event_js_namespaceObject = require("./i18n/backend/sdk-event.js");
|
|
34
35
|
const index_js_namespaceObject = require("./i18n/detection/index.js");
|
|
35
36
|
const external_utils_js_namespaceObject = require("./utils.js");
|
|
36
37
|
function createMinimalI18nInstance(language) {
|
|
@@ -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
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isBrowser } from "@modern-js/runtime";
|
|
2
2
|
import { useEffect, useRef } from "react";
|
|
3
|
+
import { I18N_SDK_RESOURCES_LOADED_EVENT, getI18nSdkBackendId } from "./i18n/backend/sdk-event.mjs";
|
|
3
4
|
import { cacheUserLanguage } from "./i18n/detection/index.mjs";
|
|
4
5
|
import { buildLocalizedUrl, detectLanguageFromPath, getEntryPath, getPathname, shouldIgnoreRedirect, useRouterHooks } from "./utils.mjs";
|
|
5
6
|
function createMinimalI18nInstance(language) {
|
|
@@ -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,6 +1,7 @@
|
|
|
1
1
|
import "node:module";
|
|
2
2
|
import { isBrowser } from "@modern-js/runtime";
|
|
3
3
|
import { useEffect, useRef } from "react";
|
|
4
|
+
import { I18N_SDK_RESOURCES_LOADED_EVENT, getI18nSdkBackendId } from "./i18n/backend/sdk-event.mjs";
|
|
4
5
|
import { cacheUserLanguage } from "./i18n/detection/index.mjs";
|
|
5
6
|
import { buildLocalizedUrl, detectLanguageFromPath, getEntryPath, getPathname, shouldIgnoreRedirect, useRouterHooks } from "./utils.mjs";
|
|
6
7
|
function createMinimalI18nInstance(language) {
|
|
@@ -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 };
|
|
@@ -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;
|
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",
|
|
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/
|
|
89
|
-
"@modern-js/
|
|
90
|
-
"@modern-js/server-
|
|
91
|
-
"@modern-js/
|
|
92
|
-
"@modern-js/
|
|
93
|
-
"@modern-js/
|
|
88
|
+
"@modern-js/plugin": "3.1.3",
|
|
89
|
+
"@modern-js/runtime-utils": "3.1.3",
|
|
90
|
+
"@modern-js/server-core": "3.1.3",
|
|
91
|
+
"@modern-js/types": "3.1.3",
|
|
92
|
+
"@modern-js/server-runtime": "3.1.3",
|
|
93
|
+
"@modern-js/utils": "3.1.3"
|
|
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.3"
|
|
101
101
|
},
|
|
102
102
|
"peerDependenciesMeta": {
|
|
103
103
|
"i18next": {
|
|
@@ -108,20 +108,17 @@
|
|
|
108
108
|
}
|
|
109
109
|
},
|
|
110
110
|
"devDependencies": {
|
|
111
|
-
"@rslib/core": "0.
|
|
112
|
-
"@types/jest": "^29.5.14",
|
|
111
|
+
"@rslib/core": "0.21.0",
|
|
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.
|
|
119
|
+
"@modern-js/app-tools": "3.1.3",
|
|
123
120
|
"@modern-js/rslib": "2.68.10",
|
|
124
|
-
"@modern-js/runtime": "3.1.
|
|
121
|
+
"@modern-js/runtime": "3.1.3"
|
|
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
|
+
}
|