@spaceflow/core 0.7.0 → 0.9.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.
Files changed (88) hide show
  1. package/dist/index.js +5621 -1027
  2. package/dist/index.js.map +1 -1
  3. package/package.json +9 -3
  4. package/src/cli-runtime/di/config.ts +157 -0
  5. package/src/cli-runtime/di/container.ts +120 -0
  6. package/src/cli-runtime/di/index.ts +3 -0
  7. package/src/cli-runtime/di/services.ts +53 -0
  8. package/src/cli-runtime/extension-loader.ts +74 -0
  9. package/src/cli-runtime/i18n/i18n.ts +89 -0
  10. package/src/cli-runtime/i18n/index.ts +20 -0
  11. package/src/cli-runtime/i18n/init.ts +117 -0
  12. package/src/cli-runtime/index.ts +131 -0
  13. package/src/cli-runtime/internal-extensions.ts +33 -0
  14. package/src/commands/build/build.service.ts +323 -0
  15. package/src/commands/build/index.ts +49 -0
  16. package/src/commands/clear/clear.service.ts +159 -0
  17. package/src/commands/clear/index.ts +35 -0
  18. package/src/commands/commit/commit.config.ts +168 -0
  19. package/src/commands/commit/commit.service.ts +950 -0
  20. package/src/commands/commit/index.ts +58 -0
  21. package/src/commands/create/create.service.ts +318 -0
  22. package/src/commands/create/index.ts +42 -0
  23. package/src/commands/dev/index.ts +30 -0
  24. package/src/commands/install/index.ts +65 -0
  25. package/src/commands/install/install.service.ts +1539 -0
  26. package/src/commands/list/index.ts +33 -0
  27. package/src/commands/list/list.service.ts +127 -0
  28. package/src/commands/mcp/index.ts +37 -0
  29. package/src/commands/mcp/mcp.service.ts +246 -0
  30. package/src/commands/runx/index.ts +47 -0
  31. package/src/commands/runx/runx.service.ts +142 -0
  32. package/src/commands/runx/runx.utils.ts +83 -0
  33. package/src/commands/schema/index.ts +30 -0
  34. package/src/commands/setup/index.ts +34 -0
  35. package/src/commands/setup/setup.service.ts +234 -0
  36. package/src/commands/uninstall/index.ts +42 -0
  37. package/src/commands/uninstall/uninstall.service.ts +166 -0
  38. package/src/commands/update/index.ts +42 -0
  39. package/src/commands/update/update.service.ts +373 -0
  40. package/src/config/index.ts +1 -30
  41. package/src/config/spaceflow.config.ts +226 -278
  42. package/src/index.ts +11 -1
  43. package/src/locales/en/build.json +22 -0
  44. package/src/locales/en/clear.json +16 -0
  45. package/src/locales/en/commit.json +45 -0
  46. package/src/locales/en/create.json +27 -0
  47. package/src/locales/en/dev.json +5 -0
  48. package/src/locales/en/install.json +71 -0
  49. package/src/locales/en/list.json +8 -0
  50. package/src/locales/en/mcp.json +19 -0
  51. package/src/locales/en/runx.json +13 -0
  52. package/src/locales/en/schema.json +4 -0
  53. package/src/locales/en/setup.json +14 -0
  54. package/src/locales/en/uninstall.json +18 -0
  55. package/src/locales/en/update.json +28 -0
  56. package/src/locales/zh-cn/build.json +22 -0
  57. package/src/locales/zh-cn/clear.json +16 -0
  58. package/src/locales/zh-cn/commit.json +45 -0
  59. package/src/locales/zh-cn/create.json +27 -0
  60. package/src/locales/zh-cn/dev.json +5 -0
  61. package/src/locales/zh-cn/install.json +71 -0
  62. package/src/locales/zh-cn/list.json +8 -0
  63. package/src/locales/zh-cn/mcp.json +19 -0
  64. package/src/locales/zh-cn/runx.json +13 -0
  65. package/src/locales/zh-cn/schema.json +4 -0
  66. package/src/locales/zh-cn/setup.json +14 -0
  67. package/src/locales/zh-cn/uninstall.json +18 -0
  68. package/src/locales/zh-cn/update.json +28 -0
  69. package/src/shared/editor-config/index.ts +2 -21
  70. package/src/shared/llm-proxy/adapters/openai.adapter.ts +3 -1
  71. package/src/shared/package-manager/index.ts +5 -76
  72. package/src/shared/source-utils/index.ts +12 -130
  73. package/src/shared/spaceflow-dir/index.ts +13 -135
  74. package/src/shared/verbose/index.ts +10 -87
  75. package/dist/524.js +0 -9
  76. package/src/config/ci.config.ts +0 -29
  77. package/src/config/config-loader.ts +0 -100
  78. package/src/config/config-reader.service.ts +0 -128
  79. package/src/config/config-reader.ts +0 -75
  80. package/src/config/feishu.config.ts +0 -35
  81. package/src/config/git-provider.config.ts +0 -29
  82. package/src/config/llm.config.ts +0 -110
  83. package/src/config/load-env.ts +0 -15
  84. package/src/config/storage.config.ts +0 -33
  85. package/src/shared/i18n/i18n.ts +0 -112
  86. package/src/shared/i18n/index.ts +0 -1
  87. /package/src/{shared → cli-runtime}/i18n/i18n.spec.ts +0 -0
  88. /package/src/{shared → cli-runtime}/i18n/locale-detect.ts +0 -0
@@ -1,128 +0,0 @@
1
- /**
2
- * 系统配置(不包含插件配置)
3
- */
4
- export interface SystemConfig {
5
- /** 已安装的技能包注册表 */
6
- dependencies?: Record<string, string>;
7
- /** 支持的编辑器列表 */
8
- support?: string[];
9
- }
10
-
11
- /**
12
- * 插件配置注册信息
13
- */
14
- export interface PluginConfigRegistry {
15
- /** 插件名称 */
16
- name: string;
17
- /** 配置 key */
18
- configKey?: string;
19
- /** 依赖的其他插件配置 */
20
- configDependencies?: string[];
21
- /** 配置 schema 工厂函数 */
22
- configSchema?: () => unknown;
23
- }
24
-
25
- /** 全局插件配置注册表(使用 global 确保跨模块共享) */
26
- const PLUGIN_REGISTRY_KEY = Symbol.for("spaceflow.pluginRegistry");
27
- const globalAny = global as any;
28
- if (!globalAny[PLUGIN_REGISTRY_KEY]) {
29
- globalAny[PLUGIN_REGISTRY_KEY] = new Map<string, PluginConfigRegistry>();
30
- }
31
- const pluginRegistry: Map<string, PluginConfigRegistry> = globalAny[PLUGIN_REGISTRY_KEY];
32
-
33
- /**
34
- * 注册插件配置(由插件加载器调用)
35
- */
36
- export function registerPluginConfig(registry: PluginConfigRegistry): void {
37
- if (registry.configKey) {
38
- pluginRegistry.set(registry.configKey, registry);
39
- }
40
- }
41
-
42
- /**
43
- * 获取已注册的插件配置
44
- */
45
- export function getRegisteredPluginConfig(configKey: string): PluginConfigRegistry | undefined {
46
- return pluginRegistry.get(configKey);
47
- }
48
-
49
- /**
50
- * 配置读取服务
51
- * 提供三种配置读取方式:
52
- * 1. getPluginConfig - 读取指定插件的配置
53
- * 2. getOtherPluginConfig - 读取其他插件的配置(需要在 metadata 中声明依赖)
54
- * 3. getSystemConfig - 读取系统配置
55
- */
56
- export class ConfigReaderService {
57
- constructor() {}
58
-
59
- /**
60
- * 读取插件的配置
61
- * 使用 schema 验证并合并默认值
62
- * @param configKey 插件的配置 key
63
- * @returns 验证后的插件配置
64
- */
65
- getPluginConfig<T>(configKey: string): T {
66
- const rawConfig = (global as any).spaceflowConfig || {};
67
- const userConfig = rawConfig[configKey] ?? {};
68
-
69
- // 从注册表获取 schema 工厂函数
70
- const registry = pluginRegistry.get(configKey);
71
- const schemaFactory = registry?.configSchema;
72
-
73
- if (!schemaFactory || typeof schemaFactory !== "function") {
74
- return userConfig as T;
75
- }
76
-
77
- // 调用工厂函数获取 schema
78
- const schema = schemaFactory();
79
- if (!schema || typeof (schema as any).parse !== "function") {
80
- return userConfig as T;
81
- }
82
-
83
- // 使用 schema.parse() 验证并填充默认值
84
- try {
85
- return (schema as any).parse(userConfig) as T;
86
- } catch (error) {
87
- console.warn(`⚠️ 配置 "${configKey}" 验证失败:`, error);
88
- return userConfig as T;
89
- }
90
- }
91
-
92
- /**
93
- * 读取其他插件的配置
94
- * 必须在插件的 metadata.configDependencies 中声明依赖
95
- * @param fromConfigKey 当前插件的配置 key
96
- * @param targetConfigKey 目标插件的配置 key
97
- * @returns 合并后的插件配置
98
- */
99
- getOtherPluginConfig<T>(fromConfigKey: string, targetConfigKey: string): T {
100
- const fromRegistry = pluginRegistry.get(fromConfigKey);
101
- if (!fromRegistry) {
102
- throw new Error(`插件 "${fromConfigKey}" 未注册`);
103
- }
104
-
105
- // 检查是否已声明依赖
106
- const dependencies = fromRegistry.configDependencies ?? [];
107
- if (!dependencies.includes(targetConfigKey)) {
108
- throw new Error(
109
- `插件 "${fromRegistry.name}" 未声明对 "${targetConfigKey}" 配置的依赖。` +
110
- `请在插件 metadata 的 configDependencies 中添加 "${targetConfigKey}"`,
111
- );
112
- }
113
-
114
- return this.getPluginConfig<T>(targetConfigKey);
115
- }
116
-
117
- /**
118
- * 读取系统配置(不包含插件配置)
119
- * @returns 系统配置
120
- */
121
- getSystemConfig(): SystemConfig {
122
- const rawConfig = (global as any).spaceflowConfig || {};
123
- return {
124
- dependencies: rawConfig.dependencies,
125
- support: rawConfig.support,
126
- };
127
- }
128
- }
@@ -1,75 +0,0 @@
1
- import type { ZodSchema } from "zod";
2
- import { readConfigSync } from "./spaceflow.config";
3
- import type { IConfigReader } from "../extension-system/types";
4
-
5
- /**
6
- * 配置读取器
7
- * 不依赖 NestJS,直接读取配置文件
8
- */
9
- export class ConfigReader implements IConfigReader {
10
- private config: Record<string, unknown>;
11
- private schemas = new Map<string, ZodSchema>();
12
-
13
- constructor(cwd?: string) {
14
- this.config = readConfigSync(cwd) as Record<string, unknown>;
15
- }
16
-
17
- /**
18
- * 获取配置值
19
- * @param key 配置路径(支持点分隔,如 "gitProvider.token")
20
- */
21
- get<T>(key: string): T | undefined {
22
- const parts = key.split(".");
23
- let current: unknown = this.config;
24
- for (const part of parts) {
25
- if (current === null || current === undefined) {
26
- return undefined;
27
- }
28
- current = (current as Record<string, unknown>)[part];
29
- }
30
- return current as T | undefined;
31
- }
32
-
33
- /**
34
- * 获取插件配置
35
- * 使用已注册的 schema 验证并填充默认值
36
- * @param key 插件配置 key
37
- */
38
- getPluginConfig<T>(key: string): T | undefined {
39
- const rawConfig = this.config[key] ?? {};
40
- const schema = this.schemas.get(key);
41
- if (!schema) {
42
- return rawConfig as T;
43
- }
44
- try {
45
- return schema.parse(rawConfig) as T;
46
- } catch (error) {
47
- console.warn(`⚠️ 配置 "${key}" 验证失败:`, error);
48
- return rawConfig as T;
49
- }
50
- }
51
-
52
- /**
53
- * 注册配置 schema
54
- * @param key 配置 key
55
- * @param schema Zod schema
56
- */
57
- registerSchema(key: string, schema: ZodSchema): void {
58
- this.schemas.set(key, schema);
59
- }
60
-
61
- /**
62
- * 重新加载配置
63
- * @param cwd 工作目录
64
- */
65
- reload(cwd?: string): void {
66
- this.config = readConfigSync(cwd) as Record<string, unknown>;
67
- }
68
-
69
- /**
70
- * 获取原始配置对象
71
- */
72
- getRawConfig(): Record<string, unknown> {
73
- return this.config;
74
- }
75
- }
@@ -1,35 +0,0 @@
1
- import { z } from "zod";
2
- import { createConfigLoader } from "./config-loader";
3
-
4
- const schemaFactory = () =>
5
- z.object({
6
- /** 飞书应用 ID */
7
- appId: z
8
- .string()
9
- .default(process.env.FEISHU_APP_ID || "")
10
- .describe("飞书应用 ID"),
11
- /** 飞书应用密钥 */
12
- appSecret: z
13
- .string()
14
- .default(process.env.FEISHU_APP_SECRET || "")
15
- .describe("飞书应用密钥"),
16
- /** 应用类型:自建应用或商店应用 */
17
- appType: z
18
- .enum(["self_build", "store"])
19
- .default((process.env.FEISHU_APP_TYPE as "self_build" | "store") || "self_build")
20
- .describe("应用类型"),
21
- /** 域名:飞书或 Lark */
22
- domain: z
23
- .enum(["feishu", "lark"])
24
- .default((process.env.FEISHU_DOMAIN as "feishu" | "lark") || "feishu")
25
- .describe("域名"),
26
- });
27
-
28
- /** 飞书配置类型 */
29
- export type FeishuConfig = z.infer<ReturnType<typeof schemaFactory>>;
30
-
31
- export const feishuConfig = createConfigLoader({
32
- configKey: "feishu",
33
- schemaFactory,
34
- description: "飞书 SDK 配置",
35
- });
@@ -1,29 +0,0 @@
1
- import { z } from "zod";
2
- import { createConfigLoader } from "./config-loader";
3
- import { detectProvider } from "../shared/git-provider/detect-provider";
4
-
5
- /** 从环境自动检测的默认值 */
6
- const detected = detectProvider();
7
-
8
- /** Git Provider 配置 Schema */
9
- const schemaFactory = () =>
10
- z.object({
11
- /** Git Provider 类型(自动检测或手动指定) */
12
- provider: z
13
- .enum(["gitea", "github", "gitlab"])
14
- .default(detected.provider)
15
- .describe("Git Provider 类型 (github | gitea | gitlab),未指定时自动检测"),
16
- /** Git Provider 服务器 URL */
17
- serverUrl: z.string().default(detected.serverUrl).describe("Git Provider 服务器 URL"),
18
- /** Git Provider API Token */
19
- token: z.string().default(detected.token).describe("Git Provider API Token"),
20
- });
21
-
22
- /** Git Provider 配置类型 */
23
- export type GitProviderConfig = z.infer<ReturnType<typeof schemaFactory>>;
24
-
25
- export const gitProviderConfig = createConfigLoader({
26
- configKey: "gitProvider",
27
- schemaFactory,
28
- description: "Git Provider 服务配置",
29
- });
@@ -1,110 +0,0 @@
1
- import { z } from "zod";
2
- import { createConfigLoader } from "./config-loader";
3
-
4
- const schemaFactory = () => {
5
- /** Claude Code 适配器配置 Schema */
6
- const ClaudeCodeConfigSchema = z.object({
7
- baseUrl: z
8
- .string()
9
- .default(process.env.CLAUDE_CODE_BASE_URL || "")
10
- .describe("API 基础 URL"),
11
- authToken: z
12
- .string()
13
- .default(process.env.CLAUDE_CODE_AUTH_TOKEN || "")
14
- .describe("认证令牌"),
15
- model: z
16
- .string()
17
- .default(process.env.CLAUDE_CODE_MODEL || "claude-sonnet-4-5")
18
- .describe("模型名称"),
19
- hasCompletedOnboarding: z.boolean().optional().describe("是否已完成 Claude Code 引导流程"),
20
- });
21
-
22
- /** OpenAI 适配器配置 Schema */
23
- const OpenAIConfigSchema = z.object({
24
- baseUrl: z
25
- .string()
26
- .default(process.env.OPENAI_BASE_URL || "")
27
- .describe("API 基础 URL"),
28
- apiKey: z
29
- .string()
30
- .default(process.env.OPENAI_API_KEY || "")
31
- .describe("API Key"),
32
- model: z
33
- .string()
34
- .default(process.env.OPENAI_MODEL || "gpt-4o")
35
- .describe("模型名称"),
36
- });
37
-
38
- /** OpenCode 适配器配置 Schema */
39
- const OpenCodeConfigSchema = z.object({
40
- serverUrl: z
41
- .string()
42
- .default(process.env.OPENCODE_SERVER_URL || "http://localhost:4096")
43
- .describe("服务器 URL"),
44
- baseUrl: z
45
- .string()
46
- .default(process.env.OPENCODE_BASE_URL || "")
47
- .describe("API 基础 URL"),
48
- apiKey: z
49
- .string()
50
- .default(process.env.OPENCODE_API_KEY || "")
51
- .describe("API Key"),
52
- providerID: z
53
- .string()
54
- .default(process.env.OPENCODE_PROVIDER_ID || "openai")
55
- .describe("Provider ID"),
56
- model: z
57
- .string()
58
- .default(process.env.OPENCODE_MODEL || "")
59
- .describe("模型名称"),
60
- });
61
-
62
- /** Gemini 适配器配置 Schema */
63
- const GeminiConfigSchema = z.object({
64
- baseUrl: z
65
- .string()
66
- .default(process.env.GEMINI_BASE_URL || "")
67
- .describe("API 基础 URL"),
68
- apiKey: z
69
- .string()
70
- .default(process.env.GEMINI_API_KEY || "")
71
- .describe("API Key"),
72
- model: z
73
- .string()
74
- .default(process.env.GEMINI_MODEL || "")
75
- .describe("模型名称"),
76
- });
77
-
78
- /** LLM 配置 Schema */
79
- const LlmConfigSchema = z.object({
80
- claudeCode: z
81
- .preprocess((v) => v ?? {}, ClaudeCodeConfigSchema)
82
- .describe("Claude Code 适配器配置"),
83
- openai: z.preprocess((v) => v ?? {}, OpenAIConfigSchema).describe("OpenAI 适配器配置"),
84
- openCode: z.preprocess((v) => v ?? {}, OpenCodeConfigSchema).describe("OpenCode 适配器配置"),
85
- gemini: z.preprocess((v) => v ?? {}, GeminiConfigSchema).describe("Gemini 适配器配置"),
86
- });
87
-
88
- return LlmConfigSchema;
89
- };
90
-
91
- /** LLM 系统配置类型 */
92
- export type LlmConfig = z.infer<ReturnType<typeof schemaFactory>>;
93
-
94
- /** Claude Code 适配器配置类型 */
95
- export type ClaudeCodeConfig = z.infer<LlmConfig["claudeCode"]>;
96
-
97
- /** OpenAI 适配器配置类型 */
98
- export type OpenAIConfig = z.infer<LlmConfig["openai"]>;
99
-
100
- /** OpenCode 适配器配置类型 */
101
- export type OpenCodeConfig = z.infer<LlmConfig["openCode"]>;
102
-
103
- /** Gemini 适配器配置类型 */
104
- export type GeminiConfig = z.infer<LlmConfig["gemini"]>;
105
-
106
- export const llmConfig = createConfigLoader({
107
- configKey: "llm",
108
- schemaFactory,
109
- description: "LLM 服务配置",
110
- });
@@ -1,15 +0,0 @@
1
- import { config } from "dotenv";
2
- import { existsSync } from "fs";
3
-
4
- /**
5
- * 加载 .env 文件
6
- * 按优先级从高到低加载,先加载的变量不会被后加载的覆盖
7
- * @param paths .env 文件路径列表(按优先级从高到低排列)
8
- */
9
- export function loadEnvFiles(paths: string[]): void {
10
- for (const envPath of paths) {
11
- if (existsSync(envPath)) {
12
- config({ path: envPath, override: false });
13
- }
14
- }
15
- }
@@ -1,33 +0,0 @@
1
- import { z } from "zod";
2
- import { createConfigLoader } from "./config-loader";
3
-
4
- /** Storage 配置 Schema */
5
- const schemaFactory = () =>
6
- z.object({
7
- /** 适配器类型:memory 或 file */
8
- adapter: z
9
- .enum(["memory", "file"])
10
- .default((process.env.STORAGE_ADAPTER as "memory" | "file") || "memory")
11
- .describe("适配器类型"),
12
- /** 文件适配器的存储路径(仅 file 适配器需要) */
13
- filePath: z.string().optional().describe("文件存储路径"),
14
- /** 默认过期时间(毫秒),0 表示永不过期 */
15
- defaultTtl: z
16
- .number()
17
- .default(process.env.STORAGE_DEFAULT_TTL ? parseInt(process.env.STORAGE_DEFAULT_TTL, 10) : 0)
18
- .describe("默认过期时间(毫秒)"),
19
- /** 最大 key 数量,0 表示不限制 */
20
- maxKeys: z
21
- .number()
22
- .default(process.env.STORAGE_MAX_KEYS ? parseInt(process.env.STORAGE_MAX_KEYS, 10) : 0)
23
- .describe("最大 key 数量"),
24
- });
25
-
26
- /** Storage 配置类型 */
27
- export type StorageConfig = z.infer<ReturnType<typeof schemaFactory>>;
28
-
29
- export const storageConfig = createConfigLoader({
30
- configKey: "storage",
31
- schemaFactory,
32
- description: "存储服务配置",
33
- });
@@ -1,112 +0,0 @@
1
- import * as i18nextModule from "i18next";
2
- import type { TOptions, i18n } from "i18next";
3
-
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";
10
-
11
- /** 默认命名空间 */
12
- const DEFAULT_NS = "translation";
13
-
14
- /** globalThis 上的 key,确保多份 core 实例共享同一个 i18n 状态 */
15
- const GLOBAL_I18N_KEY = "__spaceflow_i18n__";
16
-
17
- interface GlobalI18nState {
18
- instance: i18n;
19
- initialized: boolean;
20
- }
21
-
22
- /**
23
- * 获取全局 i18n 状态(单例)
24
- * 无论有几份 @spaceflow/core 实例,都共享同一个 i18next 实例
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;
35
- }
36
-
37
- /**
38
- * 初始化 i18n
39
- * 当提供 resources 且无后端加载器时,i18next.init() 同步完成
40
- * @param lang 指定语言,不传则自动检测
41
- */
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;
67
- }
68
-
69
- /**
70
- * 重置 i18n 状态(仅用于测试)
71
- */
72
- export function resetI18n(): void {
73
- const state = getGlobalState();
74
- state.initialized = false;
75
- }
76
-
77
- /**
78
- * 翻译函数
79
- * 通过 globalThis 共享 i18next 实例,确保多份 core 实例下翻译一致
80
- * @param key 翻译 key
81
- * @param options 插值参数
82
- */
83
- export function t(key: string, options?: TOptions): string {
84
- const state = getGlobalState();
85
- if (!state.initialized) {
86
- initI18n();
87
- }
88
- return state.instance.t(key, options) as string;
89
- }
90
-
91
- /**
92
- * 为外部 Extension 注册语言资源
93
- * @param ns 命名空间(通常为 Extension name)
94
- * @param resources 语言资源,key 为语言代码,值为翻译对象
95
- */
96
- export function addLocaleResources(
97
- ns: string,
98
- resources: Record<string, Record<string, unknown>>,
99
- ): 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);
111
- }
112
- }
@@ -1 +0,0 @@
1
- export { initI18n, t, addLocaleResources } from "./i18n";
File without changes