三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

机翻把我的排版全毁了?tri-translate 的跨格式等价救回来

机翻把我的排版全毁了?tri-translate 的跨格式等价救回来

一份英文 API 文档丢给模型翻中文,十分钟后拿回来:--dry-run被译成了「–空跑」,围栏代码块里的驼峰变量名硬生生插进两个汉字,Markdown 表格的竖线错位半行,https://api.example.com/v1结尾还被贴心地补了个中文句号。

译文读着挺顺。文档废了。

那次返工改排版花掉的时间,比我们自己从头翻一遍还长。问题不在模型的中文水平,在于它分不清哪些字符是「内容」、哪些字符是「结构」。

第一版:在提示词里求它

朴素方案——提示词末尾加一句「代码、路径、命令保持原文」。

管用吗?管一点。稳定吗?完全不。短段落它记得住,长文档翻过第三屏就开始自我发挥,尤其碰上$HOMEPOST /v1/messages这种半英文半符号的东西,模型那股「翻译本能」压不住。

我个人特别讨厌这种靠祈祷生效的方案。交付之前你永远不知道这次它听不听话,review 成本全压在人身上。

第二版:手搓正则挡代码

思路升级:翻译前把代码块抠出来换成[CODE_1]这样的占位符,翻完再塞回去。

方向是对的,我们的实现是残缺的。

正则只写了围栏代码块一条,结果行内代码漏了、环境变量漏了、API 端点漏了、七位短哈希被当成普通英文单词处理了。补一条漏一条,补到第八条我们才意识到,这活儿不该自己造轮子。

如果让我重来,那版正则我压根不会自己写,直接找现成的规则集抄。

隔离区占位法:19 类规则,顺序比规则本身更要命

tri-translate 把这一步叫「隔离区提取」,规则集 19 类,全躺在never-translate.json里:绝对路径、相对路径、围栏代码块、行内代码、命令行、API 端点、URL、域名、邮箱、配置键、环境变量、版本号、SHA 哈希、品牌名、商标、首字母缩写、技术标识符、数字与单位、日期时间。

规则条目长这样:

{"schema_version":1,"rules":[{"id":"URL","name":"URL","pattern":"https?://[^\\s)]+","placeholder":"__URL_{N}__","description":"http/https URL(先于域名识别)","preserve":true},{"id":"API_ENDPOINT","name":"API 端点","pattern":"(GET|POST|PUT|DELETE|PATCH)\\s+/[^\\s]+","placeholder":"__API_{N}__","description":"HTTP 方法的 API 端点","preserve":true}]}

扫描顺序是这套规则里最不起眼、也最容易被忽略的设计。围栏代码块排第一位,因为代码块内部什么都可能出现——URL、路径、邮箱,一旦被后面的规则先切走,代码块就碎了。URL 排在域名前面也是同理:https://example.com/docs要是先被域名规则匹配上,剩下的/docs会被当成独立路径,还原时拼不回原样。

我们手搓那版正好栽在这儿。

译后还有一道硬检查:占位符残留必须为 0。__CODEBLOCK_3__这种东西只要在译文里出现一个,整份就不交付。

三策略分层:意译、直译、不译各管一段

隔离区解决的是「不该翻的别翻」,剩下的正文还有个「翻多深」的问题。

tri-translate 的答案是三层退守:意译优先,直译次之,不译兜底。

意译打头,按上下文和读者画像传达意思,不做逐字映射。碰到术语密集、命令式语句、法律精确性要求、数字版本号这四类场景,退守直译——直译不等于欧化,中文表达习惯还是得守住。再退一步就是不译,路径、代码、URL、品牌名、首字母缩写原样保留。

上层还压着一张按场景走的策略矩阵:技术文档主直译、解释段退守意译;营销文案反过来,主意译、数据和承诺退守直译;UI 文案主意译且要精简;法律条款主直译,条款编号直接不译。

这张表的价值在于它承认了一件事——同一份文档里,不同段落该用不同策略。我们以前是整篇一个 prompt 一把梭,翻出来要么全篇死板,要么关键条款被「润色」跑偏。

术语对齐:值钱的是「不许译成什么」

第二个冷门点藏在术语表里。

多数人理解的术语表就是一张对照表,source 对 target。tri-translate 的glossary.json分了三层优先级:A 层不可译,永远保留原文,压根不进翻译流程,OpenAI、ChatGPT、GPT-4、GitHub、npm、Anthropic、Claude 都在这层;B 层已批准,必须用批准译法;C 层推荐,可以按上下文调整。

真正值钱的字段是block_synonyms

{"source":"agreement","target":"协议","priority":"B","context":"legal document","block_synonyms":["合约"],"status":"approved","example":"Sign the agreement.","notes":"法律文档统一为'协议'"}

它不是在告诉模型该译成什么,是在告诉模型不许译成什么。这两件事的约束力根本不在一个量级——正向指定顶多算「建议」,负向屏蔽才是红线。一份合同里 agreement 一会儿「协议」一会儿「合约」,法务是会打回来的。

C 层还有个反直觉的用法:target 可以是英文。pipeline的推荐译法就是Pipelinepull request的推荐译法是Pull Request,把「流水线」「拉取请求」屏蔽掉。中文技术圈本来就这么说话,硬翻反倒增加阅读成本。这两条我们改过两轮才定下来。

配置长什么样

运行时配置放在templates/meta.json,字段多,我们平时对照的是摊平成 YAML 的版本,看结构更清楚:

config:config_default_target_lang:zh-CNconfig_default_source_lang:autoconfig_default_register:formalconfig_default_doc_type:technical_docconfig_default_audience:developerconfig_quality_threshold:accuracy_critical_max:0accuracy_major_max:0design_critical_max:0design_major_max:0hallucination_critical_max:0fluency_major_max:2terminology_major_max:1config_enable_translation_memory:falseconfig_glossary_path:glossary.jsonconfig_never_translate_path:never-translate.jsonconfig_style_examples_dir:style-examples/config_max_input_chars:50000config_retry_on_critical:trueconfig_max_retries:2config_preserve_paragraph_alignment:trueconfig_preserve_markdown_structure:trueconfig_strict_term_consistency:true

config_preserve_markdown_structureconfig_preserve_paragraph_alignment这两个开关,就是所谓「跨格式等价」的落点:结构和标记原样搬过去,段落数一一对得上,被替换的只有正文文字。

不合格就不交付

质量这块用的是 MQM Core 四维加一个 Hallucination 子维。Accuracy 管语义等价,Fluency 管中文通顺,Terminology 管术语一致,Design 管 markup 保留度,Hallucination 管有没有编造原文里不存在的内容。

门槛卡得很死:Accuracy、Design、Hallucination 三项的 Critical 和 Major 错误必须为 0,Fluency 和 Terminology 允许 Minor 但要提示修正。不达标就重译,最多重试两次,两次还不行退守直译。

交付物是四件套,落在.tribro/translate/<命名>/下面:deliverable.md是译文,preserved.md是不译清单,alignment.md是段落级原文对照,quality.md是质量报告。

我们打开最多的其实是preserved.md。它把所有被保留原文的要素连同占位符、类型、位置列成表,review 时扫一眼就知道该保的保住没有,比通读全文快太多。

什么时候别用它

这套东西不是银弹,杀鸡真用不着。

tri-intent 的 I08 意图管的是「翻译转换」这一大类,跨语言翻译和跨格式转换都算——Markdown 转 HTML、JSON 转 YAML、Python 转 Go 都归它,识别特征是动词为翻译、译成、转成、转换为,涉及源到目标的形态迁移。这类轻量活儿,tri-content 自己处理就够了。

tri-translate 只在深度翻译场景被委派:要做代码路径保护、要强制术语表、要跑 MQM 自检的时候。翻一句聊天记录还上五件套,纯属给自己找活干。边界写得很直白,tri-content 自行判定是否委派,tri-translate 不主动接管 I08。

它也支持单独安装。激活时会检测上游 tri-intent 在不在:有快照就读快照里的任务领域和输出期望来增强语境;没有就提示你装;你明确拒绝,它进降级模式,并且会老实交代「本次基于自构造的等价输入执行翻译,上下文语境感知精度低于标准链路」。

一个工具肯承认自己这趟跑得不准,比它吹自己多准,可信度高得多。

收个尾

翻译这事被机翻拉低预期太久了,大家默认「能看懂就行,排版自己修」。可技术文档的排版本身就是信息——代码块是代码块,路径是路径,--dry-run是一个不能拆的整体。把结构交给规则,把语义交给模型,各干各的,返工率立刻掉下来。

我们做的雷达鸭 App 收录的是中国一人公司和超级个体的真实赚钱案例,商品页和介绍文案要中英两版,术语表这套习惯就是那阵子被逼出来的。鸿蒙版在华为应用市场能搜到,微信小程序同步在跑。

留个问题给你:如果术语表是团队共享的,谁有权限往 B 层加词、谁能改block_synonyms?这事我们到现在也没想明白。


关于我

老三,十来年软件开发经验,软件设计师、人工智能应用工程师,眼下主要做鸿蒙 ArkTS 北向开发和 Web 前端。业余折腾 AI 自动化,不定期在 CSDN 写点鸿蒙和 AI 方向的技术文章。

本文遵循 MIT 协议,转载请注明出处。
项目仓库:TrisighT-Bingo/tri-skills

请根据https://skillhub.cn/install/skillhub.md,安装 @user_989eb8f0/tri-translate。

← 返回列表