做游戏汉化时,最耗时的往往不是文本导出或程序联调,而是从原文到高质量中文译文的翻译过程。尤其是《女神异闻录Q(Persona Q)》这类剧情量极大的角色扮演游戏,仅主线剧情就可能包含上千条对话,如果靠人工一句句翻译,项目周期会被拉得很长。最近项目的主线剧情已经完成 AI 初翻,并开始进入校对阶段,其中《女神异闻录4》相关剧情线(P4线)的译文已经可以正常展示。这篇文章会把整个“AI 辅助游戏文本汉化”的流程拆开讲清楚:从文本格式设计、术语表维护,到调用大模型 API 批量翻译、断点续传和人工校对,尽量做到可以照着落地。
无论你是游戏汉化爱好者、本地化从业者,还是只是手里有大量文本需要做翻译处理的开发者,这套工作流都可以复用。需要说明的是,本文只讨论“已获得授权处理的文本翻译”环节,不涉及任何数据提取、解密、破解或盗版相关内容。
1. 背景与核心概念
1.1 什么是游戏文本汉化
游戏文本汉化,简单说就是把游戏里的剧情对话、物品说明、界面文案、系统消息等文本从原语言翻译成目标语言,并最终替换回游戏文件中,让玩家可以直接用中文阅读和游玩。
听起来很简单,但真正做起来会牵扯很多环节:
- 文本提取:从游戏资源文件中导出可翻译的文本,这一步通常涉及资源格式解析。
- 文本清洗:去除控制符、变量占位符、换行符、颜色代码等。
- 术语统一:角色名、地名、技能名、专有名词要保持全游戏一致。
- 翻译与润色:在准确表达原意的基础上,还要符合角色性格和剧情氛围。
- 文本回写:把翻译后的文本按照原格式写回游戏文件。
- 测试验证:实际游玩时检查文本是否溢出、是否缺字、是否出现乱码。
在传统汉化项目中,翻译和润色往往占用最多的人力。而 AI 大模型的出现,让“机器初翻 + 人工校对”成为一条可行的道路,尤其适合《女神异闻录Q》这种文本量大的 RPG 游戏。
1.2 AI 在汉化流程中的定位
AI 翻译并不能完全替代人工,但可以把人工从“从零开始翻译”变成“审校和润色”。以《女神异闻录Q》的主线剧情为例,AI 初翻完成后,译者看到的是完整的中文草稿,而不是一行行英文或日文原文。校对者只需要关注:
- 译文是否准确;
- 角色语气是否符合原版人设;
- 专有名词是否和术语表一致;
- 长句是否通顺;
- 有没有明显错译或漏译。
这种模式特别适合初翻阶段。主线剧情文本量大,AI 可以在较短时间内产出可读的初稿,人工再把质量从 70 分推到 95 分以上。
1.3 本文案例背景:PQ1 主线剧情与 P4 线
《女神异闻录Q》是 ATLUS 在 3DS 平台上推出的一款迷宫 RPG,核心玩法结合了《女神异闻录3》和《女神异闻录4》的角色阵容。游戏分为两个故事线,分别以 P3 和 P4 的角色视角展开。玩家选择的路线不同,对话内容、事件顺序甚至迷宫体验都会不同。
PQ1 的主线剧情文本量非常大,因此非常适合用 AI 辅助翻译来压缩工期。目前的进度是:主线剧情文本已经全部完成 AI 初翻,P4 线文本已经进入人工校对阶段,并可以在脚本输出中直接查看双语对照结果。P4 线的角色包括番长、理世、阳介、千枝、小熊等,每个人物的说话风格差异明显,这也是校对阶段重点把关的地方。
2. 汉化翻译工作流总览
一个可落地的 AI 辅助汉化流程,可以从整体上拆成 6 个阶段:
原始文本JSON ↓ 1. 文本清洗与结构标准化 ↓ 2. 生成双语工作表(TSV/Excel) ↓ 3. 维护术语表 ↓ 4. 调用AI批量翻译 ↓ 5. 人工校对与润色 ↓ 6. 导出最终文本其中 1、2、4 步都可以用 Python 脚本自动化,第 3 步看似简单,却往往决定最终译文的统一性。第 5 步不建议完全自动化,至少要让有语言能力的人过一遍。
这套流程的好处是每一阶段都有中间产物,方便备份和回滚。比如 AI 初翻结果和人工校对结果可以存成不同文件,方便后期对比。
3. 环境准备与工具选型
3.1 运行环境
本文示例代码以 Python 3.10+ 为基础,只要你的机器能跑 Python 3.8 以上都可以。如果你使用的是 Windows,建议在命令行中确认 Python 已配置到 PATH;如果你使用的是 macOS 或 Linux,直接使用终端即可。
对于大模型 API,本文使用 OpenAI 兼容接口的方式编写,方便替换成其他支持相同接口规范的服务商。你只需要准备好一个 API Key 和对应的接口地址。
3.2 核心依赖
需要安装的 Python 库很少,最核心的是requests。安装命令如下:
pip install requests如果你希望把中间结果保存为 Excel,可以额外安装pandas和openpyxl:
pip install pandas openpyxl不过为了方便演示,本文统一使用 TSV(Tab 分隔值)格式,避免引入过多依赖。TSV 文件可以直接用 Excel 或 Notepad++ 打开,兼容性很好。
3.3 项目目录规划
建议把你的汉化工程目录整理成下面的结构:
pq1_translation/ ├── main_en.json # 原始文本JSON ├── main_en.tsv # 生成的双语工作表 ├── glossary.txt # 术语表 ├── prompt_template.txt # 提示词模板 ├── pq1_translate.py # 核心脚本 └── output/ └── main_zh.tsv # 翻译输出目录规划的意义在于:原始文件、中间文件、输出文件分离,避免脚本误操作直接影响原始数据。尤其是当你需要反复调整提示词时,一个清晰的目录结构能让你少踩很多坑。
4. 核心模块设计与代码实现
这一部分是整篇文章的重点。我会从一个 JSON 原文文件出发,依次完成三件事:生成 TSV 工作表、批量调用 AI 翻译、支持断点续传。所有代码都整合在一个脚本里,方便复制和改造。
4.1 文本格式设计
假设项目组已经将游戏文本提取并整理成如下 JSON 结构:
[ { "id": "q0001", "speaker": "主角", "text": "Let's follow the doctor's advice." }, { "id": "q0002", "speaker": "番长", "text": "Everyone, stay close to me." } ]字段说明:
id:文本唯一标识,用于排序和追溯。speaker:说话角色,可以用于提示词中保持角色语气。text:原始文本。
如果你的项目有日文原文,也可以把text换成日文文本,流程完全一样。
4.2 编写核心脚本 pq1_translate.py
下面这个脚本实现了 prepare 和 translate 两个子命令:
prepare:读取 JSON,生成 TSV。translate:读取 TSV,逐条调用 AI 翻译,并保存进度。
#!/usr/bin/env python3 # pq1_translate.py import argparse import csv import json import os import time import requests def load_json(path): with open(path, "r", encoding="utf-8") as f: return json.load(f) def save_tsv(path, rows, fieldnames): with open(path, "w", encoding="utf-8", newline="") as f: writer = csv.DictWriter(f, fieldnames=fieldnames, delimiter="\t") writer.writeheader() writer.writerows(rows) def load_tsv(path): with open(path, "r", encoding="utf-8", newline="") as f: reader = csv.DictReader(f, delimiter="\t") rows = list(reader) fieldnames = reader.fieldnames return rows, fieldnames def load_glossary(path): with open(path, "r", encoding="utf-8") as f: return f.read() def translate_with_ai(source_text, glossary, prompt_template): api_url = os.getenv("AI_API_URL", "https://api.openai.com/v1/chat/completions") api_key = os.getenv("AI_API_KEY", "") model = os.getenv("AI_MODEL", "gpt-4") if not api_key: raise ValueError("请设置 AI_API_KEY 环境变量") prompt = prompt_template.replace("{source}", source_text).replace("{glossary}", glossary) payload = { "model": model, "messages": [ { "role": "system", "content": "你是一名资深的游戏本地化翻译员,擅长角色扮演类游戏的对话翻译。", }, {"role": "user", "content": prompt}, ], "temperature": 0.3, } headers = {"Authorization": f"Bearer {api_key}"} for attempt in range(3): try: resp = requests.post(api_url, json=payload, headers=headers, timeout=30) resp.raise_for_status() return resp.json()["choices"][0]["message"]["content"].strip() except requests.exceptions.RequestException as e: print(f"[WARN] 第 {attempt + 1} 次请求失败: {e}") if attempt < 2: time.sleep(2 ** attempt) else: raise RuntimeError(f"翻译请求失败: {source_text[:20]}") def prepare_command(args): data = load_json(args.input) rows = [] for item in data: rows.append( { "id": item.get("id", ""), "speaker": item.get("speaker", ""), "source": item.get("text", ""), "translation": "", } ) save_tsv(args.output, rows, ["id", "speaker", "source", "translation"]) print(f"[DONE] 生成 {len(rows)} 条文本到 {args.output}") def translate_command(args): rows, fieldnames = load_tsv(args.input) glossary = load_glossary(args.glossary) prompt_template = load_glossary(args.prompt) start = args.start limit = args.limit if args.limit else len(rows) - start total = min(limit, len(rows) - start) for i in range(start, start + total): row = rows[i] if row.get("translation", "").strip(): continue try: row["translation"] = translate_with_ai(row["source"], glossary, prompt_template) except Exception as e: print(f"[ERROR] {row['id']} 翻译失败: {e}") save_tsv(args.output, rows[:i], fieldnames) raise print(f"[INFO] {i - start + 1}/{total} {row['id']} done") time.sleep(0.5) save_tsv(args.output, rows, fieldnames) print(f"[DONE] 输出文件已保存: {args.output}") def main(): parser = argparse.ArgumentParser(description="AI 辅助游戏文本汉化工具") sub = parser.add_subparsers(dest="command") p_prepare = sub.add_parser("prepare", help="JSON 转 TSV") p_prepare.add_argument("input", help="原始 JSON 文件路径") p_prepare.add_argument("output", help="输出 TSV 文件路径") p_prepare.set_defaults(func=prepare_command) p_translate = sub.add_parser("translate", help="批量 AI 翻译 TSV") p_translate.add_argument("--input", required=True, help="待翻译 TSV 文件") p_translate.add_argument("--output", required=True, help="翻译输出 TSV 文件") p_translate.add_argument("--glossary", required=True, help="术语表文件路径") p_translate.add_argument("--prompt", required=True, help="提示词模板文件路径") p_translate.add_argument("--start", type=int, default=0, help="开始行号") p_translate.add_argument("--limit", type=int, default=None, help="最多翻译条数") p_translate.set_defaults(func=translate_command) args = parser.parse_args() if args.command == "prepare": prepare_command(args) elif args.command == "translate": translate_command(args) else: parser.print_help() if __name__ == "__main__": main()脚本中几个关键点:
- 通过环境变量
AI_API_URL、AI_API_KEY、AI_MODEL控制接口地址、密钥和模型,避免把密钥写死在代码中。 - 翻译函数自带 3 次重试,并使用指数退避,能容忍一定程度的网络抖动。
- 批量翻译时会跳过已经翻译过的行,实现断点续传。
- 每翻译完一条会写入一次? 不是每次写入,而是在完成所有请求后一次性写入。如果中途失败,会保存到当前行之前的数据。
虽然示例中没有做到每翻译一行就保存,但已经通过失败时保存rows[:i]的方式降低丢数据的风险。如果你需要更强的断点保护,可以直接把save_tsv放进每翻译一行之后。
4.3 提示词模板
提示词模板是整个流程的灵魂。一个合格的汉化提示词应该包含背景说明、术语要求、输出格式限制。下面是一份可以直接使用的模板:
请把下面这段游戏对话翻译成简体中文。 翻译要求: - 语言自然,符合游戏角色说话习惯; - 不要改变原意,不要添加注释; - 专有名词和角色名按术语表翻译; - 只输出翻译结果,不要额外内容。 术语表: {glossary} 待翻译文本: {source}把这个文件保存为prompt_template.txt,在运行脚本时传入即可。
这里特别强调的是“只输出翻译结果”这一句。如果不加这一句,AI 很可能会输出解释、备选译法或“以下是译文”之类的废话,不利于自动化流程。
4.4 术语表维护
术语表建议用纯文本维护,格式如下:
Persona=人格面具 S.O.S.=紧急求救 TV World=电视世界术语表的内容来自项目早期人工整理的名单。项目越大,术语表越重要。因为 AI 模型并不知道你的项目中哪些角色名要沿用旧版翻译、哪些名词要保留英文。在提示词中加入术语表,可以明显降低专有名词混乱的概率。
5. 实战:PQ1 主线剧情 AI 初翻与 P4 线展示
5.1 准备阶段
假设你的原始文本文件是main_en.json,首先把它转为 TSV 工作表:
python pq1_translate.py prepare main_en.json main_en.tsv运行后,会生成一个包含四列的 TSV 文件:
id speaker source translation q0001 主角 Let's follow the doctor's advice. q0002 番长 Everyone, stay close to me.这一步的意义在于:TSV 可以直接用 Excel 打开,方便人工快速浏览、筛选和修改。即使你不是程序员,也能通过表格软件参与校对。
5.2 执行 AI 翻译
接下来,用翻译子命令对 TSV 进行批量初翻。
在运行之前,先设置环境变量:
export AI_API_KEY="你的密钥" export AI_API_URL="https://api.openai.com/v1/chat/completions" export AI_MODEL="gpt-4"然后运行:
python pq1_translate.py translate \ --input main_en.tsv \ --output output/main_zh.tsv \ --glossary glossary.txt \ --prompt prompt_template.txt \ --limit 200--limit 200表示本次只翻译前 200 条,方便先观察翻译质量,再决定是否继续全量跑。
如果需要从某一行继续翻译,可以加--start:
python pq1_translate.py translate \ --input main_en.tsv \ --output output/main_zh.tsv \ --glossary glossary.txt \ --prompt prompt_template.txt \ --start 2005.3 输出与进度验证
脚本运行过程中,会打印类似下面的日志:
[INFO] 1/200 q0001 done [INFO] 2/200 q0002 done如果某条翻译失败,脚本会保存已经完成的前 N 条,并抛出异常。此时检查错误原因后,重新运行相同命令即可继续。
输出文件output/main_zh.tsv中,translation列会被填上中文译文。
5.4 P4 线翻译片段展示
为了展示 P4 线的初翻效果,下面列出几条示例文本。这里使用的是演示文本,不代表游戏最终翻译结果:
| 文本ID | 说话者 | 英文原文(示例) | AI 初翻结果 | 校对重点 |
|---|---|---|---|---|
| q0512 | 番长 | We're counting on you, partner! | 伙伴,我们可都靠你了! | “partner”是否译为“搭档”更符合角色关系 |
| q0513 | 阳介 | Let's search the school together. | 我们一起把学校搜一遍吧。 | “search”是否保留“探索”语义 |
| q0514 | 千枝 | Don't push yourself too hard. | 不要太勉强自己。 | 句末语气需符合千枝的干脆风格 |
| q0515 | 小熊 | I'll protect everyone! | 我会保护大家的! | “小熊”角色语气是否足够活泼 |
从这几条可以看出,AI 初翻已经能做到“意思基本正确、语句通顺”,但距离“在游戏里直接使用”还有一定距离。比如角色口癖、语气词、称呼方式,都需要人工校对进一步调整。
6. 常见问题与排查思路
AI 辅助汉化的流程并不复杂,但在实际操作中会遇到各种问题。下面列出高频问题和对应的解决思路:
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 翻译请求超时 | 网络波动或 API 响应时间过长 | 适当调大 timeout 参数,增加重试次数,降低单批并发量 |
| 译文出现乱码 | 文件编码不统一,比如 TSV 以 GBK 打开 | 统一使用 UTF-8 编码,代码中打开文件时指定 encoding="utf-8" |
| 专有名词翻译不一致 | 提示词没有引入术语表,或术语表内容冲突 | 维护一份完整的 glossary.txt,并在提示词中强制要求按术语表翻译 |
| 翻译结果被截断 | 单条文本过长,或模型输出 token 限制太小 | 在 API 参数中设置合理的 max_tokens,或对长文本做拆分前处理 |
| 断点续传失效 | 中间文件字段结构被修改,导致脚本无法匹配 | 不要手动变动 id、source、translation 三列结构;排序保持稳定 |
| API 调用报错 401 | API Key 错误或环境变量未生效 | 检查环境变量是否正确,优先使用 export 方式临时设置 |
| 请求频繁被限流 | 调用速度过快,触发服务商限制 | 在脚本中加入 sleep,或者实现简单的请求间隔控制 |
除了表格中的问题,还有一个值得注意的“逻辑坑”:如果你在翻译过程中修改了术语表,之前已经翻译完的文本不会自动更新术语。处理办法是,在术语表变更后,重置相关文本的translation列再重新翻译。
7. 人工校对与质量保障
7.1 为什么要人工校对
AI 初翻可以解决“有没有译文”的问题,但解决不了“译文是否适合游戏”的问题。RPG 游戏中的角色对话往往带着强烈的性格色彩,比如 P4 线中番长冷静、阳介话痨、小熊元气满满,这些差异不是靠一句 prompt 就能完全稳定复现的。
人工校对至少要覆盖以下内容:
- 准确性:原文意思有没有被 AI 曲解。
- 连续性:上一句和下一句的衔接是否自然。
- 风格一致性:同一个角色在所有场景中的语气是否稳定。
- 长度检查:译文不要过长或过短,避免游戏文本框无法显示。
- 语气和称呼:角色之间的称呼是否符合剧情关系。
7.2 校对流程建议
校对阶段推荐按下面的顺序操作:
- 先按角色筛选。把同一个说话者的所有台词放在一起校对,这样更容易统一语气。
- 再按剧情章节筛选。把同一段剧情中的连续对话放在一起检查,保证上下文连贯。
- 最后做全文抽查。随机抽取不同章节,检查是否存在漏译或错译。
如果你使用 Excel 打开 TSV 文件,可以直接用筛选功能,按speaker列筛选角色,按id前缀筛选章节。
7.3 术语一致性检查
人工校对不可能一条条地去回忆“某个专有名词之前翻译成什么”。建议写一个简单脚本来自动检查:
import csv import sys def check_glossary(tsv_path, glossary_path): with open(glossary_path, encoding="utf-8") as f: glossary_terms = [line.strip().split("=") for line in f if "=" in line] with open(tsv_path, encoding="utf-8", newline="") as f: reader = csv.DictReader(f, delimiter="\t") for row in reader: translated = row.get("translation", "") for term in glossary_terms: expected = term[1].strip() variants = set(expected) # 这里只做最简单的检查,实际可补充更多规则 if expected not in translated: pass if __name__ == "__main__": check_glossary(sys.argv[1], sys.argv[2])这个脚本只是一个检查思路,实际项目中还可以引入“禁译表”“优先级词”等规则。比如某些角色名在特定剧情中不允许直译,或者某个地名必须保留英文,都可以维护进术语表。
7.4 如何避免人工校对影响原格式
人工校对后,你可能希望把最终的translation列导出回原始 JSON,方便后续回写。这一步可以继续用 Python 完成,核心思路是读取校对后的 TSV,再把每行的translation按照原id填充到 JSON 对象中。注意不要在图里把原始 JSON 的text字段覆盖掉,最好保留一份原始文件作为备份。
8. 最佳实践与工程建议
8.1 一切文本都纳入版本管理
汉化过程中的原始文本、中间 TSV、术语表、提示词模板、校对结果都应该提交到 Git 仓库。这样做的好处是:
- 任何人改动术语表,都能看到历史记录;
- 提示词调整前后可以对比翻译效果;
- 某个文本文件被误覆盖时可以随时回滚;
- 多名成员协作时不会互相覆盖。
建议在仓库中建立一个prompts/目录,专门保存不同阶段的提示词版本。你可能会发现,同一个翻译任务,提示词从 v1 到 v5 的翻译质量差别很大。
8.2 控制请求频率与成本
调用大模型 API 是按 token 计费的。如果你的主线剧情文本有几万行,全量翻译的成本会相当可观。工程上建议:
- 先小批量试跑,确认质量和成本后再全量跑;
- 使用
limit参数限制每次运行的文本条数; - 设置合理的
temperature,0.2 到 0.4 之间通常更适合翻译任务; - 在脚本中加入
time.sleep()控制请求频率,避免触发限流。
如果你使用的 API 支持流式输出,也可以考虑接入,但这会明显增加代码复杂度。对于批量翻译,非流式已经足够。
8.3 安全与合规
这部分很重要。汉化项目必须确保你处理的文本来自合法授权渠道,不得在文章中提供或传播破解工具、ROM、解密脚本等内容。API Key 是敏感信息,绝不能写死在代码里,更不能提交到公开仓库。最稳妥的做法是使用环境变量或本地配置文件,并把配置文件加入.gitignore。
在将文本发送到第三方 AI 服务时,也要评估文本内容是否涉及敏感信息。如果有未公开的商业文本或受保密协议约束的内容,不要直接上传到公有云 API。
8.4 把流程拆成可插拔模块
我强烈建议不要把所有逻辑都塞进一个脚本。你可以把“读文件”“调 API”“写文件”分别拆成独立的模块,甚至可以把“翻译”部分做成一个命令行工具插件。这样当你从 OpenAI 兼容接口切换到其他服务时,只需要替换翻译函数。
另外,如果你的汉化项目有日语原文,可以在提示词中加入“参考日语原文的敬语和语感”等描述,让 AI 在翻译时更贴近原意。
9. 总结与下一步
这篇文章围绕《女神异闻录Q》汉化项目中的主线剧情 AI 初翻展开,完整介绍了从 JSON 原文到 TSV 工作表、从术语表维护到批量调用 AI 翻译、从断点续传到人工校对的整体过程。核心代码只有一个 Python 脚本,即可复制运行,也可以按自己的项目情况改造。
当前项目的 P4 线文本已经可以通过脚本正常展示双语对照结果,接下来的工作主要集中在三个方向:一是对 AI 初翻结果进行逐条校对和润色;二是持续扩充术语表,特别是技能名、道具名、迷宫区域名;三是把最终译文导出为游戏可用的文本格式,并进入实际运行测试。
另外,如果你不熟悉 API 环境配置,建议先拿 20 条左右的测试文本跑通整个流程,确认输出格式无误后再全量翻译。汉化文本的质量没有捷径,AI 能帮你把“从零到一”的效率提升好几倍,但“从一到十”的部分,依然需要人工的耐心和判断力。
如果你也在做类似的汉化或本地化项目,希望这篇文章能帮你省一些时间。可以收藏备用,后续有新的翻译经验我也会再整理分享。