* feat: add vue-i18n * feat: add vue-i18n * feat: add vue-i18n * feat: add language class * add: en templates and configs * add: en names * refactor: name gender id and sect id * feat(i18n): add gettext infrastructure for dynamic text translation (#81) * feat(i18n): add gettext infrastructure for dynamic text translation - Add src/i18n/ module with t() translation function - Add .po/.mo files for zh_CN and en_US locales - Update LanguageManager to reload translations on language change - Add comprehensive tests (14 tests, all passing) - Add implementation spec at docs/specs/i18n-dynamic-text.md Phase 1 of i18n dynamic text implementation. * feat(i18n): expand .po files with comprehensive translation entries Add translation messages for: - Battle result messages (fatal/non-fatal outcomes) - Fortune event messages (item discovery, cultivation gains) - Misfortune event messages (losses, damage, regression) - Death reason messages - Item exchange messages (equip, sell, discard) - Single choice context and option labels - Common labels (weapon, auxiliary, technique, elixir) Both zh_CN and en_US locales updated with matching entries. * test: add .po file integrity tests * feat: i18n for actions * feat: i18n for effects * feat: i18n for gathering * feat: i18n for classes * feat: i18n for classes * feat: i18n for classes * feat: i18n for classes * fix bugs * fix bugs * fix bugs * fix bugs * fix bugs * fix bugs * fix bugs * fix bugs * update csv * update world info * update prompt * update prompt * fix bug * fix bug * fix bug * fix bug * fix bug * fix bug * fix bug * fix bug * fix bug * update * update * update * update * update * update * update --------- Co-authored-by: Zihao Xu <xzhseh@gmail.com>
12 KiB
12 KiB
i18n 国际化测试套件
概述
本测试套件用于确保项目的国际化(i18n)工作质量,包括翻译完整性、代码规范和翻译文件的一致性。
测试文件
1. test_i18n_duplicates.py - PO 文件重复项检查
独立测试,不依赖 conftest.py,可直接运行。
测试内容
- ✅ 检查中文 PO 文件没有重复的 msgid
- ✅ 检查英文 PO 文件没有重复的 msgid
- ✅ 检查中英文 msgid 数量一致
- ✅ 检查中英文 msgid 键完全匹配
运行方式
python tests/test_i18n_duplicates.py
输出示例
============================================================
i18n PO 文件重复项检查
============================================================
检查中文 po 文件没有重复...
[PASS] 中文 po 文件没有重复的 msgid (共 519 个)
检查英文 po 文件没有重复...
[PASS] 英文 po 文件没有重复的 msgid (共 519 个)
检查中英文 msgid 数量一致...
[PASS] 中英文 po 文件的 msgid 数量一致: 519 个
检查中英文 msgid 键完全匹配...
[PASS] 中英文 po 文件的 msgid 键完全匹配
============================================================
[OK] 所有测试通过 (4/4)
2. test_i18n_po_quality.py - PO 文件质量和代码检查
独立测试,专注于静态分析,不依赖项目导入。
测试内容
- 🔍 检查源代码中是否有硬编码的中文字符串(应使用
t()函数) - 🔍 检查代码中使用的所有翻译键是否都在 PO 文件中定义
- 🔍 检查格式化参数在 msgid 和 msgstr 中的一致性
运行方式
python tests/test_i18n_po_quality.py
检查项目详情
1. 硬编码中文字符串检查
扫描 src/ 目录下的所有 Python 文件,查找可能硬编码的中文字符串。
规则:
- 跳过注释和文档字符串
- 跳过测试文件
- 检测字符串字面量中的中文字符
- 如果不在
t()调用中,可能需要修复
常见误报:
- 枚举值的注释(如
RIGHTEOUS = "righteous" # 正) - 测试数据
- 配置键名
2. 翻译键定义检查
使用 AST 解析器提取代码中所有 t() 函数调用,并与 PO 文件中定义的 msgid 对比。
检查逻辑:
# 代码中使用
result = t("{name} obtained {amount} spirit stones", name="张三", amount=100)
# 必须在 messages.po 中有定义
msgid "{name} obtained {amount} spirit stones"
msgstr "{name} 获得灵石 {amount} 枚"
如果发现缺失: 需要在两个 PO 文件中都添加这个翻译键。
3. 格式化参数一致性检查
确保翻译文本中的占位符参数与原始 msgid 一致。
示例:
✅ 正确:
msgid "{name} lost {amount} spirit stones"
msgstr "{name} 损失灵石 {amount} 枚" (参数: name, amount)
❌ 错误:
msgid "{name} lost {amount} spirit stones"
msgstr "{user} 损失灵石 {count} 枚" (参数: user, count) - 不匹配!
输出示例
============================================================
PO 文件质量和翻译键使用检查
============================================================
============================================================
测试: 检查硬编码中文字符串
============================================================
警告:发现可能的硬编码中文字符串(应使用 t() 函数):
============================================================
classes\appearance.py:35
(1, "俊朗", "你长得很成熟,举止协调,给人从容踏实感。", ...)
... 还有 448 个
注意:这可能包括误报,请手动检查
============================================================
测试: 检查翻译键定义
============================================================
PO 文件中定义了 519 个 msgid
代码中使用了 239 个唯一的 msgid
✓ 所有使用的 msgid 都已在 PO 文件中定义
============================================================
测试: 检查格式化参数一致性
============================================================
检查 519 个翻译条目的格式化参数一致性...
✓ 所有翻译的格式化参数都一致
============================================================
测试完成
============================================================
3. test_i18n_classes_coverage.py - Classes 模块国际化覆盖率
需要完整项目环境,用于深度测试 classes 模块的国际化集成。
测试内容
- 🧪 测试各种枚举类型的翻译(境界、性别、阵营等)
- 🧪 测试动作名称的翻译
- 🧪 测试效果名称的翻译
- 🧪 测试带参数的翻译
- 🧪 测试中英文切换
运行方式
python -m pytest tests/test_i18n_classes_coverage.py -v
注意: 此测试依赖项目完整环境,如果有导入错误请先修复项目依赖。
4. test_i18n_dynamic.py - 动态文本翻译测试
标准 pytest 测试,测试 i18n 模块的基本功能。
测试内容
- ✅ PO 文件语法和完整性
- ✅ 中英文基本翻译功能
- ✅ 战斗消息翻译
- ✅ 奇遇消息翻译
- ✅ 死亡原因翻译
- ✅ 语言切换功能
运行方式
python -m pytest tests/test_i18n_dynamic.py -v
快速检查清单
添加新功能时
-
编写代码时:
- ✅ 所有用户可见的文本都使用
t()函数 - ✅ 不要硬编码中文或英文字符串
- ✅ 使用有意义的 msgid(通常是英文描述)
- ✅ 所有用户可见的文本都使用
-
添加翻译:
# 代码中 message = t("{name} obtained {amount} spirit stones", name=avatar.name, amount=100)# messages.po 中(两个语言文件都要加) msgid "{name} obtained {amount} spirit stones" msgstr "{name} 获得灵石 {amount} 枚" # zh_CN msgstr "{name} obtained {amount} spirit stones" # en_US -
运行测试:
# 快速检查 python tests/test_i18n_duplicates.py python tests/test_i18n_po_quality.py # 完整测试 python -m pytest tests/test_i18n_*.py -v
修复常见问题
问题 1: 发现重复的 msgid
# 运行重复检查
python tests/test_i18n_duplicates.py
# 输出会显示重复的行号
[FAIL] 中文 po 文件中发现 2 个重复的 msgid:
- 'Encountered fortune ({theme}), {result}' 出现了 2 次
解决方法: 手动编辑 PO 文件,删除重复的条目
问题 2: 代码中使用但未定义的 msgid
python tests/test_i18n_po_quality.py
# 输出
错误:发现 9 个未在 PO 文件中定义的 msgid:
- 'Unsupported item type: {item_type}'
- '{avatar} gained cultivation experience +{exp} points'
解决方法: 在两个 PO 文件中添加这些 msgid 及其翻译
问题 3: 格式化参数不一致
# 输出
警告:发现 3 个格式化参数不一致的条目:
msgid: {name} lost {amount} spirit stones
原始参数: {'name', 'amount'}
中文参数: {'user', 'count'} # 错误!
英文参数: {'name', 'amount'}
解决方法: 修改中文翻译,使用相同的参数名
CI/CD 集成
GitHub Actions 示例
name: i18n Tests
on: [push, pull_request]
jobs:
i18n-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.11'
- name: Check PO duplicates
run: python tests/test_i18n_duplicates.py
- name: Check PO quality
run: python tests/test_i18n_po_quality.py
- name: Run i18n tests
run: |
pip install pytest
pytest tests/test_i18n_*.py -v
相关工具
tools/i18n/check_po_duplicates.py
独立的检查工具,提供更详细的输出。
python tools/i18n/check_po_duplicates.py
功能:
- 检查重复 msgid
- 检查数量一致性
- 检查键匹配
- 返回适合 CI 的退出码
最佳实践
DO ✅
-
使用 t() 函数包裹所有用户可见文本
# 好 message = t("{name} obtained {amount} spirit stones", name=name, amount=100) # 不好 message = f"{name} 获得灵石 {amount} 枚" -
使用描述性的 msgid
# 好 - 清晰描述 t("cultivate_action_name") t("{name} cultivation increased by {exp} points", ...) # 不好 - 含义不明 t("msg1") t("text_001") -
保持参数名一致
# 好 - 统一使用 name t("{name} defeated {loser}", name=winner, loser=loser) # 不好 - 混用 t("{name} defeated {loser}", user=winner, target=loser)
DON'T ❌
-
不要硬编码文本
# 错误 return "修炼" # 正确 return t("cultivate_action_name") -
不要在 PO 文件中使用不同的参数名
# 错误 msgid "{name} lost {amount} spirit stones" msgstr "{user} 损失灵石 {count} 枚" # 正确 msgid "{name} lost {amount} spirit stones" msgstr "{name} 损失灵石 {amount} 枚" -
不要忘记更新两个语言文件
- 添加 msgid 时,zh_CN 和 en_US 都要更新
- 保持两个文件的 msgid 完全一致
维护指南
定期检查
建议每次提交前运行:
# 快速检查(< 10秒)
python tests/test_i18n_duplicates.py
python tests/test_i18n_po_quality.py
# 如果有变更,运行完整测试
python -m pytest tests/test_i18n_*.py -v
修复工作流
- 发现问题 → 运行测试获取详细信息
- 根据测试输出定位问题
- 修复代码或 PO 文件
- 重新运行测试确认
- 提交更改
技术细节
工具和技术栈
- PO 文件解析: 正则表达式
msgid\s+"([^"]*)" - 代码分析: Python AST (抽象语法树)
- 中文检测: Unicode 范围
\u4e00-\u9fff - 翻译系统: Python gettext
文件结构
src/
├── i18n/
│ ├── __init__.py # t() 函数定义
│ └── locales/
│ ├── zh_CN/LC_MESSAGES/
│ │ ├── messages.po # 中文翻译
│ │ └── messages.mo # 编译后的翻译
│ └── en_US/LC_MESSAGES/
│ ├── messages.po # 英文翻译
│ └── messages.mo # 编译后的翻译
│
tests/
├── test_i18n_duplicates.py # 重复项检查
├── test_i18n_po_quality.py # 质量检查
├── test_i18n_classes_coverage.py # 覆盖率测试
└── test_i18n_dynamic.py # 功能测试
tools/
└── i18n/
└── check_po_duplicates.py # 独立检查工具
常见问题
Q: 测试报告硬编码中文,但那是注释怎么办?
A: 注释中的中文是允许的,测试会跳过。如果误报,可以忽略。
Q: 如何批量添加缺失的翻译?
A:
- 运行
python tests/test_i18n_po_quality.py获取缺失列表 - 在两个 PO 文件末尾添加
- 重新运行测试确认
Q: PO 文件太大,如何组织?
A: 考虑按模块添加注释分隔:
# ============================================================================
# Avatar System
# ============================================================================
msgid "Name"
msgstr "名字"
Q: 如何在代码中动态生成 msgid?
A: 不推荐。msgid 应该是静态的字符串字面量,便于提取和管理。