1. 双语技术写作的三大痛点
写技术文档已经够烧脑了,再叠加中英双语,痛苦指数直接翻倍。过去一年,我在云原生项目里同时维护中英文 README 和 API 文档,踩坑无数,最后把问题收敛到三个维度:
- 术语一致性:同一组件在中文叫“网关”,英文却时而 gateway 时而 API-Gateway,搜索时永远对不上号。
- 文化适配性:中文喜欢“请确保”,英文直译 please make sure 显得啰嗦;反过来,英文常用 you can simply...,中文若译成“你可以简单地”就带轻蔑感。
- 格式保持:表格、代码块、交叉引用里的占位符,一旦翻译就错位,CI 渲染直接报警。
痛点厘清后,目标就明确了:让机器先跑 80% 的机械工作,人只做 20% 的创意与校验。下面这套 ChatGPT 流水线,是我迭代 20+ 版本后跑通的最佳实践,全部可落地。
2. 分层 Prompt:把大模型当“翻译工厂”来用
直接把整段 Markdown 扔给 ChatGPT 求“中译英”,得到的是“能看但不专业”的结果。我拆成三层,每层只解决一类问题,效果反而稳。
- 基础翻译层:先让模型做“信雅达”直译,但禁止它碰代码块、表格和链接。
- 技术术语修正层:把第一层输出再喂给模型,让它对照术语表二次替换,并给出替换理由。
- 风格适配层:最后按“受众+场景”微调,比如写给开发者的注释要口语化,写给采购经理的概览要正式。
三层 Prompt 模板我放在Gist,下面给出最小可运行片段,方便你快速套娃。
from typing import List, Dict import openai def base_translate(src: str, glossary: Dict[str, str]) -> str: """基础翻译层:只翻译正文,不碰代码块""" prompt = f""" 你是一位技术文档译者。 1. 把下列 Markdown 内容译成英文,不要改动代码块、表格、链接。 2. 遇到以下术语请严格采用对应译法:{glossary} 内容: {src} """ return call_gpt(prompt) def term_fix(pass1: str, glossary: Dict[str, str]) -> str: """术语修正层:二次校验""" prompt = f""" 你是一位严苛的术语审查员。 1. 检查下列英文是否严格使用术语表,若未使用则替换并高亮原因。 2. 只输出修正后的英文,不解释。 内容: {pass1} 术语表:{glossary} """ return call_gpt(prompt) def style_polish(pass2: str, audience: str = "developer") -> str: """风格适配层:按受众微调""" tone = {"developer": "casual", "manager": "formal"}.get(audience, "neutral") prompt = f""" 把下列英文调成 {tone} 语气,保持技术准确。 {pass2} """ return call_gpt(prompt)每层都开temperature=0.3保证可重复,再辅以top_p=0.95防“死循环”。
3. 把术语库塞进流水线:JSON + 动态注入
术语表别写死,放 JSON 方便 CI 读取。示例:
{ "网关": "Gateway", "限流": "Rate Limiting", "灰度发布": "Canary Release", "Pod": "Pod" }代码里用glossary.get(term, term)兜底,防止新词缺失导致空值。为了同步团队,我把它推到仓库.github/glossary.json,PR 触发机器人检查是否出现“新词未录”。
4. 输出后处理:正则守门员
模型再强也会偶尔“手滑”——把kubectl get pods翻成kubectl get Pods。写个 30 行的小脚本,在本地/GitHub Action 做最后守门。
import re, logging from typing import Tuple def lint_code_block(md: str) -> Tuple[bool, List[str]]: """检查代码块是否被意外翻译""" errors = [] # 匹配 ``` 包裹的块 pattern = re.compile(r'```.*?```', flags=re.S) for idx, block in enumerate(pattern.findall(md)): # 如果出现中文标点或“请”“确保”等,大概率被翻译 if re.search(r'[\u4e00-\u9fff]', block): errors.append(f"代码块{idx}含中文字符") return len(errors) == 0, errors if __name__ == "__main__": with open("README_EN.md", encoding="utf-8") as f: ok, errs = lint_code_block(f.read()) if not ok: logging.error("Lint failed: %s", errs) exit(1)5. 避坑指南:多义性、文化雷、注释同步
多义性
- 策略 A:给模型“上下文锚点”,在 Prompt 里加一句“本文指 Kubernetes 里的 Pod”。
- 策略 B:术语表用“域名空间”方式,如
Pod/k8s对应Pod,Pod/iOS对应iOS 设备。 - 策略 C:出现歧义时让模型输出
<!>注释<!>,人工二次确认。
文化敏感
检查清单我缩成 5 行:- 不用国家/地区做负面比喻
- 避免“简单”“仅仅”等居高临下词
- 日期格式用 ISO,避免 6/7 美式歧义
- 货币单位写 USD/EUR,而非 $
- 不拿动物比喻性能(“蜗牛速度”在部分文化里不成立)
代码注释同步
把源码注释也当 Markdown 处理,走同一套流水线。用ast解析 Python 文件,提取 docstring,翻译后再写回,全程自动化。篇幅有限,脚本我放Gist,核心就是“注释=节点”,别动逻辑行。
6. 质量验证:BLEU + 术语一致性
自动评估省时间,但要用对指标。BLEU 适合“对照金标”场景,没有金标就退而求其次:让模型把英文再反向译成中文,计算与原文的 chrF2 分数,低于阈值就人工复核。
from sacrebleu import corpus_bleu from typing import List def compute_bleu(hyp: List[str], ref: List[str]) -> float: """计算 BLEU,返回 0-100""" return corpus_bleu(hyp, [ref]).score术语一致性脚本更直观:扫一遍译文,统计术语表 value 出现次数,与原文术语出现次数对比,缺失即报错。
def term_consistency(en_md: str, glossary: Dict[str, str]) -> List[str]: """返回未出现的术语英文""" missing = [] for en_term in glossary.values(): if en_term not in en_md: missing.append(en_term) return missing7. 人机协作工作流:让“人”做最后一厘米
完全无人化不现实,我现在的节奏是:
- 本地写完中文 → 脚本一键生成英版 → 自动提 PR
- PR 触发三个机器人:lint、术语、BLEU
- 人工只做两件事:
- 看机器人高亮的“多义性注释”
- Review 文化适配层输出,必要时改 Prompt 再跑
这样平均 3000 字的技术博客,中英双语从过去的 6 小时缩到 1.5 小时,术语一致性 98%,BLEU 提升 12 个点。
8. 延伸思考:把流水线搬到“实时通话 AI”上
写完文档,我总在想:如果读者想直接“说”中文,就让 AI 实时返回英文语音,上述三层 Prompt 能不能复用?答案是——可以,但延迟要压到 500 ms 以内。最近我在从0打造个人豆包实时通话AI动手实验里,把 ASR→LLM→TTS 整条链路跑通,发现“术语修正层”正好可以插在 LLM 节点,做一个 50 ms 的微型替换,不影响体验。整套实验从申请火山引擎密钥到在浏览器里跟 AI 唠嗑,只花了 40 分钟,连前端都配好了。对双语技术写作感兴趣的同学,不妨边写文档边试试语音交互,或许能碰撞出新的灵感。