Cataclysm-DDA 模组文本怎么提取翻译模板并生成 po 文件?
【免费下载链接】Cataclysm-DDACataclysm - Dark Days Ahead. A turn-based survival game set in a post-apocalyptic world.项目地址: https://gitcode.com/GitHub_Trending/ca/Cataclysm-DDA
你给 Cataclysm: DDA 写了一个模组(mod),现在希望模组的物品名、描述等文本能被其他语言的玩家看到。任务就两步:从模组的 JSON 文件里提取出一份.pot翻译模板,再用它为目标语言初始化一个.po翻译文件,供译者填写。官方流程记录在 doc/TRANSLATING_MOD.md 中,下面按该文档的示例(一个放在./mods/demo的演示模组)走一遍,并标注了文档与当前脚本实现之间的两处出入,避免你照着命令执行时卡住。
准备:模组 JSON 与依赖
模组目录里的 JSON 决定能提取到什么。以文档中的演示模组为例,MOD_INFO的name/description和BOOK的名称、描述都是可提取文本:
[ { "type": "MOD_INFO", "id": "demo", "name": "Demo MOD", "description": "This mod adds a book.", "category": "content", "dependencies": [ "cdda" ] }, { "type": "BOOK", "id": "demo_item", "name": { "str": "Guide to Translate a MOD", "str_pl": "copies of Guide to Translate a MOD" }, "description": "A thin book teaching how to translate a mod." } ]字符串有三种写法(语法说明见 doc/JSON/JSON_INFO.md 和 doc/TRANSLATING.md):
- 直接写字符串,例如
"name": "bar"; - 需要复数形式时用对象,
"name": { "str": "bar", "str_pl": "baz" },"str_pl"可选; - 需要给译者提供上下文时加
"//~"注释,例如"name": { "//~": "as in 'foobar'", "str": "bar" }; - 某条文本不参与翻译时,在
"//~"里写"NO_I18N",或在对象顶层指定"//I18N": false。
运行提取脚本的环境要求(依据 lang/extract_json_strings.py 源码):
- Python 3.7 或更高(脚本内明确检查,不满足会打印
Requires Python 3.7 or higher.并退出); - 脚本
import polib,即依赖第三方库 polib; - 后续生成
.po、编译.mo用到 gettext 工具链里的msginit和msgfmt。
另外注意:提取器 lang/string_extractor/parse.py 对每个带type的 JSON 对象做类型分派,遇到不认识的type会直接抛异常终止;没有type键的对象被静默忽略。所以提取前确认模组 JSON 合法、类型都是游戏已支持的。
第一步:提取 .pot 翻译模板
文档给出的命令(在 Cataclysm-DDA 根目录执行):
# In Cataclysm DDA root directory mkdir -p ./mods/demo/lang/po python3 ./lang/extract_json_strings.py -i ./mods/demo -o ./mods/demo/lang/po/demo.pot执行成功后,./mods/demo/lang/po/demo.pot就是翻译模板,包含模组全部待翻译的原文。
已知出入:当前仓库的 lang/extract_json_strings.py 参数表里没有-o,必填参数是-r(reference POT,JSON 提取出的字符串会追加写入该文件),不传-r时脚本打印Have to specify reference file path.后退出。仓库自身的 lang/update_pot.sh 也是用-r lang/po/base.pot调用它。源码还显示-r指向的文件必须先存在(有isfile检查)。若你按文档原样执行-o版本失败,改用下面这种与脚本参数一致的写法:
# 先创建模板文件满足 -r 的“文件必须已存在”前提 touch ./mods/demo/lang/po/demo.pot python3 ./lang/extract_json_strings.py -i ./mods/demo -r ./mods/demo/lang/po/demo.pot第二步:检查模板内容
打开生成的.pot文件,确认每条文本都成了msgid条目。文档示例(来自 doc/TRANSLATING_MOD.md,实际提取结果条目顺序和注释以你的模组为准):
#. ~ MOD name #: mods/demo/modinfo.json msgid "Demo MOD" msgstr "" #. ~ Description of MOD "Demo MOD" #: mods/demo/modinfo.json msgid "This mod adds a book." msgstr "" #. ~ Item name #: mods/demo/modinfo.json msgid "Guide to Translate a MOD" msgid_plural "copies of Guide to Translate a MOD" msgstr[0] "" msgstr[1] ""可以核对:#.行是译者注释(对应 JSON 里的"//~"),#:行是字符串来源文件,复数字符串带msgid_plural。你写进 JSON 的文本如果没出现在模板里,多半是命中了上面的忽略规则(NO_I18N、//I18N: false或无type的对象)。
第三步:用 msginit 初始化目标语言的 .po 文件
文档以俄语(ru)为例,从模板生成本地翻译文件:
msginit -o mods/demo/lang/po/ru.po -i mods/demo/lang/po/translation.pot -l ru-l后跟语言代码。生成./mods/demo/lang/po/ru.po后,译者在这个文件里逐条填写msgstr。
已知出入:文档第一步生成的模板叫demo.pot,这条msginit命令却引用translation.pot(文档后文的目录树里也写作translation.pot)。执行前把-i改成你实际生成的模板文件名,保证两者一致即可。
.po是纯文本,译者的填写要点(依据 doc/TRANSLATING.md 的 Tips 与文档示例):
- 复数条目要按目标语言填写全部形式。文档中的俄语示例是 3 个形式(
msgstr[0]/msgstr[1]/msgstr[2],对应Plural-Forms: nplurals=3; ...),英语模板只有 2 个;具体几格由目标语言的Plural-Forms决定,不要照抄英语的数量。 %s、%3$d这类占位符和<name>这类标签保持原样,不翻译。
第四步:编译 .mo 并确定发布形态
翻译完成后,把.po编译成游戏可加载的.mo:
mkdir -p mods/demo/lang/mo/ru/LC_MESSAGES/ msgfmt -o mods/demo/lang/mo/ru/LC_MESSAGES/demo.mo mods/demo/lang/po/ru.po注意输出文件名用模组 id(这里是demo.mo),与MOD_INFO里的"id"一致。
开发期目录结构与发布结构不同(均为文档示例):开发时保留模板和.po供译者使用;发布模组时只打包.mo,.pot和.po只你自己和译者需要:
demo ├── lang │ └── mo │ └── ru │ └── LC_MESSAGES │ └── demo.mo ├── modinfo.json └── your_mod_content.json验证方式
文档给出的验证路径是实际进游戏:玩家使用对应语言版本(示例为俄语)运行时,lang/mo/ru/LC_MESSAGES/demo.mo会被自动加载,游戏内显示俄文文本,即翻译生效。另外 doc/TRANSLATING.md 说明运行时的回退行为:运行时找不到对应翻译就返回原文。所以若游戏里某条文本仍显示英语,先回查它是否在模板里、.po里是否填了msgstr、.mo是否重新编译过——这三种情况文档均表现为“显示原文”,需自己逐层核对。
边界:模组流程与主游戏翻译脚本不要混用
仓库里还有一组主游戏维护者用的脚本,与模组的翻译流程是两套:
- lang/update_pot.sh 用
xgettext提取src/*.cpp/src/*.h的 C++ 字符串、再用extract_json_strings.py追加data/下的 JSON 字符串,最终产出主游戏的lang/po/cataclysm-dda.pot; - lang/compile_mo.sh 只遍历
lang/po/*.po,编译成lang/mo/<语言>/LC_MESSAGES/cataclysm-dda.mo,可传单语言参数只编译指定语言(例如lang/compile_mo.sh zh_TW)。
它们处理的是主游戏自身文本,不会读取你模组目录里的lang/po/*.po;模组的.po→.mo编译按上面的msgfmt命令在模组目录内完成。同理,主游戏文本走 Transifex 项目协作,模组文本走本文的本地.pot/.po流程(文档也允许把.pot上传到在线翻译平台,二选一)。
【免费下载链接】Cataclysm-DDACataclysm - Dark Days Ahead. A turn-based survival game set in a post-apocalyptic world.项目地址: https://gitcode.com/GitHub_Trending/ca/Cataclysm-DDA
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考