ByteNoteByteNote

字节笔记本

2026年2月21日

沉浸式翻译类应用实现原理剖析

API中转
¥120

本文解析沉浸式翻译类应用的技术实现原理,帮助开发者理解双语对照翻译软件的工作机制。

沉浸式翻译的核心体验

沉浸式翻译的核心价值:

  • 双语对照显示 - 原文和译文同时展示
  • 原文保留 - 不替换原页面内容
  • 段落级翻译 - 按自然段落划分,而非整页翻译

技术原理拆解

第一层:浏览器壳的选择

商业软件在移动端几乎不会自己写渲染引擎,全都是套系统 WebView:

Android: Android System WebView(Chromium 内核)

  • 由系统维护更新
  • App 本身不需要打包内核
  • 安装包体积小

iOS: WKWebView(WebKit 内核)

  • 苹果强制规定
  • 所有第三方浏览器必须使用 WKWebView
  • 不允许用自己的 JS 引擎

第二层:JS 注入机制

实现用户脚本注入的两种方式:

方式一:页面加载时注入

在 WebView 的 onPageFinished 回调触发后,调用 evaluateJavascript() 把脚本塞进去。

  • 优点: 实现简单
  • 缺点: 时机稍晚,用户会看到页面先加载出来再变化

方式二:提前注入(更专业)

通过 addUserScript 在页面 DOM 构建之前就把脚本注册进去。

  • iOS: WKWebView 原生支持
  • Android: 需要拦截 shouldInterceptRequest 来实现类似效果
  • 优点: 页面一开始解析就带着脚本跑,用户无感知

第三层:翻译 API 的调用

这是商业软件和简单实现之间最大的差距所在。

问题

直接在 WebView 里的 JS 调用翻译 API 会遇到 CORS 跨域限制,大部分翻译服务不允许跨域请求。

解决方案

text
JS 脚本(提取文本)
    ↓
postMessage / JSBridge
    ↓
原生层(Java/Kotlin 或 Swift/ObjC)
    ↓
HTTP 请求调用翻译 API(无跨域问题)
    ↓
回调传回 JS
    ↓
JS 把译文插入 DOM

优势:

  • API 密钥完全在原生层,安全
  • 不受跨域限制
  • 可以统一处理错误和重试

第四层:双语对照的 DOM 操作

沉浸式翻译的精髓所在:

javascript
// 1. 遍历页面所有文本节点
// 2. 识别段落级别的块元素(p、li、td、div 等)
// 3. 提取 innerText
// 4. 翻译完成后在原节点下方插入新 DOM 节点
// 5. 写入译文,加上特定 CSS class 控制样式
// 6. 原文保持不动

样式控制:

  • 字体颜色(通常译文用灰色)
  • 字体大小
  • 行距
  • 段落间距

动态内容处理:

javascript
// 挂载 MutationObserver 监听 DOM 变化
const observer = new MutationObserver((mutations) => {
  mutations.forEach((mutation) => {
    // 对新节点重复翻译流程
  });
});

observer.observe(document.body, {
  childList: true,
  subtree: true
});

第五层:性能优化

商业软件的关键优化策略:

1. 文本分批处理

不会把整个页面所有文本一次性发给 API:

  • 按视口优先
  • 先翻译用户当前看到的区域
  • 滚动时再翻译下方内容

2. 请求合并

  • 把多个短段落合并成一个 API 请求
  • 减少请求次数
  • 降低延迟和费用

3. 缓存机制

  • 翻译过的段落结果缓存到本地
  • 刷新页面或二次访问时直接用缓存
  • 不再重复请求

整体架构图

text
用户访问网页
     |
     v
原生浏览器壳(系统 WebView)
     |
     |--- 页面加载 ---> 注入翻译 JS 脚本
                              |
                              v
                        DOM 遍历,提取文本段落
                              |
                              v
                        JSBridge 发消息给原生层
                              |
                              v
                        原生层调用翻译 API
                              |
                              v
                        结果回传给 JS
                              |
                              v
                        在原文下方插入译文节点
                              |
                              v
                        MutationObserver 监听新内容

开源参考项目

沉浸式翻译旧版(核心 JS 逻辑)

flutter_browser_app(浏览器壳)

Userscripts(iOS Safari 扩展)

开发路径建议

基于现有开源项目,最合理的开发路径:

  1. fork flutter_browser_app 作为浏览器壳基础
  2. 从 old-immersive-translate 提取核心 JS 逻辑
    • DOM 遍历
    • 双语插入
    • MutationObserver 处理
  3. 通过 flutter_inappwebview 的 UserScript 机制注入 JS
  4. 翻译 API 请求通过 Dart 层转发处理

这三个仓库组合,基本等于 80% 的工作量已经有现成代码可参考,只需要做胶水层和 UI 定制。

关键难点

难点说明
JSBridge 设计是否稳定可靠
文本识别准确性避免翻译导航栏、按钮等非正文内容
MutationObserver 处理动态页面的完善支持
跨平台兼容iOS 和 Android WebView 行为差异

总结

沉浸式翻译类应用的技术本质并不复杂,核心在于:

  1. 选择合适的浏览器壳(系统 WebView)
  2. 设计稳定的 JSBridge 通信机制
  3. 精准的 DOM 文本识别和双语插入
  4. 完善的动态内容处理

站在开源项目的肩膀上,可以快速实现类似功能。

分享: