Files
mai-bot/docs/i18n.md
2026-03-13 00:09:08 +09:00

152 lines
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# i18n Guide
MaiBot 现在使用 `JSON + Crowdin + Babel` 的国际化方案,不依赖 gettext 的 `.po/.mo` 运行时。
## 目录结构
翻译文件位于 `locales/<locale>/*.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/<locale>/` 的单文件 Prompt 模板结构
仍然可以继续做但这次没有全量翻译的内容:
- 所有 Prompt 模板的高质量英文翻译
- 内部协议字段
- debug-only 文案