# i18n 国际化 Spaceflow 基于 [i18next](https://www.i18next.com/) 实现国际化,采用纯函数式设计,不依赖 NestJS DI。 ## 语言检测优先级 1. 环境变量 `SPACEFLOW_LANG` 2. `spaceflow.json` 中的 `lang` 字段 3. 系统 locale(`process.env.LANG` / `process.env.LC_ALL`) 4. 回退到 `zh-CN` ## 核心 API ### `initI18n(lang?: string)` 同步初始化 i18next。必须在 NestJS 模块加载前调用。 ```typescript import { initI18n } from "@spaceflow/core"; initI18n(); // 自动检测语言 initI18n("en"); // 手动指定 ``` ### `t(key: string, options?: Record)` 全局翻译函数,装饰器和运行时均可使用。 ```typescript import { t } from "@spaceflow/core"; // 公共 key(默认命名空间) t("common.executionFailed", { error: msg }); // Extension 命名空间(用 : 分隔) t("build:description"); t("review:options.dryRun"); ``` ### `addLocaleResources(ns: string, resources: Record>)` 注册 Extension 的语言资源到指定命名空间。 ```typescript import { addLocaleResources } from "@spaceflow/core"; addLocaleResources("hello", { "zh-CN": { description: "打招呼命令" }, en: { description: "Say hello" }, }); ``` ## 命名空间规则 | 类型 | 命名空间 | 示例 | |------|----------|------| | 公共 key | 默认(`translation`) | `common.*`, `config.*`, `extensionLoader.*` | | 内部 Extension | Extension 名称 | `build:`, `dev:`, `commit:`, `install:` 等 | | 外部 Extension | Extension 名称 | `review:`, `publish:`, `ci-scripts:` 等 | ## 语言包结构 ### core 公共语言包 ```text core/src/locales/ ├── zh-cn/ │ └── translation.json # 公共 key └── en/ └── translation.json ``` ### Extension 语言包 ```text cli/src/commands//locales/ ├── zh-cn/ │ └── .json ├── en/ │ └── .json └── index.ts # 导入并注册资源 ``` ## Extension 中使用 i18n ### 1. 创建语言包文件 ```json // locales/zh-cn/hello.json { "description": "打招呼命令", "options.name": "名字", "greeting": "你好,{{name}}!" } ``` ### 2. 注册语言资源 ```typescript // locales/index.ts import zhCN from "./zh-cn/hello.json"; import en from "./en/hello.json"; import { addLocaleResources } from "@spaceflow/core"; export const helloLocales = { "zh-CN": zhCN, en }; // Side-effect: 立即注册 addLocaleResources("hello", helloLocales); ``` ### 3. 在命令中使用 ```typescript import { t } from "@spaceflow/core"; // 必须在命令模块 import 之前导入 locales(side-effect) import "./locales"; @Command({ name: "hello", description: t("hello:description"), }) export class HelloCommand extends CommandRunner { // ... } ``` ### 4. 在 Extension 入口声明 ```typescript export class HelloExtension implements SpaceflowExtension { getMetadata(): SpaceflowExtensionMetadata { return { name: "hello", commands: ["hello"], locales: helloLocales, // 加载时自动注册 }; } } ``` ## 插值语法 使用 i18next 默认的 `{{variable}}` 语法: ```typescript t("hello:greeting", { name: "World" }); // → "你好,World!" ``` ## 注意事项 - **同步初始化** — `initI18n()` 使用 `initSync`,确保装饰器执行时语言包已加载 - **装饰器时机** — `@Command` / `@Option` 在 import 时执行,`initI18n()` 必须在所有命令模块 import 之前调用 - **Side-effect import** — 每个 Extension 的 `locales/index.ts` 在导入时立即调用 `addLocaleResources` - **key 不存在时** — i18next 默认返回 key 本身,不会报错