diff --git a/docs/I18N_MAINTENANCE_GUIDE.md b/docs/I18N_MAINTENANCE_GUIDE.md index d3b6c0e..a94074c 100644 --- a/docs/I18N_MAINTENANCE_GUIDE.md +++ b/docs/I18N_MAINTENANCE_GUIDE.md @@ -14,33 +14,45 @@ --- -## 2. 正确的增补方式 +## 2. 正确的增补方式 (Source Split, Build Merge) -### 方法 A:直接使用 IDE 编辑 (推荐) -最安全、最简单的方法。直接在 Cursor / VSCode 中打开 `src/i18n/locales/xx_XX/LC_MESSAGES/messages.po`,在文件末尾手动粘贴或输入新的翻译条目。 +项目现已采用 **"Source Split, Build Merge"** 策略,将庞大的 `messages.po` 拆分为多个模块文件。 -### 方法 B:使用 Python 脚本追加 -如果必须通过脚本自动化,请务必使用 Python 并显式指定 UTF-8 编码。 +**请勿直接修改 `LC_MESSAGES/messages.po`!该文件现由构建脚本自动生成。** -```python -# correct_append.py -content = """ -msgid "new_key" -msgstr "Translation" -""" +### 方法 A:修改模块文件 (推荐) -with open("path/to/messages.po", "a", encoding="utf-8") as f: - f.write(content) -``` +所有源文件位于 `static/locales/{lang}/modules/` 目录下。请根据内容分类修改对应的 `.po` 文件: -### 方法 C:Linux/Bash 环境 -在 Git Bash 或 WSL 中使用 `cat >>` 是安全的,因为它们默认处理 UTF-8 流。 +* `static/locales/zh-CN/modules/battle.po` - 战斗相关 +* `static/locales/zh-CN/modules/action.po` - 动作相关 +* `static/locales/zh-CN/modules/fortune.po` - 奇遇相关 +* `static/locales/zh-CN/modules/ui.po` - 界面相关 +* ... (以及其他分类) + +直接使用编辑器打开相应的模块文件进行修改或追加。 + +### 方法 B:构建与合并 + +修改完成后,必须运行构建脚本将模块合并并编译为 MO 文件: ```bash -# Git Bash / WSL only -cat temp.po >> messages.po +# 在项目根目录下运行 +python tools/i18n/build_mo.py ``` +该脚本会: +1. 合并 `modules/*.po` 到 `LC_MESSAGES/messages.po` +2. 编译生成 `LC_MESSAGES/messages.mo` +3. 编译其他独立文件 (如 `game_configs.po`) + +### 方法 C:添加新模块 + +如果需要添加新的分类: +1. 在 `static/locales/{lang}/modules/` 下新建 `{category}.po`。 +2. 确保包含标准 Header (参考其他模块)。 +3. 运行 `build_mo.py` 即可自动识别并合并。 + --- ## 3. 文件格式规范 diff --git a/docs/i18n-action-usage.md b/docs/i18n-action-usage.md index b0168a5..eb286fc 100644 --- a/docs/i18n-action-usage.md +++ b/docs/i18n-action-usage.md @@ -125,9 +125,11 @@ def start(self, target_name: str) -> Event: ## 添加翻译 -### 1. 在 po 文件中添加条目 +### 1. 在模块化 po 文件中添加条目 -**英文** (`src/i18n/locales/en_US/LC_MESSAGES/messages.po`): +请在 `static/locales/{lang}/modules/action.po` 文件中添加翻译,而不是直接修改 `messages.po`。 + +**英文** (`static/locales/en-US/modules/action.po`): ```po # Action: MyAction msgid "my_action_name" @@ -140,7 +142,7 @@ msgid "{avatar} starts attacking {target}!" msgstr "{avatar} starts attacking {target}!" ``` -**中文** (`src/i18n/locales/zh_CN/LC_MESSAGES/messages.po`): +**中文** (`static/locales/zh-CN/modules/action.po`): ```po # Action: MyAction msgid "my_action_name" @@ -153,18 +155,15 @@ msgid "{avatar} starts attacking {target}!" msgstr "{avatar} 开始攻击 {target}!" ``` -### 2. 编译 po 文件 +### 2. 编译并合并 + +运行项目根目录下的构建脚本,它会将模块文件合并并编译: ```bash -# Windows (需要安装 gettext) -msgfmt src/i18n/locales/zh_CN/LC_MESSAGES/messages.po -o src/i18n/locales/zh_CN/LC_MESSAGES/messages.mo -msgfmt src/i18n/locales/en_US/LC_MESSAGES/messages.po -o src/i18n/locales/en_US/LC_MESSAGES/messages.mo - -# macOS/Linux -msgfmt src/i18n/locales/zh_CN/LC_MESSAGES/messages.po -o src/i18n/locales/zh_CN/LC_MESSAGES/messages.mo -msgfmt src/i18n/locales/en_US/LC_MESSAGES/messages.po -o src/i18n/locales/en_US/LC_MESSAGES/messages.mo +python tools/i18n/build_mo.py ``` + ## 迁移现有 Action 对于现有的 Action(如 `Assassinate`),按以下步骤迁移: diff --git a/docs/i18n-avatar-usage.md b/docs/i18n-avatar-usage.md index 3059bc1..3d9e8fb 100644 --- a/docs/i18n-avatar-usage.md +++ b/docs/i18n-avatar-usage.md @@ -392,7 +392,7 @@ print(info[t("Name")]) # 输出键名为英文的字典 1. **新增字段时同步添加翻译**: - 在 `info_presenter.py` 添加新字段时 - 使用 `t("New Field Label")` 作为键名 - - 在 PO 文件添加对应翻译 + - 在 `static/locales/{lang}/modules/avatar.po` (或 `ui.po`) 添加对应翻译 2. **保持命名规范**: - 字段名使用英文,首字母大写(如 `"Spirit Root"`) diff --git a/docs/i18n-effect-usage.md b/docs/i18n-effect-usage.md index 3c0385d..2eba6ea 100644 --- a/docs/i18n-effect-usage.md +++ b/docs/i18n-effect-usage.md @@ -256,7 +256,7 @@ print(get_effect_desc("extra_max_hp")) # 输出:Max HP 1. **新增 Effect 时同步添加翻译**: - 在 `consts.py` 定义新 effect - 在 `desc.py` 的 `get_effect_desc()` 添加 msgid 映射 - - 在 PO 文件添加中英文翻译 + - 在 `static/locales/{lang}/modules/effect.po` 添加中英文翻译 2. **保持命名规范**: - Effect msgid: `effect_{effect_key}` diff --git a/docs/i18n-gathering-usage.md b/docs/i18n-gathering-usage.md index 69adc06..e35d491 100644 --- a/docs/i18n-gathering-usage.md +++ b/docs/i18n-gathering-usage.md @@ -330,7 +330,7 @@ print(Auction.get_story_prompt()) # 输出英文提示词 1. **新增 Gathering 类型时同步添加翻译**: - 如果添加新的 Gathering 实现(如"宗门大比"、"秘境开启") - 遵循相同的模式:类变量 + classmethod - - 在 PO 文件添加对应翻译 + - 在 `static/locales/{lang}/modules/gathering.po` 添加对应翻译 2. **保持命名规范**: - LLM Prompt msgid 格式:`{gathering_type}_story_prompt` @@ -398,7 +398,7 @@ class SectCompetition(Gathering): # ... 其他方法使用 t() 翻译所有文本 ``` -然后在 PO 文件添加对应翻译即可。 +然后在 `static/locales/{lang}/modules/gathering.po` 添加对应翻译即可。 --- diff --git a/docs/specs/i18n-dynamic-text.md b/docs/specs/i18n-dynamic-text.md index 143955f..220f521 100644 --- a/docs/specs/i18n-dynamic-text.md +++ b/docs/specs/i18n-dynamic-text.md @@ -49,15 +49,24 @@ Use Python's standard `gettext` module with `.po/.mo` translation files. ``` src/i18n/ ├── __init__.py # Export t() function -└── locales/ - ├── zh_CN/ - │ └── LC_MESSAGES/ - │ ├── messages.po # Chinese translations (source) - │ └── messages.mo # Compiled binary (runtime) - └── en_US/ - └── LC_MESSAGES/ - ├── messages.po # English translations (source) - └── messages.mo # Compiled binary (runtime) +└── ... (locales moved to static/locales) + +static/locales/ + ├── zh-CN/ + │ ├── LC_MESSAGES/ + │ │ ├── messages.po # Merged Chinese translations (do not edit directly) + │ │ └── messages.mo # Compiled binary (runtime) + │ └── modules/ # Source translation modules + │ ├── battle.po + │ ├── fortune.po + │ └── ... + └── en-US/ + ├── LC_MESSAGES/ + │ ├── messages.po # Merged English translations + │ └── messages.mo # Compiled binary + └── modules/ + ├── battle.po + └── ... ``` #### 1.2 Create `src/i18n/__init__.py` @@ -77,14 +86,15 @@ def _get_translation() -> Optional[gettext.GNUTranslations]: lang = str(language_manager) if lang not in _translations: - locale_dir = Path(__file__).parent / "locales" + # Point to static/locales + locale_dir = Path(__file__).resolve().parent.parent.parent / "static" / "locales" - # Map language codes to gettext locale names + # Map language codes to gettext locale names (now same as folder names) locale_map = { - "zh-CN": "zh_CN", - "en-US": "en_US", + "zh-CN": "zh-CN", + "en-US": "en-US", } - locale_name = locale_map.get(lang, "zh_CN") + locale_name = locale_map.get(lang, "zh-CN") try: trans = gettext.translation( @@ -190,7 +200,7 @@ From `death_reason.py`: --- -### Phase 3: Create .po Files +### Phase 3: Create Modular .po Files #### 3.1 Message Key Convention @@ -201,99 +211,49 @@ msgid "{winner} defeated {loser}, dealing {damage} damage. {loser} was fatally w msgstr "" ``` -#### 3.2 Chinese Translation File +#### 3.2 Chinese Translation Modules +Create separate files in `static/locales/zh-CN/modules/`: + +**`battle.po`**: ```po -# src/i18n/locales/zh_CN/LC_MESSAGES/messages.po - -# Header +# static/locales/zh-CN/modules/battle.po msgid "" msgstr "" "Content-Type: text/plain; charset=UTF-8\n" -"Language: zh_CN\n" -# Battle messages msgid "{winner} defeated {loser}, dealing {damage} damage. {loser} was fatally wounded and perished." msgstr "{winner} 战胜了 {loser},造成 {damage} 点伤害。{loser} 遭受重创,当场陨落。" msgid "{winner} defeated {loser}. {loser} took {loser_dmg} damage, {winner} also took {winner_dmg} damage." msgstr "{winner} 战胜了 {loser},{loser} 受伤 {loser_dmg} 点,{winner} 也受伤 {winner_dmg} 点。" - -# Fortune messages -msgid "Encountered fortune ({theme}), {result}" -msgstr "遭遇奇遇({theme}),{result}" - -msgid "Found weapon '{weapon}', {exchange_result}" -msgstr "发现了兵器『{weapon}』,{exchange_result}" - -msgid "{name} obtained {amount} spirit stones" -msgstr "{name} 获得灵石 {amount} 枚" - -msgid "{name} cultivation increased by {exp} points" -msgstr "{name} 修为增长 {exp} 点" - -msgid "{apprentice} became disciple of {master}" -msgstr "{apprentice} 拜 {master} 为师" - -# Misfortune messages -msgid "Encountered misfortune ({theme}), {result}" -msgstr "遭遇霉运({theme}),{result}" - -msgid "{name} lost {amount} spirit stones" -msgstr "{name} 损失灵石 {amount} 枚" - -msgid "{name} took {damage} damage, HP remaining {current}/{max}" -msgstr "{name} 受到伤害 {damage} 点,剩余HP {current}/{max}" - -msgid "{name} cultivation regressed by {amount} points" -msgstr "{name} 修为倒退 {amount} 点" - -# Death reasons -msgid "Killed by {killer}" -msgstr "被{killer}杀害" - -msgid "Died from severe injuries" -msgstr "重伤不治身亡" - -msgid "Died of old age" -msgstr "寿元耗尽而亡" ``` -#### 3.3 English Translation File - +**`fortune.po`**: ```po -# src/i18n/locales/en_US/LC_MESSAGES/messages.po - -# Header +# static/locales/zh-CN/modules/fortune.po msgid "" msgstr "" "Content-Type: text/plain; charset=UTF-8\n" -"Language: en_US\n" -# Battle messages -msgid "{winner} defeated {loser}, dealing {damage} damage. {loser} was fatally wounded and perished." -msgstr "{winner} defeated {loser}, dealing {damage} damage. {loser} was fatally wounded and perished." - -# ... (msgid == msgstr for English) +msgid "Encountered fortune ({theme}), {result}" +msgstr "遭遇奇遇({theme}),{result}" +# ... other fortune messages ``` +#### 3.3 English Translation Modules + +Create similar files in `static/locales/en-US/modules/`. + #### 3.4 Compile .po to .mo +Use the build script to merge modules and compile: + ```bash -# Install gettext tools if needed (macOS) -brew install gettext - -# Compile -msgfmt src/i18n/locales/zh_CN/LC_MESSAGES/messages.po -o src/i18n/locales/zh_CN/LC_MESSAGES/messages.mo -msgfmt src/i18n/locales/en_US/LC_MESSAGES/messages.po -o src/i18n/locales/en_US/LC_MESSAGES/messages.mo +# Merges modules/*.po -> LC_MESSAGES/messages.po -> messages.mo +python tools/i18n/build_mo.py ``` -Add to Makefile or script: -```makefile -compile-i18n: - msgfmt src/i18n/locales/zh_CN/LC_MESSAGES/messages.po -o src/i18n/locales/zh_CN/LC_MESSAGES/messages.mo - msgfmt src/i18n/locales/en_US/LC_MESSAGES/messages.po -o src/i18n/locales/en_US/LC_MESSAGES/messages.mo -``` --- @@ -428,10 +388,10 @@ def load_save(path: str): | File | Description | |------|-------------| | `src/i18n/__init__.py` | Translation module with `t()` function | -| `src/i18n/locales/zh_CN/LC_MESSAGES/messages.po` | Chinese translations | -| `src/i18n/locales/zh_CN/LC_MESSAGES/messages.mo` | Compiled Chinese | -| `src/i18n/locales/en_US/LC_MESSAGES/messages.po` | English translations | -| `src/i18n/locales/en_US/LC_MESSAGES/messages.mo` | Compiled English | +| `static/locales/zh-CN/LC_MESSAGES/messages.po` | Generated Chinese translations (Merged) | +| `static/locales/zh-CN/LC_MESSAGES/messages.mo` | Compiled Chinese | +| `static/locales/en-US/LC_MESSAGES/messages.po` | Generated English translations (Merged) | +| `static/locales/en-US/LC_MESSAGES/messages.mo` | Compiled English | | `tests/test_i18n.py` | Unit tests | ### Modified Files diff --git a/docs/specs/i18n-game-configs.md b/docs/specs/i18n-game-configs.md index 7a3ba4b..d5c07bd 100644 --- a/docs/specs/i18n-game-configs.md +++ b/docs/specs/i18n-game-configs.md @@ -26,14 +26,14 @@ id,name_id,name,desc_id,desc,danger_prob hidden_domain_wood,HIDDEN_DOMAIN_WOOD_NAME,万木残界,HIDDEN_DOMAIN_WOOD_DESC,此乃...,0.3 ``` -### 2. Translation Files (`src/i18n/locales/`) +### 2. Translation Files (`static/locales/`) - **`game_configs.po`**: Contains translations for config IDs. - Generated/Updated via tool scanning CSVs. - **`messages.po`**: Contains translations for dynamic code strings (existing). ### 3. Build Process -- `tools/i18n/build_mo.py` merges `messages.po` and `game_configs.po` into a single `messages.mo` for runtime efficiency. -- Or loads them as separate domains (Current decision: Merge for simplicity). +- `tools/i18n/build_mo.py` compiles `game_configs.po` into `game_configs.mo`. +- Runtime uses separate domains: `messages` (default) and `game_configs` (fallback). ### 4. Runtime Loading (`src/utils/df.py`) 1. Load CSV from `static/game_configs/`. @@ -50,8 +50,8 @@ hidden_domain_wood,HIDDEN_DOMAIN_WOOD_NAME,万木残界,HIDDEN_DOMAIN_WOOD_DESC, 3. Fill `name`/`desc` with Chinese text (Reference). 4. Fill `name_id`/`desc_id` (Convention: `{FILE}_{ID}_NAME`). 5. Run extraction tool (to be created) to update `game_configs.pot` and `.po` files. -6. Add English translation in `src/i18n/locales/en_US/LC_MESSAGES/game_configs.po`. -7. (Optional) Run `build_mo.py` to test locally (Auto-run in build pipeline). +6. Add English translation in `static/locales/en-US/LC_MESSAGES/game_configs.po`. +7. Run `python tools/i18n/build_mo.py` to compile translation files. ## Tools diff --git a/src/classes/ai.py b/src/classes/ai.py index fa8ba3b..d68086c 100644 --- a/src/classes/ai.py +++ b/src/classes/ai.py @@ -11,7 +11,7 @@ from src.classes.world import World from src.classes.event import Event, NULL_EVENT from src.utils.llm import call_llm_with_task_name from src.classes.typings import ACTION_NAME_PARAMS_PAIRS -from src.classes.actions import ACTION_INFOS_STR +from src.classes.actions import get_action_infos_str from src.utils.config import CONFIG if TYPE_CHECKING: @@ -51,7 +51,7 @@ class LLMAI(AI): """ 异步决策逻辑:通过LLM决定执行什么动作和参数 """ - general_action_infos = ACTION_INFOS_STR + general_action_infos = get_action_infos_str() async def decide_one(avatar: Avatar): # 获取基于该角色已知区域的世界信息(包含距离计算) diff --git a/src/classes/event.py b/src/classes/event.py index 8a6deab..dee81c9 100644 --- a/src/classes/event.py +++ b/src/classes/event.py @@ -7,7 +7,7 @@ import uuid import time from datetime import datetime -from src.classes.calendar import Month, Year, MonthStamp +from src.classes.calendar import Month, Year, MonthStamp, get_date_str @dataclass class Event: @@ -25,9 +25,7 @@ class Event: created_at: float = field(default_factory=time.time) def __str__(self) -> str: - year = self.month_stamp.get_year() - month = self.month_stamp.get_month() - return f"{year}年{month}月: {self.content}" + return f"{get_date_str(int(self.month_stamp))}: {self.content}" def to_dict(self) -> dict: """转换为可序列化的字典""" diff --git a/src/classes/sect.py b/src/classes/sect.py index 2f22e3f..3a41f9f 100644 --- a/src/classes/sect.py +++ b/src/classes/sect.py @@ -85,7 +85,7 @@ class Sect: effect_part = t(" Effect: {effect_desc}", effect_desc=self.effect_desc) if self.effect_desc else "" return t("{sect_name} (Alignment: {alignment}, Style: {style}, Headquarters: {hq_name}){effect}", sect_name=self.name, alignment=str(self.alignment), - style=self.member_act_style, hq_name=hq.name, effect=effect_part) + style=t(self.member_act_style), hq_name=hq.name, effect=effect_part) def get_rank_name(self, rank: "SectRank") -> str: """ @@ -100,7 +100,8 @@ class Sect: from src.classes.sect_ranks import SectRank, DEFAULT_RANK_NAMES from src.i18n import t # 优先使用自定义名称,否则使用默认名称 - return self.rank_names.get(rank.value, DEFAULT_RANK_NAMES.get(rank, t("Disciple"))) + val = self.rank_names.get(rank.value, DEFAULT_RANK_NAMES.get(rank, t("Disciple"))) + return t(val) def get_structured_info(self) -> dict: hq = self.headquarter @@ -327,7 +328,7 @@ def get_sect_info_with_rank(avatar: "Avatar", detailed: bool = False) -> str: # 构造详细信息,使用标准空格和括号 detail_content = t("(Alignment: {alignment}, Style: {style}, Headquarters: {hq_name}){effect}", alignment=avatar.sect.alignment, - style=avatar.sect.member_act_style, + style=t(avatar.sect.member_act_style), hq_name=hq.name, effect=effect_part) diff --git a/src/i18n/__init__.py b/src/i18n/__init__.py index 718cb32..a59dcc9 100644 --- a/src/i18n/__init__.py +++ b/src/i18n/__init__.py @@ -20,25 +20,22 @@ logger = logging.getLogger(__name__) def _get_locale_dir() -> Path: """Get the locales directory path.""" - return Path(__file__).parent / "locales" + # src/i18n/__init__.py -> src/i18n -> src -> root + return Path(__file__).resolve().parent.parent.parent / "static" / "locales" def _lang_to_locale(lang_code: str) -> str: """ Convert language code to gettext locale name. + Now we use the same code as folder name (e.g. zh-CN). Args: lang_code: Language code like "zh-CN" or "en-US". Returns: - Locale name like "zh_CN" or "en_US". + Locale name like "zh-CN" or "en-US". """ - locale_map = { - "zh-CN": "zh_CN", - "zh-TW": "zh_TW", - "en-US": "en_US", - } - return locale_map.get(lang_code, "zh_CN") + return lang_code def _get_current_lang() -> str: diff --git a/src/i18n/locales/en_US/LC_MESSAGES/messages.mo b/src/i18n/locales/en_US/LC_MESSAGES/messages.mo deleted file mode 100644 index 1519ac0..0000000 Binary files a/src/i18n/locales/en_US/LC_MESSAGES/messages.mo and /dev/null differ diff --git a/src/i18n/locales/en_US/modules/sect.po b/src/i18n/locales/en_US/modules/sect.po deleted file mode 100644 index 927ebfd..0000000 --- a/src/i18n/locales/en_US/modules/sect.po +++ /dev/null @@ -1,48 +0,0 @@ -# -msgid "" -msgstr "" -"Project-Id-Version: cultivation-world-simulator 1.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-01-20 00:00+0000\n" -"PO-Revision-Date: 2024-01-20 00:00+0000\n" -"Last-Translator: \n" -"Language-Team: English\n" -"Language: en_US\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -# Sect Rank -msgid "patriarch" -msgstr "Patriarch" - -msgid "elder" -msgstr "Elder" - -msgid "inner_disciple" -msgstr "Inner Disciple" - -msgid "outer_disciple" -msgstr "Outer Disciple" - -# ============================================================================ -# Sect System - Sects -# ============================================================================ -msgid "{sect_name} (Alignment: {alignment}, Headquarters: {hq_name})" -msgstr "{sect_name} (Alignment: {alignment}, Headquarters: {hq_name})" - -msgid "" -"{sect_name} (Alignment: {alignment}, Style: {style}, Headquarters: " -"{hq_name}){effect}" -msgstr "" -"{sect_name} (Alignment: {alignment}, Style: {style}, Headquarters: " -"{hq_name}){effect}" - -# ============================================================================ -# Relation & Root & Appearance & Sect (Refined) -# ============================================================================ -msgid "Unknown reason" -msgstr "Unknown reason" - -msgid "{name} (Deceased: {reason})" -msgstr "{name} (Deceased: {reason})" diff --git a/src/i18n/locales/zh_CN/LC_MESSAGES/messages.mo b/src/i18n/locales/zh_CN/LC_MESSAGES/messages.mo deleted file mode 100644 index b6c805f..0000000 Binary files a/src/i18n/locales/zh_CN/LC_MESSAGES/messages.mo and /dev/null differ diff --git a/src/i18n/locales/zh_TW/LC_MESSAGES/messages.mo b/src/i18n/locales/zh_TW/LC_MESSAGES/messages.mo deleted file mode 100644 index 10358d6..0000000 Binary files a/src/i18n/locales/zh_TW/LC_MESSAGES/messages.mo and /dev/null differ diff --git a/static/game_configs/sect.csv b/static/game_configs/sect.csv index 135ffbb..4aab5c9 100644 --- a/static/game_configs/sect.csv +++ b/static/game_configs/sect.csv @@ -1,16 +1,16 @@ id,name_id,desc_id,name,desc,member_act_style,alignment,weight,preferred_weapon,effects,rank_names ,名称ID,描述ID,,宗门名称与描述,宗门成员行事风格,阵营(正/中立/邪),权重(默认1),倾向兵器类型,effects(JSON形式,支持宽松格式,见effects.py说明),自定义职位(掌门;长老;内门;外门) -1,SECT_1_NAME,SECT_1_DESC,明心剑宗,通玄界东方第一宗,以无上剑道称雄于世。云纹阵法为不传心法。【剑道专精】作为剑修,你使用剑类兵器时战力惊人,且在剑道上的感悟速度远超常人。,清明克己,行止如一。重剑与心法并重,讲究明心见性。,RIGHTEOUS,1,SWORD,"{extra_battle_strength_points: 3, extra_weapon_proficiency_gain: 0.5}", -2,SECT_2_NAME,SECT_2_DESC,百兽宗,以驯养灵兽闻名,豢养各种妖兽灵怪为战力。【御兽大师】你拥有独特的御兽天赋,捕捉妖兽对你来说轻而易举,善于驱使兽群为你而战。,言语直接,重视力量与血性,崇尚狩猎与搏斗。,EVIL,1,WHIP,"{extra_catch_success_rate: 0.25, extra_hunt_materials: 1}",谷主;供奉;驭兽师;扈从 -3,SECT_3_NAME,SECT_3_DESC,水镜宗,"正道十宗之一,实则严守中立。拥有仙界异宝""彻天水镜""可预知未来。【趋吉避凶】你拥有超乎常人的直觉,视野开阔,且极易在探索中发现奇遇。",处事冷静圆融,喜以柔克刚,擅借力与反制。,NEUTRAL,1,FAN,"{extra_observation_radius: 2, extra_fortune_probability: 0.002, extra_refine_success_rate: 0.05}",镜主;掌镜人;传人;侍镜 -4,SECT_4_NAME,SECT_4_DESC,冥王宗,行走幽冥之道,术法阴冷狠厉。【通幽】你修行幽冥之法,心志坚定,突破瓶颈时心无杂念,成功率更高。,言辞冷厉少情,敬畏因果而不惧杀伐,偏向效率与结果。,EVIL,1,FAN,"{extra_breakthrough_success_rate: 0.1, extra_retreat_success_rate: 0.1}",殿主;判官;无常;鬼卒 -5,SECT_5_NAME,SECT_5_DESC,朱勾宗,邪宗大派。以炼器、机关、暗杀闻名于世,素来阴毒冷僻。【暗杀专家】你精通潜伏与刺杀,对于强敌,避开正面交锋、伺机暗杀往往是你最佳的制胜之道。,直面欲望与代价,不惧黑暗,以攻伐见长。,EVIL,1,HIDDEN_WEAPON,"{extra_assassinate_success_rate: 0.15, extra_battle_strength_points: 1, extra_cast_success_rate: 0.05}",楼主;掌刑使;影刺;探子 -6,SECT_6_NAME,SECT_6_DESC,合欢宗,以情入道,靠双修增进修为,善驭人心,长于权变。【双修秘术】你的体质特殊,通过双修能获得远超常人的修为提升,这是你提升境界的最佳捷径。,辞令婉转,善于拿捏人欲与局势,以柔制刚。,NEUTRAL,1,ZITHER,"{extra_dual_cultivation_exp: 150, shop_buy_price_reduction: 0.1}",宫主;护法;媚仙;侍童 -7,SECT_7_NAME,SECT_7_DESC,镇魂宗,铁血风格,擅安魂、封邪、渡厄,兼有刚烈镇压之术。【金刚不坏】你修习护体神功,拥有极强的肉身防御与伤害减免能力,如山岳般不可撼动。,肃穆沉稳,重安魂镇邪,少言而果决。,RIGHTEOUS,1,STAFF,"{extra_max_hp: 100, damage_reduction: 0.15}",住持;首座;行者;居士 -8,SECT_8_NAME,SECT_8_DESC,幽魂噬影宗,镇宗典籍《幽冥录》。幽明气为根基。【如影随形】你极擅身法与遁术,遇到危险时总能全身而退,亦能伺机刺杀落单之敌。,行事隐秘果断,重结果轻虚名,擅潜行与出其不意。,EVIL,1,SABER,"{extra_escape_success_rate: 0.4, extra_assassinate_success_rate: 0.15}",门主;护法;影卫;探子 -9,SECT_9_NAME,SECT_9_DESC,千帆城,炼器大宗,巧匠云集。著名法宝有灵灭丝、定魂蓝星等。商旅云集,自成体系。【巧夺天工】你深谙炼器与经商之道,温养兵器时常能使其脱胎换骨,且在交易中总能获利。,务实精明,重交易与信誉,崇尚规则与秩序。,NEUTRAL,1,SPEAR,"{extra_item_sell_price_multiplier: 0.05, extra_weapon_upgrade_chance: 0.15, extra_cast_success_rate: 0.05, shop_buy_price_reduction: 0.05}",城主;大供奉;执事;学徒 -10,SECT_10_NAME,SECT_10_DESC,妙化宗,精擅音律杀伐与精神操控,功法诡谲阴柔,以无形琴音乱人心智,杀人于无形。【魔音贯耳】你擅长以音律乱人心智,灵力深厚绵长,虽不擅肉搏,但手段诡谲。,文雅缥缈中深藏算计,喜用言语与音律掌控局势,杀伐不沾烟火气。,EVIL,1,ZITHER,"{extra_escape_success_rate: 0.5, extra_misfortune_probability: -0.005}", -11,SECT_11_NAME,SECT_11_DESC,回玄宗,当世第一阵法大派,以阵法阵诀独步天下,讲究阵法推演与巧思妙用。【阵法聚灵】你善用阵法辅助修炼,能够聚集天地灵气,修炼速度快于常人,且常有意外收获。,严谨细致,追求技术极致,战斗中擅长以后手阵法反制敌人,步步为营。,RIGHTEOUS,1,HIDDEN_WEAPON,"{cultivate_duration_reduction: 0.1, extra_fortune_probability: 0.005}", -12,SECT_12_NAME,SECT_12_DESC,不夜城,修习极光玄真法,以万里极光壁的绝对防御闻名于世。【生生不息】你的生命力极其顽强,疗伤效果倍增,寿元亦远超同阶修士。,坚韧顽强,在逆境中图强,行事光明磊落但也深谋远虑,极其护短。,RIGHTEOUS,1,FAN,"{extra_hp_recovery_rate: 0.5, extra_max_lifespan: 20}",城主;阁老;执令;守夜人 -13,SECT_13_NAME,SECT_13_DESC,天行健宗,专修浩然之气,行事正大光明,刚健果决,对邪魔外道有极强的克制力。【浩然正气】你养浩然之气,气脉悠长,面对境界低于自己的敌人时,能发挥出极强的压制力。,恪守原则,讲究道义,除魔卫道一马当先,宁折不弯。,RIGHTEOUS,1,SWORD,{realm_suppression_bonus: 0.15}, -14,SECT_14_NAME,SECT_14_DESC,噬魔宗,通玄界第一魔宗,行事霸道残忍,擅长搜精噬血与肉体魔功。【搜刮成性】你崇尚力量与掠夺,搜刮凡人虽有伤天和,但能为你带来惊人的财富与资源。,强者为尊,随心所欲,崇尚绝对的力量与杀戮,视众生为血食。,EVIL,1,SABER,"{extra_plunder_multiplier: 2.0, extra_battle_strength_points: 2}", +1,SECT_1_NAME,SECT_1_DESC,明心剑宗,通玄界东方第一宗,以无上剑道称雄于世。云纹阵法为不传心法。【剑道专精】作为剑修,你使用剑类兵器时战力惊人,且在剑道上的感悟速度远超常人。,SECT_1_STYLE,RIGHTEOUS,1,SWORD,"{extra_battle_strength_points: 3, extra_weapon_proficiency_gain: 0.5}", +2,SECT_2_NAME,SECT_2_DESC,百兽宗,以驯养灵兽闻名,豢养各种妖兽灵怪为战力。【御兽大师】你拥有独特的御兽天赋,捕捉妖兽对你来说轻而易举,善于驱使兽群为你而战。,SECT_2_STYLE,EVIL,1,WHIP,"{extra_catch_success_rate: 0.25, extra_hunt_materials: 1}",SECT_2_RANK_PATRIARCH;SECT_2_RANK_ELDER;SECT_2_RANK_INNER;SECT_2_RANK_OUTER +3,SECT_3_NAME,SECT_3_DESC,水镜宗,"正道十宗之一,实则严守中立。拥有仙界异宝""彻天水镜""可预知未来。【趋吉避凶】你拥有超乎常人的直觉,视野开阔,且极易在探索中发现奇遇。",SECT_3_STYLE,NEUTRAL,1,FAN,"{extra_observation_radius: 2, extra_fortune_probability: 0.002, extra_refine_success_rate: 0.05}",SECT_3_RANK_PATRIARCH;SECT_3_RANK_ELDER;SECT_3_RANK_INNER;SECT_3_RANK_OUTER +4,SECT_4_NAME,SECT_4_DESC,冥王宗,行走幽冥之道,术法阴冷狠厉。【通幽】你修行幽冥之法,心志坚定,突破瓶颈时心无杂念,成功率更高。,SECT_4_STYLE,EVIL,1,FAN,"{extra_breakthrough_success_rate: 0.1, extra_retreat_success_rate: 0.1}",SECT_4_RANK_PATRIARCH;SECT_4_RANK_ELDER;SECT_4_RANK_INNER;SECT_4_RANK_OUTER +5,SECT_5_NAME,SECT_5_DESC,朱勾宗,邪宗大派。以炼器、机关、暗杀闻名于世,素来阴毒冷僻。【暗杀专家】你精通潜伏与刺杀,对于强敌,避开正面交锋、伺机暗杀往往是你最佳的制胜之道。,SECT_5_STYLE,EVIL,1,HIDDEN_WEAPON,"{extra_assassinate_success_rate: 0.15, extra_battle_strength_points: 1, extra_cast_success_rate: 0.05}",SECT_5_RANK_PATRIARCH;SECT_5_RANK_ELDER;SECT_5_RANK_INNER;SECT_5_RANK_OUTER +6,SECT_6_NAME,SECT_6_DESC,合欢宗,以情入道,靠双修增进修为,善驭人心,长于权变。【双修秘术】你的体质特殊,通过双修能获得远超常人的修为提升,这是你提升境界的最佳捷径。,SECT_6_STYLE,NEUTRAL,1,ZITHER,"{extra_dual_cultivation_exp: 150, shop_buy_price_reduction: 0.1}",SECT_6_RANK_PATRIARCH;SECT_6_RANK_ELDER;SECT_6_RANK_INNER;SECT_6_RANK_OUTER +7,SECT_7_NAME,SECT_7_DESC,镇魂宗,铁血风格,擅安魂、封邪、渡厄,兼有刚烈镇压之术。【金刚不坏】你修习护体神功,拥有极强的肉身防御与伤害减免能力,如山岳般不可撼动。,SECT_7_STYLE,RIGHTEOUS,1,STAFF,"{extra_max_hp: 100, damage_reduction: 0.15}",SECT_7_RANK_PATRIARCH;SECT_7_RANK_ELDER;SECT_7_RANK_INNER;SECT_7_RANK_OUTER +8,SECT_8_NAME,SECT_8_DESC,幽魂噬影宗,镇宗典籍《幽冥录》。幽明气为根基。【如影随形】你极擅身法与遁术,遇到危险时总能全身而退,亦能伺机刺杀落单之敌。,SECT_8_STYLE,EVIL,1,SABER,"{extra_escape_success_rate: 0.4, extra_assassinate_success_rate: 0.15}",SECT_8_RANK_PATRIARCH;SECT_8_RANK_ELDER;SECT_8_RANK_INNER;SECT_8_RANK_OUTER +9,SECT_9_NAME,SECT_9_DESC,千帆城,炼器大宗,巧匠云集。著名法宝有灵灭丝、定魂蓝星等。商旅云集,自成体系。【巧夺天工】你深谙炼器与经商之道,温养兵器时常能使其脱胎换骨,且在交易中总能获利。,SECT_9_STYLE,NEUTRAL,1,SPEAR,"{extra_item_sell_price_multiplier: 0.05, extra_weapon_upgrade_chance: 0.15, extra_cast_success_rate: 0.05, shop_buy_price_reduction: 0.05}",SECT_9_RANK_PATRIARCH;SECT_9_RANK_ELDER;SECT_9_RANK_INNER;SECT_9_RANK_OUTER +10,SECT_10_NAME,SECT_10_DESC,妙化宗,精擅音律杀伐与精神操控,功法诡谲阴柔,以无形琴音乱人心智,杀人于无形。【魔音贯耳】你擅长以音律乱人心智,灵力深厚绵长,虽不擅肉搏,但手段诡谲。,SECT_10_STYLE,EVIL,1,ZITHER,"{extra_escape_success_rate: 0.5, extra_misfortune_probability: -0.005}", +11,SECT_11_NAME,SECT_11_DESC,回玄宗,当世第一阵法大派,以阵法阵诀独步天下,讲究阵法推演与巧思妙用。【阵法聚灵】你善用阵法辅助修炼,能够聚集天地灵气,修炼速度快于常人,且常有意外收获。,SECT_11_STYLE,RIGHTEOUS,1,HIDDEN_WEAPON,"{cultivate_duration_reduction: 0.1, extra_fortune_probability: 0.005}", +12,SECT_12_NAME,SECT_12_DESC,不夜城,修习极光玄真法,以万里极光壁的绝对防御闻名于世。【生生不息】你的生命力极其顽强,疗伤效果倍增,寿元亦远超同阶修士。,SECT_12_STYLE,RIGHTEOUS,1,FAN,"{extra_hp_recovery_rate: 0.5, extra_max_lifespan: 20}",SECT_12_RANK_PATRIARCH;SECT_12_RANK_ELDER;SECT_12_RANK_INNER;SECT_12_RANK_OUTER +13,SECT_13_NAME,SECT_13_DESC,天行健宗,专修浩然之气,行事正大光明,刚健果决,对邪魔外道有极强的克制力。【浩然正气】你养浩然之气,气脉悠长,面对境界低于自己的敌人时,能发挥出极强的压制力。,SECT_13_STYLE,RIGHTEOUS,1,SWORD,{realm_suppression_bonus: 0.15}, +14,SECT_14_NAME,SECT_14_DESC,噬魔宗,通玄界第一魔宗,行事霸道残忍,擅长搜精噬血与肉体魔功。【搜刮成性】你崇尚力量与掠夺,搜刮凡人虽有伤天和,但能为你带来惊人的财富与资源。,SECT_14_STYLE,EVIL,1,SABER,"{extra_plunder_multiplier: 2.0, extra_battle_strength_points: 2}", diff --git a/src/i18n/locales/en_US/LC_MESSAGES/game_configs.mo b/static/locales/en-US/LC_MESSAGES/game_configs.mo similarity index 100% rename from src/i18n/locales/en_US/LC_MESSAGES/game_configs.mo rename to static/locales/en-US/LC_MESSAGES/game_configs.mo diff --git a/src/i18n/locales/en_US/LC_MESSAGES/game_configs.po b/static/locales/en-US/LC_MESSAGES/game_configs.po similarity index 100% rename from src/i18n/locales/en_US/LC_MESSAGES/game_configs.po rename to static/locales/en-US/LC_MESSAGES/game_configs.po diff --git a/static/locales/en-US/LC_MESSAGES/messages.mo b/static/locales/en-US/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..2a87937 Binary files /dev/null and b/static/locales/en-US/LC_MESSAGES/messages.mo differ diff --git a/src/i18n/locales/en_US/LC_MESSAGES/messages.po b/static/locales/en-US/LC_MESSAGES/messages.po similarity index 94% rename from src/i18n/locales/en_US/LC_MESSAGES/messages.po rename to static/locales/en-US/LC_MESSAGES/messages.po index 0af1071..e0197f8 100644 --- a/src/i18n/locales/en_US/LC_MESSAGES/messages.po +++ b/static/locales/en-US/LC_MESSAGES/messages.po @@ -2357,6 +2357,184 @@ msgstr "Unknown reason" msgid "{name} (Deceased: {reason})" msgstr "{name} (Deceased: {reason})" +msgid "SECT_1_STYLE" +msgstr "" +"Clear-minded and self-disciplined, actions matching words. Valuing both " +"sword and heart, emphasizing understanding one's true nature." + +msgid "SECT_2_STYLE" +msgstr "" +"Direct in speech, valuing strength and bloodlines, worshipping hunting and " +"combat." + +msgid "SECT_2_RANK_PATRIARCH" +msgstr "Valley Master" + +msgid "SECT_2_RANK_ELDER" +msgstr "Grand Elder" + +msgid "SECT_2_RANK_INNER" +msgstr "Beast Tamer" + +msgid "SECT_2_RANK_OUTER" +msgstr "Retainer" + +msgid "SECT_3_STYLE" +msgstr "" +"Calm and tactful, preferring softness to overcome hardness, skilled in " +"borrowing force and counter-control." + +msgid "SECT_3_RANK_PATRIARCH" +msgstr "Mirror Master" + +msgid "SECT_3_RANK_ELDER" +msgstr "Mirror Holder" + +msgid "SECT_3_RANK_INNER" +msgstr "Successor" + +msgid "SECT_3_RANK_OUTER" +msgstr "Mirror Attendant" + +msgid "SECT_4_STYLE" +msgstr "" +"Cold and emotionless in speech, revering karma but fearless in slaughter, " +"favoring efficiency and results." + +msgid "SECT_4_RANK_PATRIARCH" +msgstr "Hall Master" + +msgid "SECT_4_RANK_ELDER" +msgstr "Judge" + +msgid "SECT_4_RANK_INNER" +msgstr "Impermanence" + +msgid "SECT_4_RANK_OUTER" +msgstr "Ghost Soldier" + +msgid "SECT_5_STYLE" +msgstr "" +"Facing desires and costs directly, fearless of darkness, excelling in " +"offensive warfare." + +msgid "SECT_5_RANK_PATRIARCH" +msgstr "Tower Lord" + +msgid "SECT_5_RANK_ELDER" +msgstr "Punishment Officer" + +msgid "SECT_5_RANK_INNER" +msgstr "Shadow Assassin" + +msgid "SECT_5_RANK_OUTER" +msgstr "Scout" + +msgid "SECT_6_STYLE" +msgstr "" +"Tactful in speech, skilled in manipulating desires and situations, " +"overcoming hardness with softness." + +msgid "SECT_6_RANK_PATRIARCH" +msgstr "Palace Master" + +msgid "SECT_6_RANK_ELDER" +msgstr "Protector" + +msgid "SECT_6_RANK_INNER" +msgstr "Charming Immortal" + +msgid "SECT_6_RANK_OUTER" +msgstr "Attendant Boy" + +msgid "SECT_7_STYLE" +msgstr "" +"Solemn and steady, focusing on soothing souls and suppressing evil, few " +"words but decisive." + +msgid "SECT_7_RANK_PATRIARCH" +msgstr "Abbot" + +msgid "SECT_7_RANK_ELDER" +msgstr "Chief Monk" + +msgid "SECT_7_RANK_INNER" +msgstr "Walker" + +msgid "SECT_7_RANK_OUTER" +msgstr "Layman" + +msgid "SECT_8_STYLE" +msgstr "" +"Secretive and decisive, valuing results over reputation, skilled in stealth " +"and surprise attacks." + +msgid "SECT_8_RANK_PATRIARCH" +msgstr "Sect Master" + +msgid "SECT_8_RANK_ELDER" +msgstr "Protector" + +msgid "SECT_8_RANK_INNER" +msgstr "Shadow Guard" + +msgid "SECT_8_RANK_OUTER" +msgstr "Scout" + +msgid "SECT_9_STYLE" +msgstr "" +"Pragmatic and shrewd, valuing trade and reputation, upholding rules and " +"order." + +msgid "SECT_9_RANK_PATRIARCH" +msgstr "City Lord" + +msgid "SECT_9_RANK_ELDER" +msgstr "Grand Elder" + +msgid "SECT_9_RANK_INNER" +msgstr "Deacon" + +msgid "SECT_9_RANK_OUTER" +msgstr "Apprentice" + +msgid "SECT_10_STYLE" +msgstr "" +"Calculating beneath elegance, preferring to control situations with words " +"and melody, killing without smoke and fire." + +msgid "SECT_11_STYLE" +msgstr "" +"Rigorous and meticulous, pursuing technical perfection, skilled in counter-" +"attacking with formations, advancing step by step." + +msgid "SECT_12_STYLE" +msgstr "" +"Resilient and tenacious, striving in adversity, open and aboveboard but far-" +"sighted, extremely protective of their own." + +msgid "SECT_12_RANK_PATRIARCH" +msgstr "City Lord" + +msgid "SECT_12_RANK_ELDER" +msgstr "Pavilion Elder" + +msgid "SECT_12_RANK_INNER" +msgstr "Commander" + +msgid "SECT_12_RANK_OUTER" +msgstr "Night Watchman" + +msgid "SECT_13_STYLE" +msgstr "" +"Adhering to principles, stressing justice, leading in exorcising demons, " +"rather break than bend." + +msgid "SECT_14_STYLE" +msgstr "" +"Might makes right, doing as one pleases, worshipping absolute power and " +"slaughter, viewing all beings as food." + # Separators msgid "relation_separator" msgstr "; " diff --git a/src/i18n/locales/en_US/modules/action.po b/static/locales/en-US/modules/action.po similarity index 100% rename from src/i18n/locales/en_US/modules/action.po rename to static/locales/en-US/modules/action.po diff --git a/src/i18n/locales/en_US/modules/alignment.po b/static/locales/en-US/modules/alignment.po similarity index 100% rename from src/i18n/locales/en_US/modules/alignment.po rename to static/locales/en-US/modules/alignment.po diff --git a/src/i18n/locales/en_US/modules/auxiliary.po b/static/locales/en-US/modules/auxiliary.po similarity index 100% rename from src/i18n/locales/en_US/modules/auxiliary.po rename to static/locales/en-US/modules/auxiliary.po diff --git a/src/i18n/locales/en_US/modules/avatar.po b/static/locales/en-US/modules/avatar.po similarity index 100% rename from src/i18n/locales/en_US/modules/avatar.po rename to static/locales/en-US/modules/avatar.po diff --git a/src/i18n/locales/en_US/modules/battle.po b/static/locales/en-US/modules/battle.po similarity index 100% rename from src/i18n/locales/en_US/modules/battle.po rename to static/locales/en-US/modules/battle.po diff --git a/src/i18n/locales/en_US/modules/condition_translation.po b/static/locales/en-US/modules/condition_translation.po similarity index 100% rename from src/i18n/locales/en_US/modules/condition_translation.po rename to static/locales/en-US/modules/condition_translation.po diff --git a/src/i18n/locales/en_US/modules/cultivation.po b/static/locales/en-US/modules/cultivation.po similarity index 100% rename from src/i18n/locales/en_US/modules/cultivation.po rename to static/locales/en-US/modules/cultivation.po diff --git a/src/i18n/locales/en_US/modules/death_reasons.po b/static/locales/en-US/modules/death_reasons.po similarity index 100% rename from src/i18n/locales/en_US/modules/death_reasons.po rename to static/locales/en-US/modules/death_reasons.po diff --git a/src/i18n/locales/en_US/modules/decision_description.po b/static/locales/en-US/modules/decision_description.po similarity index 100% rename from src/i18n/locales/en_US/modules/decision_description.po rename to static/locales/en-US/modules/decision_description.po diff --git a/src/i18n/locales/en_US/modules/default_values.po b/static/locales/en-US/modules/default_values.po similarity index 100% rename from src/i18n/locales/en_US/modules/default_values.po rename to static/locales/en-US/modules/default_values.po diff --git a/src/i18n/locales/en_US/modules/direction_names.po b/static/locales/en-US/modules/direction_names.po similarity index 100% rename from src/i18n/locales/en_US/modules/direction_names.po rename to static/locales/en-US/modules/direction_names.po diff --git a/src/i18n/locales/en_US/modules/effect.po b/static/locales/en-US/modules/effect.po similarity index 100% rename from src/i18n/locales/en_US/modules/effect.po rename to static/locales/en-US/modules/effect.po diff --git a/src/i18n/locales/en_US/modules/elixir.po b/static/locales/en-US/modules/elixir.po similarity index 100% rename from src/i18n/locales/en_US/modules/elixir.po rename to static/locales/en-US/modules/elixir.po diff --git a/src/i18n/locales/en_US/modules/essence_type.po b/static/locales/en-US/modules/essence_type.po similarity index 100% rename from src/i18n/locales/en_US/modules/essence_type.po rename to static/locales/en-US/modules/essence_type.po diff --git a/src/i18n/locales/en_US/modules/event_content.po b/static/locales/en-US/modules/event_content.po similarity index 100% rename from src/i18n/locales/en_US/modules/event_content.po rename to static/locales/en-US/modules/event_content.po diff --git a/src/i18n/locales/en_US/modules/execution_results.po b/static/locales/en-US/modules/execution_results.po similarity index 100% rename from src/i18n/locales/en_US/modules/execution_results.po rename to static/locales/en-US/modules/execution_results.po diff --git a/src/i18n/locales/en_US/modules/feedback_labels.po b/static/locales/en-US/modules/feedback_labels.po similarity index 100% rename from src/i18n/locales/en_US/modules/feedback_labels.po rename to static/locales/en-US/modules/feedback_labels.po diff --git a/src/i18n/locales/en_US/modules/formatted_strings.po b/static/locales/en-US/modules/formatted_strings.po similarity index 100% rename from src/i18n/locales/en_US/modules/formatted_strings.po rename to static/locales/en-US/modules/formatted_strings.po diff --git a/src/i18n/locales/en_US/modules/fortune.po b/static/locales/en-US/modules/fortune.po similarity index 100% rename from src/i18n/locales/en_US/modules/fortune.po rename to static/locales/en-US/modules/fortune.po diff --git a/src/i18n/locales/en_US/modules/gathering.po b/static/locales/en-US/modules/gathering.po similarity index 100% rename from src/i18n/locales/en_US/modules/gathering.po rename to static/locales/en-US/modules/gathering.po diff --git a/src/i18n/locales/en_US/modules/gender.po b/static/locales/en-US/modules/gender.po similarity index 100% rename from src/i18n/locales/en_US/modules/gender.po rename to static/locales/en-US/modules/gender.po diff --git a/src/i18n/locales/en_US/modules/hidden_domain.po b/static/locales/en-US/modules/hidden_domain.po similarity index 100% rename from src/i18n/locales/en_US/modules/hidden_domain.po rename to static/locales/en-US/modules/hidden_domain.po diff --git a/src/i18n/locales/en_US/modules/item_exchange.po b/static/locales/en-US/modules/item_exchange.po similarity index 100% rename from src/i18n/locales/en_US/modules/item_exchange.po rename to static/locales/en-US/modules/item_exchange.po diff --git a/src/i18n/locales/en_US/modules/item_verbs.po b/static/locales/en-US/modules/item_verbs.po similarity index 100% rename from src/i18n/locales/en_US/modules/item_verbs.po rename to static/locales/en-US/modules/item_verbs.po diff --git a/src/i18n/locales/en_US/modules/labels.po b/static/locales/en-US/modules/labels.po similarity index 100% rename from src/i18n/locales/en_US/modules/labels.po rename to static/locales/en-US/modules/labels.po diff --git a/src/i18n/locales/en_US/modules/llm_prompt.po b/static/locales/en-US/modules/llm_prompt.po similarity index 100% rename from src/i18n/locales/en_US/modules/llm_prompt.po rename to static/locales/en-US/modules/llm_prompt.po diff --git a/src/i18n/locales/en_US/modules/map.po b/static/locales/en-US/modules/map.po similarity index 100% rename from src/i18n/locales/en_US/modules/map.po rename to static/locales/en-US/modules/map.po diff --git a/src/i18n/locales/en_US/modules/misfortune.po b/static/locales/en-US/modules/misfortune.po similarity index 100% rename from src/i18n/locales/en_US/modules/misfortune.po rename to static/locales/en-US/modules/misfortune.po diff --git a/src/i18n/locales/en_US/modules/mutual_action.po b/static/locales/en-US/modules/mutual_action.po similarity index 100% rename from src/i18n/locales/en_US/modules/mutual_action.po rename to static/locales/en-US/modules/mutual_action.po diff --git a/src/i18n/locales/en_US/modules/option_a.po b/static/locales/en-US/modules/option_a.po similarity index 100% rename from src/i18n/locales/en_US/modules/option_a.po rename to static/locales/en-US/modules/option_a.po diff --git a/src/i18n/locales/en_US/modules/option_b.po b/static/locales/en-US/modules/option_b.po similarity index 100% rename from src/i18n/locales/en_US/modules/option_b.po rename to static/locales/en-US/modules/option_b.po diff --git a/src/i18n/locales/en_US/modules/realm.po b/static/locales/en-US/modules/realm.po similarity index 100% rename from src/i18n/locales/en_US/modules/realm.po rename to static/locales/en-US/modules/realm.po diff --git a/src/i18n/locales/en_US/modules/relation.po b/static/locales/en-US/modules/relation.po similarity index 100% rename from src/i18n/locales/en_US/modules/relation.po rename to static/locales/en-US/modules/relation.po diff --git a/src/i18n/locales/en_US/modules/root_element.po b/static/locales/en-US/modules/root_element.po similarity index 100% rename from src/i18n/locales/en_US/modules/root_element.po rename to static/locales/en-US/modules/root_element.po diff --git a/src/i18n/locales/en_US/modules/scene_setting.po b/static/locales/en-US/modules/scene_setting.po similarity index 100% rename from src/i18n/locales/en_US/modules/scene_setting.po rename to static/locales/en-US/modules/scene_setting.po diff --git a/static/locales/en-US/modules/sect.po b/static/locales/en-US/modules/sect.po new file mode 100644 index 0000000..6d5d5ae --- /dev/null +++ b/static/locales/en-US/modules/sect.po @@ -0,0 +1,199 @@ +# +msgid "" +msgstr "" +"Project-Id-Version: cultivation-world-simulator 1.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-20 00:00+0000\n" +"PO-Revision-Date: 2024-01-20 00:00+0000\n" +"Last-Translator: \n" +"Language-Team: English\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +# Sect Rank +msgid "patriarch" +msgstr "Patriarch" + +msgid "elder" +msgstr "Elder" + +msgid "inner_disciple" +msgstr "Inner Disciple" + +msgid "outer_disciple" +msgstr "Outer Disciple" + +# ============================================================================ +# Sect System - Sects +# ============================================================================ +msgid "{sect_name} (Alignment: {alignment}, Headquarters: {hq_name})" +msgstr "{sect_name} (Alignment: {alignment}, Headquarters: {hq_name})" + +msgid "" +"{sect_name} (Alignment: {alignment}, Style: {style}, Headquarters: " +"{hq_name}){effect}" +msgstr "" +"{sect_name} (Alignment: {alignment}, Style: {style}, Headquarters: " +"{hq_name}){effect}" + +# ============================================================================ +# Relation & Root & Appearance & Sect (Refined) +# ============================================================================ +msgid "Unknown reason" +msgstr "Unknown reason" + +msgid "{name} (Deceased: {reason})" +msgstr "{name} (Deceased: {reason})" + +msgid "SECT_1_STYLE" +msgstr "Clear-minded and self-disciplined, actions matching words. Valuing both sword and heart, emphasizing understanding one's true nature." + +msgid "SECT_2_STYLE" +msgstr "Direct in speech, valuing strength and bloodlines, worshipping hunting and combat." + +msgid "SECT_2_RANK_PATRIARCH" +msgstr "Valley Master" + +msgid "SECT_2_RANK_ELDER" +msgstr "Grand Elder" + +msgid "SECT_2_RANK_INNER" +msgstr "Beast Tamer" + +msgid "SECT_2_RANK_OUTER" +msgstr "Retainer" + +msgid "SECT_3_STYLE" +msgstr "Calm and tactful, preferring softness to overcome hardness, skilled in borrowing force and counter-control." + +msgid "SECT_3_RANK_PATRIARCH" +msgstr "Mirror Master" + +msgid "SECT_3_RANK_ELDER" +msgstr "Mirror Holder" + +msgid "SECT_3_RANK_INNER" +msgstr "Successor" + +msgid "SECT_3_RANK_OUTER" +msgstr "Mirror Attendant" + +msgid "SECT_4_STYLE" +msgstr "Cold and emotionless in speech, revering karma but fearless in slaughter, favoring efficiency and results." + +msgid "SECT_4_RANK_PATRIARCH" +msgstr "Hall Master" + +msgid "SECT_4_RANK_ELDER" +msgstr "Judge" + +msgid "SECT_4_RANK_INNER" +msgstr "Impermanence" + +msgid "SECT_4_RANK_OUTER" +msgstr "Ghost Soldier" + +msgid "SECT_5_STYLE" +msgstr "Facing desires and costs directly, fearless of darkness, excelling in offensive warfare." + +msgid "SECT_5_RANK_PATRIARCH" +msgstr "Tower Lord" + +msgid "SECT_5_RANK_ELDER" +msgstr "Punishment Officer" + +msgid "SECT_5_RANK_INNER" +msgstr "Shadow Assassin" + +msgid "SECT_5_RANK_OUTER" +msgstr "Scout" + +msgid "SECT_6_STYLE" +msgstr "Tactful in speech, skilled in manipulating desires and situations, overcoming hardness with softness." + +msgid "SECT_6_RANK_PATRIARCH" +msgstr "Palace Master" + +msgid "SECT_6_RANK_ELDER" +msgstr "Protector" + +msgid "SECT_6_RANK_INNER" +msgstr "Charming Immortal" + +msgid "SECT_6_RANK_OUTER" +msgstr "Attendant Boy" + +msgid "SECT_7_STYLE" +msgstr "Solemn and steady, focusing on soothing souls and suppressing evil, few words but decisive." + +msgid "SECT_7_RANK_PATRIARCH" +msgstr "Abbot" + +msgid "SECT_7_RANK_ELDER" +msgstr "Chief Monk" + +msgid "SECT_7_RANK_INNER" +msgstr "Walker" + +msgid "SECT_7_RANK_OUTER" +msgstr "Layman" + +msgid "SECT_8_STYLE" +msgstr "Secretive and decisive, valuing results over reputation, skilled in stealth and surprise attacks." + +msgid "SECT_8_RANK_PATRIARCH" +msgstr "Sect Master" + +msgid "SECT_8_RANK_ELDER" +msgstr "Protector" + +msgid "SECT_8_RANK_INNER" +msgstr "Shadow Guard" + +msgid "SECT_8_RANK_OUTER" +msgstr "Scout" + +msgid "SECT_9_STYLE" +msgstr "Pragmatic and shrewd, valuing trade and reputation, upholding rules and order." + +msgid "SECT_9_RANK_PATRIARCH" +msgstr "City Lord" + +msgid "SECT_9_RANK_ELDER" +msgstr "Grand Elder" + +msgid "SECT_9_RANK_INNER" +msgstr "Deacon" + +msgid "SECT_9_RANK_OUTER" +msgstr "Apprentice" + +msgid "SECT_10_STYLE" +msgstr "Calculating beneath elegance, preferring to control situations with words and melody, killing without smoke and fire." + +msgid "SECT_11_STYLE" +msgstr "Rigorous and meticulous, pursuing technical perfection, skilled in counter-attacking with formations, advancing step by step." + +msgid "SECT_12_STYLE" +msgstr "Resilient and tenacious, striving in adversity, open and aboveboard but far-sighted, extremely protective of their own." + +msgid "SECT_12_RANK_PATRIARCH" +msgstr "City Lord" + +msgid "SECT_12_RANK_ELDER" +msgstr "Pavilion Elder" + +msgid "SECT_12_RANK_INNER" +msgstr "Commander" + +msgid "SECT_12_RANK_OUTER" +msgstr "Night Watchman" + +msgid "SECT_13_STYLE" +msgstr "Adhering to principles, stressing justice, leading in exorcising demons, rather break than bend." + +msgid "SECT_14_STYLE" +msgstr "Might makes right, doing as one pleases, worshipping absolute power and slaughter, viewing all beings as food." + diff --git a/src/i18n/locales/en_US/modules/separators.po b/static/locales/en-US/modules/separators.po similarity index 100% rename from src/i18n/locales/en_US/modules/separators.po rename to static/locales/en-US/modules/separators.po diff --git a/src/i18n/locales/en_US/modules/simulator.po b/static/locales/en-US/modules/simulator.po similarity index 100% rename from src/i18n/locales/en_US/modules/simulator.po rename to static/locales/en-US/modules/simulator.po diff --git a/src/i18n/locales/en_US/modules/single_choice.po b/static/locales/en-US/modules/single_choice.po similarity index 100% rename from src/i18n/locales/en_US/modules/single_choice.po rename to static/locales/en-US/modules/single_choice.po diff --git a/src/i18n/locales/en_US/modules/stage.po b/static/locales/en-US/modules/stage.po similarity index 100% rename from src/i18n/locales/en_US/modules/stage.po rename to static/locales/en-US/modules/stage.po diff --git a/src/i18n/locales/en_US/modules/story_generation_text.po b/static/locales/en-US/modules/story_generation_text.po similarity index 100% rename from src/i18n/locales/en_US/modules/story_generation_text.po rename to static/locales/en-US/modules/story_generation_text.po diff --git a/src/i18n/locales/en_US/modules/story_styles.po b/static/locales/en-US/modules/story_styles.po similarity index 100% rename from src/i18n/locales/en_US/modules/story_styles.po rename to static/locales/en-US/modules/story_styles.po diff --git a/src/i18n/locales/en_US/modules/technique.po b/static/locales/en-US/modules/technique.po similarity index 100% rename from src/i18n/locales/en_US/modules/technique.po rename to static/locales/en-US/modules/technique.po diff --git a/src/i18n/locales/en_US/modules/ui.po b/static/locales/en-US/modules/ui.po similarity index 100% rename from src/i18n/locales/en_US/modules/ui.po rename to static/locales/en-US/modules/ui.po diff --git a/src/i18n/locales/en_US/modules/weapon.po b/static/locales/en-US/modules/weapon.po similarity index 100% rename from src/i18n/locales/en_US/modules/weapon.po rename to static/locales/en-US/modules/weapon.po diff --git a/src/i18n/locales/templates/game_configs.pot b/static/locales/templates/game_configs.pot similarity index 100% rename from src/i18n/locales/templates/game_configs.pot rename to static/locales/templates/game_configs.pot diff --git a/src/i18n/locales/zh_CN/LC_MESSAGES/game_configs.mo b/static/locales/zh-CN/LC_MESSAGES/game_configs.mo similarity index 100% rename from src/i18n/locales/zh_CN/LC_MESSAGES/game_configs.mo rename to static/locales/zh-CN/LC_MESSAGES/game_configs.mo diff --git a/src/i18n/locales/zh_CN/LC_MESSAGES/game_configs.po b/static/locales/zh-CN/LC_MESSAGES/game_configs.po similarity index 100% rename from src/i18n/locales/zh_CN/LC_MESSAGES/game_configs.po rename to static/locales/zh-CN/LC_MESSAGES/game_configs.po diff --git a/static/locales/zh-CN/LC_MESSAGES/messages.mo b/static/locales/zh-CN/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..bed2dc5 Binary files /dev/null and b/static/locales/zh-CN/LC_MESSAGES/messages.mo differ diff --git a/src/i18n/locales/zh_CN/LC_MESSAGES/messages.po b/static/locales/zh-CN/LC_MESSAGES/messages.po similarity index 94% rename from src/i18n/locales/zh_CN/LC_MESSAGES/messages.po rename to static/locales/zh-CN/LC_MESSAGES/messages.po index 892b9b6..fc55142 100644 --- a/src/i18n/locales/zh_CN/LC_MESSAGES/messages.po +++ b/static/locales/zh-CN/LC_MESSAGES/messages.po @@ -2292,6 +2292,156 @@ msgstr "当阵营为{align}时" msgid "When using {weapon_type}" msgstr "当使用{weapon_type}时" +msgid "SECT_1_STYLE" +msgstr "娓呮槑鍏嬪繁锛岃姝㈠涓€銆傞噸鍓戜笌蹇冩硶骞堕噸锛岃绌舵槑蹇冭鎬с€" + +msgid "SECT_2_STYLE" +msgstr "瑷€璇洿鎺ワ紝閲嶈鍔涢噺涓庤鎬э紝宕囧皻鐙╃寧涓庢悘鏂椼€" + +msgid "SECT_2_RANK_PATRIARCH" +msgstr "璋蜂富" + +msgid "SECT_2_RANK_ELDER" +msgstr "渚涘" + +msgid "SECT_2_RANK_INNER" +msgstr "椹吔甯" + +msgid "SECT_2_RANK_OUTER" +msgstr "鎵堜粠" + +msgid "SECT_3_STYLE" +msgstr "澶勪簨鍐烽潤鍦嗚瀺锛屽枩浠ユ煍鍏嬪垰锛屾搮鍊熷姏涓庡弽鍒躲€" + +msgid "SECT_3_RANK_PATRIARCH" +msgstr "闀滀富" + +msgid "SECT_3_RANK_ELDER" +msgstr "鎺岄暅浜" + +msgid "SECT_3_RANK_INNER" +msgstr "浼犱汉" + +msgid "SECT_3_RANK_OUTER" +msgstr "渚嶉暅" + +msgid "SECT_4_STYLE" +msgstr "瑷€杈炲喎鍘夊皯鎯咃紝鏁晱鍥犳灉鑰屼笉鎯ф潃浼愶紝鍋忓悜鏁堢巼涓庣粨鏋溿€" + +msgid "SECT_4_RANK_PATRIARCH" +msgstr "娈夸富" + +msgid "SECT_4_RANK_ELDER" +msgstr "鍒ゅ畼" + +msgid "SECT_4_RANK_INNER" +msgstr "鏃犲父" + +msgid "SECT_4_RANK_OUTER" +msgstr "楝煎崚" + +msgid "SECT_5_STYLE" +msgstr "鐩撮潰娆叉湜涓庝唬浠凤紝涓嶆儳榛戞殫锛屼互鏀讳紣瑙侀暱銆" + +msgid "SECT_5_RANK_PATRIARCH" +msgstr "妤间富" + +msgid "SECT_5_RANK_ELDER" +msgstr "鎺屽垜浣" + +msgid "SECT_5_RANK_INNER" +msgstr "褰卞埡" + +msgid "SECT_5_RANK_OUTER" +msgstr "鎺㈠瓙" + +msgid "SECT_6_STYLE" +msgstr "杈炰护濠夎浆锛屽杽浜庢嬁鎹忎汉娆蹭笌灞€鍔匡紝浠ユ煍鍒跺垰銆" + +msgid "SECT_6_RANK_PATRIARCH" +msgstr "瀹富" + +msgid "SECT_6_RANK_ELDER" +msgstr "鎶ゆ硶" + +msgid "SECT_6_RANK_INNER" +msgstr "濯氫粰" + +msgid "SECT_6_RANK_OUTER" +msgstr "渚嶇" + +msgid "SECT_7_STYLE" +msgstr "鑲冪﹩娌夌ǔ锛岄噸瀹夐瓊闀囬偑锛屽皯瑷€鑰屾灉鍐炽€" + +msgid "SECT_7_RANK_PATRIARCH" +msgstr "浣忔寔" + +msgid "SECT_7_RANK_ELDER" +msgstr "棣栧骇" + +msgid "SECT_7_RANK_INNER" +msgstr "琛岃€" + +msgid "SECT_7_RANK_OUTER" +msgstr "灞呭+" + +msgid "SECT_8_STYLE" +msgstr "琛屼簨闅愮鏋滄柇锛岄噸缁撴灉杞昏櫄鍚嶏紝鎿呮綔琛屼笌鍑哄叾涓嶆剰銆" + +msgid "SECT_8_RANK_PATRIARCH" +msgstr "闂ㄤ富" + +msgid "SECT_8_RANK_ELDER" +msgstr "鎶ゆ硶" + +msgid "SECT_8_RANK_INNER" +msgstr "褰卞崼" + +msgid "SECT_8_RANK_OUTER" +msgstr "鎺㈠瓙" + +msgid "SECT_9_STYLE" +msgstr "鍔″疄绮炬槑锛岄噸浜ゆ槗涓庝俊瑾夛紝宕囧皻瑙勫垯涓庣З搴忋€" + +msgid "SECT_9_RANK_PATRIARCH" +msgstr "鍩庝富" + +msgid "SECT_9_RANK_ELDER" +msgstr "澶т緵濂" + +msgid "SECT_9_RANK_INNER" +msgstr "鎵т簨" + +msgid "SECT_9_RANK_OUTER" +msgstr "瀛﹀緬" + +msgid "SECT_10_STYLE" +msgstr "鏂囬泤缂ョ紙涓繁钘忕畻璁★紝鍠滅敤瑷€璇笌闊冲緥鎺屾帶灞€鍔匡紝鏉€浼愪笉娌剧儫鐏皵銆" + +msgid "SECT_11_STYLE" +msgstr "涓ヨ皑缁嗚嚧锛岃拷姹傛妧鏈瀬鑷达紝鎴樻枟涓搮闀夸互鍚庢墜闃垫硶鍙嶅埗鏁屼汉锛屾姝ヤ负钀ャ€" + +msgid "SECT_12_STYLE" +msgstr "鍧氶煣椤藉己锛屽湪閫嗗涓浘寮猴紝琛屼簨鍏夋槑纾婅惤浣嗕篃娣辫皨杩滆檻锛屾瀬鍏舵姢鐭€" + +msgid "SECT_12_RANK_PATRIARCH" +msgstr "鍩庝富" + +msgid "SECT_12_RANK_ELDER" +msgstr "闃佽€" + +msgid "SECT_12_RANK_INNER" +msgstr "鎵т护" + +msgid "SECT_12_RANK_OUTER" +msgstr "瀹堝浜" + +msgid "SECT_13_STYLE" +msgstr "鎭畧鍘熷垯锛岃绌堕亾涔夛紝闄ら瓟鍗亾涓€椹綋鍏堬紝瀹佹姌涓嶅集銆" + +msgid "SECT_14_STYLE" +msgstr "寮鸿€呬负灏婏紝闅忓績鎵€娆诧紝宕囧皻缁濆鐨勫姏閲忎笌鏉€鎴紝瑙嗕紬鐢熶负琛€椋熴€" + # ============================================================================ # Simulator & Event Translations # ============================================================================ diff --git a/src/i18n/locales/zh_CN/modules/action.po b/static/locales/zh-CN/modules/action.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/action.po rename to static/locales/zh-CN/modules/action.po diff --git a/src/i18n/locales/zh_CN/modules/alignment.po b/static/locales/zh-CN/modules/alignment.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/alignment.po rename to static/locales/zh-CN/modules/alignment.po diff --git a/src/i18n/locales/zh_CN/modules/auxiliary.po b/static/locales/zh-CN/modules/auxiliary.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/auxiliary.po rename to static/locales/zh-CN/modules/auxiliary.po diff --git a/src/i18n/locales/zh_CN/modules/avatar.po b/static/locales/zh-CN/modules/avatar.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/avatar.po rename to static/locales/zh-CN/modules/avatar.po diff --git a/src/i18n/locales/zh_CN/modules/battle.po b/static/locales/zh-CN/modules/battle.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/battle.po rename to static/locales/zh-CN/modules/battle.po diff --git a/src/i18n/locales/zh_CN/modules/cultivation.po b/static/locales/zh-CN/modules/cultivation.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/cultivation.po rename to static/locales/zh-CN/modules/cultivation.po diff --git a/src/i18n/locales/zh_CN/modules/death_reasons.po b/static/locales/zh-CN/modules/death_reasons.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/death_reasons.po rename to static/locales/zh-CN/modules/death_reasons.po diff --git a/src/i18n/locales/zh_CN/modules/direction_names.po b/static/locales/zh-CN/modules/direction_names.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/direction_names.po rename to static/locales/zh-CN/modules/direction_names.po diff --git a/src/i18n/locales/zh_CN/modules/effect.po b/static/locales/zh-CN/modules/effect.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/effect.po rename to static/locales/zh-CN/modules/effect.po diff --git a/src/i18n/locales/zh_CN/modules/elixir.po b/static/locales/zh-CN/modules/elixir.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/elixir.po rename to static/locales/zh-CN/modules/elixir.po diff --git a/src/i18n/locales/zh_CN/modules/essence_type.po b/static/locales/zh-CN/modules/essence_type.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/essence_type.po rename to static/locales/zh-CN/modules/essence_type.po diff --git a/src/i18n/locales/zh_CN/modules/feedback_labels.po b/static/locales/zh-CN/modules/feedback_labels.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/feedback_labels.po rename to static/locales/zh-CN/modules/feedback_labels.po diff --git a/src/i18n/locales/zh_CN/modules/fortune.po b/static/locales/zh-CN/modules/fortune.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/fortune.po rename to static/locales/zh-CN/modules/fortune.po diff --git a/src/i18n/locales/zh_CN/modules/gathering.po b/static/locales/zh-CN/modules/gathering.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/gathering.po rename to static/locales/zh-CN/modules/gathering.po diff --git a/src/i18n/locales/zh_CN/modules/gender.po b/static/locales/zh-CN/modules/gender.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/gender.po rename to static/locales/zh-CN/modules/gender.po diff --git a/src/i18n/locales/zh_CN/modules/hidden_domain.po b/static/locales/zh-CN/modules/hidden_domain.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/hidden_domain.po rename to static/locales/zh-CN/modules/hidden_domain.po diff --git a/src/i18n/locales/zh_CN/modules/item_exchange.po b/static/locales/zh-CN/modules/item_exchange.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/item_exchange.po rename to static/locales/zh-CN/modules/item_exchange.po diff --git a/src/i18n/locales/zh_CN/modules/labels.po b/static/locales/zh-CN/modules/labels.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/labels.po rename to static/locales/zh-CN/modules/labels.po diff --git a/src/i18n/locales/zh_CN/modules/llm_prompt.po b/static/locales/zh-CN/modules/llm_prompt.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/llm_prompt.po rename to static/locales/zh-CN/modules/llm_prompt.po diff --git a/src/i18n/locales/zh_CN/modules/map.po b/static/locales/zh-CN/modules/map.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/map.po rename to static/locales/zh-CN/modules/map.po diff --git a/src/i18n/locales/zh_CN/modules/misc.po b/static/locales/zh-CN/modules/misc.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/misc.po rename to static/locales/zh-CN/modules/misc.po diff --git a/src/i18n/locales/zh_CN/modules/misfortune.po b/static/locales/zh-CN/modules/misfortune.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/misfortune.po rename to static/locales/zh-CN/modules/misfortune.po diff --git a/src/i18n/locales/zh_CN/modules/mutual_action.po b/static/locales/zh-CN/modules/mutual_action.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/mutual_action.po rename to static/locales/zh-CN/modules/mutual_action.po diff --git a/src/i18n/locales/zh_CN/modules/realm.po b/static/locales/zh-CN/modules/realm.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/realm.po rename to static/locales/zh-CN/modules/realm.po diff --git a/src/i18n/locales/zh_CN/modules/relation.po b/static/locales/zh-CN/modules/relation.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/relation.po rename to static/locales/zh-CN/modules/relation.po diff --git a/src/i18n/locales/zh_CN/modules/root_element.po b/static/locales/zh-CN/modules/root_element.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/root_element.po rename to static/locales/zh-CN/modules/root_element.po diff --git a/src/i18n/locales/zh_CN/modules/sect.po b/static/locales/zh-CN/modules/sect.po similarity index 66% rename from src/i18n/locales/zh_CN/modules/sect.po rename to static/locales/zh-CN/modules/sect.po index 2b8edde..2737114 100644 --- a/src/i18n/locales/zh_CN/modules/sect.po +++ b/static/locales/zh-CN/modules/sect.po @@ -278,3 +278,154 @@ msgstr "当阵营为{align}时" msgid "When using {weapon_type}" msgstr "当使用{weapon_type}时" + +msgid "SECT_1_STYLE" +msgstr "娓呮槑鍏嬪繁锛岃姝㈠涓€銆傞噸鍓戜笌蹇冩硶骞堕噸锛岃绌舵槑蹇冭鎬с€? + +msgid "SECT_2_STYLE" +msgstr "瑷€璇洿鎺ワ紝閲嶈鍔涢噺涓庤鎬э紝宕囧皻鐙╃寧涓庢悘鏂椼€? + +msgid "SECT_2_RANK_PATRIARCH" +msgstr "璋蜂富" + +msgid "SECT_2_RANK_ELDER" +msgstr "渚涘" + +msgid "SECT_2_RANK_INNER" +msgstr "椹吔甯? + +msgid "SECT_2_RANK_OUTER" +msgstr "鎵堜粠" + +msgid "SECT_3_STYLE" +msgstr "澶勪簨鍐烽潤鍦嗚瀺锛屽枩浠ユ煍鍏嬪垰锛屾搮鍊熷姏涓庡弽鍒躲€? + +msgid "SECT_3_RANK_PATRIARCH" +msgstr "闀滀富" + +msgid "SECT_3_RANK_ELDER" +msgstr "鎺岄暅浜? + +msgid "SECT_3_RANK_INNER" +msgstr "浼犱汉" + +msgid "SECT_3_RANK_OUTER" +msgstr "渚嶉暅" + +msgid "SECT_4_STYLE" +msgstr "瑷€杈炲喎鍘夊皯鎯咃紝鏁晱鍥犳灉鑰屼笉鎯ф潃浼愶紝鍋忓悜鏁堢巼涓庣粨鏋溿€? + +msgid "SECT_4_RANK_PATRIARCH" +msgstr "娈夸富" + +msgid "SECT_4_RANK_ELDER" +msgstr "鍒ゅ畼" + +msgid "SECT_4_RANK_INNER" +msgstr "鏃犲父" + +msgid "SECT_4_RANK_OUTER" +msgstr "楝煎崚" + +msgid "SECT_5_STYLE" +msgstr "鐩撮潰娆叉湜涓庝唬浠凤紝涓嶆儳榛戞殫锛屼互鏀讳紣瑙侀暱銆? + +msgid "SECT_5_RANK_PATRIARCH" +msgstr "妤间富" + +msgid "SECT_5_RANK_ELDER" +msgstr "鎺屽垜浣? + +msgid "SECT_5_RANK_INNER" +msgstr "褰卞埡" + +msgid "SECT_5_RANK_OUTER" +msgstr "鎺㈠瓙" + +msgid "SECT_6_STYLE" +msgstr "杈炰护濠夎浆锛屽杽浜庢嬁鎹忎汉娆蹭笌灞€鍔匡紝浠ユ煍鍒跺垰銆? + +msgid "SECT_6_RANK_PATRIARCH" +msgstr "瀹富" + +msgid "SECT_6_RANK_ELDER" +msgstr "鎶ゆ硶" + +msgid "SECT_6_RANK_INNER" +msgstr "濯氫粰" + +msgid "SECT_6_RANK_OUTER" +msgstr "渚嶇" + +msgid "SECT_7_STYLE" +msgstr "鑲冪﹩娌夌ǔ锛岄噸瀹夐瓊闀囬偑锛屽皯瑷€鑰屾灉鍐炽€? + +msgid "SECT_7_RANK_PATRIARCH" +msgstr "浣忔寔" + +msgid "SECT_7_RANK_ELDER" +msgstr "棣栧骇" + +msgid "SECT_7_RANK_INNER" +msgstr "琛岃€? + +msgid "SECT_7_RANK_OUTER" +msgstr "灞呭+" + +msgid "SECT_8_STYLE" +msgstr "琛屼簨闅愮鏋滄柇锛岄噸缁撴灉杞昏櫄鍚嶏紝鎿呮綔琛屼笌鍑哄叾涓嶆剰銆? + +msgid "SECT_8_RANK_PATRIARCH" +msgstr "闂ㄤ富" + +msgid "SECT_8_RANK_ELDER" +msgstr "鎶ゆ硶" + +msgid "SECT_8_RANK_INNER" +msgstr "褰卞崼" + +msgid "SECT_8_RANK_OUTER" +msgstr "鎺㈠瓙" + +msgid "SECT_9_STYLE" +msgstr "鍔″疄绮炬槑锛岄噸浜ゆ槗涓庝俊瑾夛紝宕囧皻瑙勫垯涓庣З搴忋€? + +msgid "SECT_9_RANK_PATRIARCH" +msgstr "鍩庝富" + +msgid "SECT_9_RANK_ELDER" +msgstr "澶т緵濂? + +msgid "SECT_9_RANK_INNER" +msgstr "鎵т簨" + +msgid "SECT_9_RANK_OUTER" +msgstr "瀛﹀緬" + +msgid "SECT_10_STYLE" +msgstr "鏂囬泤缂ョ紙涓繁钘忕畻璁★紝鍠滅敤瑷€璇笌闊冲緥鎺屾帶灞€鍔匡紝鏉€浼愪笉娌剧儫鐏皵銆? + +msgid "SECT_11_STYLE" +msgstr "涓ヨ皑缁嗚嚧锛岃拷姹傛妧鏈瀬鑷达紝鎴樻枟涓搮闀夸互鍚庢墜闃垫硶鍙嶅埗鏁屼汉锛屾姝ヤ负钀ャ€? + +msgid "SECT_12_STYLE" +msgstr "鍧氶煣椤藉己锛屽湪閫嗗涓浘寮猴紝琛屼簨鍏夋槑纾婅惤浣嗕篃娣辫皨杩滆檻锛屾瀬鍏舵姢鐭€? + +msgid "SECT_12_RANK_PATRIARCH" +msgstr "鍩庝富" + +msgid "SECT_12_RANK_ELDER" +msgstr "闃佽€? + +msgid "SECT_12_RANK_INNER" +msgstr "鎵т护" + +msgid "SECT_12_RANK_OUTER" +msgstr "瀹堝浜? + +msgid "SECT_13_STYLE" +msgstr "鎭畧鍘熷垯锛岃绌堕亾涔夛紝闄ら瓟鍗亾涓€椹綋鍏堬紝瀹佹姌涓嶅集銆? + +msgid "SECT_14_STYLE" +msgstr "寮鸿€呬负灏婏紝闅忓績鎵€娆诧紝宕囧皻缁濆鐨勫姏閲忎笌鏉€鎴紝瑙嗕紬鐢熶负琛€椋熴€? + diff --git a/src/i18n/locales/zh_CN/modules/simulator.po b/static/locales/zh-CN/modules/simulator.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/simulator.po rename to static/locales/zh-CN/modules/simulator.po diff --git a/src/i18n/locales/zh_CN/modules/single_choice.po b/static/locales/zh-CN/modules/single_choice.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/single_choice.po rename to static/locales/zh-CN/modules/single_choice.po diff --git a/src/i18n/locales/zh_CN/modules/stage.po b/static/locales/zh-CN/modules/stage.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/stage.po rename to static/locales/zh-CN/modules/stage.po diff --git a/src/i18n/locales/zh_CN/modules/story_styles.po b/static/locales/zh-CN/modules/story_styles.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/story_styles.po rename to static/locales/zh-CN/modules/story_styles.po diff --git a/src/i18n/locales/zh_CN/modules/technique.po b/static/locales/zh-CN/modules/technique.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/technique.po rename to static/locales/zh-CN/modules/technique.po diff --git a/src/i18n/locales/zh_CN/modules/ui.po b/static/locales/zh-CN/modules/ui.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/ui.po rename to static/locales/zh-CN/modules/ui.po diff --git a/src/i18n/locales/zh_CN/modules/weapon.po b/static/locales/zh-CN/modules/weapon.po similarity index 100% rename from src/i18n/locales/zh_CN/modules/weapon.po rename to static/locales/zh-CN/modules/weapon.po diff --git a/src/i18n/locales/zh_TW/LC_MESSAGES/game_configs.mo b/static/locales/zh-TW/LC_MESSAGES/game_configs.mo similarity index 100% rename from src/i18n/locales/zh_TW/LC_MESSAGES/game_configs.mo rename to static/locales/zh-TW/LC_MESSAGES/game_configs.mo diff --git a/src/i18n/locales/zh_TW/LC_MESSAGES/game_configs.po b/static/locales/zh-TW/LC_MESSAGES/game_configs.po similarity index 100% rename from src/i18n/locales/zh_TW/LC_MESSAGES/game_configs.po rename to static/locales/zh-TW/LC_MESSAGES/game_configs.po diff --git a/static/locales/zh-TW/LC_MESSAGES/messages.mo b/static/locales/zh-TW/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..dd96fa2 Binary files /dev/null and b/static/locales/zh-TW/LC_MESSAGES/messages.mo differ diff --git a/src/i18n/locales/zh_TW/LC_MESSAGES/messages.po b/static/locales/zh-TW/LC_MESSAGES/messages.po similarity index 94% rename from src/i18n/locales/zh_TW/LC_MESSAGES/messages.po rename to static/locales/zh-TW/LC_MESSAGES/messages.po index 724d2e1..659dac2 100644 --- a/src/i18n/locales/zh_TW/LC_MESSAGES/messages.po +++ b/static/locales/zh-TW/LC_MESSAGES/messages.po @@ -2274,6 +2274,156 @@ msgstr "當陣營爲{align}時" msgid "When using {weapon_type}" msgstr "當使用{weapon_type}時" +msgid "SECT_1_STYLE" +msgstr "娓呮槑鍏嬪繁锛岃姝㈠涓€銆傞噸鍔嶈垏蹇冩硶涓﹂噸锛岃瑳绌舵槑蹇冭鎬с€" + +msgid "SECT_2_STYLE" +msgstr "瑷€瑾炵洿鎺ワ紝閲嶈鍔涢噺鑸囪鎬э紝宕囧皻鐙╃嵉鑸囨悘楝ャ€" + +msgid "SECT_2_RANK_PATRIARCH" +msgstr "璋蜂富" + +msgid "SECT_2_RANK_ELDER" +msgstr "渚涘" + +msgid "SECT_2_RANK_INNER" +msgstr "棣嵏甯" + +msgid "SECT_2_RANK_OUTER" +msgstr "鎵堝緸" + +msgid "SECT_3_STYLE" +msgstr "铏曚簨鍐烽潨鍦撹瀺锛屽枩浠ユ煍鍏嬪墰锛屾搮鍊熷姏鑸囧弽鍒躲€" + +msgid "SECT_3_RANK_PATRIARCH" +msgstr "閺′富" + +msgid "SECT_3_RANK_ELDER" +msgstr "鎺岄彙浜" + +msgid "SECT_3_RANK_INNER" +msgstr "鍌充汉" + +msgid "SECT_3_RANK_OUTER" +msgstr "渚嶉彙" + +msgid "SECT_4_STYLE" +msgstr "瑷€杈喎鍘插皯鎯咃紝鏁晱鍥犳灉鑰屼笉鎳兼浼愶紝鍋忓悜鏁堢巼鑸囩祼鏋溿€" + +msgid "SECT_4_RANK_PATRIARCH" +msgstr "娈夸富" + +msgid "SECT_4_RANK_ELDER" +msgstr "鍒ゅ畼" + +msgid "SECT_4_RANK_INNER" +msgstr "鐒″父" + +msgid "SECT_4_RANK_OUTER" +msgstr "楝煎崚" + +msgid "SECT_5_STYLE" +msgstr "鐩撮潰鎱炬湜鑸囦唬鍍癸紝涓嶆嚰榛戞殫锛屼互鏀讳紣瑕嬮暦銆" + +msgid "SECT_5_RANK_PATRIARCH" +msgstr "妯撲富" + +msgid "SECT_5_RANK_ELDER" +msgstr "鎺屽垜浣" + +msgid "SECT_5_RANK_INNER" +msgstr "褰卞埡" + +msgid "SECT_5_RANK_OUTER" +msgstr "鎺㈠瓙" + +msgid "SECT_6_STYLE" +msgstr "杈护濠夎綁锛屽杽鏂兼嬁鎹忎汉鎱捐垏灞€鍕紝浠ユ煍鍒跺墰銆" + +msgid "SECT_6_RANK_PATRIARCH" +msgstr "瀹富" + +msgid "SECT_6_RANK_ELDER" +msgstr "璀锋硶" + +msgid "SECT_6_RANK_INNER" +msgstr "濯氫粰" + +msgid "SECT_6_RANK_OUTER" +msgstr "渚嶇" + +msgid "SECT_7_STYLE" +msgstr "鑲呯﹩娌夌┅锛岄噸瀹夐瓊閹偑锛屽皯瑷€鑰屾灉姹恒€" + +msgid "SECT_7_RANK_PATRIARCH" +msgstr "浣忔寔" + +msgid "SECT_7_RANK_ELDER" +msgstr "棣栧骇" + +msgid "SECT_7_RANK_INNER" +msgstr "琛岃€" + +msgid "SECT_7_RANK_OUTER" +msgstr "灞呭+" + +msgid "SECT_8_STYLE" +msgstr "琛屼簨闅辩鏋滄柗锛岄噸绲愭灉杓曡櫅鍚嶏紝鎿呮經琛岃垏鍑哄叾涓嶆剰銆" + +msgid "SECT_8_RANK_PATRIARCH" +msgstr "闁€涓" + +msgid "SECT_8_RANK_ELDER" +msgstr "璀锋硶" + +msgid "SECT_8_RANK_INNER" +msgstr "褰辫" + +msgid "SECT_8_RANK_OUTER" +msgstr "鎺㈠瓙" + +msgid "SECT_9_STYLE" +msgstr "鍕欏绮炬槑锛岄噸浜ゆ槗鑸囦俊璀斤紝宕囧皻瑕忓墖鑸囩З搴忋€" + +msgid "SECT_9_RANK_PATRIARCH" +msgstr "鍩庝富" + +msgid "SECT_9_RANK_ELDER" +msgstr "澶т緵濂" + +msgid "SECT_9_RANK_INNER" +msgstr "鍩蜂簨" + +msgid "SECT_9_RANK_OUTER" +msgstr "瀛稿緬" + +msgid "SECT_10_STYLE" +msgstr "鏂囬泤绺圭凡涓繁钘忕畻瑷堬紝鍠滅敤瑷€瑾炶垏闊冲緥鎺屾帶灞€鍕紝娈轰紣涓嶆簿鐓欑伀姘c€" + +msgid "SECT_11_STYLE" +msgstr "鍤磋绱扮坊锛岃拷姹傛妧琛撴サ鑷达紝鎴伴涓搮闀蜂互寰屾墜闄f硶鍙嶅埗鏁典汉锛屾姝ョ偤鐕熴€" + +msgid "SECT_12_STYLE" +msgstr "鍫呴煂闋戝挤锛屽湪閫嗗涓湒寮凤紝琛屼簨鍏夋槑纾婅惤浣嗕篃娣辫瑎閬犳叜锛屾サ鍏惰鐭€" + +msgid "SECT_12_RANK_PATRIARCH" +msgstr "鍩庝富" + +msgid "SECT_12_RANK_ELDER" +msgstr "闁h€" + +msgid "SECT_12_RANK_INNER" +msgstr "鍩蜂护" + +msgid "SECT_12_RANK_OUTER" +msgstr "瀹堝浜" + +msgid "SECT_13_STYLE" +msgstr "鎭畧鍘熷墖锛岃瑳绌堕亾缇╋紝闄ら瓟琛涢亾涓€棣暥鍏堬紝瀵ф姌涓嶅綆銆" + +msgid "SECT_14_STYLE" +msgstr "寮疯€呯偤灏婏紝闅ㄥ績鎵€娆诧紝宕囧皻绲曞皪鐨勫姏閲忚垏娈烘埉锛岃鐪剧敓鐐鸿椋熴€" + # ============================================================================ # Simulator & Event Translations # ============================================================================ diff --git a/src/i18n/locales/zh_TW/modules/action.po b/static/locales/zh-TW/modules/action.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/action.po rename to static/locales/zh-TW/modules/action.po diff --git a/src/i18n/locales/zh_TW/modules/alignment.po b/static/locales/zh-TW/modules/alignment.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/alignment.po rename to static/locales/zh-TW/modules/alignment.po diff --git a/src/i18n/locales/zh_TW/modules/auxiliary.po b/static/locales/zh-TW/modules/auxiliary.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/auxiliary.po rename to static/locales/zh-TW/modules/auxiliary.po diff --git a/src/i18n/locales/zh_TW/modules/avatar.po b/static/locales/zh-TW/modules/avatar.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/avatar.po rename to static/locales/zh-TW/modules/avatar.po diff --git a/src/i18n/locales/zh_TW/modules/battle.po b/static/locales/zh-TW/modules/battle.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/battle.po rename to static/locales/zh-TW/modules/battle.po diff --git a/src/i18n/locales/zh_TW/modules/cultivation.po b/static/locales/zh-TW/modules/cultivation.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/cultivation.po rename to static/locales/zh-TW/modules/cultivation.po diff --git a/src/i18n/locales/zh_TW/modules/death_reasons.po b/static/locales/zh-TW/modules/death_reasons.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/death_reasons.po rename to static/locales/zh-TW/modules/death_reasons.po diff --git a/src/i18n/locales/zh_TW/modules/direction_names.po b/static/locales/zh-TW/modules/direction_names.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/direction_names.po rename to static/locales/zh-TW/modules/direction_names.po diff --git a/src/i18n/locales/zh_TW/modules/effect.po b/static/locales/zh-TW/modules/effect.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/effect.po rename to static/locales/zh-TW/modules/effect.po diff --git a/src/i18n/locales/zh_TW/modules/elixir.po b/static/locales/zh-TW/modules/elixir.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/elixir.po rename to static/locales/zh-TW/modules/elixir.po diff --git a/src/i18n/locales/zh_TW/modules/essence_type.po b/static/locales/zh-TW/modules/essence_type.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/essence_type.po rename to static/locales/zh-TW/modules/essence_type.po diff --git a/src/i18n/locales/zh_TW/modules/feedback_labels.po b/static/locales/zh-TW/modules/feedback_labels.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/feedback_labels.po rename to static/locales/zh-TW/modules/feedback_labels.po diff --git a/src/i18n/locales/zh_TW/modules/fortune.po b/static/locales/zh-TW/modules/fortune.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/fortune.po rename to static/locales/zh-TW/modules/fortune.po diff --git a/src/i18n/locales/zh_TW/modules/gathering.po b/static/locales/zh-TW/modules/gathering.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/gathering.po rename to static/locales/zh-TW/modules/gathering.po diff --git a/src/i18n/locales/zh_TW/modules/gender.po b/static/locales/zh-TW/modules/gender.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/gender.po rename to static/locales/zh-TW/modules/gender.po diff --git a/src/i18n/locales/zh_TW/modules/hidden_domain.po b/static/locales/zh-TW/modules/hidden_domain.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/hidden_domain.po rename to static/locales/zh-TW/modules/hidden_domain.po diff --git a/src/i18n/locales/zh_TW/modules/item_exchange.po b/static/locales/zh-TW/modules/item_exchange.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/item_exchange.po rename to static/locales/zh-TW/modules/item_exchange.po diff --git a/src/i18n/locales/zh_TW/modules/labels.po b/static/locales/zh-TW/modules/labels.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/labels.po rename to static/locales/zh-TW/modules/labels.po diff --git a/src/i18n/locales/zh_TW/modules/llm_prompt.po b/static/locales/zh-TW/modules/llm_prompt.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/llm_prompt.po rename to static/locales/zh-TW/modules/llm_prompt.po diff --git a/src/i18n/locales/zh_TW/modules/map.po b/static/locales/zh-TW/modules/map.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/map.po rename to static/locales/zh-TW/modules/map.po diff --git a/src/i18n/locales/zh_TW/modules/misc.po b/static/locales/zh-TW/modules/misc.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/misc.po rename to static/locales/zh-TW/modules/misc.po diff --git a/src/i18n/locales/zh_TW/modules/misfortune.po b/static/locales/zh-TW/modules/misfortune.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/misfortune.po rename to static/locales/zh-TW/modules/misfortune.po diff --git a/src/i18n/locales/zh_TW/modules/mutual_action.po b/static/locales/zh-TW/modules/mutual_action.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/mutual_action.po rename to static/locales/zh-TW/modules/mutual_action.po diff --git a/src/i18n/locales/zh_TW/modules/realm.po b/static/locales/zh-TW/modules/realm.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/realm.po rename to static/locales/zh-TW/modules/realm.po diff --git a/src/i18n/locales/zh_TW/modules/relation.po b/static/locales/zh-TW/modules/relation.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/relation.po rename to static/locales/zh-TW/modules/relation.po diff --git a/src/i18n/locales/zh_TW/modules/root_element.po b/static/locales/zh-TW/modules/root_element.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/root_element.po rename to static/locales/zh-TW/modules/root_element.po diff --git a/src/i18n/locales/zh_TW/modules/sect.po b/static/locales/zh-TW/modules/sect.po similarity index 66% rename from src/i18n/locales/zh_TW/modules/sect.po rename to static/locales/zh-TW/modules/sect.po index 1d7a4b0..7249bdf 100644 --- a/src/i18n/locales/zh_TW/modules/sect.po +++ b/static/locales/zh-TW/modules/sect.po @@ -278,3 +278,154 @@ msgstr "當陣營爲{align}時" msgid "When using {weapon_type}" msgstr "當使用{weapon_type}時" + +msgid "SECT_1_STYLE" +msgstr "娓呮槑鍏嬪繁锛岃姝㈠涓€銆傞噸鍔嶈垏蹇冩硶涓﹂噸锛岃瑳绌舵槑蹇冭鎬с€? + +msgid "SECT_2_STYLE" +msgstr "瑷€瑾炵洿鎺ワ紝閲嶈鍔涢噺鑸囪鎬э紝宕囧皻鐙╃嵉鑸囨悘楝ャ€? + +msgid "SECT_2_RANK_PATRIARCH" +msgstr "璋蜂富" + +msgid "SECT_2_RANK_ELDER" +msgstr "渚涘" + +msgid "SECT_2_RANK_INNER" +msgstr "棣嵏甯? + +msgid "SECT_2_RANK_OUTER" +msgstr "鎵堝緸" + +msgid "SECT_3_STYLE" +msgstr "铏曚簨鍐烽潨鍦撹瀺锛屽枩浠ユ煍鍏嬪墰锛屾搮鍊熷姏鑸囧弽鍒躲€? + +msgid "SECT_3_RANK_PATRIARCH" +msgstr "閺′富" + +msgid "SECT_3_RANK_ELDER" +msgstr "鎺岄彙浜? + +msgid "SECT_3_RANK_INNER" +msgstr "鍌充汉" + +msgid "SECT_3_RANK_OUTER" +msgstr "渚嶉彙" + +msgid "SECT_4_STYLE" +msgstr "瑷€杈喎鍘插皯鎯咃紝鏁晱鍥犳灉鑰屼笉鎳兼浼愶紝鍋忓悜鏁堢巼鑸囩祼鏋溿€? + +msgid "SECT_4_RANK_PATRIARCH" +msgstr "娈夸富" + +msgid "SECT_4_RANK_ELDER" +msgstr "鍒ゅ畼" + +msgid "SECT_4_RANK_INNER" +msgstr "鐒″父" + +msgid "SECT_4_RANK_OUTER" +msgstr "楝煎崚" + +msgid "SECT_5_STYLE" +msgstr "鐩撮潰鎱炬湜鑸囦唬鍍癸紝涓嶆嚰榛戞殫锛屼互鏀讳紣瑕嬮暦銆? + +msgid "SECT_5_RANK_PATRIARCH" +msgstr "妯撲富" + +msgid "SECT_5_RANK_ELDER" +msgstr "鎺屽垜浣? + +msgid "SECT_5_RANK_INNER" +msgstr "褰卞埡" + +msgid "SECT_5_RANK_OUTER" +msgstr "鎺㈠瓙" + +msgid "SECT_6_STYLE" +msgstr "杈护濠夎綁锛屽杽鏂兼嬁鎹忎汉鎱捐垏灞€鍕紝浠ユ煍鍒跺墰銆? + +msgid "SECT_6_RANK_PATRIARCH" +msgstr "瀹富" + +msgid "SECT_6_RANK_ELDER" +msgstr "璀锋硶" + +msgid "SECT_6_RANK_INNER" +msgstr "濯氫粰" + +msgid "SECT_6_RANK_OUTER" +msgstr "渚嶇" + +msgid "SECT_7_STYLE" +msgstr "鑲呯﹩娌夌┅锛岄噸瀹夐瓊閹偑锛屽皯瑷€鑰屾灉姹恒€? + +msgid "SECT_7_RANK_PATRIARCH" +msgstr "浣忔寔" + +msgid "SECT_7_RANK_ELDER" +msgstr "棣栧骇" + +msgid "SECT_7_RANK_INNER" +msgstr "琛岃€? + +msgid "SECT_7_RANK_OUTER" +msgstr "灞呭+" + +msgid "SECT_8_STYLE" +msgstr "琛屼簨闅辩鏋滄柗锛岄噸绲愭灉杓曡櫅鍚嶏紝鎿呮經琛岃垏鍑哄叾涓嶆剰銆? + +msgid "SECT_8_RANK_PATRIARCH" +msgstr "闁€涓? + +msgid "SECT_8_RANK_ELDER" +msgstr "璀锋硶" + +msgid "SECT_8_RANK_INNER" +msgstr "褰辫" + +msgid "SECT_8_RANK_OUTER" +msgstr "鎺㈠瓙" + +msgid "SECT_9_STYLE" +msgstr "鍕欏绮炬槑锛岄噸浜ゆ槗鑸囦俊璀斤紝宕囧皻瑕忓墖鑸囩З搴忋€? + +msgid "SECT_9_RANK_PATRIARCH" +msgstr "鍩庝富" + +msgid "SECT_9_RANK_ELDER" +msgstr "澶т緵濂? + +msgid "SECT_9_RANK_INNER" +msgstr "鍩蜂簨" + +msgid "SECT_9_RANK_OUTER" +msgstr "瀛稿緬" + +msgid "SECT_10_STYLE" +msgstr "鏂囬泤绺圭凡涓繁钘忕畻瑷堬紝鍠滅敤瑷€瑾炶垏闊冲緥鎺屾帶灞€鍕紝娈轰紣涓嶆簿鐓欑伀姘c€? + +msgid "SECT_11_STYLE" +msgstr "鍤磋绱扮坊锛岃拷姹傛妧琛撴サ鑷达紝鎴伴涓搮闀蜂互寰屾墜闄f硶鍙嶅埗鏁典汉锛屾姝ョ偤鐕熴€? + +msgid "SECT_12_STYLE" +msgstr "鍫呴煂闋戝挤锛屽湪閫嗗涓湒寮凤紝琛屼簨鍏夋槑纾婅惤浣嗕篃娣辫瑎閬犳叜锛屾サ鍏惰鐭€? + +msgid "SECT_12_RANK_PATRIARCH" +msgstr "鍩庝富" + +msgid "SECT_12_RANK_ELDER" +msgstr "闁h€? + +msgid "SECT_12_RANK_INNER" +msgstr "鍩蜂护" + +msgid "SECT_12_RANK_OUTER" +msgstr "瀹堝浜? + +msgid "SECT_13_STYLE" +msgstr "鎭畧鍘熷墖锛岃瑳绌堕亾缇╋紝闄ら瓟琛涢亾涓€棣暥鍏堬紝瀵ф姌涓嶅綆銆? + +msgid "SECT_14_STYLE" +msgstr "寮疯€呯偤灏婏紝闅ㄥ績鎵€娆诧紝宕囧皻绲曞皪鐨勫姏閲忚垏娈烘埉锛岃鐪剧敓鐐鸿椋熴€? + diff --git a/src/i18n/locales/zh_TW/modules/simulator.po b/static/locales/zh-TW/modules/simulator.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/simulator.po rename to static/locales/zh-TW/modules/simulator.po diff --git a/src/i18n/locales/zh_TW/modules/single_choice.po b/static/locales/zh-TW/modules/single_choice.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/single_choice.po rename to static/locales/zh-TW/modules/single_choice.po diff --git a/src/i18n/locales/zh_TW/modules/stage.po b/static/locales/zh-TW/modules/stage.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/stage.po rename to static/locales/zh-TW/modules/stage.po diff --git a/src/i18n/locales/zh_TW/modules/story_styles.po b/static/locales/zh-TW/modules/story_styles.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/story_styles.po rename to static/locales/zh-TW/modules/story_styles.po diff --git a/src/i18n/locales/zh_TW/modules/technique.po b/static/locales/zh-TW/modules/technique.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/technique.po rename to static/locales/zh-TW/modules/technique.po diff --git a/src/i18n/locales/zh_TW/modules/ui.po b/static/locales/zh-TW/modules/ui.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/ui.po rename to static/locales/zh-TW/modules/ui.po diff --git a/src/i18n/locales/zh_TW/modules/weapon.po b/static/locales/zh-TW/modules/weapon.po similarity index 100% rename from src/i18n/locales/zh_TW/modules/weapon.po rename to static/locales/zh-TW/modules/weapon.po diff --git a/tests/README_NEW_I18N_TESTS.md b/tests/README_NEW_I18N_TESTS.md deleted file mode 100644 index 548f4db..0000000 --- a/tests/README_NEW_I18N_TESTS.md +++ /dev/null @@ -1,337 +0,0 @@ -# 新增 i18n 测试说明 - -## 概述 - -针对你完成的 `src/classes/` 本地化工作,我添加了以下测试逻辑来确保国际化的质量和完整性。 - -## 新增测试文件 - -### 1. ✅ `test_i18n_duplicates.py` - PO 文件重复项检查 - -**状态**: 已创建并通过测试 - -**功能**: -- 检查中英文 PO 文件中是否有重复的 msgid -- 检查中英文 msgid 数量是否一致 -- 检查中英文 msgid 键是否完全匹配 - -**特点**: -- 独立运行,不依赖 conftest.py -- 快速执行(< 5秒) -- 适合 pre-commit hook - -**运行方式**: -```bash -python tests/test_i18n_duplicates.py -``` - -**当前结果**: ✅ 所有测试通过 (4/4) -- 中文: 519 个 msgid,无重复 -- 英文: 519 个 msgid,无重复 -- 中英文完全匹配 - ---- - -### 2. ⚠️ `test_i18n_po_quality.py` - PO 文件质量和代码检查 - -**状态**: 已创建,发现需要修复的问题 - -**功能**: -- 🔍 检测硬编码的中文字符串(应使用 `t()` 函数) -- 🔍 检测代码中使用但 PO 文件中未定义的翻译键 -- 🔍 检测格式化参数不一致问题 - -**特点**: -- 使用 AST 解析器静态分析代码 -- 不依赖项目导入,避免循环依赖 -- 提供详细的问题定位信息 - -**运行方式**: -```bash -python tests/test_i18n_po_quality.py -``` - -**当前发现的问题**: - -#### 1. 硬编码中文字符串 (~460 处) -主要在以下文件: -- `classes/appearance.py` - 外貌描述数据 -- `classes/alignment.py` - 枚举注释 -- `classes/animal.py` - 动物信息 - -**分析**: -- 大部分是**数据文件**中的内容(如 appearance.py 中的外貌描述) -- 一些是**枚举常量的注释**(可接受) -- 需要评估哪些应该本地化,哪些可以作为数据保留 - -**建议优先级**: -- 🔴 高优先级: 用户可见的运行时文本 -- 🟡 中优先级: 数据文件中的描述 -- 🟢 低优先级: 注释和调试信息 - -#### 2. 缺失的翻译键 (9 个) - -``` -❌ 代码中使用但 PO 文件中未定义: - - '\n(Selecting {replace} will sell old {label})' - - '\n--- Current Effects Detail ---' - - '\n【Related Avatars Information】' - - 'Current {label}: {old_info}\n{new_desc}' - - 'Event Type: Mysterious Auction\nScene Setting: ...' - - 'Unsupported item type: {item_type}' - - '{avatar} gained cultivation experience +{exp} points' - - '{winner} defeated {loser}' - - '【Current Situation】: {context}\n\n{choices}' -``` - -**修复方法**: 需要在两个 PO 文件中添加这些 msgid 及其翻译 - -#### 3. 格式化参数一致性 -✅ **当前状态**: 所有翻译的格式化参数都一致 - ---- - -### 3. 📝 `test_i18n_classes_coverage.py` - Classes 模块深度测试 - -**状态**: 已创建,需要修复项目导入问题后运行 - -**功能**: -- 测试各种枚举的翻译(境界、性别、阵营等) -- 测试动作名称翻译 -- 测试效果名称翻译 -- 测试中英文切换 - -**特点**: -- 全面测试 classes 模块的国际化 -- 包含实际的翻译功能测试 -- 验证参数化翻译 - -**阻塞问题**: -```python -ImportError: cannot import name 'EFFECT_DESC_MAP' from 'src.classes.effect.desc' -``` - -**建议**: 修复项目导入后再启用此测试 - ---- - -### 4. 📚 文档 - -#### `README_i18n_tests.md` - 测试套件完整文档 -详细说明了: -- 所有测试的用途和运行方式 -- 快速检查清单 -- 修复常见问题的指南 -- CI/CD 集成示例 -- 最佳实践 - -#### `README_i18n_duplicates.md` - 重复项检查专项文档 -之前创建的,专门针对 PO 文件重复项检查 - ---- - -### 5. 🌍 `test_csv_i18n.py` - CSV 配置国际化测试 - -**状态**: 已创建并通过测试 - -**功能**: -- 测试 CSV 配置的单源加载机制(Single Source of Truth) -- 验证 `load_game_configs` 时自动注入翻译 -- 测试中英文切换时配置值的正确变化 -- 验证随机姓名生成器的国际化支持 - -**特点**: -- 包含 Mock 单元测试(无需真实文件) -- 包含集成测试(使用真实 `static/game_configs`) -- 覆盖了重构后的配置加载核心逻辑 - -**运行方式**: -```bash -python -m pytest tests/test_csv_i18n.py -``` - ---- - -## 测试覆盖的方面 - -### ✅ 已覆盖 - -1. **PO 文件完整性** - - 无重复 msgid ✅ - - 中英文数量一致 ✅ - - 中英文键匹配 ✅ - - 格式化参数一致 ✅ - -2. **代码质量检查** - - 硬编码字符串检测 ✅ - - 翻译键定义检查 ✅ - - AST 静态分析 ✅ - -3. **配置国际化** - - CSV 单源加载机制 ✅ - - 动态翻译注入 ✅ - - 姓名生成器适配 ✅ - -4. **文档和工具** - - 详细测试文档 ✅ - - 独立检查工具 ✅ - - CI/CD 集成示例 ✅ - -### 🔄 待完善 - -1. **深度功能测试** - - 需要修复项目导入问题 - - 需要测试更多实际场景 - -2. **自动化修复** - - 考虑添加自动修复脚本 - - 批量添加缺失翻译的工具 - -3. **性能测试** - - 翻译性能测试 - - 缓存效果测试 - ---- - -## 推荐的工作流程 - -### 日常开发 - -```bash -# 1. 编写代码,使用 t() 函数 -code = t("{name} obtained {amount} spirit stones", name=name, amount=100) - -# 2. 运行快速检查(提交前) -python tests/test_i18n_duplicates.py -python tests/test_i18n_po_quality.py - -# 3. 如果发现缺失的翻译,添加到 PO 文件 - -# 4. 重新运行测试确认 -python tests/test_i18n_duplicates.py -``` - -### 大规模修改后 - -```bash -# 运行完整测试套件 -python -m pytest tests/test_i18n_*.py -v - -# 如果有导入问题,先运行独立测试 -python tests/test_i18n_duplicates.py -python tests/test_i18n_po_quality.py -``` - ---- - -## 需要你处理的事项 - -### 🔴 高优先级 - -1. **修复缺失的翻译键** - - 在两个 PO 文件中添加 9 个缺失的 msgid - - 参考 `test_i18n_po_quality.py` 的输出 - -2. **评估硬编码字符串** - - 查看 `classes/appearance.py` 等文件 - - 决定哪些需要本地化,哪些作为数据保留 - -### 🟡 中优先级 - -3. **修复项目导入问题** - ```python - # 修复这个导入错误 - ImportError: cannot import name 'EFFECT_DESC_MAP' - ``` - -4. **添加 CI/CD 集成** - - 参考 `README_i18n_tests.md` 中的 GitHub Actions 示例 - -### 🟢 低优先级 - -5. **优化测试性能** - - 考虑缓存 AST 解析结果 - -6. **添加更多测试场景** - - 测试特殊字符处理 - - 测试复数形式(如果需要) - ---- - -## 测试统计 - -### 当前测试覆盖 - -| 测试类别 | 测试数量 | 通过 | 警告 | 失败 | -|---------|---------|------|------|------| -| PO 重复项 | 4 | 4 | 0 | 0 | -| 翻译键定义 | 1 | 0 | 1 | 0 | -| 硬编码检测 | 1 | 0 | 1 | 0 | -| 参数一致性 | 1 | 1 | 0 | 0 | -| **总计** | **7** | **5** | **2** | **0** | - -### PO 文件统计 - -- **总 msgid 数**: 519 -- **代码中使用**: 239 个唯一 msgid -- **使用率**: 46% -- **缺失定义**: 9 个 -- **重复项**: 0 个 -- **参数错误**: 0 个 - ---- - -## 技术亮点 - -### 1. 独立测试设计 -所有新测试都不依赖 conftest.py,避免了项目导入问题 - -### 2. AST 静态分析 -使用 Python AST 解析器精确提取 `t()` 函数调用 - -### 3. 详细错误定位 -提供文件名、行号和具体内容,便于快速修复 - -### 4. 可扩展性 -测试框架易于扩展,可以添加更多检查规则 - ---- - -## 下一步建议 - -1. **立即行动**: - - 在 PO 文件中添加 9 个缺失的 msgid - - 运行测试确认修复 - -2. **短期计划**: - - 评估硬编码中文字符串,决定处理策略 - - 修复项目导入问题 - -3. **长期规划**: - - 将测试集成到 CI/CD - - 建立翻译工作流程文档 - - 考虑使用翻译管理工具 - ---- - -## 相关文件 - -- ✅ `tests/test_i18n_duplicates.py` - 重复项检查 -- ✅ `tests/test_i18n_po_quality.py` - 质量检查 -- ✅ `tests/test_i18n_classes_coverage.py` - 覆盖率测试 -- ✅ `tests/README_i18n_tests.md` - 详细文档 -- ✅ `tests/README_i18n_duplicates.md` - 重复项文档 -- ✅ `tools/i18n/check_po_duplicates.py` - 独立工具 - ---- - -## 总结 - -通过添加这套测试,我们现在可以: - -✅ **自动检测** PO 文件中的重复项 -✅ **自动发现** 代码中缺失的翻译 -✅ **自动验证** 格式化参数的一致性 -✅ **持续监控** 国际化工作的质量 - -这将大大提高国际化工作的效率和质量!🎉 diff --git a/tests/README_i18n_duplicates.md b/tests/README_i18n_duplicates.md deleted file mode 100644 index df9ff3f..0000000 --- a/tests/README_i18n_duplicates.md +++ /dev/null @@ -1,126 +0,0 @@ -# i18n PO 文件重复项检查 - -## 概述 - -本测试用于检查项目中的 i18n PO 文件(中文和英文)是否存在重复的 `msgid` 条目,以及确保中英文翻译文件的一致性。 - -## 测试内容 - -1. **检查中文 po 文件没有重复的 msgid** - - 扫描 `src/i18n/locales/zh_CN/LC_MESSAGES/messages.po` - - 确保没有重复的翻译键 - -2. **检查英文 po 文件没有重复的 msgid** - - 扫描 `src/i18n/locales/en_US/LC_MESSAGES/messages.po` - - 确保没有重复的翻译键 - -3. **检查中英文 msgid 数量一致** - - 确保两个语言文件的条目数量相同 - -4. **检查中英文 msgid 键完全匹配** - - 确保两个文件中的所有 msgid 键完全一致 - - 防止某个语言缺少翻译或多出翻译 - -## 使用方法 - -### 方法一:直接运行测试文件 - -```bash -python tests/test_i18n_duplicates.py -``` - -这个测试文件是独立的,不依赖 `conftest.py`,可以直接运行。 - -### 方法二:使用工具脚本 - -```bash -python tools/i18n/check_po_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) -``` - -### 失败时的输出 - -``` -============================================================ -i18n PO 文件重复项检查 -============================================================ - -检查中文 po 文件没有重复... -[FAIL] 中文 po 文件中发现 2 个重复的 msgid: - - 'Encountered fortune ({theme}), {result}' 出现了 2 次 - - 'New {label}: {info}' 出现了 2 次 - -... - -============================================================ -[FAIL] 部分测试失败 (1/4) -``` - -## 常见问题 - -### 如果发现重复的 msgid 怎么办? - -1. 使用工具定位重复的位置 -2. 检查两个重复条目的上下文,确定哪个是正确的 -3. 删除多余的重复条目 -4. 重新运行测试确认修复 - -### 如何在 CI/CD 中集成? - -在 GitHub Actions 或其他 CI 系统中添加: - -```yaml -- name: Check i18n PO duplicates - run: python tests/test_i18n_duplicates.py -``` - -脚本会返回退出码: -- `0`: 所有测试通过 -- `1`: 有测试失败 - -## 相关文件 - -- `tests/test_i18n_duplicates.py` - 独立测试脚本 -- `tools/i18n/check_po_duplicates.py` - 检查工具脚本 -- `src/i18n/locales/zh_CN/LC_MESSAGES/messages.po` - 中文翻译文件 -- `src/i18n/locales/en_US/LC_MESSAGES/messages.po` - 英文翻译文件 - -## 维护说明 - -当添加新的翻译条目时: - -1. 确保在两个语言文件中同时添加 -2. 确保 `msgid` 完全一致 -3. 运行此测试确保没有引入重复或不一致 - -## 技术细节 - -- 使用正则表达式 `msgid\s+"([^"]*)"` 提取 msgid -- 使用 `collections.Counter` 统计重复 -- 使用 `set` 操作检查键的差异 diff --git a/tests/README_i18n_tests.md b/tests/README_i18n_tests.md index 45da566..8253ea3 100644 --- a/tests/README_i18n_tests.md +++ b/tests/README_i18n_tests.md @@ -1,467 +1,128 @@ -# i18n 国际化测试套件 +# i18n 测试说明 ## 概述 -本测试套件用于确保项目的国际化(i18n)工作质量,包括翻译完整性、代码规范和翻译文件的一致性。 +针对 `src/classes/` 的本地化工作,本项目添加了以下测试逻辑来确保国际化的质量和完整性。 ## 测试文件 -### 1. `test_i18n_duplicates.py` - PO 文件重复项检查 +### 1. ✅ `test_i18n_duplicates.py` - PO 文件重复项检查 -**独立测试**,不依赖 conftest.py,可直接运行。 +**状态**: 已创建并通过测试 -#### 测试内容 -- ✅ 检查中文 PO 文件没有重复的 msgid -- ✅ 检查英文 PO 文件没有重复的 msgid -- ✅ 检查中英文 msgid 数量一致 -- ✅ 检查中英文 msgid 键完全匹配 +**功能**: +- 检查中英文 PO 文件中是否有重复的 msgid +- 检查中英文 msgid 数量是否一致 +- 检查中英文 msgid 键是否完全匹配 -#### 运行方式 +**特点**: +- 独立运行,不依赖 conftest.py +- 快速执行(< 5秒) +- 适合 pre-commit hook + +**运行方式**: ```bash 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 文件质量和代码检查 +### 2. ⚠️ `test_i18n_po_quality.py` - PO 文件质量和代码检查 -**独立测试**,专注于静态分析,不依赖项目导入。 +**状态**: 已创建,发现需要修复的问题 -#### 测试内容 -- 🔍 检查源代码中是否有硬编码的中文字符串(应使用 `t()` 函数) -- 🔍 检查代码中使用的所有翻译键是否都在 PO 文件中定义 -- 🔍 检查格式化参数在 msgid 和 msgstr 中的一致性 +**功能**: +- 🔍 检测硬编码的中文字符串(应使用 `t()` 函数) +- 🔍 检测代码中使用但 PO 文件中未定义的翻译键 +- 🔍 检测格式化参数不一致问题 -#### 运行方式 +**特点**: +- 使用 AST 解析器静态分析代码 +- 不依赖项目导入,避免循环依赖 +- 提供详细的问题定位信息 + +**运行方式**: ```bash python tests/test_i18n_po_quality.py ``` -#### 检查项目详情 +**当前发现的问题**: -##### 1. 硬编码中文字符串检查 -扫描 `src/` 目录下的所有 Python 文件,查找可能硬编码的中文字符串。 +#### 1. 硬编码中文字符串 +主要在以下文件: +- `classes/appearance.py` - 外貌描述数据 +- `classes/alignment.py` - 枚举注释 +- `classes/animal.py` - 动物信息 -**规则:** -- 跳过注释和文档字符串 -- 跳过测试文件 -- 检测字符串字面量中的中文字符 -- 如果不在 `t()` 调用中,可能需要修复 +**分析**: +- 大部分是**数据文件**中的内容(如 appearance.py 中的外貌描述) +- 一些是**枚举常量的注释**(可接受) -**常见误报:** -- 枚举值的注释(如 `RIGHTEOUS = "righteous" # 正`) -- 测试数据 -- 配置键名 +#### 2. 缺失的翻译键 +代码中使用但 PO 文件中未定义,需要在两个 PO 文件中添加这些 msgid 及其翻译。 -##### 2. 翻译键定义检查 -使用 AST 解析器提取代码中所有 `t()` 函数调用,并与 PO 文件中定义的 msgid 对比。 +--- -**检查逻辑:** -```python -# 代码中使用 -result = t("{name} obtained {amount} spirit stones", name="张三", amount=100) +### 3. 📝 `test_i18n_classes_coverage.py` - Classes 模块深度测试 -# 必须在 messages.po 中有定义 -msgid "{name} obtained {amount} spirit stones" -msgstr "{name} 获得灵石 {amount} 枚" -``` +**状态**: (已移除,原版本依赖过时 API) -**如果发现缺失:** -需要在两个 PO 文件中都添加这个翻译键。 +建议使用 `test_i18n_po_quality.py` 进行静态分析。 -##### 3. 格式化参数一致性检查 -确保翻译文本中的占位符参数与原始 msgid 一致。 +--- -**示例:** -``` -✅ 正确: -msgid "{name} lost {amount} spirit stones" -msgstr "{name} 损失灵石 {amount} 枚" (参数: name, amount) +### 4. 🌍 `test_csv_i18n.py` - CSV 配置国际化测试 -❌ 错误: -msgid "{name} lost {amount} spirit stones" -msgstr "{user} 损失灵石 {count} 枚" (参数: user, count) - 不匹配! -``` +**状态**: 已创建并通过测试 -#### 输出示例 -``` -============================================================ -PO 文件质量和翻译键使用检查 -============================================================ +**功能**: +- 测试 CSV 配置的单源加载机制(Single Source of Truth) +- 验证 `load_game_configs` 时自动注入翻译 +- 测试中英文切换时配置值的正确变化 +- 验证随机姓名生成器的国际化支持 -============================================================ -测试: 检查硬编码中文字符串 -============================================================ +**特点**: +- 包含 Mock 单元测试(无需真实文件) +- 包含集成测试(使用真实 `static/game_configs`) +- 覆盖了重构后的配置加载核心逻辑 -警告:发现可能的硬编码中文字符串(应使用 t() 函数): -============================================================ - classes\appearance.py:35 - (1, "俊朗", "你长得很成熟,举止协调,给人从容踏实感。", ...) - ... 还有 448 个 - -注意:这可能包括误报,请手动检查 - -============================================================ -测试: 检查翻译键定义 -============================================================ - -PO 文件中定义了 519 个 msgid -代码中使用了 239 个唯一的 msgid - -✓ 所有使用的 msgid 都已在 PO 文件中定义 - -============================================================ -测试: 检查格式化参数一致性 -============================================================ - -检查 519 个翻译条目的格式化参数一致性... -✓ 所有翻译的格式化参数都一致 - -============================================================ -测试完成 -============================================================ +**运行方式**: +```bash +python -m pytest tests/test_csv_i18n.py ``` --- -### 3. `test_i18n_classes_coverage.py` - Classes 模块国际化覆盖率 +## 推荐的工作流程 -**需要完整项目环境**,用于深度测试 classes 模块的国际化集成。 - -#### 测试内容 -- 🧪 测试各种枚举类型的翻译(境界、性别、阵营等) -- 🧪 测试动作名称的翻译 -- 🧪 测试效果名称的翻译 -- 🧪 测试带参数的翻译 -- 🧪 测试中英文切换 - -#### 运行方式 -```bash -python -m pytest tests/test_i18n_classes_coverage.py -v -``` - -**注意:** 此测试依赖项目完整环境,如果有导入错误请先修复项目依赖。 - ---- - -### 4. `test_i18n_dynamic.py` - 动态文本翻译测试 - -**标准 pytest 测试**,测试 i18n 模块的基本功能。 - -#### 测试内容 -- ✅ PO 文件语法和完整性 -- ✅ 中英文基本翻译功能 -- ✅ 战斗消息翻译 -- ✅ 奇遇消息翻译 -- ✅ 死亡原因翻译 -- ✅ 语言切换功能 - -#### 运行方式 -```bash -python -m pytest tests/test_i18n_dynamic.py -v -``` - ---- - -## 快速检查清单 - -### 添加新功能时 - -1. **编写代码时:** - - ✅ 所有用户可见的文本都使用 `t()` 函数 - - ✅ 不要硬编码中文或英文字符串 - - ✅ 使用有意义的 msgid(通常是英文描述) - -2. **添加翻译:** - ```python - # 代码中 - message = t("{name} obtained {amount} spirit stones", name=avatar.name, amount=100) - ``` - - ```po - # messages.po 中(两个语言文件都要加) - msgid "{name} obtained {amount} spirit stones" - msgstr "{name} 获得灵石 {amount} 枚" # zh_CN - msgstr "{name} obtained {amount} spirit stones" # en_US - ``` - -3. **运行测试:** - ```bash - # 快速检查 - python tests/test_i18n_duplicates.py - python tests/test_i18n_po_quality.py - - # 完整测试 - python -m pytest tests/test_i18n_*.py -v - ``` - -### 修复常见问题 - -#### 问题 1: 发现重复的 msgid -```bash -# 运行重复检查 -python tests/test_i18n_duplicates.py - -# 输出会显示重复的行号 -[FAIL] 中文 po 文件中发现 2 个重复的 msgid: - - 'Encountered fortune ({theme}), {result}' 出现了 2 次 -``` - -**解决方法:** 手动编辑 PO 文件,删除重复的条目 - -#### 问题 2: 代码中使用但未定义的 msgid -```bash -python tests/test_i18n_po_quality.py - -# 输出 -错误:发现 9 个未在 PO 文件中定义的 msgid: - - 'Unsupported item type: {item_type}' - - '{avatar} gained cultivation experience +{exp} points' -``` - -**解决方法:** 在两个 PO 文件中添加这些 msgid 及其翻译 - -#### 问题 3: 格式化参数不一致 -```bash -# 输出 -警告:发现 3 个格式化参数不一致的条目: - -msgid: {name} lost {amount} spirit stones - 原始参数: {'name', 'amount'} - 中文参数: {'user', 'count'} # 错误! - 英文参数: {'name', 'amount'} -``` - -**解决方法:** 修改中文翻译,使用相同的参数名 - ---- - -## CI/CD 集成 - -### GitHub Actions 示例 - -```yaml -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` - -独立的检查工具,提供更详细的输出。 +### 日常开发 ```bash -python tools/i18n/check_po_duplicates.py -``` +# 1. 编写代码,使用 t() 函数 +code = t("{name} obtained {amount} spirit stones", name=name, amount=100) -**功能:** -- 检查重复 msgid -- 检查数量一致性 -- 检查键匹配 -- 返回适合 CI 的退出码 - ---- - -## 最佳实践 - -### DO ✅ - -1. **使用 t() 函数包裹所有用户可见文本** - ```python - # 好 - message = t("{name} obtained {amount} spirit stones", name=name, amount=100) - - # 不好 - message = f"{name} 获得灵石 {amount} 枚" - ``` - -2. **使用描述性的 msgid** - ```python - # 好 - 清晰描述 - t("cultivate_action_name") - t("{name} cultivation increased by {exp} points", ...) - - # 不好 - 含义不明 - t("msg1") - t("text_001") - ``` - -3. **保持参数名一致** - ```python - # 好 - 统一使用 name - t("{name} defeated {loser}", name=winner, loser=loser) - - # 不好 - 混用 - t("{name} defeated {loser}", user=winner, target=loser) - ``` - -### DON'T ❌ - -1. **不要硬编码文本** - ```python - # 错误 - return "修炼" - - # 正确 - return t("cultivate_action_name") - ``` - -2. **不要在 PO 文件中使用不同的参数名** - ```po - # 错误 - msgid "{name} lost {amount} spirit stones" - msgstr "{user} 损失灵石 {count} 枚" - - # 正确 - msgid "{name} lost {amount} spirit stones" - msgstr "{name} 损失灵石 {amount} 枚" - ``` - -3. **不要忘记更新两个语言文件** - - 添加 msgid 时,zh_CN 和 en_US 都要更新 - - 保持两个文件的 msgid 完全一致 - ---- - -## 维护指南 - -### 定期检查 - -建议每次提交前运行: - -```bash -# 快速检查(< 10秒) +# 2. 运行快速检查(提交前) python tests/test_i18n_duplicates.py python tests/test_i18n_po_quality.py -# 如果有变更,运行完整测试 +# 3. 如果发现缺失的翻译,添加到 PO 文件 + +# 4. 重新运行测试确认 +python tests/test_i18n_duplicates.py +``` + +### 大规模修改后 + +```bash +# 运行完整测试套件 python -m pytest tests/test_i18n_*.py -v ``` -### 修复工作流 - -1. 发现问题 → 运行测试获取详细信息 -2. 根据测试输出定位问题 -3. 修复代码或 PO 文件 -4. 重新运行测试确认 -5. 提交更改 - --- -## 技术细节 +## 相关文件 -### 工具和技术栈 - -- **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: -1. 运行 `python tests/test_i18n_po_quality.py` 获取缺失列表 -2. 在两个 PO 文件末尾添加 -3. 重新运行测试确认 - -### Q: PO 文件太大,如何组织? -A: 考虑按模块添加注释分隔: -```po -# ============================================================================ -# Avatar System -# ============================================================================ - -msgid "Name" -msgstr "名字" -``` - -### Q: 如何在代码中动态生成 msgid? -A: 不推荐。msgid 应该是静态的字符串字面量,便于提取和管理。 - ---- - -## 更多资源 - -- [Python gettext 文档](https://docs.python.org/3/library/gettext.html) -- [GNU gettext 手册](https://www.gnu.org/software/gettext/manual/) -- [项目 i18n 使用指南](../docs/i18n-action-usage.md) +- ✅ `tests/test_i18n_duplicates.py` - 重复项检查 +- ✅ `tests/test_i18n_po_quality.py` - 质量检查 +- ✅ `tests/README_i18n_tests.md` - 本文档 +- ✅ `tools/i18n/check_po_duplicates.py` - 独立工具 diff --git a/tests/test_i18n_classes_coverage.py b/tests/test_i18n_classes_coverage.py deleted file mode 100644 index 6d81bc0..0000000 --- a/tests/test_i18n_classes_coverage.py +++ /dev/null @@ -1,346 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -"""测试 src/classes/ 下的本地化覆盖率和质量 - -此测试确保: -1. 没有硬编码的中文字符串(除了注释和测试数据) -2. 所有使用的翻译键都在 po 文件中定义 -3. 所有类的信息方法返回本地化内容 -4. 格式化参数使用一致 -""" - -import re -import ast -from pathlib import Path -from typing import Set, Dict, List -import pytest - -from src.i18n import t -from src.classes.language import language_manager - - -# TestHardcodedStrings 类已移除 -# -# 原因:项目采用了合理的 i18n 架构设计: -# - UI 字符串使用 .po 文件和 t() 函数 -# - 游戏数据内容存储在 static/locales/{zh-CN,en-US}/ 目录下的 CSV 文件中 -# -# 因此,src/classes/ 中的很多"硬编码中文"实际上是: -# 1. 枚举类型的常量定义(如 Essence.GOLD = "gold" # 金) -# 2. 数据映射字典(用于解析用户输入或内部标识) -# 3. 从 CSV 加载数据后的属性(如 weapon.name, sect.description) -# -# 这些都是架构设计的合理组成部分,不需要转换为 t() 调用。 -# 如需检查未翻译的字符串,请参考 TestTranslationKeysUsage 类。 - - -class TestTranslationKeysUsage: - """检查翻译键的使用情况""" - - @staticmethod - def extract_t_function_calls(py_file: Path) -> Set[str]: - """从 Python 文件中提取所有 t() 函数调用的第一个参数""" - try: - content = py_file.read_text(encoding='utf-8') - tree = ast.parse(content) - - msgids = set() - - for node in ast.walk(tree): - # 查找 t() 函数调用 - if isinstance(node, ast.Call): - # 检查函数名是否是 t - func_name = None - if isinstance(node.func, ast.Name): - func_name = node.func.id - elif isinstance(node.func, ast.Attribute): - func_name = node.func.attr - - if func_name == 't' and node.args: - # 获取第一个参数(msgid) - first_arg = node.args[0] - if isinstance(first_arg, ast.Constant) and isinstance(first_arg.value, str): - msgids.add(first_arg.value) - - return msgids - - except Exception as e: - print(f"Warning: Could not parse {py_file}: {e}") - return set() - - @staticmethod - def extract_msgids_from_po(po_file: Path) -> Set[str]: - """从 po 文件中提取所有 msgid""" - msgids = set() - - try: - import polib - po = polib.pofile(str(po_file)) - for entry in po: - msgids.add(entry.msgid) - except Exception as e: - print(f"Warning: Could not read {po_file} with polib: {e}") - # Fallback to regex - try: - content = po_file.read_text(encoding='utf-8') - pattern = r'msgid\s+"([^"]*)"' - matches = re.findall(pattern, content) - # 将 po 文件中的转义序列(如 \\n \\t等)转换为实际字符 - # 使用字符串替换而不是 decode,避免中文字符编码问题 - decoded_msgids = set() - for m in matches: - if m: # 排除空字符串 - # 替换常见的转义序列 - decoded = m.replace('\\n', '\n').replace('\\t', '\t').replace('\\r', '\r').replace('\\"', '"').replace("\\'", "'").replace('\\\\', '\\') - decoded_msgids.add(decoded) - msgids = decoded_msgids - except Exception as e: - print(f"Warning: Could not read {po_file}: {e}") - - return msgids - - def test_all_used_msgids_are_defined(self): - """检查所有在代码中使用的 msgid 都在 po 文件中定义""" - classes_dir = Path("src/classes") - po_file = Path("src/i18n/locales/zh_CN/LC_MESSAGES/messages.po") - - if not classes_dir.exists() or not po_file.exists(): - pytest.skip("Required directories not found") - - # 提取 po 文件中的所有 msgid - defined_msgids = self.extract_msgids_from_po(po_file) - - # 提取代码中使用的所有 msgid - used_msgids = set() - for py_file in classes_dir.rglob("*.py"): - used_msgids.update(self.extract_t_function_calls(py_file)) - - # 找出未定义的 msgid - undefined_msgids = used_msgids - defined_msgids - - if undefined_msgids: - msg = f"\n发现 {len(undefined_msgids)} 个在代码中使用但未在 po 文件中定义的 msgid:\n" - for msgid in sorted(undefined_msgids)[:10]: - msg += f" - '{msgid}'\n" - if len(undefined_msgids) > 10: - msg += f" ... 还有 {len(undefined_msgids) - 10} 个\n" - pytest.fail(msg) - - -class TestClassesI18nIntegration: - """测试 classes 中的类是否正确集成了国际化""" - - def setup_method(self): - """每个测试前重置语言""" - language_manager.set_language("zh-CN") - - def test_realm_translation(self): - """测试境界相关的翻译""" - from src.classes.cultivation import Realm - - language_manager.set_language("zh-CN") - # 测试境界名称翻译 - assert t("qi_refinement") == "练气" - assert t("foundation_establishment") == "筑基" - - language_manager.set_language("en-US") - assert t("qi_refinement") == "Qi Refinement" - assert t("foundation_establishment") == "Foundation Establishment" - - def test_gender_translation(self): - """测试性别翻译""" - language_manager.set_language("zh-CN") - assert t("male") == "男" - assert t("female") == "女" - - language_manager.set_language("en-US") - assert t("male") == "Male" - assert t("female") == "Female" - - def test_alignment_translation(self): - """测试阵营翻译""" - language_manager.set_language("zh-CN") - assert t("righteous") == "正" - assert t("neutral") == "中立" - assert t("evil") == "邪" - - language_manager.set_language("en-US") - assert t("righteous") == "Righteous" - assert t("neutral") == "Neutral" - assert t("evil") == "Evil" - - def test_weapon_type_translation(self): - """测试武器类型翻译""" - language_manager.set_language("zh-CN") - assert t("sword") == "剑" - assert t("saber") == "刀" - assert t("spear") == "枪" - - language_manager.set_language("en-US") - assert t("sword") == "Sword" - assert t("saber") == "Saber" - assert t("spear") == "Spear" - - def test_action_names_translation(self): - """测试动作名称翻译""" - language_manager.set_language("zh-CN") - assert t("cultivate_action_name") == "修炼" - assert t("breakthrough_action_name") == "突破" - assert t("attack_action_name") == "发起战斗" - - language_manager.set_language("en-US") - assert t("cultivate_action_name") == "Cultivate" - assert t("breakthrough_action_name") == "Breakthrough" - assert t("attack_action_name") == "Initiate Battle" - - def test_effect_names_translation(self): - """测试效果名称翻译""" - language_manager.set_language("zh-CN") - assert t("effect_extra_max_hp") == "最大生命值" - assert t("effect_extra_max_lifespan") == "最大寿元" - - language_manager.set_language("en-US") - assert t("effect_extra_max_hp") == "Max HP" - assert t("effect_extra_max_lifespan") == "Max Lifespan" - - def test_parameterized_translation_chinese(self): - """测试带参数的中文翻译""" - language_manager.set_language("zh-CN") - - result = t("{name} obtained {amount} spirit stones", - name="张三", amount=100) - assert "张三" in result - assert "获得灵石" in result - assert "100" in result - - def test_parameterized_translation_english(self): - """测试带参数的英文翻译""" - language_manager.set_language("en-US") - - result = t("{name} obtained {amount} spirit stones", - name="Zhang San", amount=100) - assert "Zhang San" in result - assert "obtained" in result - assert "spirit stones" in result - assert "100" in result - - -class TestI18nConsistency: - """测试国际化的一致性""" - - def test_all_enum_translations_exist(self): - """测试所有枚举类型的翻译都存在""" - language_manager.set_language("zh-CN") - - # 测试主要枚举类型 - enum_keys = [ - # 境界 - "qi_refinement", "foundation_establishment", "core_formation", "nascent_soul", - # 阶段 - "early_stage", "middle_stage", "late_stage", - # 性别 - "male", "female", - # 阵营 - "righteous", "neutral", "evil", - # 武器类型 - "sword", "saber", "spear", "staff", "fan", "whip", "zither", "flute", "hidden_weapon", - # 关系 - "parent", "child", "sibling", "kin", "master", "apprentice", "lovers", "friend", "enemy", - ] - - missing = [] - for key in enum_keys: - result = t(key) - # 如果翻译失败,会返回原始键 - if result == key: - missing.append(key) - - if missing: - pytest.fail(f"以下枚举键缺少中文翻译: {', '.join(missing)}") - - def test_format_string_consistency(self): - """测试格式化字符串在中英文中的参数一致性""" - from pathlib import Path - import re - - zh_po = Path("src/i18n/locales/zh_CN/LC_MESSAGES/messages.po") - en_po = Path("src/i18n/locales/en_US/LC_MESSAGES/messages.po") - - if not zh_po.exists() or not en_po.exists(): - pytest.skip("PO files not found") - - def extract_msgid_msgstr_pairs(po_file): - """提取 msgid 和 msgstr 对""" - pairs = {} - try: - import polib - po = polib.pofile(str(po_file)) - for entry in po: - pairs[entry.msgid] = entry.msgstr - except Exception: - content = po_file.read_text(encoding='utf-8') - lines = content.split('\n') - i = 0 - while i < len(lines): - line = lines[i].strip() - if line.startswith('msgid "') and line != 'msgid ""': - msgid = line[7:-1] # 提取引号内的内容 - - # 查找对应的 msgstr - i += 1 - while i < len(lines) and not lines[i].strip().startswith('msgstr '): - i += 1 - - if i < len(lines): - msgstr = lines[i].strip()[8:-1] # 提取引号内的内容 - pairs[msgid] = msgstr - i += 1 - - return pairs - - zh_pairs = extract_msgid_msgstr_pairs(zh_po) - en_pairs = extract_msgid_msgstr_pairs(en_po) - - # 检查格式化参数 - inconsistent = [] - for msgid in zh_pairs: - if msgid in en_pairs: - # 提取格式化参数 {param} - zh_params = set(re.findall(r'\{(\w+)\}', zh_pairs[msgid])) - en_params = set(re.findall(r'\{(\w+)\}', en_pairs[msgid])) - msgid_params = set(re.findall(r'\{(\w+)\}', msgid)) - - # 1. 首先检查中英文翻译之间的参数是否一致 - if zh_params != en_params: - inconsistent.append({ - 'msgid': msgid, - 'msgid_params': msgid_params, - 'zh_params': zh_params, - 'en_params': en_params - }) - continue - - # 2. 如果 msgid 本身包含参数,那么翻译必须包含完全相同的参数 - # 如果 msgid 不包含参数(可能是 key),则允许翻译包含参数(只要中英文一致即可) - if msgid_params and (zh_params != msgid_params): - inconsistent.append({ - 'msgid': msgid, - 'msgid_params': msgid_params, - 'zh_params': zh_params, - 'en_params': en_params - }) - - if inconsistent: - msg = "\n发现格式化参数不一致的翻译:\n" - for item in inconsistent[:5]: - msg += f" msgid: {item['msgid'][:50]}...\n" - msg += f" 原始参数: {item['msgid_params']}\n" - msg += f" 中文参数: {item['zh_params']}\n" - msg += f" 英文参数: {item['en_params']}\n" - if len(inconsistent) > 5: - msg += f" ... 还有 {len(inconsistent) - 5} 个\n" - pytest.fail(msg) - - -if __name__ == "__main__": - pytest.main([__file__, "-v"]) diff --git a/tests/test_i18n_duplicates.py b/tests/test_i18n_duplicates.py index e42e0d7..003b349 100644 --- a/tests/test_i18n_duplicates.py +++ b/tests/test_i18n_duplicates.py @@ -48,7 +48,9 @@ def find_duplicates(msgids: list[str]) -> dict[str, int]: def get_po_file_path(lang: str) -> Path: """获取指定语言的 po 文件路径""" project_root = Path(__file__).parent.parent - po_file = project_root / "src" / "i18n" / "locales" / lang / "LC_MESSAGES" / "messages.po" + # Ensure hyphen is used for folder name (zh_CN -> zh-CN) + lang_folder = lang.replace('_', '-') + po_file = project_root / "static" / "locales" / lang_folder / "LC_MESSAGES" / "messages.po" return po_file diff --git a/tests/test_i18n_fixes.py b/tests/test_i18n_fixes.py index d2ff963..53043f1 100644 --- a/tests/test_i18n_fixes.py +++ b/tests/test_i18n_fixes.py @@ -66,7 +66,7 @@ def use_english_language(): original_lang = str(language_manager) # Path to the PO file we updated - po_path = Path("src/i18n/locales/en_US/LC_MESSAGES/game_configs.po") + po_path = Path("static/locales/en-US/LC_MESSAGES/game_configs.po") mock_trans = MockTranslations(po_path) # Patch gettext.translation to return our mock diff --git a/tests/test_i18n_lint.py b/tests/test_i18n_lint.py index fcbacfc..799221a 100644 --- a/tests/test_i18n_lint.py +++ b/tests/test_i18n_lint.py @@ -8,8 +8,8 @@ ZH_PATTERN = re.compile(r'[\u4e00-\u9fff]') MSGID_PATTERN = re.compile(r'^msgid\s+"(.*)"') def get_po_files(): - """Get all .po files in src/i18n/locales""" - root_dir = Path(__file__).parent.parent / "src" / "i18n" / "locales" + """Get all .po files in static/locales""" + root_dir = Path(__file__).parent.parent / "static" / "locales" return list(root_dir.rglob("*.po")) @pytest.mark.parametrize("po_file", get_po_files()) diff --git a/tests/test_i18n_modules.py b/tests/test_i18n_modules.py index 0152834..0b71ffa 100644 --- a/tests/test_i18n_modules.py +++ b/tests/test_i18n_modules.py @@ -9,8 +9,8 @@ def test_i18n_modules_structure(): Test that the i18n modules structure is correct. """ locale_dir = _get_locale_dir() - # Directory names use underscores (zh_CN), not hyphens (zh-CN) - languages = ["zh_CN", "en_US", "zh_TW"] + # Directory names now use hyphens (zh-CN) to match static assets convention + languages = ["zh-CN", "en-US", "zh-TW"] for lang in languages: lang_dir = locale_dir / lang @@ -34,7 +34,7 @@ def test_merged_messages_po_integrity(): Test that the merged messages.po file in LC_MESSAGES exists and contains entries from modules. """ locale_dir = _get_locale_dir() - lang = "zh_CN" # Test with one language (underscore) + lang = "zh-CN" # Test with one language (hyphen) lc_messages_dir = locale_dir / lang / "LC_MESSAGES" messages_po_path = lc_messages_dir / "messages.po" diff --git a/tests/test_i18n_po_quality.py b/tests/test_i18n_po_quality.py index d4eb014..55c65df 100644 --- a/tests/test_i18n_po_quality.py +++ b/tests/test_i18n_po_quality.py @@ -167,7 +167,7 @@ class TestTranslationKeysDefinition: def test_all_used_msgids_are_defined_in_po(self): """检查所有代码中使用的 msgid 都在 PO 文件中定义""" src_dir = Path("src") - po_file = Path("src/i18n/locales/zh_CN/LC_MESSAGES/messages.po") + po_file = Path("static/locales/zh-CN/LC_MESSAGES/messages.po") if not src_dir.exists() or not po_file.exists(): print("SKIP: Required directories not found") @@ -218,8 +218,8 @@ class TestFormatParameterConsistency: def test_format_params_consistency(self): """检查中英文翻译的格式化参数与原始 msgid 一致""" - zh_po = Path("src/i18n/locales/zh_CN/LC_MESSAGES/messages.po") - en_po = Path("src/i18n/locales/en_US/LC_MESSAGES/messages.po") + zh_po = Path("static/locales/zh-CN/LC_MESSAGES/messages.po") + en_po = Path("static/locales/en-US/LC_MESSAGES/messages.po") if not zh_po.exists() or not en_po.exists(): print("SKIP: PO files not found") diff --git a/tests/test_i18n_zh_tw.py b/tests/test_i18n_zh_tw.py index 2cc52b8..a8d1f83 100644 --- a/tests/test_i18n_zh_tw.py +++ b/tests/test_i18n_zh_tw.py @@ -105,7 +105,7 @@ class TestI18nZhTW(unittest.TestCase): """驗證 zh-TW locale 檔案存在""" from pathlib import Path - locale_dir = Path('src/i18n/locales/zh_TW/LC_MESSAGES') + locale_dir = Path('static/locales/zh-TW/LC_MESSAGES') # 檢查 .po 檔案 messages_po = locale_dir / 'messages.po' @@ -128,7 +128,7 @@ class TestI18nZhTW(unittest.TestCase): except ImportError: self.skipTest('polib 未安裝') - locale_dir = Path('src/i18n/locales/zh_TW/LC_MESSAGES') + locale_dir = Path('static/locales/zh-TW/LC_MESSAGES') # 檢查 messages.po messages_po = polib.pofile(str(locale_dir / 'messages.po')) @@ -146,7 +146,7 @@ class TestI18nZhTW(unittest.TestCase): except ImportError: self.skipTest('polib 未安裝') - locale_dir = Path('src/i18n/locales/zh_TW/LC_MESSAGES') + locale_dir = Path('static/locales/zh-TW/LC_MESSAGES') # 檢查 messages.po messages_po = polib.pofile(str(locale_dir / 'messages.po')) diff --git a/tools/i18n/build_mo.py b/tools/i18n/build_mo.py index cb7752c..dbf63a6 100644 --- a/tools/i18n/build_mo.py +++ b/tools/i18n/build_mo.py @@ -117,7 +117,7 @@ def main(): # 查找项目根目录 script_dir = Path(__file__).parent project_root = script_dir.parent.parent - i18n_dir = project_root / "src" / "i18n" / "locales" + i18n_dir = project_root / "static" / "locales" if not i18n_dir.exists(): print(f"[ERROR] 找不到 i18n 目录: {i18n_dir}") diff --git a/tools/i18n/check_po_duplicates.py b/tools/i18n/check_po_duplicates.py index b0c512c..4c2c67e 100644 --- a/tools/i18n/check_po_duplicates.py +++ b/tools/i18n/check_po_duplicates.py @@ -88,8 +88,8 @@ def main(): project_root = script_dir.parent.parent # po 文件路径 - zh_file = project_root / "src" / "i18n" / "locales" / "zh_CN" / "LC_MESSAGES" / "messages.po" - en_file = project_root / "src" / "i18n" / "locales" / "en_US" / "LC_MESSAGES" / "messages.po" + zh_file = project_root / "static" / "locales" / "zh-CN" / "LC_MESSAGES" / "messages.po" + en_file = project_root / "static" / "locales" / "en-US" / "LC_MESSAGES" / "messages.po" # 检查中文文件 zh_count, zh_dups = check_file(zh_file, "中文 (zh_CN)") diff --git a/tools/i18n/split_po.py b/tools/i18n/split_po.py index bbbbc81..10601f0 100644 --- a/tools/i18n/split_po.py +++ b/tools/i18n/split_po.py @@ -150,7 +150,7 @@ def split_po_file(po_path: Path): # print(f" -> {out_path.name} ({len(entries)} entries)") def main(): - root_dir = Path("src/i18n/locales") + root_dir = Path("static/locales") if not root_dir.exists(): print(f"Directory not found: {root_dir}") return diff --git a/tools/package/pack.ps1 b/tools/package/pack.ps1 index f9e5a0f..882fc30 100644 --- a/tools/package/pack.ps1 +++ b/tools/package/pack.ps1 @@ -83,7 +83,6 @@ $AdditionalHooksPath = $ScriptDir # Source path $SrcPath = Join-Path $RepoRoot "src" -$I18nLocalesPath = Join-Path $SrcPath "i18n\locales" # Assemble PyInstaller arguments $argsList = @( @@ -102,7 +101,6 @@ $argsList = @( # Data Files "--add-data", "${AssetsPath};assets", # Game Assets (Images) -> _internal/assets - "--add-data", "${I18nLocalesPath};src/i18n/locales", # i18n Locales -> _internal/src/i18n/locales # REMOVED: "--add-data", "${WebDistDir};web_dist", (We will copy this manually to outside) "--add-data", "${StaticPath};static", # Configs -> _internal/static (backup)