dsh-translate-docs
双语工作流的完整版:更新走 briefing 驱动的小路,新文档走整篇翻译的大路。只允许用户显式调用。
这是 .agents/skills/dsh-translate-docs/SKILL.md 的中文精读。它是双语工作流的「完整版」——注意它的 frontmatter 里有 disable-model-invocation: true:这个 skill 只允许用户点名调用,agent 不能自己选用它。
调用边界
只有用户按名字显式调用 dsh-translate-docs 时才运行这个扩展工作流。日常文档工作、从另一个 skill 里、或「推测出需要翻译」都不得选用它——例行翻译遵守 docs/AGENTS.md 的一次性单遍规则。
它是引导,不是翻译记忆库。它是让 foo.md ↔ foo.zh.md 配对在两种语言里都一致且自然的工作流地图。两种语言权威平等——改动可以在任一侧写作,那一侧就是这次更新的源。你是译者:下面的规则说什么必须成立,而不是某句话怎么措辞——措辞判断归你,术语不归你。
按改动类型分诊——它决定其他一切
- 更新(配对已存在、改了一侧):走 briefing 驱动的更新路径——刻意便宜:不读指南语料、不做 git 考古、最小化对侧编辑。绝不为应用一个更新而重译整篇——最小更新保住未动部分已被 review 过的措辞,重译等于把那次 review 扔掉。
- 新配对(还没有对侧):走整篇翻译路径。
- 删除或改名:对侧和
.i18n.yaml一起删/改——否则门禁会报不完整配对。
.agents/notes/archived/ 下冻结的 Agent Note 不是翻译工作:三件套已被归档验证器封死,归档后永不更新、重录或修复任一侧。
更新路径(briefing 驱动)
这条路以小得多的成本达到指南语料级的质量;基准证据由「briefed-updates」Agent Note 持有。
- 生成 briefing:
pnpm run gen-translation-brief <配对的任一文件>(无参数则为所有失同步的配对生成)。briefing 以最窄的安全对齐粒度映射改动——改动的 Markdown 单元(段落、表格行、列表项、标题),再到整个标题小节,再到整篇——并包含:写作侧自上次确认一致以来的 diff、每个改动单元的「上次确认源 / 当前源 / 当前对侧文本(带行号)」、改动触到的术语行、首次出现位置变动说明、以及约束性更新规则的摘要。 - 纯机械 diff?
--apply掉它。所有改动都落在两侧逐字节相同的代码围栏内时,briefing 会说明;pnpm run gen-translation-brief --apply <pair>把改过的围栏拼进对侧并先做结构校验再写盘——不用 subagent,不用手编。 - 散文 diff?委派给 subagent,把 briefing(或生成它的命令)递过去。briefing 就是译者的全部工作集——subagent 不重读指南语料、不重新推导 diff。只有当 briefing 让某个决定真的做不出(周围文本没有先例的未列术语,或整篇级 briefing 即「两侧都改了」/单元和小节都对不齐)时,才升级到整篇路径的事实来源,在 translation-rules.md 下手工调和。
- 覆盖 diff 的最小编辑。保住 diff 没碰到的一切的已审措辞,然后逐子句对照源验证改动的块:无添加、无遗漏、术语按内联行、代码逐字。
- 记录与验证,范围化:
pnpm run verify-translation-pairing --write <pair>然后pnpm run verify-translation-pairing <pair>。--write只处理你点名确认的配对——它拒绝裸跑,所以批量重录必须显式--all。全语料检查仍在doc-sync/CI 里跑,不要每次更新都跑。
整篇路径(新配对)
需要从零写翻译时,编排的 agent 自己不翻:起一个 subagent 做翻译。译者先读下列事实来源,再整篇翻成另一语言——长文档逐节进行,每节的结构边走边对齐源,而不是最后再调结构。
事实来源(去读,不要复述):
- docs/i18n/README.md——配对契约:三文件对(
foo.md、foo.zh.md、foo.i18n.yaml)、一致性记录的两侧 blob hash、语言切换行、范围与排除; - translation-rules.md——怎么翻:忠实、结构保持、术语纪律、排版(MUST/SHOULD 级);
- terminology.md——术语表,双向约束。翻译前加载,不是拿不准时才查——你没注意到的词才是会漂移的词;
- translation-prompt.md——自动化管线的校准模板,agent 使用本 skill 时不渲染它;术语表是自动渲染器唯一注入的仓库文件,而本 skill 与 translation-rules.md 对 agent 写作翻译保持约束;
- dsh-prose-standard——必备散文覆盖与编辑判断,两侧都适用,不增删源的命题。
翻译
- 第一遍——写,不是转置。读一个语义单元,然后以最贴近的文体样本的语域,像一个母语技术作者那样重述。保住必备框架,不强求逐句对应。
- 第二遍——逐子句对照源验证。忠实是在这里检查的,不是写进去的:确认无添加无遗漏、每个术语按表、每个代码逐字存活。修的方法是原生地重写句子,不是把词补丁进去。
- 单独读完对侧。对照完之后,把译文离开源单独读一遍,重写那些只有孤立看才显别扭的措辞。
- 写进文件的只有最终文本,绝不写草稿或笔记。
- terminology.md 里每个术语严格按表渲染。中文目标用中文列和首现列;未列术语需要可引用的中文开源/厂商先例,否则按「待定术语」保留英文。英文目标用英文列和已确立的英文技术词;源词含糊时保留原词加短注并列为待定。绝不在行内自造译法。
- 代码块两侧逐字节相同(含注释)。仓库相对文档链接保持同一语义目标和精确的 query/fragment 后缀:活跃双语语料内的目标,英文侧用
.md、中文侧用.zh.md;范围内缺失对侧是错误;语料外目标保持原路径;切换行是唯一的跨 locale 例外。 - 配对门禁检查标题深度、围栏块、表格行列数、列表种类、有序列表起点、列表项数、链接 locale 与语义目标。第二遍里人工核对列表与表格顺序、非规范列表编号、行内代码、强调、含义、术语、语气。
找到待办
pnpm run verify-translation-pairing --list打印每个范围内文档:missing / out-of-sync / ok。missing 和 out-of-sync 是契约违规,常规检查会拒;pnpm run gen-translation-brief无参数时为每个失同步配对打印 briefing;- 在改了配对文档的 PR 里,待办清单就是 diff 本身:每个改过的侧都需要对侧更新并在同一 PR 重录——忘了门禁就红。
收尾一对配对
- 切换行:中文文件 H1 后立即放
[English](foo.md) | 中文,英文文件 H1 后放English | [中文](foo.zh.md)——新配对两边都加;例外是生成器拥有的英文源保持与生成器输出逐字节一致、省略切换行,中文对侧仍然链接回去。 - 记录一致性:
pnpm run verify-translation-pairing --write <pair>重算并在foo.i18n.yaml里记录两侧完整 blob hash。PR 里的 yaml diff 就是那句可 review 的声明——「我确认过这两份说的是同一件事」——所以只在你真的确认过之后跑。 - 普通文档不需要清单条目:每个范围内源都必须有配对。只有当属主政策记录了真实的「生成的 / 指示性的 / 构造即双语」豁免时,才改
scripts/translation-pairing.manifest.json。 - PR 之前:触动的配对在范围化检查下全绿;
pnpm run doc-sync(含全语料配对检查及verify-md-wrap/verify-md-links)按 dsh-pre-push-checks 在 PR 级跑一次,不在每个翻译任务内部跑。 - 让 PR 可 review:说清哪些配对是新翻的、哪些是最小更新,把「待定术语」显著列出。
怎么回应翻译 review
按 dsh-code-review 的汇报指引:逐条按是非评估;对术语评论记住术语表才是契约——reviewer 的译法决定落进 terminology.md,而不是只改一个文件。