@spaceflow/core 0.7.0 → 0.8.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/index.js +76 -101
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/shared/i18n/i18n.ts +53 -76
- package/src/shared/i18n/index.ts +14 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spaceflow/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Spaceflow 核心能力库",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Lydanne",
|
|
@@ -81,7 +81,6 @@
|
|
|
81
81
|
"@rspack/core": "^1.7.4",
|
|
82
82
|
"chalk": "^5.6.2",
|
|
83
83
|
"dotenv": "^16.4.5",
|
|
84
|
-
"i18next": "^25.8.4",
|
|
85
84
|
"json-stringify-pretty-compact": "^4.0.0",
|
|
86
85
|
"jsonrepair": "^3.13.1",
|
|
87
86
|
"log-update": "^7.1.0",
|
|
@@ -109,6 +108,7 @@
|
|
|
109
108
|
"typescript": "^5.7.3",
|
|
110
109
|
"typescript-eslint": "^8.20.0",
|
|
111
110
|
"@vitest/coverage-v8": "^4.0.18",
|
|
111
|
+
"i18next": "^25.8.4",
|
|
112
112
|
"unplugin-swc": "^1.5.9",
|
|
113
113
|
"vitest": "^4.0.18"
|
|
114
114
|
},
|
package/src/shared/i18n/i18n.ts
CHANGED
|
@@ -1,95 +1,70 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/** globalThis 上的 key */
|
|
2
|
+
const GLOBAL_T_KEY = "__spaceflow_t__";
|
|
3
|
+
const GLOBAL_ADD_LOCALE_KEY = "__spaceflow_add_locale__";
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
(i18nextModule as unknown as { default: i18n }).default || (i18nextModule as unknown as i18n);
|
|
7
|
-
import { detectLocale } from "./locale-detect";
|
|
8
|
-
import zhCN from "../../locales/zh-cn/translation.json";
|
|
9
|
-
import en from "../../locales/en/translation.json";
|
|
5
|
+
/** 翻译函数类型 */
|
|
6
|
+
export type TranslateFn = (key: string, options?: Record<string, unknown>) => string;
|
|
10
7
|
|
|
11
|
-
/**
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
/** 注册翻译资源函数类型 */
|
|
9
|
+
export type AddLocaleResourcesFn = (
|
|
10
|
+
ns: string,
|
|
11
|
+
resources: Record<string, Record<string, unknown>>,
|
|
12
|
+
) => void;
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
/**
|
|
15
|
+
* 设置全局翻译函数
|
|
16
|
+
* 由 CLI 在启动时调用,将 i18next 的 t 函数挂载到 globalThis
|
|
17
|
+
*/
|
|
18
|
+
export function setGlobalT(fn: TranslateFn): void {
|
|
19
|
+
(globalThis as Record<string, unknown>)[GLOBAL_T_KEY] = fn;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
23
|
+
* 设置全局翻译资源注册函数
|
|
24
|
+
* 由 CLI 在启动时调用
|
|
25
25
|
*/
|
|
26
|
-
function
|
|
27
|
-
|
|
28
|
-
if (!g[GLOBAL_I18N_KEY]) {
|
|
29
|
-
g[GLOBAL_I18N_KEY] = {
|
|
30
|
-
instance: i18next,
|
|
31
|
-
initialized: false,
|
|
32
|
-
} satisfies GlobalI18nState;
|
|
33
|
-
}
|
|
34
|
-
return g[GLOBAL_I18N_KEY] as GlobalI18nState;
|
|
26
|
+
export function setGlobalAddLocaleResources(fn: AddLocaleResourcesFn): void {
|
|
27
|
+
(globalThis as Record<string, unknown>)[GLOBAL_ADD_LOCALE_KEY] = fn;
|
|
35
28
|
}
|
|
36
29
|
|
|
37
30
|
/**
|
|
38
|
-
*
|
|
39
|
-
* 当提供 resources 且无后端加载器时,i18next.init() 同步完成
|
|
40
|
-
* @param lang 指定语言,不传则自动检测
|
|
31
|
+
* 获取全局翻译函数
|
|
41
32
|
*/
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (state.initialized) return;
|
|
45
|
-
const lng = lang || detectLocale();
|
|
46
|
-
// i18next v25+ 移除了 initSync,但提供内联 resources 时 init() 同步完成
|
|
47
|
-
void state.instance.init({
|
|
48
|
-
lng,
|
|
49
|
-
fallbackLng: "zh-CN",
|
|
50
|
-
defaultNS: DEFAULT_NS,
|
|
51
|
-
ns: [DEFAULT_NS],
|
|
52
|
-
resources: {
|
|
53
|
-
"zh-CN": { [DEFAULT_NS]: zhCN },
|
|
54
|
-
en: { [DEFAULT_NS]: en },
|
|
55
|
-
},
|
|
56
|
-
interpolation: {
|
|
57
|
-
escapeValue: false,
|
|
58
|
-
},
|
|
59
|
-
returnNull: false,
|
|
60
|
-
returnEmptyString: false,
|
|
61
|
-
// 确保 init 同步完成(默认 initImmediate: true 会将加载推到 setTimeout)
|
|
62
|
-
initImmediate: false,
|
|
63
|
-
// i18next v25.8+ 会在 init 时输出 locize.com 推广日志
|
|
64
|
-
showSupportNotice: false,
|
|
65
|
-
});
|
|
66
|
-
state.initialized = true;
|
|
33
|
+
function getGlobalT(): TranslateFn | undefined {
|
|
34
|
+
return (globalThis as Record<string, unknown>)[GLOBAL_T_KEY] as TranslateFn | undefined;
|
|
67
35
|
}
|
|
68
36
|
|
|
69
37
|
/**
|
|
70
|
-
*
|
|
38
|
+
* 简单的模板插值(fallback 用)
|
|
39
|
+
* 支持 {{key}} 格式
|
|
71
40
|
*/
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
41
|
+
function interpolate(template: string, options?: Record<string, unknown>): string {
|
|
42
|
+
if (!options) return template;
|
|
43
|
+
return template.replace(/\{\{(\w+)\}\}/g, (_, k: string) => {
|
|
44
|
+
const val = options[k];
|
|
45
|
+
return val !== undefined ? String(val) : `{{${k}}}`;
|
|
46
|
+
});
|
|
75
47
|
}
|
|
76
48
|
|
|
77
49
|
/**
|
|
78
50
|
* 翻译函数
|
|
79
|
-
*
|
|
51
|
+
* 优先使用 CLI 通过 setGlobalT 挂载的翻译函数
|
|
52
|
+
* 未挂载时回退到返回 key(带插值)
|
|
80
53
|
* @param key 翻译 key
|
|
81
54
|
* @param options 插值参数
|
|
82
55
|
*/
|
|
83
|
-
export function t(key: string, options?:
|
|
84
|
-
const
|
|
85
|
-
if (
|
|
86
|
-
|
|
56
|
+
export function t(key: string, options?: Record<string, unknown>): string {
|
|
57
|
+
const globalT = getGlobalT();
|
|
58
|
+
if (globalT) {
|
|
59
|
+
return globalT(key, options);
|
|
87
60
|
}
|
|
88
|
-
|
|
61
|
+
// fallback: 直接返回 key(带插值)
|
|
62
|
+
return interpolate(key, options);
|
|
89
63
|
}
|
|
90
64
|
|
|
91
65
|
/**
|
|
92
66
|
* 为外部 Extension 注册语言资源
|
|
67
|
+
* 委托给 CLI 通过 setGlobalAddLocaleResources 挂载的实际实现
|
|
93
68
|
* @param ns 命名空间(通常为 Extension name)
|
|
94
69
|
* @param resources 语言资源,key 为语言代码,值为翻译对象
|
|
95
70
|
*/
|
|
@@ -97,16 +72,18 @@ export function addLocaleResources(
|
|
|
97
72
|
ns: string,
|
|
98
73
|
resources: Record<string, Record<string, unknown>>,
|
|
99
74
|
): void {
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
state.instance.addResourceBundle(lng, ns, translations, true, true);
|
|
106
|
-
}
|
|
107
|
-
if (!state.instance.options.ns) {
|
|
108
|
-
state.instance.options.ns = [DEFAULT_NS, ns];
|
|
109
|
-
} else if (Array.isArray(state.instance.options.ns) && !state.instance.options.ns.includes(ns)) {
|
|
110
|
-
state.instance.options.ns.push(ns);
|
|
75
|
+
const fn = (globalThis as Record<string, unknown>)[GLOBAL_ADD_LOCALE_KEY] as
|
|
76
|
+
| AddLocaleResourcesFn
|
|
77
|
+
| undefined;
|
|
78
|
+
if (fn) {
|
|
79
|
+
fn(ns, resources);
|
|
111
80
|
}
|
|
112
81
|
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* 重置全局翻译函数(仅用于测试)
|
|
85
|
+
*/
|
|
86
|
+
export function resetI18n(): void {
|
|
87
|
+
(globalThis as Record<string, unknown>)[GLOBAL_T_KEY] = undefined;
|
|
88
|
+
(globalThis as Record<string, unknown>)[GLOBAL_ADD_LOCALE_KEY] = undefined;
|
|
89
|
+
}
|
package/src/shared/i18n/index.ts
CHANGED
|
@@ -1 +1,14 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {
|
|
2
|
+
t,
|
|
3
|
+
setGlobalT,
|
|
4
|
+
setGlobalAddLocaleResources,
|
|
5
|
+
addLocaleResources,
|
|
6
|
+
resetI18n,
|
|
7
|
+
type TranslateFn,
|
|
8
|
+
type AddLocaleResourcesFn,
|
|
9
|
+
} from "./i18n";
|
|
10
|
+
export { detectLocale } from "./locale-detect";
|
|
11
|
+
|
|
12
|
+
// 导出 core 基础翻译资源,供 CLI 注册
|
|
13
|
+
export { default as coreZhCN } from "../../locales/zh-cn/translation.json";
|
|
14
|
+
export { default as coreEn } from "../../locales/en/translation.json";
|