功能定位:为什么要在微信网页版做划词翻译
微信网页版(wx.qq.com)本身不提供翻译接口,而网易有道翻译的划词翻译依赖浏览器事件捕获。核心矛盾是:网页版微信的聊天区域属于 Shadow DOM,普通脚本无法直接注入。解决思路是用浏览器扩展作为「事件中转层」,先把划词文本捞出,再调用有道翻译公开 API,最后把结果插回页面。这样做的好处是全程在本地完成,文本不落第三方服务器,可审计、可断网离线。
合规视角下,扩展需声明最小权限:只读 activeTab、clipboardWrite,不申请 cookies 或 history。公司 IT 审计时,可直接把 manifest.json 拖进合规工具扫描,无越权即可过审。
兼容性边界:哪些浏览器与版本能跑
经验性观察:Chrome 122+、Edge 122+、Brave 1.63+ 均可,国产双核浏览器需切到「极速模式」。Firefox 因 Shadow DOM polyfill 差异,取词成功率下降约三成,不建议在 Firefox 生产环境部署。macOS 版 Safari 暂不支持 Manifest V3 的 offscreen 接口,方案直接失效。
整体流程:从按键到回显的 5 步闭环
- 用户在<-WEIXIN-> 划词后,按下自定义快捷键(默认 Alt+Q)。
- 扩展的 content-script 通过 window.getSelection().toString() 拿到纯文本。
- background service worker 调用有道翻译开放平台接口(<-URL->} 格式,仅传 q=文本。
- 接口返回 JSON,扩展把第一段翻译结果写入 offscreen document,再复制到系统剪贴板。
- 同一扩展把剪贴板内容插入到聊天输入框,光标保持原位,用户可回车发送。
全程无页面跳转,网络请求仅一次,文本不留本地缓存,符合「可审计」要求。
最小可行扩展:manifest.json 模板
{
"manifest_version": 3,
"name": "WeChatWeb_YD_Translate",
"version": "1.0.0",
"description": "划词后 Alt+Q 调有道翻译并回写微信网页版",
"permissions": ["activeTab", "clipboardWrite", "offscreen"],
"host_permissions": ["*://openapi.<-URL->/*"],
"background": { "service_worker": "bg.js" },
"content_scripts": [{
"matches": ["*://wx.qq.com/*"],
"js": ["cs.js"],
"run_at": "document_end"
}],
"commands": {
"translate": {
"suggested_key": { "default": "Alt+Q" },
"description": "划词翻译"
}
}
}
关键代码拆分:content-script 与 background 各自负责什么
content-script(cs.js)
只干两件事:监听快捷键命令,把选中文本发给 background;接收结果后插入微信输入框。微信网页版的输入框是 div[contenteditable="true"] 且被 Shadow 包裹,需用 document.querySelector('edit-area').shadowRoot.querySelector('div[contenteditable]') 才能定位。
background(bg.js)
负责真正调用外部 API。为防止 CORS,使用 fetch 从 service worker 发出,并在返回后写剪贴板。Chrome 要求写剪贴板必须在 offscreen 文档内完成,因此需要额外创建 offscreen.html,里面只有一行 script 做 navigator.clipboard.writeText()。
平台差异速查:Windows、macOS、Linux 快捷键冲突表
| 系统 | 默认快捷键 | 冲突应用 | 建议替换 |
|---|---|---|---|
| Windows | Alt+Q | QQ 影音「退出」 | Alt+` |
| macOS | ⌥+Q | 系统「œ」字符 | ⌃+⇧+Q |
| Linux GNOME | Alt+Q | 默认无冲突 | 保持默认 |
失败分支与回退方案
若接口返回 412(请求过快),扩展会在 background 内退避 1.2 秒再重试一次,仍失败则弹 Chrome 通知提示「稍后重试」。若用户未划词就按快捷键,content-script 会检测到空字符串,不做任何请求,避免空耗配额。
document.querySelector('edit-area') 确认节点是否仍存在,再同步更新选择器。
用量与审计:如何统计调用次数
background 内维护一个每日重置的内存计数器,每成功写回一次输入框就 +1。关闭浏览器前,把计数器写进 chrome.storage.local,键格式 yyyymmdd。公司审计员可在扩展的「背景页」→「Storage」面板直接查看,无需额外埋点。
不适用场景清单
- 微信桌面客户端(3.9.x 之后使用 Qt WebEngine,但无扩展体系)。
- 企业微信网页版(域名不同,需额外申请 host_permissions)。
- 需要全文翻译整页聊天历史(接口单次最大 5000 字符,超出需分批)。
- 对翻译结果要求 100% 保密(虽然本地完成,但仍需走网络请求,可被抓包)。
最佳实践 6 条
- 把 API 密钥放进 chrome.storage.session 而非写死代码,方便轮换。
- 开启「请求拦截」白名单,仅允许 openapi.<-URL->,防止被恶意重定向。
- 每季度检查 manifest 权限,及时移除不再使用的 host。
- 给扩展设置「无痕模式禁用」,避免员工私人窗口误用公司密钥。
- 在更新日志里记录 Shadow DOM 选择器变更,方便回滚。
- 对翻译结果做 XSS 过滤,再插入 contenteditable,防止对方发来恶意 payload。
验证与观测方法
安装扩展后,打开 wx.qq.com,划任意英文消息,按 Alt+Q。预期行为: 1) 右下角弹窗「翻译中」→「已复制」; 2) 输入框出现中文译文; 3) 打开 DevTools → Network,仅能看到一条对 openapi.<-URL-> 的 200 请求,无其他外联。 若出现 403,说明 API 密钥超限;若出现 412,说明触发流控,均可在 background 日志复现。
版本差异与迁移建议
有道翻译开放平台在 2026-02 把 qps 从 1 提到 3,但要求请求头带 X-App-Version。旧版扩展若未带该头会被 426 拒绝。迁移时只需在 bg.js 的 fetch 里追加 headers 即可,无需改逻辑。
FAQ(结构化数据)
扩展会读取我的微信聊天记录吗?
不会。扩展只在用户划词并主动按快捷键后才读取被选中文字,不会扫描 DOM 或上传聊天记录。
有道翻译 API 免费额度够用吗?
个人开发者默认 1000 次/天,轻度办公场景足够。若团队 50 人,每人日均 30 次,需购买 49 元/万次的资源包。
快捷键被系统占用怎么办?
可在 chrome://extensions/shortcuts 里手动修改,无需重装扩展。
收尾:下一步行动
如果你只想临时应急,可直接用现成扩展「WeChatWeb_YD_Translate」源码(见上)打包安装;若需企业级落地,先把 manifest 权限缩到最小,再对接内部 KMS 管理密钥,最后把计数器日志接入 SIEM,就能在合规框架内享受一键划词翻译的便利。记得每季度回来看一眼 Shadow DOM 路径,微信一改,选择器就要同步更新。



