4.7 KiB
4.7 KiB
04 本地化工作流 (Localization Workflow)
项目遵循 ADR-A1:所有玩家可见字符串必须通过
tr("KEY")包裹,禁止业务代码中出现裸字符串。
1. 文件位置
translations/
zh_CN.po ← 简体中文(权威主档)
zh_TW.po ← 繁体中文
en.po ← 英文
ja.po ← 日文
2. .po 文件格式
每条翻译的格式为:
msgid "UI_WAVE"
msgstr "第 %d 波"
msgid:代码中tr("KEY")使用的键msgstr:该语言显示的文字%d、%s、%.1f等格式占位符必须与代码中tr("KEY") % value完全对应
3. 添加新翻译字符串(标准流程)
Step 1 — 在代码中使用 tr() 键
# ❌ 错误:裸字符串
label.text = "商店已关闭"
# ✅ 正确:通过键引用
label.text = tr("SHOP_CLOSED_MSG")
# 带参数
label.text = tr("UI_WAVE") % current_wave # → "第 3 波"
label.text = tr("UI_KILLS") % [kills, alive] # → "击杀: 7 存活: 3"
Step 2 — 在全部四个 .po 文件中添加对应条目
zh_CN.po(权威档,写游戏实际中文):
msgid "SHOP_CLOSED_MSG"
msgstr "商店已关闭"
zh_TW.po(繁体,改繁体字):
msgid "SHOP_CLOSED_MSG"
msgstr "商店已關閉"
en.po(英文):
msgid "SHOP_CLOSED_MSG"
msgstr "Shop Closed"
ja.po(日文):
msgid "SHOP_CLOSED_MSG"
msgstr "ショップが閉店しました"
Step 3 — 验证(运行时检查)
在游戏内执行脚本验证无缺键:
var keys = ["SHOP_CLOSED_MSG"] # 你新加的键
for loc in ["zh_CN","zh_TW","en","ja"]:
Locale.set_locale(loc)
for k in keys:
if tr(k) == k:
print("缺键!语言: %s 键: %s" % [loc, k])
4. 键名规范
格式:<模块>_<实体>_<含义>,全大写 + 下划线
| 前缀 | 用途 | 示例 |
|---|---|---|
UI_ |
通用 HUD 标签 | UI_WAVE, UI_HP |
SHOP_ |
商店界面 | SHOP_TITLE, SHOP_REROLL |
INV_ |
背包界面 | INV_TITLE, INV_BENCH |
SETTLE_ |
结算屏 | SETTLE_TITLE, SETTLE_STATS |
SETTINGS_ |
设置面板 | SETTINGS_DIFFICULTY |
STATUS_ |
状态消息 | STATUS_PURCHASED |
DIFF_ |
难度名称 | DIFF_BEGINNER, DIFF_CHALLENGE |
SPELL_ |
法术名/描述 | SPELL_SPARK_BOLT_NAME, SPELL_SPARK_BOLT_DESC |
CORE_ |
Core 名/描述 | CORE_WAND_BASIC_NAME |
STATUS_EFFECT_ |
状态效果名 | STATUS_EFFECT_BURN_NAME |
BOSS_ |
Boss 名称 | BOSS_FINAL_NAME |
5. 法术 / Core 名称本地化(待完成)
当前法术 display_name 字段存储的是裸英/中文字符串(如 "Spark Bolt")。正式发布前需键化。
注意:修改后须同步更新商店按钮渲染(
combat_s2.gd → _refresh_shop_ui),将spell.display_name改为tr(spell.display_name)。
Step 1 — 修改 wand_preset.gd
# 当前(裸字符串)
n.display_name = "Spark Bolt"
n.description = "发射一颗期限 4s 的电光飞弹,造成 3 伤害。"
# 修改为(键)
n.display_name = "SPELL_SPARK_BOLT_NAME"
n.description = "SPELL_SPARK_BOLT_DESC"
Step 2 — 在四语 .po 中添加
# zh_CN.po
msgid "SPELL_SPARK_BOLT_NAME"
msgstr "电花弹"
msgid "SPELL_SPARK_BOLT_DESC"
msgstr "发射一颗快速电花飞弹,造成 3 点闪电伤害。"
Step 3 — 显示时包裹 tr()
# UI 显示法术名时
btn.text = tr(spell.display_name)
# 法术描述
desc_label.text = tr(spell.description)
6. 添加新语言
Step 1 — 创建新 .po 文件(以韩语为例)
translations/ko.po
内容:复制 en.po,将 Language: en 改为 Language: ko,翻译所有 msgstr。
Step 2 — 在 locale_manager.gd 中注册
const LOCALES: Array = ["zh_CN", "zh_TW", "en", "ja", "ko"] # 追加 "ko"
新语言将自动在商店语言切换按钮中循环出现。
7. 在游戏内切换语言(测试用)
# 切换到英文
Locale.set_locale("en")
# 循环切换(等同商店 🌐 按钮)
Locale.cycle_locale()
# 查看当前语言
print(Locale.get_locale())
8. 提交规范
每次提交涉及玩家可见字符串的改动时,须同时更新四个 .po 文件。允许以英文或空字符串占位(msgstr ""),但 PR 审查时须标注"待翻译"。
9. 工具推荐
| 工具 | 用途 |
|---|---|
| Poedit | .po 文件 GUI 编辑器,支持模糊匹配和自动翻译接口 |
| VSCode + gettext 插件 | 轻量化文本编辑 |
| Godot 内置本地化 | Project → Project Settings → Localization → Translations 可预览各语言 |