A Tour of Go 简体中文第一阶段已经完成。
目前 103 个课程页面全部进入 ready 状态,公共 UI、文章元数据、生产发布、示例代码运行与格式化等环节也已经陆续完成。换句话说,现在的中文版本已经不是一个正在等待补齐的实验项目,而是一个可以实际访问和学习的完整版本。
但完成第一阶段以后,我又重新回到了一个此前暂时搁置的问题:
当前的 protected-token 翻译模式,是否已经保护得太多了?
如果进一步减少保护,让 GLM-5.2 看到更多完整、真实的英文页面上下文,能不能继续提高翻译质量?
而且,这个问题现在已经不仅关系到简体中文。
整个项目从一开始就按照多语言方向设计。后面如果继续增加其他官方没有提供、停止维护或者需要重新翻译的语言,那么现在形成的翻译方法,很可能还会继续沿用。
因此,重新研究 minimal-protect,主要是在回答两个问题:
能不能继续提高译文质量?
以及:
哪些保护能力能够成为跨语言共用的基础设施,哪些规则又应该由具体语言自行决定?

一、第一阶段已经完成,终于可以重新研究翻译输入架构
整个 A Tour of Go 简体中文第一阶段共有 103 个课程页面。
目前状态已经是:
total=103
ready=103
pending=0
blocked=0
在第一阶段翻译尚未完成时,我其实已经研究过一次更开放的翻译输入方式。
但当时项目最重要的目标仍然是:
先把全部 103 个正式课程页面稳定翻译完成。
因此,在已经成熟、经过大量页面验证的 protected-token 模式和仍然存在未知问题的 minimal-protect 之间,当时继续使用成熟方案是合理的。
现在情况已经不同。
103 个页面全部完成以后,即使继续进行翻译架构实验,也不会再阻塞第一阶段发布。
因此,现在正好适合重新回答这个问题:
在保证页面结构安全的前提下,到底需要保护多少内容?
二、当前中文译文大约处在什么水平
在决定是否值得重新翻译以前,我先重新看了一遍目前的中文译文质量。
这里的分数不是专业翻译机构的正式评分,也不是对全部 103 页逐句人工审校后的统计结果,而是结合代表页、现有正式译文、英文原文以及此前长期翻译过程得到的工程性估计。
如果以 100 分为满分,目前我对正式 zh-CN 版本的估计是:
约 94 分,合理范围大约为 93~95 分。
现在的主要优点包括:
- 英文原意基本准确;
- Go 技术术语比较稳定;
- 中文已经很少出现明显机器翻译腔;
- 整页上下文总体连贯;
- 教程式表达比较自然;
- 103 个页面全部通过统一结构和页面验证。
所以现在重新研究 minimal-protect,并不是因为当前译文质量差。
恰恰相反:
是在当前已经达到较高质量以后,继续寻找剩下的提升空间。
如果 minimal-protect 最终成熟,我目前对它的预期目标大约是:
96~97 分。
也就是说,我并不期待它带来十几分的巨大变化。
更现实的目标可能只是:
当前正式版:约 94
↓
成熟 minimal-protect:约 96~97但对于一个以“翻译”为核心产品的项目来说,这两三分本身仍然值得研究。
普通软件项目里,94 分的翻译可能已经足够。
但这里的核心价值之一,本来就是:
把官方 A Tour of Go 尽可能高质量地带到更多语言中。
因此,进一步提高翻译质量,本身就是产品升级。
三、一个历史质量参考:已经停止运行的 Go-zh
在重新思考翻译质量时,我也回头看了以前的 Go-zh 中文 Tour。
Go-zh 曾经维护过一套质量相当不错的 A Tour of Go 中文翻译,也是中文 Go 社区过去比较有代表性的项目之一。
现在对应的网站已经无法正常使用,代码仓库也已经归档,而且内容停留在较早时期,没有覆盖当前新版 A Tour of Go 的全部课程。
事实上,它的停止运行,也是后来促使我认真考虑重新做一个可持续维护版本的原因之一。
如果暂时不考虑项目现在是否在线,只评价当年已经完成的中文正文,我目前给出的工程性估计大约是:
90~93 分。
它的不少译文明显带有人工翻译和长期维护留下来的痕迹,中文表达比较成熟,一些技术概念的处理也很好。
所以我觉得它依然很适合作为一个历史质量基准。
这也给现在的项目提出了一个比较明确的要求。
新的项目不能只是因为:
源码更新
+
网站可以访问
+
课程数量更多就认为翻译工作已经完成。
至少对于简体中文,我希望做到的是:
内容更新
+
完整覆盖
+
功能可用
+
结构可靠
+
翻译质量达到甚至超过过去成熟的人工作品目前我认为正式 zh-CN 已经基本达到了这个目标。
接下来研究 minimal-protect,则是在继续寻找更高的质量上限。
四、protected-token 为什么能够保证稳定
当前成熟的默认翻译流程,大致可以理解为:
完整英文课程页面
↓
识别高风险结构
↓
替换为 protected token
↓
GLM-5.2 整页翻译
↓
恢复 protected token
↓
present 解析
↓
结构比较
↓
页面校验
↓
ready这种方法最大的优势就是稳定。
像下面这些内容,可以在翻译前先保护:
.play directive
链接 target
行内代码
预格式化代码
其他容易被模型修改的机器结构模型主要负责真正需要翻译的自然语言内容。
这也是第一阶段最终能够做到 103 / 103 ready 的一个重要原因。
但是保护机制越强,也意味着另外一个问题:
模型能够直接看到的原始页面上下文会越来越少。
比如一个英文技术名词原本同时出现在正文、链接、行内代码和其他结构中,如果其中很多部分都被替换成:
__PROTECTED_TOKEN_001__
__PROTECTED_TOKEN_002__那么从模型的视角来看,原本连续的语义环境实际上被切断了一部分。
对于简体中文,这种影响可能还不是特别明显。
但如果以后扩展到更多语言,不同语言还可能涉及:
- 词序;
- 单复数;
- 性;
- 格;
- 冠词;
- 词形变化;
- 前后文指代。
这时候,模型能不能看到完整上下文就会更加重要。
五、minimal-protect 真正吸引我的地方:让更多真实上下文留给模型
所以重新研究 minimal-protect,最重要的原因仍然是翻译质量。
它的基本思路不是:
尽量把所有可能变化的内容全部保护起来。
而是:
只把模型绝对不应该修改的机器结构拿走,其余真实页面尽可能完整地交给模型理解。
这意味着模型看到的不再是大量被占位符切碎的页面,而是更接近真正源文件的上下文。
从翻译角度看,这一点很重要。
因为语言模型真正擅长的事情,本来就是:
根据上下文理解一句话究竟在说什么。
如果在送入模型之前先人为切掉大量上下文,那么即使结构更安全,也可能牺牲语言理解空间。
所以我现在更倾向于:
尽可能保留完整上下文
+
只禁止修改少数机器结构
+
最终由严格 validator 判断是否合格六、raw-input 证明了方向,但也证明了完全不保护不可行
最激进的实验是 raw-input。
它基本不再做大量结构保护,而是直接把原始页面交给 GLM-5.2:
完整原始页面
↓
GLM-5.2
↓
validator这样做的好处非常明显:
模型能够看到最完整的上下文。
但问题也同样明显。
在 methods/24 页面中,原始内容包含:
.play methods/images.goraw-input 实验中,模型先后把它修改成了类似:
.play methods/images.go /zh-cn/methods/24以及:
.play methods/images.go /src/methods/images.go这些变化对于自然语言模型来说,可能只是一次“看起来合理”的补充。
但对于 present 来说,.play 是机器指令。
它不是自然语言,也不能被模型自由改写。
所以 raw-input 虽然最大化了上下文,却也把模型本来不应该拥有的修改权限一起开放了。
这说明:
完全不保护也不是正确答案。
真正需要寻找的是中间状态。
七、minimal-protect:只保护已经证明危险的结构
于是就有了 minimal-protect。
例如在 methods/24 中,首先只保护完整 .play:
.play methods/images.go把这一整行作为一个不可修改的 token 交给模型。
实验结果很明确。
在 raw-input 中连续两次发生的 .play 改写,在 minimal-protect 中消失了。
.play protected/restored: OK
.play mutated: NO也就是说:
.play 这一层问题已经被最小保护成功解决。

但是这一页仍然没有通过最终校验。
随后 validator 又发现:
link inline-code count mismatch
expected=0 actual=1继续实验以后,又遇到了:
font span count mismatch
expected=10 actual=9这反而正是 minimal-protect 实验中很有价值的一部分。
因为它说明 validator 正在按照预期工作:
减少保护
↓
让模型处理更多真实上下文
↓
出现真实结构错误
↓
validator 精确指出问题
↓
再判断这一类结构是否真的需要限制而不是一开始就假设:
所有理论上可能出问题的结构,都必须提前保护。
八、同一个页面:15 个 protected token 降到 1 个
methods/24 还有一个很直观的对比。
在同一个页面、同一个 source SHA、同一个 glm-5.2 模型下,默认 protected-token 使用了:
15 个 protected token包括:
9 个 inline-code span
4 个 link target
1 个 preformatted code block
1 个 .play directive当时真实请求记录为:
prompt_tokens=1660而 minimal-protect attempt-005 中只保护:
1 个完整 .play directive对应:
prompt_tokens=1449也就是:
15 → 1少了 14 个 protected token。
模型直接能够看到的原始页面结构也明显更多。

这里需要特别说明:
prompt_tokens 从 1660 降至 1449,是两次真实请求观察到的结果。
不能简单理解为这 211 个 token 的差距全部由保护 token 数量减少造成。
Token 减少当然是一个附带收益。
但是比节省 Token 更重要的是:
更多原始内容重新进入了模型真正能够理解的上下文。
九、跨语言以后,保护规则到底能够复用多少
这里还有一个我现在并不准备提前下结论的问题:
如果未来增加其他语言,现有 protected-token 和 minimal-protect 的实现到底能够复用多少?
目前从结构上看,我认为至少可以把它分成两层。
第一层是明显与语言无关的机器结构。
例如:
.play directive
代码路径
不可修改的链接 target
静态代码块
present 指令
页面结构解析
token 恢复完整性
结构数量比较这些东西无论翻译中文、日文、德文还是其他语言,本质上仍然是同一种机器结构。
因此,它们的:
识别
占位
恢复
校验
测试大概率具有很高的复用价值。
这也是此前 protected-token 已经积累下来的重要资产。
但是第二层就不一定能够完全复用。
例如:
某种行内代码是否一定需要保护
某种强调结构是否允许改变位置
术语如何处理
自然语言与代码之间的空格
标点习惯
词形变化
模型容易犯哪一类语言特有错误这些问题很可能与目标语言有关。
所以未来更现实的架构,也许并不是:
所有语言共享完全相同的保护规则而是:
共享机器结构保护能力
+
每种语言选择自己的最小保护策略例如:
通用层
├─ .play 识别与恢复
├─ present 结构解析
├─ link target 校验
├─ code block 校验
└─ validator
zh-CN
└─ zh-CN minimal protection policy
未来语言 A
└─ language-A minimal protection policy
未来语言 B
└─ language-B minimal protection policy这比直接声称“minimal-protect 一定让多语言架构更简单”更加准确。
现在真正需要验证的是:
通用机器结构能力能够复用到什么程度,而不同语言的保护策略又需要差异化到什么程度。
如果最后发现大部分底层能力都能共享,而每种语言只需要维护少量策略差异,那么 minimal-protect 的长期维护价值就会非常明显。
如果实际结果证明不同语言需要大量完全不同的规则,那么架构设计也应该根据真实情况调整。
所以这一点现在更适合作为:
下一阶段需要验证的工程问题。
而不是已经得到证明的结论。
十、protected-token 不会被废弃
即使最终选择 minimal-protect,此前 protected-token 做的大量工作也不会浪费。
第一阶段开发过程中已经积累了很多成熟能力:
结构识别
token 占位
恢复
数量校验
结构比较
错误分类
回归测试这些能力本身和“默认到底启用多少保护规则”是两件不同的事情。
所以以后更理想的关系可能是:
protected-token
=
经过大量真实页面验证的保护能力库
minimal-protect
=
根据目标语言和真实失败,
从能力库中启用最少必要规则例如 .play 已经有非常明确的实验依据。
那么 minimal-protect 就没有必要重新发明 .play 的识别和恢复方式。
直接复用现有成熟实现即可。
以后如果新的实验又证明:
某一种结构确实必须保护。
同样优先检查 protected-token 是否已经存在成熟能力。
这样第一阶段积累的经验就可以继续发挥作用,而不是重新从零开始摸索。
十一、下一步先重新验证原来的 7 个代表页
即使 minimal-protect 的方向很有吸引力,我现在也不准备直接把 103 个页面全部重新翻译。
首先还是使用第一阶段开发过程中长期验证过的 7 个代表页:
generics/1
flowcontrol/8
methods/16
methods/20
concurrency/7
concurrency/11
methods/24继续使用同一组页面有一个很大的好处:
可以保持第一阶段和下一阶段的实验口径一致。
接下来重点需要观察:
语言质量
validator 通过率
重试次数
blocked 情况
保护规则数量
Token 使用其中最重要的还是一个问题:
minimal-protect 带来的语言质量提升,是否足以抵消可能增加的结构失败和重试成本?
如果最后只能从大约 94 分提高一点点,却明显增加失败率,那么重新翻译全部页面的意义就比较有限。
但如果代表页能够稳定接近:
96~97 分
同时 validator 通过率和重试成本仍然可以接受,那么这条路线就值得继续推进。
十二、真正决定是否切换的,不只是 validator 能不能通过
对于这个项目,我现在越来越明确一件事:
结构正确只是发布门槛,而不是翻译质量本身。
一个页面即使:
present parse = PASS
directive = PASS
link = PASS
inline code = PASS
render = PASS也只能说明:
页面没有被翻译坏。
它并不能说明:
这是能够做到的最好译文。
如果一个翻译项目长期只追求:
结构不坏最后很容易得到“正确但生硬”的译文。
而我真正希望这个项目追求的是:
准确
+
自然
+
完整上下文
+
术语一致
+
教学表达清晰
+
结构安全所以 validator 和翻译质量实际上承担的是不同角色:
validator
=
决定译文有没有资格发布
翻译质量
=
决定这个项目最终能够做到什么水平两者都不能少。
十三、如果最终采用 minimal-protect,仍然按每批 10 页推进
如果 7 个代表页最终证明 minimal-protect 足够稳定,而且实际译文质量确实更好,那么后续重新翻译 zh-CN 时,我仍然准备沿用第一阶段已经比较熟悉的节奏:
每批 10 个普通页面
↓
GLM-5.2 整页翻译
↓
统一 validator
↓
处理真实失败
↓
下一批不会一次性把 103 个页面全部重新跑完。
这种节奏已经证明比较适合当前项目。
既不会因为批次太小推进过慢,也不会因为范围过大,让一种新的结构问题一次影响大量页面。
遇到新的失败类型以后,则先暂停继续扩大范围,判断:
这是偶发模型行为,还是一种确实需要加入 minimal-protect 的结构风险?
如果确实需要保护,再优先复用此前 protected-token 已经积累的实现经验。
十四、现在真正要寻找的是“最小必要保护集”
第一阶段解决的问题是:
怎样稳定完成 103 个中文页面。
现在希望解决的问题则更进一步:
在保证所有机器结构安全的情况下,究竟最少只需要保护哪些内容?
我目前更希望最终得到的翻译流程是:
尽可能完整的原始页面上下文
↓
少量经过真实失败证明必须保护的机器结构
↓
GLM-5.2 整页翻译
↓
最小恢复
↓
严格统一 validator
↓
针对真实失败进行 retry对于简体中文,这条路线首先需要证明一件事:
能不能把当前大约 94 分的译文继续稳定提高到更接近 96~97 分。
对于未来其他语言,则还需要继续验证另一个问题:
哪些底层结构能力可以完全共享,哪些最小保护规则必须按语言调整。
现在还没有到宣布 minimal-protect 一定会成为最终默认模式的时候。
7 个代表页还需要重新验证,新的失败类型还需要继续观察,最终译文质量也需要真正比较。
但是第一阶段 103 页已经完成以后,终于可以不再只考虑:
怎样安全地把页面翻译出来。
而开始认真研究:
怎样把它翻译得更好。
以及:
在增加更多语言以后,怎样让机器结构保护尽可能复用,同时又不给不同语言施加不必要的统一限制。
这才是这次重新回到 minimal-protect 的真正意义。
A Tour of Go 多语言翻译项目
本系列完整记录 A Tour of Go 多语言翻译项目从架构设计、整页翻译、结构保护、自动校验,到生产发布与后续维护的实际开发过程。
项目入口:
✅ 在线学习:A Tour of Go 简体中文版
✅ 项目源码:GitHub:shuijingwan/go-tour-i18n
当前第一阶段已完成简体中文版本。项目属于非官方社区多语言翻译项目,与 Go 官方无隶属或授权关系。


发表回复