OpenCode 国际化体系中的韩语词汇表 ko.md:翻译规则、禁译边界与自动化翻译流水线
本文以 韩语词汇表 为核心,逐条解析 OpenCode 仓库中“locale glossary(地域词汇表)”机制的规则内容与设计意图,并结合 translate:app 脚本、翻译提示词模板 与 i18n 一致性测试 说明该词汇表如何被自动注入翻译流水线、如何约束模型行为,以及词汇表条目最终如何体现到 韩语字典文件 中。读完后你能够独立维护一份词汇表,并理解 OpenCode 多语言 UI 翻译从漂移检测到会话校验的完整链路。
1. ko.md 在词汇表体系中的定位
OpenCode 将地域级翻译指引集中存放在 .opencode/glossary/ 目录。根据 词汇表总览 的约定:
- 每个 locale 一个文件,文件名使用小写 slug(例如
ko.md对应韩语、zh-cn.md对应简体中文); - 全局词汇表(README 提到其补充关系为
.opencode/agent/translator.md的全局条目)仍是共享“禁译术语”的事实来源,locale 文件只承载该地域特有的措辞与术语偏好; - 每个 locale 文件的标准结构为:
Sources(来源 PR/issue)、Do Not Translate (Locale Additions)(地域禁译补充)、Preferred Terms(首选术语表)、Guidance(语气与风格指引)、Avoid(应避免的直译与措辞,可选)。
当前仓库已为 ar、br、bs、da、de、es、fr、ja、ko、no、pl、ru、th、tr、zh-cn、zh-tw 共 16 个地域建立了词汇表,其中 ko.md 是韩语版本的规则载体,服务于 app、ui、desktop 三个 UI 域的 60 余个 key 翻译(韩语字典 ko.ts 超过 1100 行)。
2. 逐节解读 ko.md 的完整规则
以下是 ko.md 原文各节的完整继承与技术解读。
2.1 Sources:规则的来源可追溯性
ko.md 的第一节记录了一条来源引用:
Sources: PR #9817
这符合 README 模板 中“每新增一条规则,必须在 Sources 中记录对应的 PR/issue”的贡献要求。它的作用不是装饰性的:词汇表条目代表社区评审中被反复纠正过的措辞,记录来源 PR 能让后续维护者追溯“为什么这样规定”,也避免在无人认领的条目上随意改动。
2.2 Do Not Translate (Locale Additions):韩语禁译清单
ko.md 列出的地域级禁译项为:
OpenCode(正文中保留原始大小写;仅当出现在命令、包名、路径或代码中时才使用小写opencode);OpenCode CLI;CLI、TUI、MCP、OAuth;- 命令、flag、文件路径与代码字面量(保持原样,一字不改)。
这条清单与翻译提示词模板 translate-app.md 中的全局要求是双层叠加关系:模板要求“所有 locale 一律精确保留 OpenCode、API 名称、标识符、代码、命令、flag、路径、URL、版本、错误消息、配置 key 与占位符 token”,而 ko.md 在通用规则之上追加了韩语特有的判定——例如 OpenCode 在韩语句子中出现时必须保留驼峰大小写,不能因为韩语行文习惯而改写或音译。
在自动翻译时,这一节的内容会被脚本原样塞进模型提示词(见第 4 节),因此它是机器可读的约束而非仅给人看的备注。
2.3 Preferred Terms:首选术语表
ko.md 当前在 Preferred Terms 一节中声明:
No PR-backed term mappings yet. Add entries here when review PRs introduce repeated wording corrections.
也就是说韩语目前尚无“经 PR 验证的术语映射”,这正对应 README 的贡献建议:优先收录有 PR 支撑的指引,而不是凭空发明的术语映射;在还没有术语级纠正记录时,先保留通用指引占位。当未来某个韩语翻译 PR 中评审者反复把某个词从直译改为固定译法(例如统一“session”的译名),该映射就会以表格形式沉淀到这里:
| English | Preferred | Notes |
| ------- | --------- | --------- |
| prompt | ... | preferred |
| session | ... | preferred |
值得注意的是,提示词模板 本身还要求模型在选词时参考 Firefox、KDE、VS Code 等至少两个持续维护的本地化开发者语料库,并沿用这些语料库中已确立的英文借词。这一要求已在实际韩语字典中得到体现:ko.ts 中大量高频概念直接采用英语借词拼写,例如 "command.category.session": "세션"(session)、"command.category.mcp": "MCP"、"command.category.agent": "에이전트"(agent)、"command.category.context": "컨텍스트"(context),这与 ko.md “保留已确立英文借词”的方向一致。
2.4 Guidance:语气与风格指引
ko.md 给出三条韩语行文准则:
- 优先自然的韩语表达,而非逐词直译(Prefer natural Korean phrasing over literal translation);
- UI 标签与文档行文保持清晰、直接的语气(Keep tone clear and direct in UI labels and docs prose);
- 精确保留技术性产物:命令、flag、代码、URL、模型 ID 与文件路径(Preserve technical artifacts exactly)。
这三条是地域层的风格约束;跨 locale 的通用约束(如保留 Markdown/MDX 结构、不改 fenced code block)则写在 translate-app.md 中。两者共同构成一次翻译会话的完整行为边界。
2.5 Avoid:需要避免的措辞
ko.md 的 Avoid 节包含两条负面规则:
- 不要翻译作为固定标识符的产品名与协议名;
- 一旦某个反复出现的 UI 动作确立了首选术语,就避免在同一动作上混用多个韩语词。
第二条针对的是本地化中最常见的漂移问题——同一按钮在 A 界面叫“닫기”、在 B 界面叫“종료”。由于词汇表会随每次翻译请求整体注入提示词,该规则实际上是对翻译会话的跨文件一致性约束。
3. 词汇表如何进入翻译流水线:glossaryFile 与提示词组装
translate:app 脚本("translate:app": "bun run script/translate-app.ts")是把上述文件串起来的执行层。关键源码路径如下。
3.1 按 locale 解析词汇表文件
glossaryFile() 决定了“哪个 locale 读哪个词汇表”:
export function glossaryFile(locale: Locale) {
if (locale === "zh") return ".opencode/glossary/zh-cn.md"
if (locale === "zht") return ".opencode/glossary/zh-tw.md"
return `.opencode/glossary/${locale}.md`
}
对韩语(ko)走默认分支,即直接定位 .opencode/glossary/ko.md。简体中文/繁体中文因字典 slug(zh/zht)与文档 slug(zh-cn/zh-tw)不一致而做了显式别名——这正是 README 中“locale 别名需在 Guidance 中说明”的机制背景。
3.2 漂移检测:missing / extra / placeholders
翻译前先对三个 UI 域分别做字典比对(见 findDrift()):
- missing:英文源字典有、目标 locale 缺失的 key;
- extra:目标 locale 多出、英文源没有的 key(允许存在本地复数变体);
- placeholders:
{{token}}占位符与英文源不一致的 key。
复数变体的判定基于 desktop-native.ts 提供的 desktopNativePluralCategories(locale):凡该 locale 除 one/other 外还存在其他 CLDR 复数类目(如阿拉伯语、俄语的多复数形态),其变体 key 会被自动纳入 missing/extra 计算。从 CLDR 规则看,韩语复数形态只有 one 与 other 两类,因此韩语字典通常不产生额外复数变体需求,但检测逻辑仍然对 ko 一视同仁地运行。
三个域各自的目标文件由 targetFiles() 给出:
return [
`packages/app/src/i18n/${locale}.ts`,
`packages/ui/src/i18n/${locale}.ts`,
...(desktopLocales.has(locale) ? [`packages/desktop/src/renderer/i18n/${locale}.ts`] : []),
]
即韩语翻译同时覆盖 app 域、ui 域 与 desktop 域 三份字典。
3.3 提示词组装:词汇表原文整体注入
translate() 中,词汇表内容以 JSON 形式嵌入每次翻译请求:
const glossary = glossaryFile(plan.locale)
const glossaryContent = (await Bun.file(path.join(root, glossary)).exists())
? await Bun.file(path.join(root, glossary)).text()
: undefined
const prompt = template.replaceAll("$1", plan.locale).replaceAll(
"$ARGUMENTS",
JSON.stringify({
locale: plan.locale,
language: plan.language,
glossary: glossaryContent ? { file: glossary, content: glossaryContent } : undefined,
domains: plan.domains.map((domain) => ({
source: domain.source,
target: domain.target,
...domain.drift,
})),
}, null, 2),
)
也就是说,ko.md 的全文(Sources、禁译清单、Guidance、Avoid)连同 locale: "ko"、language: "Korean"、各域的源/目标文件路径以及逐项漂移清单一起,被写进 translate-app.md 模板的 $ARGUMENTS 占位符。模板同时规定:“Apply the locale glossary included in the request(应用请求中附带的地域词汇表)”“Edit only the target files listed in the request(只编辑请求中列出的目标文件)”。因此词汇表不是建议性文档,而是每次韩语翻译会话的硬性输入。
3.4 沙箱化的翻译会话配置
脚本还会通过 translationConfig() 生成一个临时 OpenCode 配置并写入 OPENCODE_CONFIG_CONTENT 环境变量:
share: "disabled"、formatter: false、lsp: false、snapshot: false,关闭分享、格式化与 LSP;- 权限策略默认全拒绝(
"*": "deny"),只放行read/glob/grep/webfetch/websearch,edit则精确放行到本次任务的目标文件列表(如三个ko.ts)之外一律拒绝; - 翻译会话以
--pure模式运行(不加载项目自身配置,避免被仓库内opencode.jsonc干扰),命令形态为opencode --pure run --dir <repo> --agent translate-app-ko-<pid> --model <model> --format json。
会话结束后,脚本还会 opencode --pure export <sessionID> --sanitize 导出会话,并用 sessionModels() 校验实际使用的模型与 variant 是否与请求一致(不一致即判失败);同时以 worktreeSnapshot() 的 SHA-256 快照对比翻译前后的工作区,确保没有目标文件之外的任何改动(unexpectedChanges)。这套机制保证了词汇表规则的执行结果是可审计、可回归的。
4. 质量闸门:一致性测试与 CLI 用法
4.1 结构性验证:parity.test.ts
即便翻译由模型完成,parity.test.ts 仍会在 CI 层做结构性把关,韩语 ko 在其 appLocales 列表中:
- key 全量对齐:非英语 locale 必须拥有英文源的全部 key,且除该 locale 要求的复数变体外不得有多余 key(
missing: []、extra: expected); - 占位符一致:每个共有 key 的
{{token}}集合必须与英文完全一致,复数变体相对*.other源同样校验; - 关键 key 不得留英文:
command.session.previous.unseen/command.session.next.unseen必须已翻译(值不等于英文源); - 完整短语本地化:
ui.sessionTurn.diffs.changed.one/.other必须保留{{count}}且整句自然翻译,而非拼凑碎片——这正与 translate-app.md 中针对该两个 key 的专门条款一一对应。
4.2 手动执行翻译同步
脚本自带的 help 文本(main())给出了完整用法:
Usage: bun run translate:app -- <locale|all> [options]
Options:
-c, --concurrency <count> Maximum parallel OpenCode runs for 'all' (default: 4)
--model <provider/id> OpenCode model (default: opencode/gpt-5.5)
--variant <name> Model variant (default: xhigh)
--dry-run Report drift without running OpenCode
--check Exit nonzero when translation drift exists
-h, --help Show this help message
Examples:
bun run translate:app -- fr
bun run translate:app -- all --concurrency 4
对应韩语场景即 bun run translate:app -- ko:先打印 [ko] app: N missing, M extra, K placeholder mismatches; ui: ...; desktop: ... 的漂移报告,仅当存在漂移时才拉起翻译会话;--check 模式用于 CI 门禁(有漂移即非零退出),--dry-run 只报告不动手。参数解析逻辑见 parseTranslationArgs(),其中单 locale 目标会强制并发为 1,all 时默认并发 4。
5. 规则落地效果:从词汇表到韩语字典
词汇表条目最终的价值体现在字典内容上。以 packages/app/src/i18n/ko.ts 为例:
- 禁译清单生效:
MCP、CLI相关标签原样保留缩写(如"command.category.mcp": "MCP");产品名 OpenCode 不出现在被翻译的标签文本中; - 保留既定借词:
세션(session)、에이전트(agent)、컨텍스트(context)等开发者社区惯用音译,而非生造汉字词; - 占位符严格对齐:
"command.theme.set": "테마 사용: {{theme}}"等 key 中{{theme}}、{{language}}等 token 与英文源一一对应,这正是findDrift的placeholders检测与 parity 测试第 2 条持续守护的内容; - 语气直接简短:命令标签普遍采用两字动词短语(
"새 세션"、"파일 열기"、"탭 닫기"),符合 Guidance 中“UI 标签清晰直接”的要求。
若需要查看某条规则的“执法过程”,可以按以下顺序阅读仓库证据链:glossaryFile 解析 → 提示词注入 → 会话权限配置 → 漂移与快照校验 → 一致性测试。
6. 维护指南:如何为韩语补充词汇表条目
结合 README 的贡献注记 与 ko.md 现状,维护 ko.md 的推荐流程:
- 只收录 PR 支撑的规则:当某个韩语翻译 PR 的评审中出现了重复的措辞纠正,再把该映射写入
Preferred Terms,而不是预先发明术语; - 同步更新 Sources:每新增一条规则,在
Sources追加对应 PR 编号; - 条目要跨页面可复用:优先选择“在多份文档/界面中反复出现、易于一致执行”的词,一次性偶发措辞不入表;
- 区分地域补充与全局禁译:通用禁译项(命令、代码、路径)已由全局词汇表与提示词模板覆盖,ko.md 的
Do Not Translate (Locale Additions)只放韩语特有的大小写或形态决定; - 改动后验证:运行
bun run translate:app -- ko --check确认漂移状态,并用bun test packages/app/src/i18n/parity.test.ts复核结构与占位符一致性。
小结
.opencode/glossary/ko.md 虽然只有 27 行,却是 OpenCode 国际化流水线中“地域知识”的规范承载点:它用 Sources 保证规则可追溯,用禁译清单划定不可变边界,用 Guidance/Avoid 约束韩语的行文一致性;而 translate:app 脚本 把这份全文连同漂移清单注入每次翻译会话,并以权限白名单、模型导出校验和工作区快照三重机制确保规则被严格执行、结果可回归。对贡献者而言,理解这条“词汇表 → 提示词 → 沙箱会话 → parity 测试”的链路,是参与韩语乃至其他 locale 翻译维护的前提。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00