Feat/i18n (#92)

* 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>
This commit is contained in:
4thfever
2026-01-24 13:47:23 +08:00
committed by GitHub
parent 6f4b648d6e
commit e1091fdf5a
243 changed files with 18297 additions and 3148 deletions

View File

@@ -15,18 +15,32 @@ class TestSectLoading:
# 不夜城 (sect_id=12) 的驻地应该是 "大千光极城"
sect = sects_by_id.get(12)
assert sect is not None, "宗门 ID=12 应该存在"
assert sect.name == "不夜城", "宗门名称应该是 '不夜城'"
assert sect.headquarter.name == "大千光极城", (
f"驻地名称应该是 '大千光极城',而不是 '{sect.headquarter.name}'"
# 兼容多语言环境:检查中文或英文名称
expected_names = {"Sleepless City", "不夜城"}
assert sect.name in expected_names, f"宗门名称 '{sect.name}' 不在预期列表中: {expected_names}"
expected_hqs = {"Daqian Aurora City", "大千光极城"}
assert sect.headquarter.name in expected_hqs, (
f"驻地名称 '{sect.headquarter.name}' 不在预期列表中: {expected_hqs}"
)
def test_sect_headquarter_desc_loaded(self):
"""测试宗门驻地描述正确加载(来自 sect_region.csv 的 desc 列)"""
sect = sects_by_id.get(12)
assert sect is not None
# 验证描述不为空且包含关键词
# 验证描述不为空且包含关键词 (兼容中英文)
assert sect.headquarter.desc, "驻地描述不应为空"
assert "极光" in sect.headquarter.desc, "驻地描述应该包含 '极光'"
desc = sect.headquarter.desc.lower()
# 简单宽松的检查:只要包含任一语言的关键词即可,
# 因为测试环境加载语言的顺序可能不确定pytest 并行或 fixture 顺序)。
# 这样无论当前加载的是哪种语言的数据,只要数据本身正确就能通过。
keywords = ["aurora", "极光", "不夜"]
found = any(k in desc for k in keywords)
assert found, f"驻地描述 '{desc}' 应该包含以下关键词之一: {keywords}"
def test_all_sects_have_headquarters(self):
"""测试所有宗门都有驻地信息"""
@@ -61,9 +75,13 @@ class TestTechniqueLoading:
# 草字剑诀 (id=30) 属于明心剑宗 (sect_id=1)
technique = techniques_by_id.get(30)
assert technique is not None, "功法 ID=30 应该存在"
assert technique.name == "草字剑诀", f"功法名称应该是 '草字剑诀',而不是 '{technique.name}'"
# 兼容多语言环境
expected_names = {"Grass Word Sword Formula", "草字剑诀"}
assert technique.name in expected_names, f"功法名称 '{technique.name}' 不在预期列表中: {expected_names}"
assert technique.sect_id == 1, (
f"功法 '草字剑诀' 的 sect_id 应该是 1而不是 {technique.sect_id}"
f"功法 '{technique.name}' 的 sect_id 应该是 1而不是 {technique.sect_id}"
)
def test_technique_without_sect(self):