@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spaceflow/core",
3
- "version": "0.7.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
  },
@@ -1,95 +1,70 @@
1
- import * as i18nextModule from "i18next";
2
- import type { TOptions, i18n } from "i18next";
1
+ /** globalThis 上的 key */
2
+ const GLOBAL_T_KEY = "__spaceflow_t__";
3
+ const GLOBAL_ADD_LOCALE_KEY = "__spaceflow_add_locale__";
3
4
 
4
- // 兼容 CJS/ESM 混合环境
5
- const i18next: i18n =
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
- const DEFAULT_NS = "translation";
13
-
14
- /** globalThis 上的 key,确保多份 core 实例共享同一个 i18n 状态 */
15
- const GLOBAL_I18N_KEY = "__spaceflow_i18n__";
8
+ /** 注册翻译资源函数类型 */
9
+ export type AddLocaleResourcesFn = (
10
+ ns: string,
11
+ resources: Record<string, Record<string, unknown>>,
12
+ ) => void;
16
13
 
17
- interface GlobalI18nState {
18
- instance: i18n;
19
- initialized: boolean;
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
- * 获取全局 i18n 状态(单例)
24
- * 无论有几份 @spaceflow/core 实例,都共享同一个 i18next 实例
23
+ * 设置全局翻译资源注册函数
24
+ * CLI 在启动时调用
25
25
  */
26
- function getGlobalState(): GlobalI18nState {
27
- const g = globalThis as Record<string, unknown>;
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
- * 初始化 i18n
39
- * 当提供 resources 且无后端加载器时,i18next.init() 同步完成
40
- * @param lang 指定语言,不传则自动检测
31
+ * 获取全局翻译函数
41
32
  */
42
- export function initI18n(lang?: string): void {
43
- const state = getGlobalState();
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
- * 重置 i18n 状态(仅用于测试)
38
+ * 简单的模板插值(fallback 用)
39
+ * 支持 {{key}} 格式
71
40
  */
72
- export function resetI18n(): void {
73
- const state = getGlobalState();
74
- state.initialized = false;
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
- * 通过 globalThis 共享 i18next 实例,确保多份 core 实例下翻译一致
51
+ * 优先使用 CLI 通过 setGlobalT 挂载的翻译函数
52
+ * 未挂载时回退到返回 key(带插值)
80
53
  * @param key 翻译 key
81
54
  * @param options 插值参数
82
55
  */
83
- export function t(key: string, options?: TOptions): string {
84
- const state = getGlobalState();
85
- if (!state.initialized) {
86
- initI18n();
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
- return state.instance.t(key, options) as string;
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 state = getGlobalState();
101
- if (!state.initialized) {
102
- initI18n();
103
- }
104
- for (const [lng, translations] of Object.entries(resources)) {
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
+ }
@@ -1 +1,14 @@
1
- export { initI18n, t, addLocaleResources } from "./i18n";
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";