☰
FluentRead 文档翻译实战指南:从本地文件批量导入到双语对照、校订与保真导出
2026/9/27 9:59:29 网站建设 项目流程
  • 前端
  • AI 应用
  • 本地部署

【免费下载链接】FluentRead

An open-source browser extension for bilingual translation. 一款开源的浏览器双语翻译插件。

项目地址:https://gitcode.com/gh_mirrors/fl/FluentRead
点击查看免费下载

导读

本文以 FluentRead 的文档翻译(Document translation)独立工作台为主题,系统讲解其完整的用户流程:从扩展菜单导入 PDF、ePub、DOCX 与各类文本/字幕文件,到批量排队翻译、暂停续译、校订译文,再到按原格式导出双语或纯译文文件。读者读完本文,不仅能掌握该功能的所有操作细节与限制,还能从源码层面理解各格式解析、批量调度与下载产物是如何实现的。

文档翻译是 FluentRead 中独立于网页翻译的一个完整功能模块,其入口页面、领域模型、批量翻译编排与二进制文档解析分别位于 src/app/document-translation、src/features/document-translation/core 与 src/features/document-translation/services。本文所有操作说明以 docs/en/guide/document-translation.md 为准,原理细节以仓库源码为准;中文版说明见 docs/guide/document-translation.md。

打开文件:入口与支持格式

如何进入文档翻译

从扩展菜单选择Document translation(文档翻译),会打开一个独立的翻译工作台页面。导入文件有两种方式:

  1. 将文件直接拖放到页面中央的拖放区;
  2. 点击页面上的文件选择按钮(或队列中的Add files / 添加文件)使用系统文件选择器,支持一次选择多个文件。

导入的文件会立即在浏览器本地解析,解析完成后页面会显示可翻译片段数量与文件大小,之后才进入翻译确认环节。

支持的格式与大小限制

源码 src/features/document-translation/core/document.ts 中的SUPPORTED_DOCUMENT_EXTENSIONS定义了完整支持列表,共 14 种扩展名:

类别扩展名说明
文档pdf需含可选中文本(文本层)
电子书epubZIP 容器格式,按章节解析
Worddocx旧版.doc需先另存为.docx
网页html、htm保留标签结构
纯文本txt保留换行结构
Markdownmd、markdown保护代码块与行内语法
字幕srt、vtt、ass、ssa保留时间轴与标签
歌词lrc保留时间标签
数据json只翻译字符串叶节点,保持 JSON 合法

每个文件的上限为 10 MiB,定义于 core/document.ts 的DOCUMENT_MAX_BYTES(10 * 1024 * 1024)。文件类型由扩展名识别(getDocumentFormat),与 MIME 类型一一对应(getDocumentMimeType)。仓库的 examples/document-translation 目录提供了上述各类格式的样例文件(如sample.pdf、sample.epub、sample.srt、sample.json等),可用于快速验证功能。

文本格式与二进制格式的解析分界

从源码结构看,解析被清晰地划分为两条路径:

  • 文本格式(txt/markdown/html/srt/vtt/ass/lrc/json)由 core/document.ts 的parseDocument统一处理,纯同步、不依赖外部库;
  • 二进制格式(pdf/epub/docx)由 services/binary.ts 的parseBinaryDocument处理,按需动态加载pdfjs-dist(PDF.js)、jszip、pdf-lib等库。

每种格式解析后会生成统一的ParsedDocument模型,包含可翻译的segments(片段列表)、用于无损还原的parts结构,以及二进制格式特有的版面/章节/段落元数据。

各格式解析的底层原理

PDF:文本原子 → 行 → 段落块

services/binary.ts 的parsePdf使用 PDF.js 逐页提取文本,经过三段式重建:

  1. pdfTextAtoms将 PDF.js 的文本项(含仿射变换坐标)过滤旋转过大的项,转换为带 x/y/宽高/字体的文本原子;
  2. pdfTextLines按 y 坐标聚类成行、按 x 坐标排序拼接,处理字间距与行内断点;
  3. pdfTextBlocks依据行高(标题判定阈值bodyHeight * 1.32)、垂直间距、重叠率与对齐关系把行合并为段落块,并推断fontWeight(标题 700、短句 600、正文 400)与居中对齐。

每个段落块对应一个翻译片段,并记录其在页面上的位置(x/y/width/height/fontSize/lineHeight等PdfDocumentBlock字段),这些坐标正是后续"译文写回文本框、版面保持原位"的依据。若 PDF 没有任何可提取文字,会明确报错"扫描版 PDF 暂不支持 OCR,请上传包含文本层的 PDF"。

ePub:读取 OPF 清单按阅读顺序取章

ePub 本质是 ZIP 容器。services/binary.ts 的parseEpub依次校验mimetype条目(必须为application/epub+zip)、META-INF/container.xml中指向的 OPF 内容清单,再解析 OPF 的<manifest>与<spine>(<itemref>顺序),只取 XHTML/HTML 章节;每章复用parseDocument('chapter.html', source)走 HTML 解析,并记录章节标题与片段偏移(EpubDocumentChapter),供阅读时按章节导航。

DOCX:正文、页眉页脚、脚注尾注分别处理

services/binary.ts 的parseDocx校验[Content_Types].xml与word/document.xml后,按word/document.xml、header*.xml、footer*.xml、footnotes.xml、endnotes.xml的优先级扫描<w:p>段落,提取<w:t>文本、<w:tab>制表符与<w:br/>换行,并根据段落样式(w:pStyle中的 title/heading、w:numPr列表标记)标注title/heading/list-item/paragraph/header/footer/note角色。

JSON:只翻译字符串叶节点

core/document.ts 的parseJsonDocument深度遍历 JSON,只把字符串叶节点送入翻译队列,并记录其在结构中的JSONPath(如$.items[0].label);渲染时在深拷贝上按路径回填译文,再用JSON.stringify(output, null, 2)输出,保证导出结果始终是合法 JSON。

字幕与歌词:时间轴与标签不参与翻译

SRT/VTT 的时间戳行(TIMED_SUBTITLE_PATTERN)与 ASS 的Dialogue:行按规则切分:ASS 在第 9 个逗号后取正文字段,LRC 只把[mm:ss.xx]时间标签之后的内容作为片段。SegmentPart会携带timeStart/timeEnd元数据并在预览表格中展示;翻译结果通过preserveSubtitleMarkup保留开头的 ASS 覆盖代码({...})或行内 HTML 标签(如<i>…</i>)。

归档安全上限

为避免畸形压缩包导致资源耗尽,services/binary.ts 对 ePub/DOCX 设定了三层上限:条目数不超过 4000、单个条目解压后不超过 24 MiB、解压总量不超过 96 MiB(assertArchiveSafety)。超限会停止解析并提示。

批量翻译:队列、暂停与断点续译

文件队列与独立进度

进入工作台后,所有导入的文件会出现在顶部文件队列中。可以随时点击Add files / 添加文件追加文件。每份文件:

  • 独立显示翻译进度(已完成片段数 / 总片段数);
  • 导入或翻译失败不影响其他文件——失败项在队列中标记错误,其余文件继续处理;
  • 未解析成功的文件不会阻塞后续文件(见 DocumentApp.vue 的loadFiles逐文件 try/catch)。

开始批量翻译

确认语言、翻译服务与模型后,点击Translate remaining files / 翻译剩余文件,队列会按顺序处理所有尚未完成的文档。页面会先校验凭据(credentialWarning)与设置一致性,再逐个文档执行翻译(DocumentApp.vue 的startBatch)。

暂停全部与续译

点击Pause all / 暂停全部会通过AbortController中止当前翻译任务,但已完成并提交的片段会保留(translations数组中已写入的译文不回退)。再次开始时:

  • 单文件场景通过initialTranslations把已有译文作为"已完成"片段传入,只翻译剩余空白片段;
  • 批量场景会逐文件继续未完成的部分。

这一行为在 services/translation.ts 的createDocumentSegmentTranslator中体现:pending只取!translations[id].trim()的片段;也由 DocumentApp.vue 的startTranslation(initialTranslations: [...translatedSegments.value])驱动。暂停或单段请求失败后,已完成片段可立即在校订视图中查看。

设置变更需要确认重译

翻译开始时会为当前设置生成"指纹"(currentFingerprint,包含源语言、目标语言、服务、模型、术语库 ID 与修订号)。若之后更改了这些设置,页面会提示"设置已更改。现有译文仍保留,按新设置翻译会从头开始",并要求逐份确认重新翻译(settingsChanged判断 + 确认对话框),避免静默覆盖已校订的译文。批量翻译过程中检测到设置被外部修改也会暂停并提示(DocumentApp.vue)。

批量下载 ZIP

队列停止后,可以点击队列中的任意文件单独阅读、校订或下载。批量导出流程(DocumentApp.vue 的downloadBatch):

  1. 选择输出模式:bilingual(双语对照)或translated(仅译文);
  2. 点击Download completed files (ZIP) / 下载已完成文件(ZIP);
  3. 只有翻译完成的文件会进入压缩包;未完成文件被排除;
  4. 同名文件放入不同编号目录(zip.file(${index + 1}/${name})),避免覆盖;
  5. 下载成功后记录已下载修订号,移除未下载的译文时会弹出确认。

会话隔离与离开保护

文件和译文只保存在当前页面内存中,刷新、关闭页面或打开其他文档前必须下载。页面注册了beforeunload与pagehide监听(DocumentApp.vue):存在未下载译文(editRevision > downloadedRevision)时会拦截关闭并提醒;切换队列文件会先saveActiveDocument()保存当前文件状态,保证切换不丢工作。

翻译与对照阅读

翻译设置与开始

在左侧设置面板依次确认:

  1. 源语言——可选"自动检测"(auto);
  2. 目标语言;
  3. 翻译服务——列表来自可用服务目录;使用 AI 服务(含自定义 OpenAI 兼容服务)时还需确认模型;
  4. 术语库(Glossary)——可继承全局设置、关闭或按需选择术语库,仅当当前服务支持时才可启用。

若服务凭据缺失、模型未配置或服务不可用,面板会显示警告并引导去设置页配置。确认设置后,先在右侧预览原文,再点击Start translation / 开始翻译。

三种阅读方式

预览区提供原文 / 双语 / 译文三种视图切换(previewMode)。没有译文时预览强制停留在原文视图。文本格式(HTML/Markdown/TXT)的预览由 core/preview.ts 的createDocumentPreviewHtml生成:

  • HTML 与 ePub 章节走readerShell沙箱外壳:注入严格的 CSP(default-src 'none'等)并通过stripActiveHtml剥离script/iframe/object/embed/form/base、meta refresh与on*事件属性,防止脚本执行;
  • Markdown 按源行渲染标题、列表、引用、代码围栏与分割线,双语模式逐行配对(pairedUnit);
  • TXT 按段落块配对渲染。

PDF 使用专用连续阅读视图(DocumentApp.vue):逐页渲染原页与译页并排显示,支持 100% / 125% / 150% 缩放;ePub 提供章节导航;DOCX 提供正文/页眉/页脚/脚注/尾注分区;字幕以时间轴表格展示;JSON 以 JSONPath 对照表展示。

长文档的暂停与恢复

较长文档可随时暂停;暂停或请求失败后已完成片段保留,继续翻译时只处理剩余部分。更换语言、服务、模型或术语设置后,需要按新设置重新翻译,页面会先提示(见上文"设置变更")。

底层批量调度机制

翻译编排集中在 services/translation.ts,通过DocumentTranslationGateway端口注入翻译能力(不直接绑定具体 provider)。两个关键机制:

  • 批处理拆分:BATCH_ITEM_LIMIT = 16、BATCH_CHARACTER_LIMIT = 3_500(translation.ts),splitBatches按"最多 16 段且不超过 3500 字符"拆批,单批提交给支持批量的服务;
  • 顺序兜底:不支持批量的服务按每段请求,并发 worker 数Math.min(3, pending.length)(translation.ts)。

任务开始时会固定语言对快照(sourceLanguage/targetLanguage),防止设置页同步更新污染后续批次;每次提交前检查AbortSignal,批量结果会校验长度与空值("翻译服务返回的片段不完整,请重试"),并阻止取消或失败后的迟到提交(stopped标志与提交代次校验)。文档级上下文(buildDocumentContext,截取前 24 段预览、上限 4000 字符)会随每个请求发送,帮助模型保持术语一致。

校订与下载

校订译文

点击工具栏的Edit translation / 校订译文进入校订视图(DocumentSegmentEditor.vue):

  • 支持搜索要修改的句子;
  • 支持筛选尚未翻译的片段;
  • 直接在编辑框中修改译文,修改立即生效并计入editRevision。

校订结果同时应用于预览和下载产物——renderDocument/createDocumentDownload都读取同一个translatedSegments数组,且译文替换的是片段对应的翻译槽位,不会动原文结构。

下载文件

点击Download file / 下载文件,选择双语对照或仅译文,按原文件格式保存。翻译未完成时,可以勾选"我已了解,下载当前结果"确认部分下载;缺少译文的片段保留原文。

导出由 services/binary.ts 的createDocumentDownload统一实现,各格式行为如下:

格式双语产物仅译文产物
PDF原页 + 译页左右并排的整页 PDF(pdf-lib生成)仅含译页图像的 PDF
ePub回写 ZIP 中各章节 XHTML,双语时原段落后追加译文段落替换为纯译文章节
DOCX原段落后追加粉色(#E83B6B)译文段落原位替换<w:t>文本
文本类双语时原文下附译文(HTML 用<span>
  • 前端
  • AI 应用
  • 本地部署

【免费下载链接】FluentRead

An open-source browser extension for bilingual translation. 一款开源的浏览器双语翻译插件。

项目地址:https://gitcode.com/gh_mirrors/fl/FluentRead
点击查看免费下载

相关推荐

上一篇:深入解析 lib/pq:KubeEdge 项目中使用的纯 Go PostgreSQL 驱动
下一篇:终极指南:如何在Windows上零重启实现键盘鼠标游戏手柄全面映射

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询