Files
cultivation-world-simulator/docs/i18n-action-usage.md
2026-02-06 00:43:08 +08:00

346 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Action 多语言使用指南
本文档说明如何为 Action 类添加多语言支持。
## 已完成的改动
### 1. 基类增强 (`src/classes/action/action.py`)
`Action` 基类中添加了三个类方法和三个类变量:
**类变量**(子类覆盖):
```python
ACTION_NAME_ID: str = "" # 动作名称的 msgid
DESC_ID: str = "" # 动作描述的 msgid
REQUIREMENTS_ID: str = "" # 可执行条件的 msgid
```
**类方法**
```python
@classmethod
def get_action_name(cls) -> str:
"""获取动作名称的翻译"""
@classmethod
def get_desc(cls) -> str:
"""获取动作描述的翻译"""
@classmethod
def get_requirements(cls) -> str:
"""获取可执行条件的翻译"""
```
### 2. 示例实现 (`src/classes/action/assassinate.py`)
`Assassinate` 为例,展示了完整的多语言支持:
```python
@cooldown_action
class Assassinate(InstantAction, TargetingMixin):
# 多语言 ID
ACTION_NAME_ID = "assassinate_action_name"
DESC_ID = "assassinate_description"
REQUIREMENTS_ID = "assassinate_requirements"
# 不需要翻译的常量
EMOJI = "🗡️"
PARAMS = {"avatar_name": "AvatarName"}
ACTION_CD_MONTHS = 12
# LLM 提示词 ID
STORY_PROMPT_SUCCESS_ID = "assassinate_story_prompt_success"
STORY_PROMPT_FAIL_ID = "assassinate_story_prompt_fail"
# 自定义翻译方法(用于非标准字段)
@classmethod
def get_story_prompt_success(cls) -> str:
from src.i18n import t
return t(cls.STORY_PROMPT_SUCCESS_ID)
@classmethod
def get_story_prompt_fail(cls) -> str:
from src.i18n import t
return t(cls.STORY_PROMPT_FAIL_ID)
```
## 使用方法
### 方法一:使用基类提供的标准方法
适用于只有 `ACTION_NAME``DESC``REQUIREMENTS` 的 Action
```python
class MyAction(InstantAction):
# 1. 设置 msgid
ACTION_NAME_ID = "my_action_name"
DESC_ID = "my_action_description"
REQUIREMENTS_ID = "my_action_requirements"
# 2. 其他代码保持不变
EMOJI = "⚔️"
def _execute(self, **kwargs):
# 实现逻辑
pass
# 使用时:
action_name = MyAction.get_action_name() # 自动翻译
desc = MyAction.get_desc()
```
### 方法二:自定义翻译方法
适用于有额外字段需要翻译的 Action如 LLM 提示词):
```python
class MyAction(InstantAction):
# 标准字段
ACTION_NAME_ID = "my_action_name"
DESC_ID = "my_action_description"
# 自定义字段
CUSTOM_PROMPT_ID = "my_action_custom_prompt"
@classmethod
def get_custom_prompt(cls) -> str:
from src.i18n import t
return t(cls.CUSTOM_PROMPT_ID)
```
### 方法三:动态文本翻译
在运行时动态生成的文本(带占位符):
```python
def start(self, target_name: str) -> Event:
from src.i18n import t
# 使用 t() 函数翻译并格式化
content = t("{avatar} starts attacking {target}!",
avatar=self.avatar.name,
target=target_name)
return Event(self.world.month_stamp, content, ...)
```
## 添加翻译
### 1. 在模块化 po 文件中添加条目
请在 `static/locales/{lang}/modules/action.po` 文件中添加翻译,而不是直接修改 `messages.po`
**英文** (`static/locales/en-US/modules/action.po`)
```po
# Action: MyAction
msgid "my_action_name"
msgstr "My Action"
msgid "my_action_description"
msgstr "This is my action description"
msgid "{avatar} starts attacking {target}!"
msgstr "{avatar} starts attacking {target}!"
```
**中文** (`static/locales/zh-CN/modules/action.po`)
```po
# Action: MyAction
msgid "my_action_name"
msgstr "我的动作"
msgid "my_action_description"
msgstr "这是我的动作描述"
msgid "{avatar} starts attacking {target}!"
msgstr "{avatar} 开始攻击 {target}"
```
### 2. 编译并合并
运行项目根目录下的构建脚本,它会将模块文件合并并编译:
```bash
python tools/i18n/build_mo.py
```
## 迁移现有 Action
对于现有的 Action`Assassinate`),按以下步骤迁移:
### 步骤 1替换类变量
**修改前**
```python
class OldAction(InstantAction):
ACTION_NAME = "旧动作"
DESC = "这是旧动作的描述"
```
**修改后**
```python
class OldAction(InstantAction):
ACTION_NAME_ID = "old_action_name"
DESC_ID = "old_action_description"
```
### 步骤 2更新引用
**修改前**
```python
# 在代码中直接使用
text = f"执行了{self.ACTION_NAME}"
```
**修改后**
```python
# 使用类方法获取
text = f"执行了{self.get_action_name()}"
```
### 步骤 3动态文本改用 t()
**修改前**
```python
event_text = f"{self.avatar.name} 开始了动作"
```
**修改后**
```python
from src.i18n import t
event_text = t("{avatar} started the action", avatar=self.avatar.name)
```
## 最佳实践
1. **msgid 使用英文**:便于回退和调试
2. **msgid 具有描述性**:如 `assassinate_action_name` 而非 `act1`
3. **占位符使用具名参数**`{avatar}` 而非 `%s`
4. **完整句子作为 msgid**:不要拼接字符串
5. **添加注释**:在 po 文件中标注每个 msgid 的用途
## 测试
```python
# 切换语言
from src.classes.language import language_manager
language_manager.set_language("zh-CN")
# 测试翻译
from src.classes.action.assassinate import Assassinate
print(Assassinate.get_action_name()) # 输出:暗杀
# 切换到英文
language_manager.set_language("en-US")
print(Assassinate.get_action_name()) # 输出Assassinate
```
## MutualAction 多语言支持
### 基类增强 (`src/classes/mutual_action/mutual_action.py`)
**类变量**(子类覆盖):
```python
ACTION_NAME_ID: str = ""
DESC_ID: str = ""
REQUIREMENTS_ID: str = ""
STORY_PROMPT_ID: str = ""
FEEDBACK_LABEL_IDS: dict[str, str] = {...} # 反馈标签 msgid 映射
```
**类方法**
```python
@classmethod
def get_feedback_label(cls, feedback_name: str) -> str:
"""获取反馈标签的翻译"""
@classmethod
def get_story_prompt(cls) -> str:
"""获取故事提示词的翻译"""
```
### 示例实现 (`src/classes/mutual_action/dual_cultivation.py`)
```python
@cooldown_action
class DualCultivation(MutualAction):
# 多语言 ID
ACTION_NAME_ID = "dual_cultivation_action_name"
DESC_ID = "dual_cultivation_description"
REQUIREMENTS_ID = "dual_cultivation_requirements"
STORY_PROMPT_ID = "dual_cultivation_story_prompt"
# 不需要翻译的常量
EMOJI = "💕"
PARAMS = {"target_avatar": "AvatarName"}
FEEDBACK_ACTIONS = ["Accept", "Reject"]
def start(self, target_avatar: "Avatar|str") -> Event:
from src.i18n import t
# 使用 t() 翻译动态文本
content = t("{initiator} invites {target} for dual cultivation",
initiator=self.avatar.name, target=target_name)
# ...
```
### 反馈标签翻译
在 PO 文件中定义通用反馈标签:
```po
# Feedback labels
msgid "feedback_accept"
msgstr "接受" / "Accept"
msgid "feedback_reject"
msgstr "拒绝" / "Reject"
msgid "feedback_yield"
msgstr "让步" / "Yield"
```
## 已支持的 Action
### InstantAction & TimedAction
-`Assassinate` - 暗杀
-`Attack` - 发起战斗
-`Breakthrough` - 突破
-`Buy` - 购买
-`Cast` - 铸造
-`Catch` - 御兽
-`Cultivate` - 修炼
-`DevourMortals` - 吞噬凡人
-`Escape` - 逃离
-`Harvest` - 采集
-`HelpMortals` - 帮助凡人
-`Hunt` - 狩猎
-`Mine` - 挖矿
-`Move` - 移动(基类)
-`MoveAwayFromAvatar` - 远离角色
-`MoveAwayFromRegion` - 离开区域
-`MoveToAvatar` - 移动到角色
-`MoveToDirection` - 移动探索
-`MoveToRegion` - 移动到区域
-`NurtureWeapon` - 温养兵器
-`Play` - 消遣
-`PlunderMortals` - 搜刮凡人
-`Refine` - 炼丹
-`SelfHeal` - 疗伤
-`Sell` - 出售
### MutualAction
-`MutualAttack` - 攻击(互动版)
-`Conversation` - 交谈
-`DriveAway` - 驱赶
-`DualCultivation` - 双修
-`Gift` - 赠送
-`Impart` - 传道
-`Occupy` - 抢夺洞府
-`Spar` - 切磋
-`Talk` - 攀谈
## TODO
- [x] 遍历所有 Action 并添加多语言支持
- [x] 为 MutualAction 添加类似的基类方法
- [x] 考虑为 LLM 提示词创建统一的辅助方法