把一份排版精美的英文 PDF 翻译成中文,还要保持原来的版式,表格不错位、图片不乱跑——这个需求在我混的几个技术群里几乎每个月都会被翻出来问一次。以前大家要么一页页截图丢进翻译软件,要么先转成 Word 再手动调格式,碰到几十页的文档效率低到怀疑人生。直到我在 Dify 里把这条链路由工作流串起来之后,上传 PDF、自动解析、调用大模型翻译、最终输出一份保留原格式的译文,十几页的文档大概来回十分钟就能出第一版。这篇就把整套方案复盘出来,包括我最开始踩过的坑和最后沉淀下来的流程细节。如果你是正在用 Dify 处理文档类需求、或者被 PDF 翻译折磨过的朋友,这篇应该能帮你少走不少弯路。
1. 动手之前,先把方案想清楚
1.1 “原格式翻译”的本质是三条子任务的组合
很多朋友第一次听到“PDF 原格式翻译”,第一反应是“这有什么难的,复制粘贴到翻译引擎不就完了”。真做一次就明白了,这件事根本不是“翻译”本身难,而是它把三件性质完全不同的任务绑在了一起。
第一件是内容提取。你得从 PDF 里拿到干净、顺序正确的文本。第二件才是语言转换,让大模型或翻译引擎把内容翻成目标语言。第三件是格式重建,把翻译后的内容重新渲染成一份版式可用的文档。大多数在线翻译工具只解决了第二件事,第一件事靠上传整个 PDF 让工具后台处理,第三件事则是直接丢弃——给你一段纯文本或一个排版崩坏的网页,让你自己再手工排版一次。
明白了这一点,你的思路就会清晰很多:如果我们要在 Dify 里实现端到端流程,真正要下功夫的不是翻译 Prompt,而是两头的“提取”和“重建”。翻译是把文本从 A 语言变成 B 语言,提取和重建是把无结构的 PDF 文件变成有结构、可重新输出的中间格式。
1.2 为什么选 Dify,而不是抱着现成翻译工具不放
市面上其实有不少能直接处理 PDF 翻译的工具,DeepL、Google 翻译都有文档翻译入口,沉浸式翻译这类浏览器插件也很流行。但用它们做一批、几十份文档的时候,问题就来了。
- 在线工具的交互是封闭的:上传、等待、下载,每一份文档都要重复一遍,没有批处理。
- 术语不可控:公司内部的产品名、行业专有名词,翻译工具不会替你遵守术语表,而且你没法在没有企业版的前提下干预结果。
- 数据安全边界不清晰:合同、技术手册这类文档直接传到第三方服务,很多公司是不允许的。
- 定制能力为零:你想在翻译前过滤页眉页脚、想在翻译后统一术语、想在结果里保留表格结构,它都做不到。
Dify 的定位是 LLM 应用开发平台,你可以在里面编排工作流、挂载知识库、配置多个模型,甚至可以把自己公司内部的术语表做成知识库喂给模型。它能解决上面那些问题的本质原因是:你不受制于某个产品的固定交互,而是按自己的业务逻辑搭流水线。而且近期 Dify 社区版的迭代节奏很快,文档解析、知识库流水线这些能力一直在补强,这种“平台 + 工作流”的玩法,比死磕单一翻译工具要灵活得多。
当然它也有门槛,最常见的门槛是自己部署、维护一套 Dify 实例,需要花点时间。但一旦跑起来,后续做多语言文档批处理、知识库问答、内容抽取,都是同一套底座上继续长出来的能力,性价比是值得的。
1.3 技术路径选型:转中间格式再重建,比直接动 PDF 坐标靠谱
决定用 Dify 之后,还有一个绕不开的选型:用什么方式实现“原格式”三个字。
我最早尝试过直接在 PDF 上做文本替换,就是用 PyMuPDF 找到每个文本块的位置,把译文替换进去。这个思路看起来直接,实际操作下来问题非常大:译文和原文的长度通常不一样,英译中平均会短 30% 左右,中译英又会变长,一个词替换成另一个词,原有文本框根本装不下,要么溢出要么重叠,表格和列表更是重灾区。这个方法只适合短文本、小幅修改,不适合整篇文档翻译。
后来我换了一个思路,不追求在原始页面坐标上做文章,而是把 PDF 先转成有逻辑结构的中间格式,翻译完再重建文档。具体有两条路:
- PDF 转 DOCX,翻译后利用 Word 或 LibreOffice 导出 PDF。适合版式复杂的商务文档、合同、标书,Word 的流式排版会自动处理换行、分页和表格列宽。
- PDF 转 Markdown 或 HTML,翻译后通过 Pandoc 或 WeasyPrint 生成新 PDF。适合技术文档、论文、说明手册,对标题层级和代码块的还原很好。
我现在默认采用第二条路线,因为 Markdown 是 Dify 工作流里最好处理的文本格式,LLM 对 Markdown 结构标记的理解非常成熟,生成结果稳定。如果遇到对版式要求极其苛刻的文档,再临时切到 DOCX 管线。
2. PDF 翻译的难点不在语言,而在文档结构
2.1 PDF 的底层逻辑是“排版坐标”,不是“内容流”
在处理 PDF 之前,有必要理解一个关键概念:PDF 文件本质上记录的是每个字符在页面上的精确坐标,而不是像 Word 那样的逻辑内容流。你看到的一个段落,在 PDF 内部可能是几十个独立的文本绘制指令,每个指令指定字体、字号、位置、颜色。PDF 没有“段落”这个概念,更没有“这一段和下一段是连续的”这种语义信息。
这个特性带来的直接后果就是:用程序提取 PDF 文本时,提取工具只能按照文件内部的顺序把字符“倒”出来,而这个顺序很可能不是人眼阅读的顺序。双栏论文里,第一栏读完之后应该接第二栏顶部,但工具可能把第一栏和第二栏的文字交错输出;表格里的数字、图注、页眉页脚也可能混在正文里,顺序完全看构建文件时的内部组织方式。
我经常用一个类比来跟朋友解释:PDF 就像一张已经拍好的照片,Word 则是一篇带大纲的作文。照片里的每个元素位置固定,你想修改其中一个字,必须重新拍一张;作文里的大纲则能让你调整段落顺序,字变多字变少都会自动重排。PDF 翻译要面对的,就是“怎么把照片里的信息无损还原成作文,再重新拍成另一张照片”。
2.2 三类典型 PDF 的难度分级
不是所有 PDF 难度都一样。我自己按提取难度把 PDF 分成三类,不同类别处理策略完全不同。
| 类型 | 特征 | 提取难度 | 最佳处理路径 |
|---|---|---|---|
| 数字化单栏文档 | 网页直接打印或 Word 导出的单栏 PDF,有文本层 | 低 | 常规提取后分块翻译 |
| 多栏/复杂排版文档 | 学术论文、杂志、产品手册,双栏或多栏,含表格、图注、页眉页脚 | 高 | 坐标排序 + 分栏处理,或先转 DOCX |
| 扫描件 | 图片型 PDF,没有文本层 | 很高 | 先 OCR,再进入翻译流水线 |
单栏文档最简单,PDF 里文字的存储顺序基本等于阅读顺序,直接提取就能拿到相对干净的文本。多栏文档我通常会先看看提取结果乱到什么程度,再用 pdfplumber 按坐标排序或者借助 OCR 引擎的版面分析能力重排。扫描件是另一回事,没有文本层就谈不上提取,必须先做 OCR,而且扫描件的版面分析还涉及表格识别、图片区域检测,现在一般都直接交给 PaddleOCR 或 RapidOCR 这类完整 OCR 引擎。
记住一条经验:拿到 PDF 后不要急着搭流水线,先用工具抽一页看看文本提取质量,再决定路径。很多人在这一步偷懒,后面代码节点写了一堆补丁也救不回来。
2.3 翻译后的版式失衡:文本长度变化比想象中更麻烦
就算文本提取干净了,翻译完成之后还会遇到一个特别容易被忽略的问题:译文长度和原文不一样,而且不是简单的等比例缩放。
英文翻译成中文,同样的内容字数通常会缩短 30% 到 40%,因为中文的信息密度更高;中译英则反过来,长度可能膨胀 20% 到 50%。放在原始坐标上替换文本,文本框大小不变,短了留白太多,长了溢出换行。即便是用流式排版的重建方案,也可能出现这样的情况:原文五行的段落译文只有三行,原来的分页位置失效;原文两栏高度一致,译文一栏明显比另一栏短,版式看起来很不协调。
处理这个问题的核心原则是:不要试图在新文档里保持“每一段长度一致”,而是保持“段落逻辑一致 + 整体版式风格一致”。简单说,标题还是标题,层级不变;表格还是表格,列数和数据结构不变;图片位置不追求像素级对齐,但顺序和上下文不变。接受这种“逻辑上的原格式”,你的实现难度会下降一大截,出稿速度也快得多。
3. 基于 Dify 工作流的整体设计
3.1 把 Dify 当作流水线调度中心
明确了技术路径之后,我回到 Dify 里开始设计工作流。一个核心观念先摆出来:Dify 不是翻译引擎,它是流水线调度中心。
Dify 工作流最大的价值是把你需要人工连接的操作变成可视化节点:文件上传、文本提取、代码处理、LLM 调用、结果输出,每个环节都变成一个可以单独调试的模块。某个环节出问题,你只要看日志定位到具体节点,不用整个流程从头跑。对我这种习惯反复改的人来说,这个特性太重要了。
在 Dify 里搭建这条流水线用到的核心能力有四块:文件变量、文档提取器、代码节点、LLM 节点。文件变量用来接收上传的 PDF;文档提取器负责把 PDF 内容转成纯文本;代码节点做文本清洗、分块、结果组装这些不适合 LLM 干的活;LLM 节点才是真正执行多语言翻译的地方。模型管理则允许你随时切换底层模型,中英互译我常用 Claude 和 GPT 系,预算敏感时也能切到国产模型。
3.2 节点编排与数据流向
这条流水线我最终的节点编排是这样的:
开始节点 → 文档提取器 → 文本预处理代码节点 → LLM 翻译节点 → 结果组装代码节点 → 结束节点
开始节点定义了一个“文件”类型的变量,用来承接上传的 PDF。文档提取器节点读取这个文件,输出包含全文的字符串。文本预处理代码节点拿到字符串后,做几件事:清理页眉页脚、压缩多余空行、识别标题和表格标记、按段落切分成长度合适的文本块。LLM 翻译节点按分块顺序逐块翻译,输出译文。结果组装代码节点把所有译文块按阅读顺序拼接成一份完整 Markdown,最后在结束节点里作为文件或文本输出。
这里要特别说明一点:Dify 的文档提取器对数字化 PDF 识别效果尚可,但它只提取文本,不做版面分析。如果你处理的是双栏论文,提取器也会把文本顺序搞乱,所以我在它后面一定接一个代码节点做预处理。扫描件则不能在文档提取器这里硬扛,需要提前 OCR 成带文本层的 PDF,再进入流水线。
数据流向方面,文件变量只在开始节点产出,不会自动传给后面所有节点,你得在后续节点里显式引用它。字符串变量则可以通过“变量赋值”或代码节点的返回值不断更新。这块刚上手容易搞混,我的建议是先在草稿纸上把每个节点的输入输出画一遍,再回 Dify 里拖节点。
3.3 分块策略和术语一致性
LLM 翻译不是把整篇文档一次性丢进去就行。超长文档超出上下文窗口,必得分块;分得太碎,上下文一断,前后术语就翻得不一致了。分块策略我踩过好几轮。
我现在采用按语义段落分块,单块控制在 1000 到 2000 字符左右,最长不超过 3000。为什么不按固定字符数切?因为固定字符数很容易把一个完整段落从中间截断,LLM 拿到半段话,很难判断整体语义。按段落切分虽然块长度参差不齐,但每块都是完整语义单元,翻译质量稳定得多。如果相邻两块内容联系紧密,比如一个长列表被拆开了,我会在分块时保留 100 到 200 字符的重叠,把上一块结尾带进下一块开头,给模型多一点上下文。
术语一致性是另一个容易被忽略的点。技术文档里“Transformer”该翻成“变压器”还是“Transformer”,产品名该不该保留原文,这些规则如果不告诉模型,模型就会按自己的理解随意发挥。我在 Dify 里的做法是给系统 Prompt 塞一份术语表,同时把公司常用的术语表构件成知识库作为可选输入。不是每个项目都需要挂知识库,但一份几十行的术语表对专业文档的帮助立竿见影。
3.4 需要准备的模型和外部依赖
跑这套流水线之前,有几个基础设施要提前确认。第一是模型,翻译场景对指令遵循能力要求不低,建议至少选一个当前主流的商用模型或者能力达标的开源模型,我自己的默认配置是用中长上下文模型,并开启 Dify 里的模型 API 配置。第二是格式转换工具,如果你要最终导出 PDF,Dify 沙箱里不一定有 LibreOffice 或 Pandoc,我通常是把组装好的 Markdown 或 DOCX 通过 API 回传给自己的一台服务器或本地脚本,再调用 Pandoc 转 PDF。第三是 OCR 引擎,只处理数字化 PDF 可以不准备,一旦出现扫描件,就得提前把 OCR 服务接入到文档提取之前。
这些依赖不用一天全部配齐,可以先跑通核心链路,再按需追加。我最初做的时候系统 Prompt 写得很随意,文档提取后也没做清洗,第一版结果惨不忍睹,后来一步步把预处理和术语表加进去,效果才稳定下来。
4. 手把手实现多语言 PDF 翻译流水线
4.1 创建应用与配置模型
打开 Dify 控制台,新建一个应用,类型选“工作流”,而不是“聊天助手”。聊天助手偏对话式交互,适合问答场景;我们要实现的是确定性的批处理流程,工作流才能精确控制每一步。
创建后先进入“编排”页面,右侧找到模型配置区域,选择你已经接入的模型供应商。我的建议是设置两个模型:一个做翻译主模型,配置低一点温度,控制创造性;另一个备用模型或小模型做文本清洗、关键词校验这类轻量任务。模型没接的话,Dify 里各模型的配置差异不大,按官方文档把 API Key 填进去即可。
接下来拖出开始节点,添加一个“文件”类型的变量,命名为 pdf_file,用来接收后续上传的 PDF 文件。再拖一个结束节点,在输出里预留一个字符串变量和一个文件变量位置,分别用来放译文 Markdown 和最终生成的文档。这个时候工作流还是空的,先把变量打通,后面填节点就不容易乱。
4.2 文档解析与文本预处理
在 Dify 的节点列表里找到“文档提取器”,输入端引用开始节点的 pdf_file。这个节点直接输出一个字符串,就是提取出来的全部文本。你可以在预览面板快速验证提取质量,看看是不是乱序、有没有把页眉页脚混进来。
提取出来的文本通常脏得很,需要代码节点清洗。我习惯在文档提取器后面放一个 Python 代码节点,做以下几件固定动作:
- 删除重复的页眉页脚行,比如每页都出现的公司名称、页码、章节名。
- 把多个连续空行压缩成一个。
- 识别明显的标题行,如果原来是“1.2.3 xxx”这种编号,给它加上 Markdown 标题标记。
- 按段落切分成长度合适的文本块,存入数组变量。
一个简化版的分块代码大概长这样:
import re def main(text: str): # 去掉页码等纯数字行 lines = [line.strip() for line in text.splitlines() if line.strip() and not re.fullmatch(r'\d{1,4}', line.strip())] # 合并成段落 paragraphs = [] current = [] for line in lines: if line.endswith(('.', '。', ':', ':', ';', ';')): current.append(line) paragraphs.append(" ".join(current)) current = [] else: current.append(line) if current: paragraphs.append(" ".join(current)) # 按段落切分,块大小控制在1500字符左右 chunks = [] block = [] size = 0 for p in paragraphs: block.append(p) size += len(p) if size > 1500: chunks.append("\n".join(block)) block = [] size = 0 if block: chunks.append("\n".join(block)) return {"chunks": chunks}这个代码不复杂,但能解决大部分“提取结果没法直接用”的问题。注意 Dify 代码节点有自己的输入输出约定,函数名必须是 main,返回必须是可 JSON 序列化的结构,我在上面示例里已经把格式写成了适配 Dify 的形式。
4.3 翻译 Prompt 的设计
LLM 节点是整条流水线的核心,Prompt 设计直接决定翻译质量。我踩过最大的坑是给模型的指令太笼统,只有一句“翻译成中文”,结果标题层级丢了、表格标记没了、术语五花八门。
现在我的翻译 Prompt 长这样,分享出来可直接抄:
你是一位资深技术文档翻译专家,擅长多语言互译。请把用户给出的原文片段翻译成指定的目标语言。 要求: 1. 完整保留原文的结构标记,包括 Markdown 标题符号 #、列表符号 - 和数字序号、表格分隔符 | 和 ---。 2. 严格使用用户提供的术语表,不得随意替换术语;术语表中未出现的专有名词,第一次出现时可以保留英文原文并在括号里给中文译名,之后统一使用中文译名。 3. 表格只翻译单元格内容,不改变行列数。 4. 不要添加原文没有的解释或说明,不要输出翻译以外的任何内容。 5. 目标语言:{{language}} 术语表: {{glossary}} 原文片段: {{text}}三个占位变量要分别接到上游数据:text 接分块后的原文,glossary 接一个包含术语对的文本,language 接目标语言。它们分别在前面节点定义好或作为工作流输入参数传入。
模型温度我设置为 0.2 到 0.3,不设太低,否则翻译容易变得机械、失去流畅度,但也必须控制创造性和随意发挥。每次改完 Prompt,我在预览里用同一段测试原文跑两次,观察输出是否稳定,稳定了再推进下一个节点。
4.4 结果组装与输出下载
LLM 节点翻译完,输出的是一个一个独立译文块。结果组装代码节点把数组里的译文块按原顺序拼接,并做最后清理,比如把块与块之间多余的换行合并、统一每个段落前是否有缩进。
拼接后的完整译文是一个 Markdown 字符串。这个字符串直接放在结束节点的文本输出里,用户在运行工作流后就能在结果页复制。但光有文本不够,很多人要的是能直接分发或打印的 PDF 文件,所以还要多一步格式导出。
Dify 沙箱环境对第三方库限制比较严,我不建议在 Dify 代码节点里直接尝试“生成 PDF”这种操作,大概率会碰到库缺失或权限不足。更稳的做法是分两步走:第一步,在工作流结束时用 API 把译文 Markdown 回传到你自己的服务器或本地目录;第二步,在服务器上执行一条 Pandoc 命令完成转换。这是我本地标准化的导出命令:
pandoc output.md \ -o output.pdf \ --pdf-engine=xelatex \ -V CJKmainfont="Noto Sans CJK SC" \ -V geometry:margin=2.5cm如果你更想要 DOCX 而不是 PDF,就把输出格式改成 docx,命令更简单,Word 会负责自动重排,对表格和长文档更友好:
pandoc output.md -o output.docx这条链路绕了一层,但胜在灵活,Dify 负责翻译质量,外部脚本负责版式成品,各干各的强项。我实际项目里就是用一个监听 Dify Webhook 的小脚本,收到译文后自动执行 Pandoc,然后上传到指定目录,整条链路全自动。
4.5 完整测试与调优流程
新搭建的流水线第一次跑通常不会完美,我有自己的一套调优顺序,从快到慢,能快速定位问题。
先用一页内容做小样测试。上传一个只有两三页的简单文档,跑通全流程,重点看输出有没有明显乱序。然后增加一个带多栏或表格的页面,看预处理代码节点是否能把结构保留下来。接着检查术语,找几个技术名词,看译文是否按术语表执行。最后才整篇文档跑一次完整流程,随机抽三页人工对照原文和译文。
这个顺序每次都能帮我节省很多时间,因为如果你在小样本阶段就发现问题,处理成本往往只有几分钟;等整篇跑完才发现分块错乱,返工成本就高了。调优过程中我会持续盯着 Dify 每个节点的运行日志,LLM 节点可以看完整输入输出,代码节点则看返回的 JSON 结构,出问题一目了然。
5. 常见问题速查与踩坑实录
5.1 提取出来的文本顺序全乱了
这是大多数人在 PDF 翻译上碰到的第一个拦路虎。原因前面说过,双栏或表格布局下,内部文本对象顺序不等于阅读顺序。乱序的具体表现是:第一栏读一半,突然跳到第二栏,再跳回来;表格里数字和其它单元格内容被拆得七零八落。
我对付这个问题有两招。第一招是换提取工具,Dify 内置提取器输出乱序时,用 pdfplumber 或 PyMuPDF 这类能拿坐标的工具做一次重排。第二招是直接放弃“从 PDF 提取顺序”这件事,改用转 DOCX 的方式,Word 引擎会自动根据版面分析重建阅读顺序。我现在处理双栏论文时,默认先转 DOCX 再进 Dify,效果比纯文本提取稳定得多。
5.2 扫描件 PDF 一个字符都提不出来
文档提取器输出空字符串,基本可以断定这份 PDF 是扫描件,没有文本层。很多人在这一步以为自己的 Dify 配置坏了,其实不是,是文件本身的问题。
解决方案是 OCR。我常用的流程是:先用 PaddleOCR 对每页做文字识别,生成带文本层的新 PDF,再把新 PDF 丢进原有的 Dify 流水线。注意 OCR 识别的准确率直接影响后面翻译质量,尤其是术语和缩写。扫描件比较多的场景,我会在文档提取器前增加一个 OCR 分流节点,自动判断文件是否包含文本层,没有就进入 OCR 分支,有就走常规提取分支。
5.3 译文段落变短,表格溢出
这个属于“格式重建”问题,不是翻译质量的问题。原文五行的段落译成中文可能只有三行,如果直接按原文坐标排版,页面下半部分会出现大片空白;表格里的单元格装不下中文时,内容就会溢出。
我试过很多办法,最有效的是放弃“按原页面坐标逐行对应”的思路,改用流式文档重建。把译文写进 Markdown,再通过 Pandoc 导出,让排版引擎自己处理换行和分页。这样虽然不会跟原文件像素级一致,但逻辑结构和阅读体验都保留住了,交付给业务方完全够用。如果你面对的是合同、标书这种对版式特别敏感的文档,就改用 Markdown 转 DOCX 再手工微调,效率也比从零排版高得多。
5.4 模型翻译时把 Markdown 标记弄丢了
这种情况最气人:内容翻译对了,但标题的 # 号没了,表格的 | 分隔符不见了,列表编号变成纯文本。原因通常是 Prompt 里对结构标记的约束不够强,或者模型为了“让译文更通顺”主动把标记当作噪音清理掉了。
针对性解决办法有几个。第一,在 Prompt 里明确强调“保留所有结构标记”,并给一两个示例,few-shot 比单纯指令可靠。第二,把温度降到 0.2 以下,减少模型自由发挥空间。第三,在后置代码节点里做一次结构校验,比如检查原文的 # 数量是否和译文一致,不一致时再重投一次翻译。我的流程里已经把第二和第三个办法都加进去了,在实践中校验成本远低于人工返工成本。
5.5 Dify 输出文件下载与格式转换的那些坑
工作流跑完后,译文在结束节点输出,很多朋友希望在页面里直接下载一个 PDF 文件。这里有个现实问题:Dify 沙箱环境内直接生成 DOCX 或 PDF 文件并挂载到输出节点,在社区版里支持有限。最开始的版本里我试着在代码节点里用 Python 生成一个 DOCX 文件返回,结果运行报错或者文件变量无法正常输出,调试到怀疑人生。
最终稳定方案是,Dify 只负责输出 Markdown 文本,通过 Webhook 或 API 把文本发送到自己的中转服务,再在那边调用 Pandoc 转文件。中转服务可以是几十行代码的小 Flask 应用,也可以是 n8n 这类自动化平台。整个过程不算难,但确实需要一点点前后端配合的思维,这也是整套方案里对我而言唯一需要“再写一个小系统”的地方。
6. 一些扩展和我的实际体会
6.1 接入术语库,让专业翻译更可控
基础流水线跑通后,我第一个做的扩展是接术语库。Dify 的知识库天然适合存术语表,我把每个客户或每个产品的术语做成一个独立知识库,在工作流里作为“知识检索”节点挂进去,让 LLM 在翻译前先检索相关术语。
这里有一个非常实在的效果:不同业务线的文档翻译术语风格完全一致了。公司的产品经理和技术人员都很在意“超融合”“数据面”“控制面”这些词在不同文档里的译法是否统一,知识库接入后,这个问题基本没有再出现过。如果你只是个人使用,不搭知识库也行,直接在 Prompt 里写死后缀也够用。
6.2 批量处理与定时任务
单篇文档跑通之后,自然想批量处理。Dify 的界面操作适合小批量和调试,几十份文档逐一点运行太痛苦。我后来写了一个 Python 脚本,通过 Dify 服务端 API 批量提交文件,回调接收翻译结果,再自动执行 Pandoc 导出。这个脚本大概三百行,跑完整个流程完全不依赖人工干预,白天丢一批文件进去,下班前就能收到全部译文文档。
批量处理有个注意点:要控制并发和限额,避免瞬间打爆 Dify 服务或模型 API 配额。我在脚本里做了简单的时间间隔控制和失败重试机制,每提交一份休眠几秒,失败任务先记日志,全部跑完后统一人工处理重试项。
6.3 我越来越觉得“格式”才是文档翻译的门槛
整套方案从想法到稳定运行,前后折腾了大概两周,期间反复在“提取乱序”“格式重建”“术语不统一”几个问题上打转。到后面我越来越确定一件事:语言转换本身已经不是门槛了,多语言模型的翻译质量远超绝大多数人的预期,真正的门槛在“格式”二字。谁能把 PDF 解析得干净、谁能让译文漂亮地重排回一份可用文档,谁才真正解决业务问题。
我现在的这套 Dify 流水线,本质上是在“内容翻译质量”和“格式还原成本”之间找到了平衡点——不追求像素级还原,但保证结构清晰、排版自然、术语一致,交付速度还足够快。遇到特别敏感的版式要求,就落到 DOCX 分支再做精修。这也是我在这件事上最重要的体会:先跑通流程,再逐步加约束,别指望第一次就把文档翻译做成工业级产品,做成这样已经能省掉团队大量手工时间了。