一次 DELTARUNE 语言文件自动翻译流水线的失败复盘

这次任务的目标很明确:在 DELTARUNE 更新后,无人值守地完成语言文件提取、机器翻译、控制符校验、修复和重新生成。理想状态下,电脑更新游戏后就可以交给自动流程,第二天早上拿到一份可运行的中文语言文件。
实际结果比较尴尬。工程流水线跑通了,翻译结果也能生成,但翻译质量和资源消耗都不适合抢首发汉化。它证明了解析和校验路径可行,也暴露了用代码 Agent 批量翻译游戏文本的成本和上下文问题。
输入文件
这次模拟使用的是 DELTARUNE 第 4 章目录里的语言文件:
chapter4_windows/lang/lang_ja.json文件大小约 1.6 MB,结构是一个 JSON 对象:
date是元信息。- 其他 key 是游戏内文本条目。
- 文本中包含大量游戏控制符,例如
\M1、^6、&、%、换行和双引号。
这些控制符不能被翻译模型改坏。少一个、多个、顺序错,都可能导致游戏内显示异常,甚至影响脚本解析。
交付结果
最终自动流程生成了一个独立的中文语言文件:
lang_zh_ch4_dryrun.json同时生成校验报告:
validation_report_ch4.json最终统计:
- 源文件条目数:15479
- 可翻译文本条目:15478
- 翻译 chunk:194 个
- 第一轮控制符错误:227 个错误,涉及 81 个独立条目
- 第二轮剩余错误:26 个错误,涉及 10 个独立条目
- 最终校验错误:0
文件生成和控制符校验这两件事已经跑通。翻译质量、耗时和资源消耗没有达到可用标准。
自动流程
流水线分成五个阶段。
第一阶段是提取。脚本读取 lang_ja.json,跳过 date,把每个文本条目转成结构化记录:
{
"id": 1,
"key": "DEVICE_CONTACT_slash_Step_0_gml_6_0",
"source": "聞コエマスカ^6?\\M1 ^6 %",
"text": "聞コエマスカ__CTRL_000__?__CTRL_001__ __CTRL_002__ __CTRL_003__",
"tokens": ["^6", "\\M1", "^6", "%"]
}第二阶段是保护控制符。脚本把 \M1、^6、&、%、/、换行、英文双引号替换成 __CTRL_000__ 这种占位符。模型只翻译普通文本,占位符必须原样保留。
第三阶段是批量翻译。最初按 80 条一个 chunk 切分,调用 Claude CLI。当前 CLI 实际走的是 DeepSeek 模型。每个 chunk 都要求返回 JSON 数组:
[
{ "id": 1, "text": "能听见吗__CTRL_000__?__CTRL_001__ __CTRL_002__ __CTRL_003__" }
]第四阶段是合并校验。脚本把翻译结果按 id 合回原始对象,同时检查:
- 每个条目是否都有翻译。
- 占位符数量是否一致。
- 占位符编号是否存在缺失或新增。
- 占位符顺序是否一致。
- 输出文件是否能被 JSON 解析。
第五阶段是自动修复。初翻里有部分条目被模型改坏了控制符。脚本从校验报告里收集坏条目,生成更小的 repair chunk,重新翻译。修复结果覆盖初翻结果,再重新合并校验。
Agent 架构
这次任务采用了多层 Agent 调用链。
最外层是 Codex,负责分析文件结构、写脚本、跑测试、调度命令、合并结果和做控制符校验。翻译执行链路是 Codex 调用 Claude CLI,Claude CLI 里配置了 DeepSeek,实际翻译请求最终落到 DeepSeek 模型上。
这条链路的初衷是降低模型调用成本:让 Claude Code 负责工程编排,让 DeepSeek 承担大批量翻译。但是实际运行时,每个翻译 chunk 都经过 Claude CLI 的代码 Agent 环境,带上了大量与翻译无关的上下文、工具说明和会话包装。DeepSeek 虽然在最内层负责生成译文,但它收到的是被 Agent 环境包装后的重上下文请求。
这也是缓存命中率低的直接原因之一。194 个 chunk 看起来只是并发翻译,实际是 194 次重上下文调用。并发只缩短等待时间,没有降低总 token 消耗。
实际翻译质量
流程能让文件通过结构校验,但结构校验不代表翻译正确。
样例问题包括:
- 句子没有足够剧情上下文,模型按局部字面意思翻译。
- 角色语气不稳定。
- 术语没有统一约束。
- 日文文本到中文文本时,缺少英文原文作为语义参照。
- 80 条一个 chunk 太局部,跨句承接关系很容易断掉。
例如涉及核心剧情名词、阵营称呼、专有道具和反复出现的动词时,模型需要知道既有译名和上下文。只给它当前 chunk,很难稳定处理这些句子。
截图里的句子就是这种失败的直观例子:要制造暗泉…?住手!不要造!。控制符没有坏,但句子语气、断句和术语都显得像未经审校的草稿。
这说明本地化翻译不能只靠“把 JSON 分块丢给模型”。游戏文本有角色、场景、剧情状态和术语体系。没有共享背景,批量翻译只会得到一份格式正确但风格松散的草稿。
资源消耗
这次最明显的问题是执行方式太重。
整轮任务烧了约 914 万 token,缓存命中率只有 2.1%。原始语言文件只有约 1.6 MB,但翻译调用走的是 Claude Code CLI。每个 chunk 都要加载代码 Agent 的上下文、工具说明、权限信息和任务规则。
并发启动多个翻译进程只能缩短等待时间,不能减少总消耗。相反,每个进程都在重复加载上下文,缓存命中率很低。
这类任务不应该用代码 Agent 做翻译执行器。代码 Agent 适合写脚本、搭流水线、做校验;批量翻译应该走极简 API 或专门的翻译服务。
主要问题
第一,任务切分太碎。15478 条文本被切成 194 个 chunk,每个 chunk 都重复一遍翻译规则。调度开销和提示词重复太多。
第二,没有先去重。语言文件里存在大量重复短句、纯控制符、菜单项、数字、英文 UI 和专名。它们不应该都送给模型翻译。
第三,没有翻译记忆。旧章节、旧版本和重复文本都应该先本地复用。模型只处理新增文本和无法规则化的文本。
第四,上下文共享失败。每个 chunk 都是独立请求,没有稳定的术语表、角色表和剧情摘要。缓存命中低,翻译质量也不稳定。
第五,校验只覆盖格式。控制符校验可以防止游戏文件损坏,但不能判断一句台词是否符合剧情、角色和既有译名。
应该怎样改
下一版流程应该先做压缩,再做翻译。
本地预处理:
- 去掉纯控制符条目。
- 跳过纯数字、纯符号和明显无需翻译的英文标识。
- 对 source 去重,只翻唯一文本。
- 建立
source -> target翻译记忆。 - 和旧版本做 diff,只翻新增或变化文本。
翻译执行:
- 不再用 Claude Code CLI 批量翻译。
- 不再通过 Claude 间接调用 DeepSeek。
- 由脚本直接原生调用 DeepSeek API,避免加载 Claude Code 的 Agent 上下文。
- 请求里只放短规则、术语表和当前文本。
- 不传长 key,key 只保留在本地映射中。
- 增大 chunk,减少请求次数。
- 按文本类型分层:UI、战斗描述、剧情台词分别处理。
上下文设计:
- 建立固定术语表,例如“暗之泉”“封印”“骑士”等。
- 建立角色语气表。
- 主线剧情文本使用更小批量和更多上下文。
- 普通 UI 和短句使用规则或低成本模型。
- 不确定文本进入待审列表,不强行多轮重试。
执行前还应该先输出预估:
- 需要翻译的唯一文本数。
- 预计输入 token。
- 预计输出 token。
- 预计缓存命中策略。
- 预计耗时。
没有确认,不做全量翻译。
结论
这次流水线的价值不在翻译结果,而在暴露边界。
可保留的部分是:
- 语言文件解析。
- 控制符保护。
- JSONL 中间格式。
- chunk 合并。
- 控制符校验。
- 自动 repair。
- 最终报告。
需要推倒重做的部分是:
- 用代码 Agent 执行批量翻译。
- 多进程重复加载上下文。
- 不去重直接全量翻。
- 缺少术语表和剧情背景。
- 只用格式校验判断交付质量。
游戏本地化自动化要把模型调用压到最小。先复用、先过滤、先分类、先估算,再把真正需要语言理解的部分交给模型。
本文由 AI 辅助生成,可能存在错误或遗漏,请以实际资料和官方文档为准。