Files
spaceflow/docs/advanced/i18n.md
2026-02-15 22:02:21 +08:00

3.6 KiB
Raw Blame History

i18n 国际化

Spaceflow 基于 i18next 实现国际化,采用纯函数式设计,不依赖 NestJS DI。

语言检测优先级

  1. 环境变量 SPACEFLOW_LANG
  2. spaceflow.json 中的 lang 字段
  3. 系统 localeprocess.env.LANG / process.env.LC_ALL
  4. 回退到 zh-CN

核心 API

initI18n(lang?: string)

同步初始化 i18next。必须在 NestJS 模块加载前调用。

import { initI18n } from "@spaceflow/core";

initI18n();      // 自动检测语言
initI18n("en");  // 手动指定

t(key: string, options?: Record<string, unknown>)

全局翻译函数,装饰器和运行时均可使用。

import { t } from "@spaceflow/core";

// 公共 key默认命名空间
t("common.executionFailed", { error: msg });

// Extension 命名空间(用 : 分隔)
t("build:description");
t("review:options.dryRun");

addLocaleResources(ns: string, resources: Record<string, Record<string, string>>)

注册 Extension 的语言资源到指定命名空间。

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 公共语言包

core/src/locales/
├── zh-cn/
│   └── translation.json    # 公共 key
└── en/
    └── translation.json

Extension 语言包

cli/src/commands/<name>/locales/
├── zh-cn/
│   └── <name>.json
├── en/
│   └── <name>.json
└── index.ts                # 导入并注册资源

Extension 中使用 i18n

1. 创建语言包文件

// locales/zh-cn/hello.json
{
  "description": "打招呼命令",
  "options.name": "名字",
  "greeting": "你好,{{name}}"
}

2. 注册语言资源

// 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. 在命令中使用

import { t } from "@spaceflow/core";

// 必须在命令模块 import 之前导入 localesside-effect
import "./locales";

@Command({
  name: "hello",
  description: t("hello:description"),
})
export class HelloCommand extends CommandRunner {
  // ...
}

4. 在 Extension 入口声明

export class HelloExtension implements SpaceflowExtension {
  getMetadata(): SpaceflowExtensionMetadata {
    return {
      name: "hello",
      commands: ["hello"],
      locales: helloLocales, // 加载时自动注册
    };
  }
}

插值语法

使用 i18next 默认的 {{variable}} 语法:

t("hello:greeting", { name: "World" });
// → "你好World"

注意事项

  • 同步初始化initI18n() 使用 initSync,确保装饰器执行时语言包已加载
  • 装饰器时机@Command / @Option 在 import 时执行,initI18n() 必须在所有命令模块 import 之前调用
  • Side-effect import — 每个 Extension 的 locales/index.ts 在导入时立即调用 addLocaleResources
  • key 不存在时 — i18next 默认返回 key 本身,不会报错