首页
/ OpenCode 国际化体系中的韩语词汇表 ko.md:翻译规则、禁译边界与自动化翻译流水线

OpenCode 国际化体系中的韩语词汇表 ko.md:翻译规则、禁译边界与自动化翻译流水线

2026-09-05 19:48:50作者:瞿蔚英Wynne

本文以 韩语词汇表 为核心,逐条解析 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 是韩语版本的规则载体,服务于 appuidesktop 三个 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
  • CLITUIMCPOAuth
  • 命令、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 给出三条韩语行文准则:

  1. 优先自然的韩语表达,而非逐词直译(Prefer natural Korean phrasing over literal translation);
  2. UI 标签与文档行文保持清晰、直接的语气(Keep tone clear and direct in UI labels and docs prose);
  3. 精确保留技术性产物:命令、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 规则看,韩语复数形态只有 oneother 两类,因此韩语字典通常不产生额外复数变体需求,但检测逻辑仍然对 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: falselsp: falsesnapshot: false,关闭分享、格式化与 LSP;
  • 权限策略默认全拒绝("*": "deny"),只放行 read/glob/grep/webfetch/websearchedit 则精确放行到本次任务的目标文件列表(如三个 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 列表中:

  1. key 全量对齐:非英语 locale 必须拥有英文源的全部 key,且除该 locale 要求的复数变体外不得有多余 key(missing: []extra: expected);
  2. 占位符一致:每个共有 key 的 {{token}} 集合必须与英文完全一致,复数变体相对 *.other 源同样校验;
  3. 关键 key 不得留英文command.session.previous.unseen / command.session.next.unseen 必须已翻译(值不等于英文源);
  4. 完整短语本地化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 为例:

  • 禁译清单生效MCPCLI 相关标签原样保留缩写(如 "command.category.mcp": "MCP");产品名 OpenCode 不出现在被翻译的标签文本中;
  • 保留既定借词세션(session)、에이전트(agent)、컨텍스트(context)等开发者社区惯用音译,而非生造汉字词;
  • 占位符严格对齐"command.theme.set": "테마 사용: {{theme}}" 等 key 中 {{theme}}{{language}} 等 token 与英文源一一对应,这正是 findDriftplaceholders 检测与 parity 测试第 2 条持续守护的内容;
  • 语气直接简短:命令标签普遍采用两字动词短语("새 세션""파일 열기""탭 닫기"),符合 Guidance 中“UI 标签清晰直接”的要求。

若需要查看某条规则的“执法过程”,可以按以下顺序阅读仓库证据链:glossaryFile 解析提示词注入会话权限配置漂移与快照校验一致性测试

6. 维护指南:如何为韩语补充词汇表条目

结合 README 的贡献注记 与 ko.md 现状,维护 ko.md 的推荐流程:

  1. 只收录 PR 支撑的规则:当某个韩语翻译 PR 的评审中出现了重复的措辞纠正,再把该映射写入 Preferred Terms,而不是预先发明术语;
  2. 同步更新 Sources:每新增一条规则,在 Sources 追加对应 PR 编号;
  3. 条目要跨页面可复用:优先选择“在多份文档/界面中反复出现、易于一致执行”的词,一次性偶发措辞不入表;
  4. 区分地域补充与全局禁译:通用禁译项(命令、代码、路径)已由全局词汇表与提示词模板覆盖,ko.md 的 Do Not Translate (Locale Additions) 只放韩语特有的大小写或形态决定;
  5. 改动后验证:运行 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 翻译维护的前提。

登录后查看全文
热门项目推荐
相关项目推荐