22种语言零漂移:World of ClaudeCraft sim-emits-keys国际化管道设计揭秘
【免费下载链接】world-of-claudecraft项目地址: https://gitcode.com/gh_mirrors/wo/world-of-claudecraft
World of ClaudeCraft 是一款运行在浏览器里的经典风 MMO,它用一条「确定性模拟输出键 + 客户端边界重渲染」的国际化(i18n)管道,让 22 种语言零漂移共存。本文将快速拆解这条管道的设计精髓:从懒加载语言包、两级 CI 门禁,到 S3 漂移守卫和伪语言自检,帮你完整理解一个开源项目如何优雅地管理多语言。
为什么「sim-emits-keys」是关键
多语言网游最常见的坑是:文本一旦混进游戏逻辑,不同语言就可能改变判定,破坏确定性(determinism)。World of ClaudeCraft 的解法非常克制:
- 模拟层(Sim)永远只说英文。位于 src/sim/ 的确定性内核不依赖任何 DOM、Three.js 或语言资源,它只向外发送「稳定的英文文本 + 结构化事件」。
- 客户端在边界重渲染。玩家看到的每一句日志、战利品、报错,都由客户端的
localizeSimText/localizeServerText在最后一刻翻译成当前语言。
这样做的直接好处:逻辑层零语言耦合。同一段战斗在 22 种语言下行为完全一致,本地化只影响「皮肤」,从不触碰「骨骼」。相关规则见 docs/i18n-scaling/translation-workflow.md。
懒加载语言包:默认访客零字节开销
打开 src/ui/i18n.ts 你会发现一个精巧的「懒加载翻转」设计:
| 语言包 | 加载方式 | 用途 |
|---|---|---|
en | 静态急加载 | 全局默认 + 同步兜底 |
en_XA | 仅开发期 | 伪语言自检,生产构建被树摇剔除 |
| 其余 21 种 | 动态import()分块 | 按内容哈希单独下载 |
也就是说,一位默认英文玩家下载到的非英文语言字节为 0。21 个非英文切片各自成为独立的内容哈希 chunk,通过LOCALE_LOADERS[lang]()按需加载。这套「lazy locale flip」是整条管道里最划算的性能优化。
两级 CI 门禁:英文 PR 合法,发布必须全量翻译
管道最「硬核」的部分,是把它拆成两道门禁:
- PR 级门禁(
npm test):只要求英文完整。未翻译的键渲染英文并标记为pending,直接通过——保证贡献者「只提交英文」的契约永远安全。 - 发布级门禁(
I18N_RELEASE_TIER=1 npm test):在release/**分支上强制pending = 0,任何一行未翻译都会让构建失败。
这个分层让「稀疏覆盖 + 批量填充」成为可能:贡献者只加英文,维护者在每次发布前统一补全其余 21 种语言,既省 token 预算,又避免 PR 里塞满会被重做的机器翻译。
S3 漂移守卫:让新字符串无法悄悄漏网
tests/localization_fixes.test.ts(俗称 S3 守卫)在测试时解析src/sim/sim.ts 和 server/game.ts,枚举所有玩家可见的 emit 点,并断言每一处都被客户端 matcher 识别(或在文档化的兜底名单里)。
- 它扫的是字面量输出:
emit({type:'log'|'loot', text})、this.error(id, lit)等。 - 新增一个未被 matcher 覆盖的 Sim 字符串?直接让测试变红,不可能静默上线。
- 已知盲区(变量路由、
?? 'English'兜底)由人工登记 + 定向测试补齐,文档在 docs/i18n-scaling/translation-workflow.md 中写得很清楚。
en_XA伪语言:揪出所有漏网的硬编码
一条妙计藏在开发期的en_XA伪语言里:它把英文渲染成「带重音 + 方括号」的形式(如P‾r̆e̅ṗa̅r̈ë!)。
在任意非发布构建加?lang=en_XA,屏幕上凡是保持纯 ASCII、没有方括号的文字,就是没进t()的硬编码字面量。这等于给整条管道配了一台「漏网探测器」,而它本身会被树摇剔出生产包。
REST 错误:按代码翻译,而非按英文
API 报错走的是另一条更稳的路:服务端只发出稳定错误码,绝不发出英文句子。
- server/http/error_codes.ts 是只增不减的目录,形如
auth.invalid_credentials。 - 客户端的
userFacingApiError把代码逐字映射到apiError.<domain>.<reason>键。 - 占位符(如
{date}、{seconds})一律在客户端拼装,绝不落在服务端。
这条「code-first」设计让错误文案与语言彻底解耦,tests/api_error_code_parity.test.ts还会拦截任何「服务端有码、客户端无键」的失配。
确定性构建:两次运行,字节一致
生成器 scripts/i18n_build.mjs 把英文en作为权威嵌套基座,把 21 个语言覆盖层(unflatten 回嵌套)叠加其上,缺失的叶子用英文兜底,输出稠密的i18n.resolved.generated/。它:
- 键顺序由
en驱动,缩进与引号固定; - 没有任何
Date.now/Math.random,两次运行字节级一致(可复现性检查); - 生成类型标为
: EnTranslations,让tsc对缺失/改名键编译期报错。
术语锁定词表:品牌与专名永不漂移
scripts/i18n_glossary.json 是人工维护的「锁定术语」清单,例如品牌名 "World of ClaudeCraft"、职业名、技能名、区域与副本名。npm run i18n:worklist会把词表原样随每个语言批次一起下发,确保既有译名被复用而非重新发明——这是「22 种语言零漂移」里最容易被人忽略、也最致命的一环。
给项目维护者的 5 条实用建议
- 逻辑层说键,渲染层说话——把本地化严格限制在客户端边界。
- 默认语言零开销,其余按需懒加载分块。
- 门禁分级:开发期宽松(只查英文),发布期严格(
pending = 0)。 - 用运行时解析测试(S3 式守卫)枚举所有 emit 点,堵住新字符串漏网。
- 伪语言 + 术语词表双保险,分别抓硬编码漏网和专名漂移。
小结
World of ClaudeCraft 的国际化不是「翻译一堆文件」那么简单,而是一套确定性优先、门禁分级、可自检、可复现的工程管道。Sim 只发键、客户端边界重渲染、en_XA自检、S3 漂移守卫与字节级一致的生成器,共同保证了 22 种语言下的行为零漂移。如果你也在为多语言项目头疼,这套「sim-emits-keys」的边界设计值得直接借鉴。
【免费下载链接】world-of-claudecraft项目地址: https://gitcode.com/gh_mirrors/wo/world-of-claudecraft
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考