Skip to content

Repository files navigation

FTB Translator

用于汉化现代 FTB Quests 任务文本的桌面工具,基于 Rust + Tauri 构建,支持 OpenAI 兼容接口、DeepL 官方 API,以及无需 API Key 的 Google/DeepL 网页翻译。固定翻译方向:en_us → zh_cn

默认翻译服务为免 API Key 的 Google 网页翻译。DeepSeek / OpenAI 兼容接口、DeepL 官方 API 和 DeepL 网页翻译仍可在设置中切换;内置 Minecraft/模组词表是 API 模式的可选增强项,默认关闭。

翻译模式与配置

设置页不会向所有提供商展示同一套表单,而是按提供商能力组合配置:

配置项 Google 网页 DeepL 网页 DeepL 官方 API DeepSeek / OpenAI 兼容
API Key Authentication Key API Key
接口地址 Free / Pro 地址 可配置兼容地址
模型与翻译要求 可配置
Minecraft/模组词表 可选 可选
批大小与并发 内置安全策略 内置安全策略 可配置 可配置

Google 网页翻译是默认模式,无需任何 Key。DeepL 网页模式同样免 Key,但属于实验性匿名接口。DeepL 官方 API 默认使用 Free 地址,Pro 用户可以改成 https://api.deepl.com。DeepSeek/OpenAI 兼容模式默认指向 DeepSeek,也可以填写其他兼容服务。

运行方法

从源码启动

需要 Node.js 24+、Rust stable 和 Tauri 2 对应的系统依赖

npm install
npm run tauri dev

默认 Google 网页模式不需要额外环境变量或 API Key。若使用 DeepL 官方 API 或 DeepSeek/OpenAI 兼容模式,请在应用的“服务设置”中填写凭证,不要把 Key 写入项目文件。

实际使用流程

  1. 打开“服务设置”,选择翻译提供商并保存。首次运行可以直接保留默认的 Google 网页翻译。
  2. 回到“翻译工作台”,选择整合包根目录,或直接选择 config/ftbquests/questslangchapters 目录。
  3. 点击“扫描任务书”,确认识别出的格式、文件数和待翻译条目数。
  4. 点击“开始翻译”。程序调用所选服务,但不会立即覆盖任务书;完成后先生成可编辑的 .cmp 英文 → 中文校对文件。
  5. 在弹窗中选择“是,直接覆盖”,或选择“否,人工校对”。人工校对时可以打开、另存或选择修改后的 CMP;表格会标出同源多译、保持英文、疑似未汉化和异常状态,只修改箭头右侧中文。
  6. 可以先点击“验证 CMP”查看任务书归属、源指纹、可应用/保持英文/格式失败数量和预计修改文件;这一步只在内存中验证当前表格译文,不修改 CMP、任务书、备份、缓存、历史或报告。
  7. 点击“校验并覆盖”。程序会独立重新核对任务书指纹、英文原文、标签、数字、JSON 和 SNBT 结构,不依赖之前的验证结果;通过后才创建备份并写回。
  8. 翻译与写回状态会保存在系统应用数据目录。重复点击、并发命令或重启后重新导入已应用的 CMP 都会由后端拒绝再次写回;若上次进程在翻译中异常退出,重新开始时可显式确认恢复中断状态,正在写回的状态不会自动解锁。
  9. 完成后检查格式告警。网页翻译只能作为机器初译,发布前仍应进行术语和语义审校。

构建安装包

npm run tauri -- build

构建产物位于 src-tauri/target/release/bundle/

功能

  • 支持两种模式:语言文件(lang/en_us.snbt)和章节文件(chapters/*.snbt
  • 自动识别整合包目录结构,并按文件列出待翻译条目
  • API 翻译后先生成可编辑、可导入导出的 .cmp 英文 → 中文校对文件
  • CMP 表格提供同源多译、保持英文、疑似未汉化和异常状态筛选,帮助集中人工审校
  • 只有确认应用 CMP 后才备份并写回;拒绝英文、回填位置或任务书指纹被修改的文件
  • 官方 API 支持批量并发,网页翻译以大批次、低并发方式减少匿名请求
  • 可选的版本化 Minecraft/模组词表,默认关闭;切换到 API 模式后可按需启用
  • 翻译缓存、JSON 报告、SQLite 历史与 ZIP 导出
  • 格式安全保护 + CMP 人工校对流程 + 写回后的告警修正页(见下方原理)
  • API Key 存入系统密钥管理器;应用启动、切换服务和修改普通设置不会读取钥匙串,只有明确查看/修改 Key 或实际翻译需要 Key 时才按需读取一次,并在当前应用会话中复用
  • 浅色/深色主题,响应式桌面布局
  • 纯 Rust,运行时不依赖 Python 或任何 sidecar

工作原理

1. 文件解析

工具支持两种文件格式,分别对应 FTB Quests 的两种任务书结构:

  • lang 模式:解析 lang/en_us.snbt,这是一个类 JSON 的 SNBT 格式文件,值可以是字符串或字符串数组(多行描述)。工具自己实现了 SNBT 解析器(snbt.rs),保留键的原始顺序,写出时也生成合法 SNBT。
  • chapters 模式:遍历 chapters/*.snbt,用逐字符 token/span walker 跳过注释和字符串内伪字段,从嵌套结构提取任务标题、描述等目标字符串,同时保留原始字节位置用于写回。

如果条目是 Minecraft JSON 富文本组件,程序不会把整个 JSON 交给翻译接口。它会先解析组件树,只抽取玩家可见的根字符串、textextrawithseparator,以及 hoverEvent 中可显示的文本;translatekeybindclickEvent、颜色、样式、命令、URL 和资源 ID 保持原值。每个抽取结果会形成一条带原条目 ID 和 JSON Pointer 回填路径的翻译单元,API 只翻译其中的纯文本,随后程序按路径写回原组件并再次比较结构。包含重复键或无法安全解析的疑似 JSON 组件会保留原文,不会交给翻译接口重新生成。

API 阶段完成后,程序在任务书目录的 .ftb-translator/reviews/ 中生成玩家可见、可导出的 .cmp 校对文件。每个单元包含不可修改的 @ 回填位置,以及一行 JSON 转义后的 "英文" -> "中文"。新版 CMP 还保存不覆盖右侧译文的受保护区域哈希;人工校对只修改箭头右侧,修改 meta、状态、位置或左侧英文会被拒绝。内置表格使用整文件修订号,外部编辑后不会被旧页面静默覆盖。

校对表格可以按状态和审校线索筛选。线索使用保守启发式发现同一英文对应多个中文、译文仍等于原文、译文没有中文以及异常处理状态;它们只用于缩小人工检查范围,不是语义准确率结论,也不参与写回权限判断。接口限流会单独标记为 rate_limited,可用“重试限流项”仅重新请求这一批;重试前会再次校验 CMP 与当前任务书的一致性,成功后更新同一个 CMP,其他译文和人工编辑保持不变。

## file "chapters/example.snbt"
@ {"file":"chapters/example.snbt","entry_id":"example.snbt:0:description","path":"/extra/0/text","status":"translated"}
"Open guide" -> "打开指南"

.ftb-translator/translation-units-latest.jsonl 仍作为最近一次实际接口调用的内部诊断记录;正常人工校对和导出使用 .cmp。从旧版本升级时,应用会迁移旧 bundle 标识下的设置、历史和默认词表,并按需迁移钥匙串凭证;更名前生成的 .ftb-translater 缓存和旧 CMP 文件仍可读取,新版只向 .ftb-translator 写入新数据。

CMP v1 的完整字段、解析规则、状态含义和兼容性约束见 docs/cmp-format.md

2. Token 保护

翻译前,每条原文会经过一道占位符替换流程(core/protection.rs::protect):

用正则匹配以下模式,将它们替换为 ⟨P_0⟩⟨P_1⟩…… 形式的不透明占位符:

类型 示例
Minecraft 颜色/格式码 &e§6§k
printf 格式占位符 %s%1$d
尖括号标签 <item:minecraft:stone>
花括号宏 {@player}{amount}
资源/路径标识符 minecraft:stone#forge:ingots/ironassets/mod/textures/a.png
Minecraft 选择器 @p@e[type=minecraft:zombie]
数字、版本和单位 161.20.150%
转义序列 \n\t\\
URL https://...
十六进制颜色 #FF5733

保护后的文本只包含自然语言和占位符,例如:

Use &eGold Ingot&r on <item:minecraft:gold_ingot>
→ Use ⟨P_0⟩Gold Ingot⟨P_1⟩ on ⟨P_2⟩

被保护的 token 列表与原文一起保存,翻译后用于恢复。

3. 批量并发翻译

待翻译条目按 batch_size(默认 25)分批。OpenAI 兼容接口和 DeepL 官方 API 可使用 concurrency 并发请求(默认 6,上限 12);匿名网页接口固定低并发,通过增大单次请求减少 HTTP 调用:

  • Google 网页翻译:使用不可翻译批次标记,一次 POST 尽量装入约 4500 字符,返回后按标记拆回原条目。
  • DeepL 网页翻译:一次请求使用文本数组装入约 1500 字符,符合匿名端点限制。
  • 超长单条文本会在标点或空白附近拆分,并避免切断 ⟨P_N⟩ 占位符。

OpenAI 兼容模式下,每批以 JSON 对象形式发送,键是条目 ID,值是保护后的文本。模型被要求:

  • 保持键集合不变
  • 不修改任何 ⟨P_N⟩ 占位符
  • 返回同结构的 JSON 对象

所有提供商请求失败时最多重试 3 次,间隔递增。整批失败时,该批所有条目回退为原文。网页接口不是官方稳定 API,服务端限流或接口变化都可能导致暂时不可用。

Google 网页翻译全量实测

以下数据来自一次真实的端到端运行,不是理论估算。测试于 2026-07-13 使用 StoneBlock 4 1.15.3 的完整 lang/en_us.snbt 进行,初始缓存为空,全程使用免 API Key 的 Google 网页翻译,未使用 DeepSeek。

指标 实测结果
原始语言文件 440,833 字节、7,145 行
解析后的翻译条目 2,515 条
Core 批大小 250 条/批
Google 单次请求上限 尽量装满约 4,500 字符
配置并发数 8
网页提供商有效并发数 1(安全上限强制收敛)
总耗时 209.09 秒(约 3 分 29 秒)
平均处理速度 12.03 条/秒
接口级成功 2,515 / 2,515(100%)
接口级失败 0 / 2,515(0%)
格式守卫拦截并回退 14 / 2,515(0.56%)
格式守卫通过 2,501 / 2,515(99.44%)
输出文件 427,139 字节、7,457 行,SNBT 重新解析通过

这里的“接口级成功”只表示接口为条目返回了结果;“格式守卫通过”只表示当前规则没有发现换行、格式码、占位符、资源标识或 JSON 结构异常。两者都不代表翻译语义准确,也不代表译文适合直接发布。14 条被当前守卫发现的异常译文会自动回退英文原文,并写入人工修正报告。

配置中的并发数为 8,但匿名 Google/DeepL 网页端点在程序内固定限制为有效并发 1。全量实测表明,在单并发下通过约 4,500 字符的大请求批处理,已经能在约三分半内处理 2,515 个真实条目。更高并发容易触发匿名服务限流,也会放大批次标记被改写或响应不完整的风险。实际耗时仍会随网络、文本长度和服务端状态变化;此数据应视为一次可复现的参考基准,而不是稳定性承诺。

翻译准确度审计

在上述全量运行后,又对 2,515 个 key、5,789 个文本片段进行了独立质量审计。所有条目均经过程序化风险扫描,并人工复核了固定随机样本、全部富文本组件、全部原文未变化片段、全部同源异译组和高风险术语项,合计约 350 个不同片段。以下准确度比例是基于全量扫描与人工复核的估算值,合理误差约为 ±5–7 个百分点:

准确度等级 估算比例 含义
A 约 48% 语义正确,术语和表达基本可直接使用
B 约 29% 大意正确,但存在明显机翻腔、术语或一致性问题
C 约 18% 关键术语、信息关系或动作对象错误,需要重译
D 约 5% 未翻译、内容损坏、严重幻觉或富文本无法解析
严格可发布准确率 约 45%–55% 未经进一步审校时可直接公开发布的估算范围

全量扫描确认的主要问题包括:

  • 44 条 JSON 富文本组件中有 19 条目标内容无法作为 JSON 解析,占 43.2%;多数没有被现有格式守卫拦截。
  • 52 个有意义的英文片段完全未译,涉及 26 个 key;其中至少 12 个 key 未被报告标记。
  • 相同英文原文出现不同译法,共 30 组。
  • item/items 被误译为“项目”至少 71 处,能量语境中的 power 被译为“电源”至少 32 处,普通方块 block/blocks 被译为“区块”至少 27 处。
  • enchanting 被译为“迷人”至少 11 处,vanilla 被译为“香草”至少 8 处。
  • MekanismStoneBlock 4Draconic Evolution 等模组或整合包名称被按普通英语直译,且同一术语存在多套译名。

因此,这次 Google 网页翻译结果应定位为机器初译草稿,不适合直接发布。当前 99.44% 数据只能用于衡量现有格式守卫的通过情况,不能作为翻译准确率。正式发布前至少需要加入 Minecraft/模组术语表、从模组 zh_cn.json 复用官方译名、对 JSON 富文本只翻译允许的展示字段,并进行第二阶段语义审校。完整方法、统计和具体错译案例见 docs/translation-accuracy-audit.md

4. Token 恢复与校验

API 返回后,每条译文经过两步处理:

恢复:将 ⟨P_N⟩ 替换回对应的原始 token。

恢复前会严格比较不透明占位符集合。任何占位符被删除、修改、重复或凭空增加,整条翻译都会回退原文;API 返回的未知 ⟨P_N⟩ / ⟨G_N⟩ 不会进入输出文件。

校验core/translation.rs::warnings):对恢复后的译文与原文做以下比较:

  • 换行、回车、制表符数量是否一致
  • 保护 token 集合(排序后)是否完全一致——即没有缺失、没有多余
  • Minecraft 颜色/样式码形成的生效作用域是否等价;即使 token 数量相同,样式被后续颜色码重置、重置码提前或样式码悬空也会拒绝
  • 如果原文是 JSON 文本组件,校验除允许回填的展示文本外,所有键、类型和非展示字段是否保持不变

校验失败:该条译文不写入,原文被保留,条目进入「人工修正」列表。校验通过的译文才写入文件并存入缓存。

生成 CMP 时不会创建备份或修改任务书。用户确认应用后,程序会验证受保护区域哈希,以及覆盖源文件路径、完整字节、解析管线和提取身份的 SHA-256 内容指纹,再核对英文原文和回填位置;验证通过才创建备份。最终写回时,语言文件会重新解析生成后的完整 SNBT;章节文件会验证每个替换位置唯一且存在,并检查写回后的引号、转义和括号结构。多文件写入任一失败时会回滚本次已写文件。

5. 翻译缓存

每条成功通过校验的翻译以 SHA-256 散列为键存入 cache.json。散列输入包含原文、提供商标识、模型/接口和风格提示,保证不同服务之间缓存不复用;普通文本的原有 OpenAI/DeepSeek 缓存保持兼容。富文本缓存额外包含处理管线版本,因此升级到安全字段回填后不会继续使用旧流程生成的富文本译文。下次翻译同一整合包时,命中缓存的条目直接跳过请求。

6. 可选 Minecraft/模组词表

切换到 DeepL 官方 API 或 DeepSeek/OpenAI 兼容模式后,设置页可以手动开启词表。词表默认关闭;Google/DeepL 网页模式不显示该设置,后端也会强制关闭词表。

开启后,工具会先保护颜色码、URL、资源路径等格式 token,再按最长词优先和英文单词边界匹配术语,将命中的词替换为 ⟨G_N⟩ 占位符。翻译服务只处理剩余自然语言,返回后工具把占位符恢复成词表中的统一中文。这个机制适用于 DeepSeek、OpenAI 兼容接口和 DeepL 官方 API;它是应用本地的术语保护层,不是 DeepL 官方 Glossary 功能,也不依赖模型提示词。

首次运行时,程序会把 src-tauri/resources/minecraft_glossary.json 作为初始模板复制到应用数据目录。设置页会显示这份可编辑 JSON 的完整路径,用户可以直接修改文件、手动输入其他路径、通过文件选择器切换自定义词表,或恢复默认路径。已有的用户词表不会被后续启动覆盖。

初始词表覆盖 600+ 个条目,面向常见整合包而不是单个整合包定制。除 Minecraft 通用术语外,还覆盖新旧版本常见的技术与自动化、存储与物流、魔法、冒险与维度、农业与食物、建筑和任务辅助模组,并收录这些生态中容易被通用翻译引擎误译的机器与机制短语。译名优先采用中文社区通行名称;没有稳定中文名的专名保留英文。

对于 CreateCarry OnControllingArtifactsSpectrum 等同时也是普通英文词的模组名,词表只收录带 mod 的明确写法或更完整的模组内术语,避免把普通句子中的动词、形容词和名词误替换成模组名称。

旧版 220 条词表曾在 StoneBlock 4 1.15.3 中命中 103 条、保护 1,295 处术语;该结果仅作为历史基线。当前词表已改为跨整合包覆盖,实际命中率应针对目标整合包重新扫描,且命中率本身不代表语义准确率。

词表开关和所选 JSON 文件的 SHA-256 内容指纹都会参与缓存键计算,因此启用/禁用词表、修改文件或切换路径都不会误用旧译文缓存。保存设置和开始翻译时会校验 JSON 结构、空条目和重复术语。词表是用于兜底术语一致性的增强层,不能替代语义审校。

7. 写回与备份

确认应用 CMP 后,先将原始 langchapters 目录整体备份到 .ftb-translator/backups/<时间戳>/。API 翻译和人工校对阶段不会提前覆盖文件。

  • lang 模式:写出 lang/zh_cn.snbt,写前再次解析验证格式合法。
  • chapters 模式:按原文件路径就地修改各章节文件中的对应字段。

维护者文档


数据位置

应用设置、可编辑的默认 minecraft_glossary.json、历史数据库和 task-state.sqlite3 任务状态库保存到系统应用数据目录(AppData/Application Support/~/.local/share)。任务状态库只保存任务身份、规范化任务书路径与 createdtranslatingreview_readyapplyingappliedfailed 状态,不保存 Key、译文或接口请求/响应。状态转换使用 SQLite 事务并在进程内串行化;任务书目录中不会因 API 翻译阶段新增状态文件。

每个任务书的运行数据保存在整合包目录内:

config/ftbquests/quests/.ftb-translator/
├── cache.json               # 翻译缓存(以 SHA-256 为键)
├── report-latest.json       # 最近一次运行的完整报告
├── translation-units-latest.jsonl # 最近一次接口调用诊断记录
├── reviews/*.cmp            # 可见、可编辑和可导出的人工校对文件
└── backups/YYYYMMDD-HHMMSS/ # 确认应用 CMP 后创建的自动备份

开发验证

# Rust 单元测试
cargo test --manifest-path src-tauri/Cargo.toml

# TypeScript 检查与前端构建
npm run build

About

用来进行自动翻译FTB任务书的小组件,使用DeepSeekAPI来进行智能翻译从而获取更好的效果,但是目前为了节约成本打算接入普通的翻译 API 试试兼容性,Deepseek 的成功率已经 99.44%(完整翻译一个整合包大概会消耗 2 块的 Token),另外支持免费的谷歌翻译 API

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages