# i18n Guide MaiBot 现在使用 `JSON + Crowdin + Babel` 的国际化方案,不依赖 gettext 的 `.po/.mo` 运行时。 ## 目录结构 翻译文件位于 `locales//*.json`,当前默认语言是 `zh-CN`。 建议按模块拆分文件: - `core.json` - `startup.json` - `config.json` - `prompts.json` 长 Prompt 模板使用单文件本地化目录: ```text prompts/ zh-CN/ replyer.prompt planner.prompt ``` 注意: - `prompts/zh-CN/` 是 prompt source。 - 不要把 `zh-CN` 原文整批复制到 `prompts/en-US/` 后直接提交。 - 目标语言 prompt 文件应该由 Crowdin 下载生成;在本地还没有目标文件时,运行时会自动回退到 `zh-CN`。 ## 在代码中使用 统一从 [`src/common/i18n/__init__.py`](../src/common/i18n/__init__.py) 导入: ```python from src.common.i18n import t, tn logger.info(t("startup.launching_script", script_file=script_file)) logger.info(tn("core.tasks_cancelled", count)) ``` 可用能力: - `t(key, locale=None, **kwargs)`:普通翻译 - `tn(key, count, locale=None, **kwargs)`:plural 翻译 - `set_locale(locale)` / `get_locale()`:设置或读取当前默认 locale - `format_datetime_localized(...)` - `format_number_localized(...)` - `format_decimal_localized(...)` Prompt 模板统一从 [`src/common/prompt_i18n.py`](../src/common/prompt_i18n.py) 加载: ```python from src.common.prompt_i18n import load_prompt template = load_prompt("replyer") rendered = load_prompt("replyer", identity="Mai", bot_name="麦麦") ``` Prompt 加载规则: - 优先读取 `prompts/<当前 locale>/` - 找不到时回退到 `prompts/zh-CN/` - 如果新目录中还没有对应文件,再回退到历史兼容目录 `prompts/*.prompt` ## locale 优先级 运行时按以下顺序决定 locale: 1. 显式传入 `locale` 2. 当前上下文中的 locale 覆盖(如使用 `use_locale(...)`) 3. 环境变量 `MAIBOT_LOCALE` 4. 默认值 `zh-CN` ## key 规范 - 使用稳定的点分 key,例如 `startup.env_created` - 全部小写 - 不要把中文原文直接当 key ## 新增翻译的步骤 1. 先在 `locales/zh-CN/*.json` 添加 source 文案。 2. 在 `locales/en-US/*.json` 中补上同名 key。 3. 在代码中用 `t()` 或 `tn()` 替换硬编码字符串。 4. 运行 `python scripts/i18n_validate.py` 校验结构。 ## 校验脚本 运行: ```bash python scripts/i18n_validate.py ``` 校验内容包括: - JSON 语法是否合法 - 是否存在重复 key - 是否存在空字符串 key - 各语言 key 集合是否与 `zh-CN` 对齐 - 占位符集合是否一致 - plural 结构是否一致 - prompt 模板已存在时,其占位符集合必须与 `prompts/zh-CN/` 对齐 对于 prompt 模板: - 缺少目标 locale 文件只会给 warning,不会阻断,因为运行时有 fallback - 目标 locale 文件如果存在但占位符漂移,会直接校验失败 ## 候选扫描 如果你想继续做下一批迁移,可以运行: ```bash python scripts/i18n_extract_candidates.py ``` 这个脚本会扫描仓库中的 Python 文件,输出仍然包含中文字符串常量的位置,方便人工挑选下一批适合迁移到 i18n 的文案。 ## Crowdin 项目根目录的 [`crowdin.yml`](../crowdin.yml) 使用 `locales/zh-CN/*.json` 作为 source。 现在也会把 `prompts/zh-CN/**/*.prompt` 作为单文件 Prompt 模板 source 上传到 Crowdin。 GitHub Actions 中的 [`crowdin-sync.yml`](../.github/workflows/crowdin-sync.yml) 会负责和 Crowdin 同步。 常用命令: ```bash crowdin upload sources crowdin upload translations crowdin download translations python scripts/i18n_validate.py ``` ## 当前迁移范围 这一批已经覆盖: - `bot.py` 启动、重启、退出与协议确认提示 - `src/config` 中第一批配置加载、热重载、校验异常提示 - `src/main.py` 的主要启动链路提示 - `src/prompt/prompt_manager.py` 的 locale 感知 Prompt 加载 - `prompts//` 的单文件 Prompt 模板结构 仍然可以继续做但这次没有全量翻译的内容: - 所有 Prompt 模板的高质量英文翻译 - 内部协议字段 - debug-only 文案