字
字节笔记本
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 逻辑)
- GitHub: https://github.com/immersive-translate/old-immersive-translate
- 说明: 早期开源版本,核心 JS 逻辑完整可读,包含 DOM 遍历和双语插入的最佳实践
flutter_browser_app(浏览器壳)
- GitHub: https://github.com/pichillilorenzo/flutter_browser_app
- 说明: 基于 flutter_inappwebview 的完整浏览器 App,包含多标签页、地址栏等完整功能
Userscripts(iOS Safari 扩展)
- GitHub: https://github.com/quoid/userscripts
- 说明: Safari 开源扩展,支持 JS 脚本注入,可控制注入时机
开发路径建议
基于现有开源项目,最合理的开发路径:
- fork flutter_browser_app 作为浏览器壳基础
- 从 old-immersive-translate 提取核心 JS 逻辑
- DOM 遍历
- 双语插入
- MutationObserver 处理
- 通过 flutter_inappwebview 的 UserScript 机制注入 JS
- 翻译 API 请求通过 Dart 层转发处理
这三个仓库组合,基本等于 80% 的工作量已经有现成代码可参考,只需要做胶水层和 UI 定制。
关键难点
| 难点 | 说明 |
|---|---|
| JSBridge 设计 | 是否稳定可靠 |
| 文本识别准确性 | 避免翻译导航栏、按钮等非正文内容 |
| MutationObserver 处理 | 动态页面的完善支持 |
| 跨平台兼容 | iOS 和 Android WebView 行为差异 |
总结
沉浸式翻译类应用的技术本质并不复杂,核心在于:
- 选择合适的浏览器壳(系统 WebView)
- 设计稳定的 JSBridge 通信机制
- 精准的 DOM 文本识别和双语插入
- 完善的动态内容处理
站在开源项目的肩膀上,可以快速实现类似功能。
分享: