没有不值得去解决的问题,也没有不值得去学习的技术!

A Tour of Go de-DE 上线复盘:第三门语言用了约 16 小时,下一门如何压到 8 小时?

图 1:A Tour of Go 德语版 de-DE 已正式运行在生产环境

作者:

在

Go 学习与文档多语言本地化项目

图3:访问过去的 Go Tour 简体中文站 tour.go-zh.org 时,当前已经无法正常建立连接。

(1) 从「A Tour of Go 中文版」这个搜索词开始:我决定做一个持续维护的 Go Tour 中文版

本地运行的 A Tour of Go「Methods continued」课程页面,左侧为课程说明,右侧为 Go 代码编辑器及运行结果。

(2) A Tour of Go 中文版项目设计冻结:从 101 页到 103 页,从 Gin 转向 Cobra CLI

A Tour of Go 中文版开发实战:英文基线、在线运行与 101 页上游同步体系

(3) A Tour of Go 中文版开发实战:英文基线、在线运行与 101 页上游同步体系

go-tour-i18n 项目完成首个简体中文课程页面 welcome/1 的整页翻译、结构校验和本地预览。

(4) A Tour of Go 多语言翻译项目实录:完成首个 zh-CN 页面翻译闭环

图 1:DeepSeek 官方更新日志显示,本次只更新 DeepSeek-V4-Flash,DeepSeek-V4-Pro API 与 APP、Web 模型均未更新

(5) A Tour of Go 中文翻译项目进展:完成前 8 页、修复 present 语法,并暂缓 DeepSeek 对比

图 1:generics/1 简体中文页面本地预览

(6) 一个页面重试五次:使用 GLM-5.2 翻译 A Tour of Go 时遇到的 Token 与 Present 结构问题

图 1:methods/16 简体中文页面浏览器预览

(7) A Tour of Go 中文翻译实录:如何只翻译教学代码注释,而不破坏 Go 代码

图 2:A Tour of Go methods/20「练习:错误」中文候选页面最终渲染效果

(8) A Tour of Go 多语言翻译:当正确的中文语序被受保护标记顺序校验误判

图 3:methods/24 中文页面,静态代码、Bounds 行内代码和链接内的 image.Rectangle 均正确渲染

(9) A Tour of Go 中文翻译完成 7 个代表页校准:最后 3 页又发现了哪些真实问题

图 2:首批 10 个普通页面经过试跑与流程校准后全部进入 ready

(10) A Tour of Go 多语言翻译项目:首批 10 个普通页面试跑,从 2 个 blocked 到全部 ready

图 2:flowcontrol/6 最终中文页面,return 与 v 为适应自然中文语序发生整体换位

(11) A Tour of Go 中文翻译第二批实跑:从 Inline Code 顺序误判到历史响应重新验证

图 1:flowcontrol/6 首次原始输入实验直接通过统一自动校验

(12) A Tour of Go 多语言翻译项目:从 swap 问题重新审视 Token 保护,原始输入与最小保护的一次真实实验

图 7:moretypes/1 最终中文页面预览。左侧课程正文、静态代码块、行内代码和教学注释均正常渲染,右侧官方 Go 示例继续保持原样。

(13) A Tour of Go 多语言翻译实战:第三批 10 页全部 Ready,继续校准 Protected Token 的结构角色

图 4:上游源码确认共有 103 个课程页面,zh-CN 最终达到 ready=103、pending=0、blocked=0

(14) A Tour of Go 多语言翻译项目:zh-CN 103 个课程页面全部 ready,课程正文翻译阶段完成

图 4:GitHub 与 ChatGPT 已成功连接

(15) ChatGPT 连接 GitHub 实测:让 AI 直接读取 go-tour-i18n 仓库参与译文审核

图 3:中文 Go 术语校准完成后,将确定的译法写入 zh-CN glossary

(16) 为什么 channel 最终选择“通道”:A Tour of Go 中文术语统一的一次实践

图 1:技术含义基本正确,但“返回一个返回……”已经明显影响阅读,因此仍被列入 C 类修订

(17) 103 页逐页审核后,只返修 16 页:A Tour of Go 中文正文发布前质量审计

图 2:中文课程页面以及已经完成本地化的编辑器控制区

(18) A Tour of Go 多语言翻译项目:公共 UI 本地化完成,从课程译文走向完整中文界面

图 2:完整 zh-CN 正式投影成功生成,103 个课程页面被重新组装为 7 个 .article

(19) 从 103/103 ready 到完整站点验收:A Tour of Go 中文版补齐正式投影与课程元数据本地化

图 3:从 production bundle 独立启动的 A Tour of Go 简体中文页面,课程正文、公共 UI 和官方 Go 示例均已进入最终发布形态。

(20) A Tour of Go 多语言翻译项目:103 页全部完成后,我终于生成了可独立部署的 zh-CN Production Bundle

图 1:A Tour of Go 简体中文版正式生产页面,远程运行已经成功输出“Hello, 世界”。

(21) A Tour of Go 多语言翻译项目:zh-CN 正式上线,从生产发布到 go.dev Playground 的完整部署记录

图 1:新生产域名 go-dev.shuijingwanwq.com 已正常访问,Go 示例远程运行成功

(22) A Tour of Go 多语言翻译项目:从 go-tour 到 go-dev,完成 EdgeOne、Nginx 与 HTTPS 生产域名迁移

图 1:A Tour of Go 多语言翻译项目正式生产首页

(23) A Tour of Go 多语言翻译项目正式上线:从项目首页、公共 Footer 到生产发布元数据的完整收尾

图 3:GA4 g/collect 请求返回 HTTP 204,并携带当前课程页面地址,确认 Google Analytics 已产生真实事件上报

(24) A Tour of Go 多语言翻译项目:接入 Google Analytics 与百度统计,从 systemd 注入到 EdgeOne 与真实上报验证

图 1:生产环境 robots.txt 与 sitemap.xml 已正确对外提供,Sitemap 共包含 104 个规范 URL。

(25) A Tour of Go 中文站上线后:补齐 robots.txt、Sitemap,并完成五大搜索引擎提交

图 4:发布生产并刷新 EdgeOne 缓存后,再次通过真实手机访问,顶栏项目名称已经完整保持在一行,最终移动端验收通过。

(26) A Tour of Go 多语言翻译项目:修复手机端首页顶栏标题换行,并完成真机验证

图 3:生产自动部署脚本第一次真实运行时,systemd 已经显示 active,但首次 localhost 探测仍然得到 HTTP 000;随后连续 3 次同时满足 active + HTTP 200 后,脚本才判定部署成功,并继续完成公网 HTTP 200 验收。这次真实运行验证了连续应用层健康检查的必要性。

(27) A Tour of Go 多语言翻译项目:从一次 203/EXEC 故障到生产自动部署脚本落地

图 1:阿里云生产环境访问 go.dev Playground 时出现 TLS 握手超时

(28) A Tour of Go 多语言翻译项目:为 Playground 搭建独立的 ZgoCloud 执行代理

图 3:清除 /tour/script.js 缓存后,Run 已直接请求 ZgoCloud /compile 并返回 HTTP 200

(29) A Tour of Go 多语言翻译项目:将生产 Run / Format 切换到 ZgoCloud 执行节点

【图 1:微信中运行 Go 示例时出现 Error communicating with remote server.】

(30) A Tour of Go 中文版手机端运行与格式化偶发失败排查:从间歇性报错到补强 Nginx 可观测性

【图 4:向 golang-dev 公开邮件列表发送 Playground 使用告知邮件并投递成功】

(31) A Tour of Go 多语言项目:为 Playground 代理增加唯一 User-Agent,并主动告知 Go 官方

【图 3:百度剩余 9 个核心 URL 提交成功,remain 归零】

(32) A Tour of Go 搜索引擎收录实测:从 Google 自然索引到百度主动提交与 Bing IndexNow

【图 1:当前正式中文 methods/24 页面,右侧示例代码运行成功】

(33) A Tour of Go 中文翻译完成后,我为什么重新评估 minimal-protect 翻译模式

【图 3:5 个页面 Request SHA256 完全一致,但 Response SHA256 全部不同】

(34) A Tour of Go 翻译实验:更多原始上下文为什么没有更好?从 157 个保护标记到 30 次重复盲评

图 3:3 个代表页 × 4 个评审模型,共 12 次匿名评审的完整排名与第一名票数。

(35) A Tour of Go 翻译质量再评估:minimal-protect 未达预期后,我开始比较 ChatGPT、Codex 与 GLM-5.2

图 2:GitHub 中的 chatgpt-zh-CN-008 重译批次。一个 Batch 同时保存 inputs、raw-responses、candidates、validation 和 retry 记录,GitHub 成为 ChatGPT 与本地翻译流水线之间的数据交接层。

(36) 没有 OpenAI API,我如何用 ChatGPT + GitHub 完成 A Tour of Go 103 页全量重译

图 1:103 个正式课程页面完成最终语义质量审核,结果为 A=103、B/C/D=0,同时不存在缺失、重复或额外页面。A/B/C/D 是本轮项目内部语义质量分级,并不是自动结构 validator 的结果。

(37) 103 页翻完还不能发布:A Tour of Go ChatGPT 译文的语义审核与 Canonical Promotion

图 3:7 个 article endpoint 的 production origin 与 EdgeOne 公网响应全部 exact match,同时新的 ChatGPT 译文标记存在,旧版译文标记已经消失。

(38) 103/103 与 7/7 Exact Match:A Tour of Go ChatGPT 新译文的最终线上验收

【图 2:upstream source preview】

(39) A Tour of Go 多语言翻译项目首次实现 upstream 同步机制:从一次性翻译到长期维护

图 2:A/B/C/D 质量评级规则,展示正式质量 rubric 与 Promotion gate。

(40) A Tour of Go 多语言翻译项目引入 Translation Quality Review:从自动验证到 AI 翻译质量控制

图 4:翻译后 Playground Example,展示中文注释与保持不变的 Go 代码结构。

(41) A Tour of Go 多语言翻译项目实现 Playground Example 本地化:从代码注释翻译到完整学习体验

图 5:公网页面验证广告脚本输出

(42) A Tour of Go 多语言翻译项目接入广告系统:从 AdSense 专用配置到通用 HTML 注入架构

图 3:百度统计单页应用设置

(43) go-dev 单页网站接入统计与 Google AdSense Auto Ads 验证记录

图 1:GitHub 仓库中的多语言翻译项目结构

(44) A Tour of Go 多语言翻译项目:选择日语作为第二语言并启动翻译验证

图 5:模型身份描述不一致

(45) A Tour of Go 多语言翻译项目中的 AI 协作异常排查:一次长期工程会话失效分析

【图 1:ChatGPT GitHub 写入流程调整说明截图】

(46) go-tour-i18n 翻译流程调整:从 ChatGPT GitHub 写入到本地 artifact 导入

图 4 展示了本次异常状态。

(47) go-tour-i18n 翻译自动化流程复盘:已验证的 ChatGPT 翻译能力在新任务中的稳定性问题

【图 6:全部评审结束以后才读取 secret key,完成最终揭盲】

(48) A Tour of Go 翻译质量再评估:Codex High 已接近 ChatGPT High,我决定调整默认翻译引擎

图 4:ja-JP 生产课程页实际运行 Go 示例

(49) A Tour of Go 日语版正式上线:第二门语言 ja-JP 完成生产发布

图 1:ja-JP 上线以后,先提交“新增语言标准化流程”

(50) A Tour of Go 多语言扩展复盘:为第三门语言建立标准化流程

图 1:课程正文结束以后,页面左侧仍然存在大块视觉空白,但 AdSense 并没有在这里插入展示广告。

(51) A Tour of Go 明明有大片空白,为什么 AdSense 就是不显示展示广告?

图 2:golang/website 当前的 _content/tour/。课程内容、静态资源和模板都在这个上游目录中持续维护。

(52) 为了 AdSense,要不要放弃 SPA?A Tour of Go 页面架构的一次取舍

图 4:最终的手动课程广告真实展示在课程内容区域内,而不是 footer 之后。

(53) 保留 SPA 以后,广告应该放在哪里?从 AdSense 预览到方案 B

图 1:Google Search Console 中,多个不同的 A Tour of Go 课程 URL 被判断为“重复网页,用户未选定规范网页”。

(54) SPA 的 SEO 老问题:为什么最后还是给 103 个 A Tour of Go 课程页生成了 Prerender HTML

图 2:方案 B 生产环境中,源码已经正常,但课程主体高度异常缩短,footer 提前进入第一屏。

(55) 从源码空白到 AdSense 高度污染:A Tour of Go 方案 B 的生产收尾

图 1:A Tour of Go 德语版 de-DE 已正式运行在生产环境

(56) A Tour of Go de-DE 上线复盘:第三门语言用了约 16 小时,下一门如何压到 8 小时?

图 1:fr-FR 首次 production 验收完成后,我没有立即开始 ko-KR,而是先连续完成新增语言与首次生产流程的优化

(57) 法语版上线后,我没有马上开始韩语:A Tour of Go 新增语言流程的一轮完善与简化

图 1:根据 ko-KR 期间 76 次 Git 提交估算实际工作时间

(58) 原本预计 6 小时,最后用了约 16~18 小时:A Tour of Go 韩语版上线复盘

图 2:英文 source 与当时发生 validation failure 的 ko-KR candidate 对比

(59) Validator 报错,到底该改译文还是改规则?一次 A Tour of Go 韩语翻译实战

图 2:法语 A Tour of Go 仓库目前已经归档,页面仍保留 553 Commits 和 61 Contributors 的历史

(60) 从法语 553 次提交到韩语两代离线:A Tour of Go 社区翻译为什么难以长期维护

【图 4:es-ES 首次 Production 收口后连续完成的流程优化 commit】

(61) 从 es-ES 首次上线复盘:我把 A Tour of Go 新增语言的 Production 流程又收敛了一轮

图 1:旧公网验收链路连续出现 curl 28 超时,最终导致 public-machine 阶段失败

(62) A Tour of Go Production 公网验收踩坑:从跨境 SOCKS 链路改为 zgocloud direct

图 1:两次 Production Machine Acceptance 都已经通过,但 Headless Chrome 分别在 / 和 /tour/ 判定页面没有完成渲染

(63) 页面明明能打开,为什么 Headless Chrome 仍然判定 Production 失败?

图 3:Bing 从 Google Search Console 中识别到新的 it-IT 站点,并同时发现已有的 1 个 sitemap

(64) GSC → Bing Webmaster Tools:多语言站点如何减少重复验证

图 3:英文站 3 小时内出现 565 个 Cloudflare 来源 URL

(65) IndexNow 实战:手工提交长期不显示,Cloudflare Crawler Hints 却很快出现在 Bing Webmaster Tools

【图 1:A Tour of Go 项目首页目前的语言版本列表】

(66) 从 nl-NL 到 tr-TR:A Tour of Go 连续上线三门语言后,我又优化了哪些流程

【图 4:Go local 页面中已经出现 French、German、Korean、Simplified Chinese】

(67) 从邮件无人回复到进入 Go 官方 Go local:我的 4 个 A Tour of Go 翻译站终于被收录

图8:最终只保留一把启用的新 API Key

(68) 腾讯云 EdgeOne API 自动化:从 CAM 子用户到最小权限 API Key 的完整配置

【图 7:Production Release Batch 最终汇总】

(69) 从同步 Go 官方上游到一个命令发布 10 个语言站:A Tour of Go Production 流程的再次收敛

【图 3:Cloudflare Smart Tiered Cache 已启用】

(70) Cloudflare 缓存 HIT 很快,MISS 却不稳定:回源阿里云杭州的一次真实优化

【图 3:简体中文站 Support 页面】

(71) 广告之外,社区项目如何长期活下去?我给 A Tour of Go 多语言项目加了 Support

图5:评论成功发布

(72) 从 Go Weekly 到 Reddit、DEV 和 Go Forum:第一次系统推广 A Tour of Go 多语言项目

【图 4:RTL 桌面课程布局修复后的效果】

(73) 第一次把 A Tour of Go 做成 RTL:阿拉伯语版本上线,以及我踩过的几个坑

多语言项目应该先做哪些语言?我的 66 个语言版本商业优先级排序

(74) 多语言项目应该先做哪些语言?我的 66 个语言版本商业优先级排序

当术语一致性遇到性能瓶颈:Go 多语言翻译项目的一次架构取舍

(75) 当术语一致性遇到性能瓶颈:Go 多语言翻译项目的一次架构取舍

A Tour of Go 的第三门社区语言 de-DE 已经正式上线。

生产地址:

https://de-go-dev.shuijingwanwq.com

至此,目前项目已经有简体中文、日语和德语三个实际运行的社区语言版本。

这一次德语版仍然不是“翻译完成就上线”。

103 个课程 Page、19 个 eligible Example,共 122 个 TranslationUnit,仍然完整经过 automatic validation、Quality Check、Final Review、promotion、Locale Surface Review、production 部署和真实浏览器验收。

第一次 Quality Check 中,122 个 TranslationUnit 里有 119 个达到 A,另外 3 个被判定为 B,没有直接放行,而是重新进入 revision。修订完成以后,最终 122 个 TranslationUnit 全部达到 A。

Final Review 又重新独立审核了一遍,最终同样是 122 个 A + approved。

也就是说,这次并没有因为已经是第三门语言,就降低原来的质量门槛。

图 1:A Tour of Go 德语版 de-DE 已正式运行在生产环境
图 1:A Tour of Go 德语版 de-DE 已正式运行在生产环境

先说明:这 16 小时并不是从零开始

这篇文章的标题里有一个很醒目的数字:

约 16 小时。

按每天 8 小时计算,大约就是两个工作人日。

这个数字如果脱离整个项目的前期投入,很容易产生误解。

它并不是说:

“从零开始完整翻译、审核、开发并上线一门 A Tour of Go 语言,只需要 16 个小时。”

实际上完全不是这样。

我大约从 2026 年 7 月 28 日开始形成比较明确的 A Tour of Go 多语言计划。

真正开始集中推进第一门简体中文,大约是从 8 月 1 日开始。

一直到 8 月 22 日左右,第一门语言的完整翻译、质量审核、工具、生产环境和上线流程才真正走完整。

仅仅从 8 月 1 日到 8 月 22 日这一阶段,我基本上没有完整休息过,每天投入时间通常都超过 10 个小时。

即使只按照每天 10 个小时进行非常保守的计算:

22 天 × 10 小时 = 220 小时

也已经超过 220 个小时。

而这还只是第一门语言最集中的一个阶段。

中文完成以后,第二门语言 ja-JP 又继续承担了一项很重要的任务:验证此前为中文构建的能力到底能不能真正扩展到另一个 locale。

也是在日语完成以后,我才进一步把新增 locale 的完整生命周期、Locale Surface Review、生产服务器基线、首次部署与日常部署等内容固化成正式 Runbook。

所以,当 de-DE 开始的时候,很多非常昂贵的问题已经不需要重新解决了。

TranslationUnit 怎样定义,不需要重新研究。

Quality Check 和 Final Review 怎样执行,不需要重新设计。

glossary 怎样约束全站,不需要重新决定。

服务器使用什么目录结构、systemd 怎么管理、Nginx 怎么接入、Playground 怎么复用,也不需要重新探索。

广告、共享静态资源、生产部署和 CDN 同样已经有现成基线。

因此,更准确的理解应该是:前面用了数百个小时逐渐把“增加一门语言”做成了一套系统,而 de-DE 第一次比较清晰地展示了,在这套基础已经存在以后,再增加一门语言的边际人工成本可以下降到约 16 个小时。

这也是为什么我认为这个 16 小时值得记录。

它不是用来说明翻译工作本身有多轻松。

恰恰相反,它说明的是:

大量工作其实已经提前完成了。


上一轮解决“流程怎么走”,这一轮开始回答“流程到底有多快”

ja-JP 完成以后,我没有直接开始第三门语言,而是先整理了一轮新增 locale 标准化。

当时最重要的问题是:

如果增加第三门语言,还要不要重新理解一遍整个项目?

现在 de-DE 真正走完以后,这个问题已经基本得到回答。

至少从架构层面来看,答案是:

不需要。

de-DE 没有重新设计 TranslationUnit。

没有重新设计 Quality Check。

没有重新设计 Final Review。

没有重新设计共享广告架构。

也没有重新设计 SPA 生命周期和 Playground。

整个过程基本按照已有 Runbook 往前走。

但新的问题也很快出现了:

即使路线已经知道,真正走完这条路线仍然需要不少人工时间。

这就成为第三门语言和第二门语言最大的区别。

第二门语言以后,我主要在解决:

有没有一条正式流程?

第三门语言完成以后,我开始更关心:

这条正式流程中,还有多少时间其实花在了重复操作、历史遗留问题和人工搬运上?


de-DE 的 16 小时,并不全是“正常新增语言成本”

如果这 16 个小时全部都是:

翻译 → 审核 → 发布

那么下一门语言想压缩到 8 小时,难度其实会很大。

但实际执行以后我发现,其中相当一部分时间并不是德语本身必然需要的。

而是在第三次完整执行时,又发现了一批以前没有完全暴露出来的历史问题。

例如 status.tsv。

第一门、第二门语言时已经有状态文件和相关流程,但到了第三门语言,某些生成和同步边界才真正被完整验证。

再例如翻译文件末尾空行和 EOF normalization。

单独看只是非常小的格式问题,但当 TranslationUnit 数量达到 122 个,而且还涉及 candidate、promotion、diff 和 validation 时,一个很小的不一致就可能不断产生额外确认成本。

除此之外,这一轮还遇到了旧 upstream commit/time fixture。

有 4 个测试仍然期待以前的 upstream baseline:

645042eb

而当前正式 FrozenUpstreamCommit 已经更新。

最终确认以后发现,这和 de-DE 本身、SHA-256、language selector 都没有关系,只是测试中的历史 fixture 没有同步。

问题很小,但如果不把根因确认清楚,就很容易在完全错误的方向上浪费时间。

生产部署阶段还出现过一个首次 deployment 特有的问题。

已有 locale 部署时始终存在 old release,但 de-DE 是真正的首次部署,没有 old release。

原来的 SSH 参数传递在这种情况下会丢失一个空 positional argument,最终触发:

unbound variable

后来专门改成显式 sentinel,才彻底区分“没有旧 release”和“参数丢失”。

这些事情都不是“每新增一种语言理应重新处理一次”的工作。

所以我的处理原则基本都是:

这次既然已经发现,就尽量不要让下一门语言重新支付同样的成本。

图 2:de-DE 上线过程中持续修复流程问题,并把部署与生产验收进一步自动化
图 2:de-DE 上线过程中持续修复流程问题,并把部署与生产验收进一步自动化

从图里的提交记录也可以看到,这次 de-DE 并不是只有翻译内容的变化。

上线过程中不断有测试、部署脚本、生产验收、shared-assets、语言列表规则以及历史问题被继续收紧。


一些“看起来很小”的问题,其实很消耗人工时间

这次有一个感受变得越来越明显:

真正影响效率的,往往不是一个需要两小时开发的大功能,而是连续出现十几个需要人判断十分钟的小问题。

比如一个测试为什么失败。

一个目录到底是不是 production profile。

一个广告环境变量名称在文档里是不是已经过期。

shared-assets 是否真的需要重新部署。

Cloudflare 缓存到底应该强制要求 MISS -> HIT,还是只需要确认缓存状态正常。

新增 de-DE 后,是否必须马上重新部署中文和日语,让旧站首页立即出现 Deutsch。

单独一个问题可能并不复杂。

但每一次都需要:

查看代码 → 找文档 → 判断现状 → 执行命令 → 看结果 → 再决定下一步。

这些操作累计起来,时间很快就上去了。

所以 de-DE 这一轮除了“完成第三门语言”,另一项很重要的结果就是:

继续把这些需要临时分析的问题,尽可能变成代码里的明确行为和仓库里的正式规则。


语言列表最终也选择了“最终一致”,而不是每次全站同步

de-DE 上线以后,还有一个很典型的问题。

新的 language registry 已经包含德语。

因此新构建的 de-DE 自然可以看到:

简体中文、English、Deutsch、日语。

但已经运行在 production 的 zh-CN 和 ja-JP,使用的是它们之前构建好的 release。

旧 release 不会因为 Git 仓库里增加了一个语言,就自动获得新的语言列表。

最开始很容易把这理解为:

新增 de-DE 后,是不是应该马上重新 publish 中文和日语?

这次实际上也额外同步了一次 zh-CN 和 ja-JP,并确认两个站点都正确显示了 Deutsch。

但在继续分析以后,我最终决定:

以后不把这种反向同步作为新增 locale 的上线 gate。

首页的 language registry 是 build-time 数据。

因此已有 locale 的语言列表正式采用 eventual consistency。

新语言上线时,必须确认:

新 locale 自己能够正确看到已有语言。

但是已有的旧 locale,不要求在新语言上线当天立即反向显示它。

它们等下一次正常 upstream sync、UI 更新或者日常 release 时,自然获得最新 registry 就可以。

这个决定看起来只是少部署两个站点。

但如果以后变成 10 门、20 门甚至更多语言,意义就完全不同了。

如果每增加一门语言,都必须立即重新构建、部署和清理其他所有 locale 的缓存,那么成本会随着语言数量不断放大。

而 eventual consistency 可以把这部分成本基本消掉。


production 验收开始真正收敛成一个命令

de-DE 这一轮,我认为最有实际效率价值的改进之一,是:

scripts/verify-production.sh

以前 production 部署完成以后,需要继续手动确认很多事情。

例如:

release identity 是否正确。

服务器上的 current 是否真的是目标 release。

localhost 是否正常。

公网几个关键路由是不是 200。

sitemap 到底有多少 URL。

里面有没有错误 hostname。

有没有 HTTP failure。

/socket 是否仍然保持预期边界。

CDN 有没有真正返回缓存状态。

这些检查单独执行都不复杂。

问题是需要不断复制命令、看输出,再人工记住哪些已经检查过。

现在这部分被正式压缩成:

Plaintext
scripts/verify-production.sh <release-dir>

de-DE 的最终结果是:

Plaintext
release identity: PASS
remote identity: PASS
source routes: 7/7 PASS
public routes: 7/7 PASS
html identity: PASS
sitemap: 105/105 PASS
socket boundary: PASS
CDN: PASS

PRODUCTION MACHINE ACCEPTANCE: PASS
图 3:verify-production.sh 将 de-DE 的生产机器验收收敛为一次执行,并最终全部 PASS
图 3:verify-production.sh 将 de-DE 的生产机器验收收敛为一次执行,并最终全部 PASS

这里我很在意的一点是:

自动化并没有减少验收项目。

不是为了快,就少检查几个 URL。

也不是为了快,就不检查 sitemap。

实际上恰恰相反。

把检查变成脚本以后,可以更稳定地每次都执行完整范围。

所以效率提升和质量降低,并不是一回事。

很多时候,自动化以后反而更容易维持严格标准。


最终验收仍然保留人工 HUMAN GATE

当然,也不是所有事情都适合交给脚本。

机器可以判断:

HTTP 是不是 200。

hostname 是否正确。

sitemap 是不是 105/105。

release SHA 是否一致。

但是机器很难完全替代:

页面到底看起来正不正常。

德语标题有没有溢出。

移动端 header 是否被裁切。

按钮宽度是否够用。

footer 有没有和内容重叠。

点击 Weiter 以后 SPA 是否仍然自然。

Run / Format / Reset 是否真的能正常交互。

广告加载机会是否会破坏课程布局。

所以 de-DE 在机器验收 PASS 后,仍然完整进行了真实浏览器验收。

这一轮实际还发现并修复过一些只有 rendered surface 才比较容易暴露的问题。

包括移动端标题、按钮宽度、课程列表 footer、分页居中和页面之间的视觉细节。

这也是为什么项目现在会明确区分:

machine acceptance

和:

browser HUMAN GATE

我的目标不是把 HUMAN GATE 去掉。

而是尽量让人只判断真正需要人看的东西。


de-DE 最终不是“翻译完成”,而是完整 production gate 通过

最终 de-DE 的 Locale Surface Review 得到:

Plaintext
decision = passed

并且不是只有 TranslationUnit 通过。

最终 evidence 中记录的是:

Plaintext
A language quality review: passed
preview rendered acceptance: passed
production machine acceptance: passed
production browser acceptance: passed
lightweight ads confirmation: passed

同时:

Plaintext
unresolved language blocker: none
unresolved rendered blocker: none
unresolved production blocker: none
图 4:de-DE Locale Surface Review 最终通过,语言质量、预览、生产机器、浏览器与广告验收全部完成
图 4:de-DE Locale Surface Review 最终通过,语言质量、预览、生产机器、浏览器与广告验收全部完成

这也是我比较看重的一点。

无论译文最初通过什么方式产生,最终决定它能不能进入 production 的,不应该只是“生成完成”。

真正重要的是后面的:

结构验证、完整 source ↔ target 审核、A-only Quality Check、独立 Final Review、Surface Review 和 production acceptance。

这也是为什么我不准备为了把下一门语言压缩到 8 个小时,就删掉这些 gate。


到了第三门语言,最大的瓶颈已经开始变成人工操作

de-DE 做完以后,我现在觉得整个项目的瓶颈已经发生了一次比较明显的变化。

最开始最大的瓶颈是:

能力不存在。

需要先写工具、做架构、建立 workflow。

后来最大的瓶颈变成:

流程不够明确。

所以 ja-JP 完成以后,我专门建立 Runbook 和 Locale Surface Review。

现在到了 de-DE,越来越明显的瓶颈已经变成:

人工审核与人工操作。

特别是 Quality Check 和 Final Review。

正式规则要求每一个 TranslationUnit 都必须单独审核。

这一点我目前并不打算改变。

122 个 TranslationUnit 就应该有 122 个明确的质量结论。

不能因为前面 20 个都很好,就推测后面的也没问题。

不能用 automatic validation 替代语言质量判断。

也不能因为某种翻译方式过去表现不错,就跳过审核。

真正可以优化的是另外一层。

现在人工审核过程中,人不只是在“判断译文”。

还需要做很多辅助操作:

找当前 TranslationUnit。

读取 source。

读取 candidate。

确认 glossary。

确认 validation evidence。

组织审核上下文。

记录结果。

切换到下一个 TranslationUnit。

如果出现 B,再整理 revision unit。

然后重新进入下一轮。

这里真正有质量价值的,是:

判断这个 TranslationUnit 是否达到 A。

其他相当多动作,其实只是信息搬运。


下一步真正应该优化的,是“让人只负责判断”

所以如果下一门语言还要继续提速,我现在最想优化的不是翻译速度。

而是:

减少一个完整 locale 生命周期里人工需要操作多少次。

比如 Quality Check。

理想状态应该逐渐变成:

Plaintext
生成 Candidate Snapshot
→ 自动准备完整 review packet
→ 连续执行逐 TranslationUnit 审核
→ 自动记录每个 A/B/C/D
→ 自动汇总
→ B/C/D 自动形成 revision unit list

这里仍然是逐 TranslationUnit 审核。

标准一点都没有降低。

只是把:

122 次找文件和组织上下文

变成:

少数几次启动审核任务。

Final Review 也一样。

仍然独立重新读取:

source、candidate、glossary、validation evidence、TranslationUnit identity。

但是这些材料应该尽可能自动准备。

最终只让人关注:

这个结果是否可以 approved。

生产流程其实已经开始朝这个方向走了。

目前机器部分越来越接近:

Plaintext
deploy
→ CDN purge HUMAN GATE
→ verify-production.sh
→ browser HUMAN GATE

我希望 TranslationUnit 审核以后也能逐渐达到类似状态。


下一门语言为什么目标是 8 小时

如果 de-DE 大约花了 16 个小时,那么下一门直接要求 4 小时,我觉得暂时还是有些激进。

因为语言本身可能出现更多 revision。

不同 locale 的 UI 长度也可能暴露新布局问题。

production 同样可能出现真实异常。

这些事情没有必要为了追求一个漂亮数字而忽略。

所以目前比较现实的下一阶段目标是:

完整新增一门语言控制在 8 小时以内。

这里的“8 小时”同样不是指传统意义上的纯翻译工时。

它仍然指:

在已有生产体系基础上的新增 locale 增量执行时间。

而且前提是不降低现在的质量标准。

122 个 TranslationUnit 仍然逐个 Quality Check。

Final Review 仍然 A-only。

Locale Surface Review 仍然执行。

production machine acceptance 和 browser acceptance 仍然保留。

我要减少的是:

重复复制命令。

重复找文件。

重复确认已经有正式答案的问题。

重复执行可以被脚本稳定完成的机器检查。

以及下一门语言再次踩到这一门语言已经修过的坑。


4 小时可以作为更后面的“无异常路径”目标

如果 8 小时以后也能够稳定达到,我觉得才适合继续看 4 小时。

4 小时更适合被理解成:

基础设施稳定、翻译质量较高、没有明显 revision 风暴、没有生产异常时的一条理想 happy path。

而不是给所有语言设置硬指标。

因为如果一个 locale 在 Quality Check 中真的发现十几个 B,那么就应该老老实实 revision。

质量问题不应该因为“4 小时预算已经到了”而被放过去。

所以从长期来看,我更关心的可能不只是:

Plaintext
一门语言用了多少小时

还应该开始记录:

Plaintext
需要多少次人工介入
需要多少次异常回流
需要多少个 HUMAN GATE
多少时间真正花在语言判断
多少时间花在操作和等待

只有这样,后面的效率优化才会越来越清楚。


第三门语言真正留下的,不只是 de-DE

从最终 Git 记录来看,de-DE 上线以后,这一轮又留下了不少可以继续复用的东西。

首次 production deployment 对新 locale 的支持已经更完整。

production machine acceptance 已经有正式的一键入口。

shared-assets 的生产验收也进一步自动化。

旧 upstream fixture 已经清理。

retranslation batch 的默认命名也同步到了当前正式工作流。

language registry 的 eventual consistency 规则已经明确写进正式文档。

这些事情意味着:

第四门语言开始的时候,项目状态应该比 de-DE 开始的时候更加干净。

图 5:de-DE 上线后继续清理本轮发现的问题,让第四门语言不再重复支付相同的流程成本
图 5:de-DE 上线后继续清理本轮发现的问题,让第四门语言不再重复支付相同的流程成本

最终工作区重新回到 clean。

对我来说,这也是一次新增 locale 真正结束的重要标志。

不是:

“页面已经可以访问,所以先算完成。”

而是:

这轮发现的问题已经尽量回收到代码、测试、脚本和文档里。


小结

A Tour of Go de-DE 已经正式上线。

如果只看这一轮新增语言本身,从开始集中推进到最终 production,大约花了 16 个小时。

但是这个数字不能脱离前面的长期投入理解。

从 7 月 28 日左右开始形成明确计划,到 8 月初集中推进第一门中文,再到 8 月 22 日左右完成第一门语言完整上线,仅中文最密集的阶段就已经投入超过 220 个小时。

随后 ja-JP 又继续验证第二门语言,并把很多经验变成正式 Runbook 和质量流程。

所以 de-DE 的 16 小时,不是整个项目的成本。

它更接近于:

当底层能力已经存在以后,新增第三门语言的边际成本。

而这一轮最重要的收获,也不仅仅是多了一个德语站点。

更重要的是,我开始能够比较清楚地看到:

哪些时间属于真正不可省略的语言质量判断。

哪些时间属于历史遗留问题。

哪些时间属于机械操作。

哪些操作已经可以交给脚本。

以及整个项目下一阶段真正的效率瓶颈在哪里。

目前看来,最大的瓶颈已经越来越不是“怎么部署一门语言”。

也不是“新增 locale 的架构应该怎么设计”。

而是:

怎样在不降低逐 TranslationUnit Quality Check、A-only Final Review、Locale Surface Review 和 production acceptance 标准的前提下,把大量没有判断价值的人工操作从流程中移出去。

所以第四门语言,我现在给自己的目标是:

8 小时以内。

如果后面能够稳定做到,再尝试把没有明显异常的理想路径进一步压到 4 小时左右。

从 200 多个小时建立第一套完整能力,到第三门语言开始出现大约 16 小时的边际成本,我觉得真正值得继续做的事情已经越来越清楚:

不是单纯追求“翻译得更快”,而是让此前投入的工程能力不断产生复利。

从源码空白到 AdSense 高度污染:A Tour of Go 方案 B 的生产收尾 法语版上线后,我没有马上开始韩语:A Tour of Go 新增语言流程的一轮完善与简化

Go 学习与文档多语言本地化项目

本系列完整记录 Go 学习与文档多语言本地化项目从 A Tour of Go 起步,逐步扩展到站点首页、项目说明页、学习内容、文档以及未来内容包的实际开发过程,包括架构设计、统一术语治理、整页翻译、结构保护、自动校验、独立质量审核、生产发布与长期维护。

项目源码:
✅ GitHub:shuijingwan/go-tour-i18n

语言版本:

当前跨项目目标语言池共包含 66 个语言版本。Go 项目本身目前提供 65 个社区 Production 语言版本,下面每一门 Go 语言版本都直接链接到其当前公开站点。语言列表沿用项目首页现有的展示顺序。

英语(美国)仅作为跨项目目标语言纳入列表,并不是单独的 Go Production 语言版本。当前 Go 的英文源内容仍为官方 generic English,因此英语(美国)链接到 Go 官方站点,而不是不存在的本地社区部署。

  1. 阿姆哈拉语
  2. 阿拉伯语
  3. 孟加拉语
  4. 葡萄牙语(巴西)
  5. 保加利亚语
  6. 加泰罗尼亚语
  7. 克罗地亚语
  8. 捷克语
  9. 丹麦语
  10. 荷兰语
  11. 英语(美国)(Go 官方英文站点)
  12. 英语(澳大利亚)
  13. 英语(加拿大)
  14. 英语(印度)
  15. 英语(新加坡)
  16. 英语(南非)
  17. 英语(英国)
  18. 爱沙尼亚语
  19. 菲律宾语
  20. 芬兰语
  21. 法语(法国)
  22. 法语(加拿大)
  23. 德语(德国)
  24. 德语(奥地利)
  25. 德语(瑞士)
  26. 希腊语
  27. 古吉拉特语
  28. 希伯来语
  29. 印地语
  30. 匈牙利语
  31. 印度尼西亚语
  32. 意大利语
  33. 日语
  34. 卡纳达语
  35. 哈萨克语
  36. 韩语
  37. 西班牙语(拉丁美洲)
  38. 拉脱维亚语
  39. 立陶宛语
  40. 马来语
  41. 马拉雅拉姆语
  42. 马拉地语
  43. 书面挪威语(Bokmål)
  44. 波斯语
  45. 波兰语
  46. 葡萄牙语(葡萄牙)
  47. 旁遮普语(果鲁穆奇文,印度)
  48. 罗马尼亚语
  49. 俄语
  50. 塞尔维亚语(西里尔文)
  51. 简体中文(中国大陆)
  52. 简体中文(新加坡)
  53. 斯洛伐克语
  54. 斯洛文尼亚语
  55. 西班牙语(西班牙)
  56. 斯瓦希里语(坦桑尼亚)
  57. 瑞典语
  58. 泰米尔语
  59. 泰卢固语
  60. 泰语
  61. 繁体中文(台湾)
  62. 繁体中文(香港)
  63. 土耳其语
  64. 乌克兰语
  65. 乌尔都语
  66. 越南语

项目正在持续扩展新的 Go 学习与文档内容,并长期维护各语言版本的术语一致性、翻译质量、独立审核、生产发布与后续更新。

本项目属于非官方社区多语言本地化项目,与 Go 官方无隶属、授权或背书关系。