@bleedingdev/modern-js-plugin-i18n 3.4.0-ultramodern.0 → 3.4.0-ultramodern.10
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/cli/index.js +2 -1
- package/dist/cjs/runtime/context.js +8 -0
- package/dist/cjs/runtime/core.js +217 -0
- package/dist/cjs/runtime/i18n/backend/middleware.node.js +22 -4
- package/dist/cjs/runtime/index.js +44 -173
- package/dist/cjs/runtime/no-react-i18next.js +76 -0
- package/dist/esm/cli/index.mjs +2 -1
- package/dist/esm/runtime/context.mjs +8 -0
- package/dist/esm/runtime/core.mjs +152 -0
- package/dist/esm/runtime/i18n/backend/middleware.node.mjs +19 -4
- package/dist/esm/runtime/index.mjs +5 -140
- package/dist/esm/runtime/no-react-i18next.mjs +6 -0
- package/dist/esm-node/cli/index.mjs +2 -1
- package/dist/esm-node/runtime/context.mjs +8 -0
- package/dist/esm-node/runtime/core.mjs +153 -0
- package/dist/esm-node/runtime/i18n/backend/middleware.node.mjs +19 -4
- package/dist/esm-node/runtime/index.mjs +5 -140
- package/dist/esm-node/runtime/no-react-i18next.mjs +7 -0
- package/dist/types/runtime/context.d.ts +1 -0
- package/dist/types/runtime/core.d.ts +30 -0
- package/dist/types/runtime/i18n/backend/middleware.node.d.ts +4 -1
- package/dist/types/runtime/index.d.ts +2 -24
- package/dist/types/runtime/no-react-i18next.d.ts +3 -0
- package/package.json +21 -11
- package/rstest.config.mts +1 -0
- package/src/cli/index.ts +6 -1
- package/src/runtime/context.tsx +13 -0
- package/src/runtime/core.tsx +360 -0
- package/src/runtime/i18n/backend/middleware.node.ts +31 -1
- package/src/runtime/index.tsx +4 -316
- package/src/runtime/no-react-i18next.tsx +7 -0
- package/tests/i18nUtils.test.ts +34 -0
- package/tests/localisedUrls.test.ts +35 -0
- package/tests/reactI18nextRuntimeBoundary.test.ts +36 -0
- package/tests/routerAdapter.test.tsx +58 -1
|
@@ -1,143 +1,8 @@
|
|
|
1
1
|
import "node:module";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import { useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
7
|
-
import { ModernI18nProvider, useModernI18n } from "./context.mjs";
|
|
8
|
-
import { createContextValue, useClientSideRedirect, useLanguageSync, useSdkResourcesLoader } from "./hooks.mjs";
|
|
9
|
-
import { getI18nInstance } from "./i18n/index.mjs";
|
|
10
|
-
import { mergeBackendOptions } from "./i18n/backend/index.mjs";
|
|
11
|
-
import { useI18nextBackend } from "./i18n/backend/middleware.mjs";
|
|
12
|
-
import { detectLanguageWithPriority, exportServerLngToWindow, mergeDetectionOptions } from "./i18n/detection/index.mjs";
|
|
13
|
-
import { useI18nextLanguageDetector } from "./i18n/detection/middleware.mjs";
|
|
14
|
-
import { getI18nextInstanceForProvider } from "./i18n/instance.mjs";
|
|
15
|
-
import { changeI18nLanguage, ensureLanguageMatch, initializeI18nInstance, setupClonedInstance } from "./i18n/utils.mjs";
|
|
16
|
-
import { buildLocalizedUrl, getPathname, splitUrlTarget } from "./utils.mjs";
|
|
17
|
-
import "./types.mjs";
|
|
18
|
-
const i18nPlugin = (options)=>({
|
|
19
|
-
name: '@modern-js/plugin-i18n',
|
|
20
|
-
setup: (api)=>{
|
|
21
|
-
const { entryName, i18nInstance: userI18nInstance, initOptions, localeDetection, backend, htmlLangAttr = false, reactI18next = true } = options;
|
|
22
|
-
const { localePathRedirect = false, i18nextDetector = true, languages = [], fallbackLanguage = 'en', detection, ignoreRedirectRoutes, localisedUrls } = localeDetection || {};
|
|
23
|
-
const { enabled: backendEnabled = false } = backend || {};
|
|
24
|
-
let latestI18nInstance;
|
|
25
|
-
let I18nextProvider;
|
|
26
|
-
const loadReactI18nextIntegration = async ()=>{
|
|
27
|
-
if (!reactI18next) return null;
|
|
28
|
-
const { getReactI18nextIntegration } = await import("./i18n/react-i18next.mjs");
|
|
29
|
-
return getReactI18nextIntegration();
|
|
30
|
-
};
|
|
31
|
-
api.onBeforeRender(async (context)=>{
|
|
32
|
-
let i18nInstance = await getI18nInstance(userI18nInstance);
|
|
33
|
-
const { i18n: otherConfig } = api.getRuntimeConfig();
|
|
34
|
-
const { initOptions: otherInitOptions } = otherConfig || {};
|
|
35
|
-
const userInitOptions = merge(otherInitOptions || {}, initOptions || {});
|
|
36
|
-
const reactI18nextIntegration = await loadReactI18nextIntegration();
|
|
37
|
-
I18nextProvider = reactI18nextIntegration?.I18nextProvider ?? null;
|
|
38
|
-
if (reactI18nextIntegration?.initReactI18next) i18nInstance.use(reactI18nextIntegration.initReactI18next);
|
|
39
|
-
const pathname = getPathname(context);
|
|
40
|
-
if (i18nextDetector) useI18nextLanguageDetector(i18nInstance);
|
|
41
|
-
const mergedDetection = mergeDetectionOptions(i18nextDetector, detection, localePathRedirect, userInitOptions);
|
|
42
|
-
const mergedBackend = mergeBackendOptions(backend, userInitOptions);
|
|
43
|
-
const hasSdkConfig = 'function' == typeof userInitOptions?.backend?.sdk || mergedBackend?.sdk && 'function' == typeof mergedBackend.sdk;
|
|
44
|
-
if (mergedBackend && (backendEnabled || hasSdkConfig)) useI18nextBackend(i18nInstance, mergedBackend);
|
|
45
|
-
const { finalLanguage } = await detectLanguageWithPriority(i18nInstance, {
|
|
46
|
-
languages,
|
|
47
|
-
fallbackLanguage,
|
|
48
|
-
localePathRedirect,
|
|
49
|
-
i18nextDetector,
|
|
50
|
-
detection,
|
|
51
|
-
userInitOptions,
|
|
52
|
-
mergedBackend,
|
|
53
|
-
pathname,
|
|
54
|
-
ssrContext: context.ssrContext
|
|
55
|
-
});
|
|
56
|
-
await initializeI18nInstance(i18nInstance, finalLanguage, fallbackLanguage, languages, mergedDetection, mergedBackend, userInitOptions);
|
|
57
|
-
if (!isBrowser() && i18nInstance.cloneInstance) {
|
|
58
|
-
i18nInstance = i18nInstance.cloneInstance();
|
|
59
|
-
await setupClonedInstance(i18nInstance, finalLanguage, fallbackLanguage, languages, backendEnabled, backend, i18nextDetector, detection, localePathRedirect, userInitOptions);
|
|
60
|
-
}
|
|
61
|
-
if (localePathRedirect) await ensureLanguageMatch(i18nInstance, finalLanguage);
|
|
62
|
-
if (!isBrowser()) exportServerLngToWindow(context, finalLanguage);
|
|
63
|
-
context.i18nInstance = i18nInstance;
|
|
64
|
-
latestI18nInstance = i18nInstance;
|
|
65
|
-
context.changeLanguage = async (newLang)=>{
|
|
66
|
-
await changeI18nLanguage(i18nInstance, newLang, {
|
|
67
|
-
detectionOptions: mergedDetection
|
|
68
|
-
});
|
|
69
|
-
};
|
|
70
|
-
});
|
|
71
|
-
api.wrapRoot((App)=>(props)=>{
|
|
72
|
-
const runtimeContext = useContext(RuntimeContext);
|
|
73
|
-
const i18nInstance = runtimeContext.i18nInstance || latestI18nInstance;
|
|
74
|
-
const initialLang = useMemo(()=>i18nInstance?.language || (localeDetection?.fallbackLanguage ?? 'en'), [
|
|
75
|
-
i18nInstance?.language,
|
|
76
|
-
localeDetection?.fallbackLanguage
|
|
77
|
-
]);
|
|
78
|
-
const [lang, setLang] = useState(initialLang);
|
|
79
|
-
const [forceUpdate, setForceUpdate] = useState(0);
|
|
80
|
-
const prevLangRef = useRef(lang);
|
|
81
|
-
const runtimeContextRef = useRef(runtimeContext);
|
|
82
|
-
runtimeContextRef.current = runtimeContext;
|
|
83
|
-
useEffect(()=>{
|
|
84
|
-
if (i18nInstance?.language) {
|
|
85
|
-
const translator = i18nInstance.translator;
|
|
86
|
-
if (translator) translator.language = i18nInstance.language;
|
|
87
|
-
}
|
|
88
|
-
}, [
|
|
89
|
-
i18nInstance?.language
|
|
90
|
-
]);
|
|
91
|
-
useEffect(()=>{
|
|
92
|
-
prevLangRef.current = lang;
|
|
93
|
-
}, [
|
|
94
|
-
lang
|
|
95
|
-
]);
|
|
96
|
-
useSdkResourcesLoader(i18nInstance, setForceUpdate);
|
|
97
|
-
useLanguageSync(i18nInstance, localePathRedirect, languages, runtimeContextRef, prevLangRef, setLang);
|
|
98
|
-
useClientSideRedirect(i18nInstance, localePathRedirect, languages, fallbackLanguage, ignoreRedirectRoutes, localisedUrls);
|
|
99
|
-
const contextValue = useMemo(()=>createContextValue(lang, i18nInstance, entryName, languages, localePathRedirect, ignoreRedirectRoutes, localisedUrls, setLang), [
|
|
100
|
-
lang,
|
|
101
|
-
i18nInstance,
|
|
102
|
-
entryName,
|
|
103
|
-
languages,
|
|
104
|
-
localePathRedirect,
|
|
105
|
-
ignoreRedirectRoutes,
|
|
106
|
-
localisedUrls,
|
|
107
|
-
forceUpdate
|
|
108
|
-
]);
|
|
109
|
-
const children = props.children;
|
|
110
|
-
const appContent = /*#__PURE__*/ jsxs(Fragment, {
|
|
111
|
-
children: [
|
|
112
|
-
Boolean(htmlLangAttr) && /*#__PURE__*/ jsx(Helmet, {
|
|
113
|
-
htmlAttributes: {
|
|
114
|
-
lang
|
|
115
|
-
}
|
|
116
|
-
}),
|
|
117
|
-
/*#__PURE__*/ jsx(ModernI18nProvider, {
|
|
118
|
-
value: contextValue,
|
|
119
|
-
children: App ? /*#__PURE__*/ jsx(App, {
|
|
120
|
-
...props,
|
|
121
|
-
children: children
|
|
122
|
-
}) : children
|
|
123
|
-
})
|
|
124
|
-
]
|
|
125
|
-
});
|
|
126
|
-
if (!i18nInstance) return appContent;
|
|
127
|
-
if (I18nextProvider) {
|
|
128
|
-
const i18nextInstanceForProvider = getI18nextInstanceForProvider(i18nInstance);
|
|
129
|
-
return /*#__PURE__*/ jsx(I18nextProvider, {
|
|
130
|
-
i18n: i18nextInstanceForProvider,
|
|
131
|
-
children: appContent
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
return appContent;
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
});
|
|
2
|
+
import { createI18nPlugin } from "./core.mjs";
|
|
3
|
+
import { getReactI18nextIntegration } from "./i18n/react-i18next.mjs";
|
|
4
|
+
export * from "./core.mjs";
|
|
5
|
+
const i18nPlugin = createI18nPlugin(getReactI18nextIntegration);
|
|
138
6
|
const runtime = i18nPlugin;
|
|
139
|
-
export { I18nLink } from "./I18nLink.mjs";
|
|
140
|
-
export { Link } from "./Link.mjs";
|
|
141
|
-
export { canonicalPath, localizePath, useLocalizedLocation, useLocalizedPaths } from "./localizedPaths.mjs";
|
|
142
7
|
export default runtime;
|
|
143
|
-
export {
|
|
8
|
+
export { i18nPlugin };
|
|
@@ -19,6 +19,7 @@ export declare const ModernI18nProvider: FC<ModernI18nProviderProps>;
|
|
|
19
19
|
export interface UseModernI18nReturn {
|
|
20
20
|
language: string;
|
|
21
21
|
changeLanguage: (newLang: string) => Promise<void>;
|
|
22
|
+
t: (key: string | string[], ...args: any[]) => string;
|
|
22
23
|
i18nInstance: I18nInstance;
|
|
23
24
|
supportedLanguages: string[];
|
|
24
25
|
localisedUrls?: LocalisedUrlsOption;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type RuntimePlugin } from '@modern-js/runtime';
|
|
2
|
+
import type React from 'react';
|
|
3
|
+
import type { BaseBackendOptions, BaseLocaleDetectionOptions } from '../shared/type';
|
|
4
|
+
import type { I18nInitOptions, I18nInstance } from './i18n';
|
|
5
|
+
import './types';
|
|
6
|
+
export type { I18nSdkLoader, I18nSdkLoadOptions } from '../shared/type';
|
|
7
|
+
export type { Resources } from './i18n/instance';
|
|
8
|
+
export interface I18nPluginOptions {
|
|
9
|
+
entryName?: string;
|
|
10
|
+
localeDetection?: BaseLocaleDetectionOptions;
|
|
11
|
+
backend?: BaseBackendOptions;
|
|
12
|
+
i18nInstance?: I18nInstance;
|
|
13
|
+
changeLanguage?: (lang: string) => void;
|
|
14
|
+
initOptions?: I18nInitOptions;
|
|
15
|
+
htmlLangAttr?: boolean;
|
|
16
|
+
reactI18next?: boolean;
|
|
17
|
+
[key: string]: any;
|
|
18
|
+
}
|
|
19
|
+
export interface ReactI18nextIntegration {
|
|
20
|
+
I18nextProvider: React.ComponentType<any> | null;
|
|
21
|
+
initReactI18next: any | null;
|
|
22
|
+
}
|
|
23
|
+
export type LoadReactI18nextIntegration = () => Promise<ReactI18nextIntegration | null>;
|
|
24
|
+
export declare const createI18nPlugin: (loadReactI18nextIntegration?: LoadReactI18nextIntegration) => ((options: I18nPluginOptions) => RuntimePlugin);
|
|
25
|
+
export type { AllowedLinkTarget, CanonicalRoutePath, UltramodernCanonicalRoutes, } from './canonicalRoutes';
|
|
26
|
+
export { useModernI18n } from './context';
|
|
27
|
+
export { I18nLink, type I18nLinkProps } from './I18nLink';
|
|
28
|
+
export { Link, type LinkActiveOptions, type LinkBaseProps, type LinkParams, type LinkProps, } from './Link';
|
|
29
|
+
export { canonicalPath, type LocalizedPathsConfig, localizePath, type UseLocalizedLocationReturn, type UseLocalizedPathsReturn, useLocalizedLocation, useLocalizedPaths, } from './localizedPaths';
|
|
30
|
+
export { buildLocalizedUrl, splitUrlTarget } from './utils';
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import Backend from 'i18next-fs-backend/cjs';
|
|
2
1
|
import type { ExtendedBackendOptions } from '../../../shared/type';
|
|
3
2
|
import type { I18nInstance } from '../instance';
|
|
3
|
+
type BackendConstructor = new (...args: any[]) => any;
|
|
4
|
+
export declare const resolveFsBackendConstructor: (backendModule: unknown) => BackendConstructor;
|
|
5
|
+
declare const Backend: BackendConstructor;
|
|
4
6
|
/**
|
|
5
7
|
* Wrapper for FS backend to add a no-op save method
|
|
6
8
|
* This is required for i18next-chained-backend to trigger refresh logic
|
|
@@ -11,3 +13,4 @@ export declare class FsBackendWithSave extends Backend {
|
|
|
11
13
|
}
|
|
12
14
|
export declare const HttpBackendWithSave: typeof FsBackendWithSave;
|
|
13
15
|
export declare const useI18nextBackend: (i18nInstance: I18nInstance, backend?: ExtendedBackendOptions) => void;
|
|
16
|
+
export {};
|
|
@@ -1,25 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import type { I18nInitOptions, I18nInstance } from './i18n';
|
|
4
|
-
import './types';
|
|
5
|
-
export type { I18nSdkLoader, I18nSdkLoadOptions } from '../shared/type';
|
|
6
|
-
export type { Resources } from './i18n/instance';
|
|
7
|
-
export interface I18nPluginOptions {
|
|
8
|
-
entryName?: string;
|
|
9
|
-
localeDetection?: BaseLocaleDetectionOptions;
|
|
10
|
-
backend?: BaseBackendOptions;
|
|
11
|
-
i18nInstance?: I18nInstance;
|
|
12
|
-
changeLanguage?: (lang: string) => void;
|
|
13
|
-
initOptions?: I18nInitOptions;
|
|
14
|
-
htmlLangAttr?: boolean;
|
|
15
|
-
reactI18next?: boolean;
|
|
16
|
-
[key: string]: any;
|
|
17
|
-
}
|
|
18
|
-
export declare const i18nPlugin: (options: I18nPluginOptions) => RuntimePlugin;
|
|
19
|
-
export type { AllowedLinkTarget, CanonicalRoutePath, UltramodernCanonicalRoutes, } from './canonicalRoutes';
|
|
20
|
-
export { useModernI18n } from './context';
|
|
21
|
-
export { I18nLink, type I18nLinkProps } from './I18nLink';
|
|
22
|
-
export { Link, type LinkActiveOptions, type LinkBaseProps, type LinkParams, type LinkProps, } from './Link';
|
|
23
|
-
export { canonicalPath, type LocalizedPathsConfig, localizePath, type UseLocalizedLocationReturn, type UseLocalizedPathsReturn, useLocalizedLocation, useLocalizedPaths, } from './localizedPaths';
|
|
24
|
-
export { buildLocalizedUrl, splitUrlTarget } from './utils';
|
|
1
|
+
export * from './core';
|
|
2
|
+
export declare const i18nPlugin: (options: import("./core").I18nPluginOptions) => import("@modern-js/runtime").RuntimePlugin;
|
|
25
3
|
export default i18nPlugin;
|
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"modern",
|
|
18
18
|
"modern.js"
|
|
19
19
|
],
|
|
20
|
-
"version": "3.4.0-ultramodern.
|
|
20
|
+
"version": "3.4.0-ultramodern.10",
|
|
21
21
|
"engines": {
|
|
22
22
|
"node": ">=20"
|
|
23
23
|
},
|
|
@@ -48,6 +48,13 @@
|
|
|
48
48
|
},
|
|
49
49
|
"default": "./dist/esm/runtime/index.mjs"
|
|
50
50
|
},
|
|
51
|
+
"./runtime/no-react-i18next": {
|
|
52
|
+
"types": "./dist/types/runtime/no-react-i18next.d.ts",
|
|
53
|
+
"node": {
|
|
54
|
+
"module": "./dist/esm/runtime/no-react-i18next.mjs"
|
|
55
|
+
},
|
|
56
|
+
"default": "./dist/esm/runtime/no-react-i18next.mjs"
|
|
57
|
+
},
|
|
51
58
|
"./server": {
|
|
52
59
|
"types": "./dist/types/server/index.d.ts",
|
|
53
60
|
"node": {
|
|
@@ -72,6 +79,9 @@
|
|
|
72
79
|
"runtime": [
|
|
73
80
|
"./dist/types/runtime/index.d.ts"
|
|
74
81
|
],
|
|
82
|
+
"runtime/no-react-i18next": [
|
|
83
|
+
"./dist/types/runtime/no-react-i18next.d.ts"
|
|
84
|
+
],
|
|
75
85
|
"server": [
|
|
76
86
|
"./dist/types/server/index.d.ts"
|
|
77
87
|
],
|
|
@@ -87,15 +97,15 @@
|
|
|
87
97
|
"i18next-fs-backend": "^2.6.6",
|
|
88
98
|
"i18next-http-backend": "^4.0.0",
|
|
89
99
|
"i18next-http-middleware": "^3.9.7",
|
|
90
|
-
"@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.4.0-ultramodern.
|
|
91
|
-
"@modern-js/
|
|
92
|
-
"@modern-js/
|
|
93
|
-
"@modern-js/
|
|
94
|
-
"@modern-js/
|
|
95
|
-
"@modern-js/
|
|
100
|
+
"@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.4.0-ultramodern.10",
|
|
101
|
+
"@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.4.0-ultramodern.10",
|
|
102
|
+
"@modern-js/server-runtime": "npm:@bleedingdev/modern-js-server-runtime@3.4.0-ultramodern.10",
|
|
103
|
+
"@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.4.0-ultramodern.10",
|
|
104
|
+
"@modern-js/types": "npm:@bleedingdev/modern-js-types@3.4.0-ultramodern.10",
|
|
105
|
+
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.4.0-ultramodern.10"
|
|
96
106
|
},
|
|
97
107
|
"peerDependencies": {
|
|
98
|
-
"@modern-js/runtime": "3.4.0-ultramodern.
|
|
108
|
+
"@modern-js/runtime": "3.4.0-ultramodern.10",
|
|
99
109
|
"i18next": ">=26.3.1",
|
|
100
110
|
"react": "^19.2.7",
|
|
101
111
|
"react-dom": "^19.2.7",
|
|
@@ -111,7 +121,7 @@
|
|
|
111
121
|
},
|
|
112
122
|
"devDependencies": {
|
|
113
123
|
"@rslib/core": "0.23.0",
|
|
114
|
-
"@types/node": "^26.0.
|
|
124
|
+
"@types/node": "^26.0.1",
|
|
115
125
|
"@typescript/native-preview": "7.0.0-dev.20260624.1",
|
|
116
126
|
"i18next": "26.3.2",
|
|
117
127
|
"react": "^19.2.7",
|
|
@@ -119,8 +129,8 @@
|
|
|
119
129
|
"react-i18next": "17.0.8",
|
|
120
130
|
"ts-node": "^10.9.2",
|
|
121
131
|
"typescript": "^6.0.3",
|
|
122
|
-
"@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.4.0-ultramodern.
|
|
123
|
-
"@modern-js/runtime": "npm:@bleedingdev/modern-js-runtime@3.4.0-ultramodern.
|
|
132
|
+
"@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.4.0-ultramodern.10",
|
|
133
|
+
"@modern-js/runtime": "npm:@bleedingdev/modern-js-runtime@3.4.0-ultramodern.10"
|
|
124
134
|
},
|
|
125
135
|
"sideEffects": false,
|
|
126
136
|
"publishConfig": {
|
package/rstest.config.mts
CHANGED
package/src/cli/index.ts
CHANGED
|
@@ -126,10 +126,15 @@ export const i18nPlugin = (
|
|
|
126
126
|
backend: backendOptions,
|
|
127
127
|
...extendedConfig,
|
|
128
128
|
};
|
|
129
|
+
const runtimePluginPath =
|
|
130
|
+
customPlugin?.runtime?.path ||
|
|
131
|
+
(config.reactI18next === false
|
|
132
|
+
? `@${metaName}/plugin-i18n/runtime/no-react-i18next`
|
|
133
|
+
: `@${metaName}/plugin-i18n/runtime`);
|
|
129
134
|
|
|
130
135
|
plugins.push({
|
|
131
136
|
name: customPlugin?.runtime?.name || 'i18n',
|
|
132
|
-
path:
|
|
137
|
+
path: runtimePluginPath,
|
|
133
138
|
config,
|
|
134
139
|
});
|
|
135
140
|
return {
|
package/src/runtime/context.tsx
CHANGED
|
@@ -53,6 +53,7 @@ export const ModernI18nProvider: FC<ModernI18nProviderProps> = ({
|
|
|
53
53
|
export interface UseModernI18nReturn {
|
|
54
54
|
language: string;
|
|
55
55
|
changeLanguage: (newLang: string) => Promise<void>;
|
|
56
|
+
t: (key: string | string[], ...args: any[]) => string;
|
|
56
57
|
i18nInstance: I18nInstance;
|
|
57
58
|
supportedLanguages: string[];
|
|
58
59
|
localisedUrls?: LocalisedUrlsOption;
|
|
@@ -250,6 +251,17 @@ export const useModernI18n = (): UseModernI18nReturn => {
|
|
|
250
251
|
],
|
|
251
252
|
);
|
|
252
253
|
|
|
254
|
+
const t = useCallback(
|
|
255
|
+
(key: string | string[], ...args: any[]) => {
|
|
256
|
+
if (typeof i18nInstance.t !== 'function') {
|
|
257
|
+
throw new Error('i18nInstance.t is required');
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return i18nInstance.t(key, ...args) as string;
|
|
261
|
+
},
|
|
262
|
+
[currentLanguage, i18nInstance],
|
|
263
|
+
);
|
|
264
|
+
|
|
253
265
|
// Helper function to check if a language is supported
|
|
254
266
|
const isLanguageSupported = useCallback(
|
|
255
267
|
(lang: string) => {
|
|
@@ -310,6 +322,7 @@ export const useModernI18n = (): UseModernI18nReturn => {
|
|
|
310
322
|
return {
|
|
311
323
|
language: currentLanguage,
|
|
312
324
|
changeLanguage,
|
|
325
|
+
t,
|
|
313
326
|
i18nInstance,
|
|
314
327
|
supportedLanguages: languages || [],
|
|
315
328
|
localisedUrls,
|