你可以说我有点轴:别人遇到系统不好用,第一反应是找个替代品,我的第一反应是“那我给它写一个”。SnapLingo 就是这么来的——一个 Windows 上的全局翻译软件,只做三件事:划词翻译、截图翻译、剪贴板翻译,外加一个随时能被快捷键叫出来的悬浮面板。名字拆开看很直白:Snap 是快速抓取,Lingo 是语言,合起来就是“把屏幕上任意一段语言快速抓下来翻成另一种”。
做它的原因其实不复杂:我在 Windows 上处理外文资料有六七年了,一直没找到一个真正顺手、开机就在、不折腾的桌面翻译工具,于是决定自己做。如果你跟我一样,每天要跟英文技术文档、外文产品需求、多语言聊天记录打交道,又总觉得现有方案差一口气,这篇内容值得看完。我会把为什么偏偏在 Windows 上做、核心交互和选型的取舍、以及开发中踩过的几个代表性坑,原原本本摊开讲。
1. 为什么偏偏是 Windows:Mac 上长出来的好东西,Windows 用户一直缺
1.1 Windows 不是没有翻译,是缺“系统级顺手”的翻译
说句公道话,Windows 上的翻译入口并不少:Edge 浏览器右键就能翻译整页,Microsoft Office 自带翻译功能,各种翻译网站、浏览器插件更是数不过来。但这些方案都卡在同一个地方——它们只活在某个应用内部。你在 Edge 里看英文网页是舒服的,可一旦切到记事本、PDF 阅读器、IDE、聊天窗口,翻译能力就立刻断掉了。系统层面没有一个“当前光标在哪,翻译就跟到哪”的常驻能力。
对比之下,macOS 生态里早就有 Bob、Easydict 这类开源的全局翻译工具:选中文本按个键就出结果、截图划区就 OCR、剪贴板一变就翻好。Windows 这边不是没人想做,而是这个生态位一直空着。商业软件普遍偏向文档翻译、字幕翻译这种重场景,对这种“随手选中一段就翻一下”的轻交互看不上;开源社区也鲜有人愿意为一个常驻托盘程序去磨全局快捷键、剪贴板监听、DPI 适配这些底层细节。市场不大,需求又是刚性的,那就只能自己动手。
我不是说 Windows 平台不好,恰恰相反,Windows 的开放性是它能做这件事的前提。Win32 API 提供了全局钩子、剪贴板监听、UI Automation 这些完整的能力,只是没人把它们组合成一个体面的工具。
1.2 我的高频场景:每天有几十段外文要处理
我自己的使用场景其实非常具体。白天的工作大量涉及研读 IETF 文档和英文技术博客,GitHub 上的长 issue 和 PR 讨论经常是几十条英文来回;傍晚可能要处理海外同事的邮件和消息,里面的语气、术语需要仔细看;偶尔还要读游戏更新日志、外区产品文档。这些场景的共同点是:内容不是连续的整页文档,而是一段一段散落在各种界面里的小文本。
以前我的工作流是:选中文字 → Ctrl+C → 切到浏览器 → 粘贴到翻译页面 → 复制结果 → 切回原窗口。粗算一下,单次操作大约 8 到 15 秒。一天处理三五十段外文,就是十分钟到二十分钟的纯浪费,更致命的是频繁切窗口会打断心流。翻译完切回来看代码,经常要想“我刚看到哪一行”,这种注意力损失比时间损失贵得多。
所以我对工具的核心诉求不是“翻得有多准”,而是“从产生翻译念头到看见译文,中间不要超过三步”。这个诉求听起来简单,真正做好却牵扯到一堆 Windows 桌面开发的细节,这也是我写 SnapLingo 的原始动力。
1.3 需求收敛:三个动作,砍掉所有花活
立项的时候我给自己定的原则是:目标用户只有我自己,不搞大而全。于是把所有可能的翻译功能梳理了一遍,只留下了三个动作:
- 划词翻译:鼠标选中一段文字,立刻触发翻译;
- 截图翻译:框选屏幕区域,OCR 识别后翻译;
- 剪贴板翻译:用户复制了一段内容,屏幕角落自动出现译文卡片;
再加一个普适入口:全局快捷键呼出主面板,可以手动输入或粘贴任意文本。
这之外的所有东西,第一版全部砍掉:语音朗读、多引擎对照、术语管理、整篇文档翻译,统统不做。原因很简单,这些功能能提升“上限”,但对日常的“下限”没有帮助。软件最先要解决的问题是让用户以最低成本得到译文,其他都是锦上添花。等你每天要用五十次的时候会发现,稳定地 1 秒出结果,比能翻 50 种语言重要得多。
2. SnapLingo 的交互模型:最好的状态是“工具不存在”
2.1 常驻托盘 + 随时可呼出的悬浮窗
大多数时候 SnapLingo 是不存在的。主窗口平时根本不显示,程序只在系统托盘留一个小图标,内存和 CPU 占用趋近于零。用户通过全局快捷键或触发动作叫出翻译结果,结果以一张无边框半透明卡片的形式悬浮在屏幕边缘,展示几秒后自动淡出。
这里有个关键细节:悬浮窗绝对不能抢焦点。Windows 上很多弹窗工具做得让人难受,就是因为它一弹出来就把输入焦点从当前窗口抢走了,用户正在打字会被打断,正在玩游戏会被切出去。我的做法是给窗口设置WS_EX_NOACTIVATE和WS_EX_TOOLWINDOW两个扩展样式,前者保证它弹出来时不会激活自己、不抢焦点,后者保证它不进入 Alt+Tab 切换列表。再加上窗体的ShowActivated=false,这样即使用户正在飞快打字,翻译卡片也只会安静地出现在角落,不会打扰任何输入过程。
这个逻辑用一句话总结:好的全局翻译工具应该像外卖闪送,敲门递货就走,而不是闯进你家里坐下聊天。用户最舒服的状态是压根感觉不到这个工具存在,只在需要的瞬间看见结果。
2.2 划词、截图、剪贴板三种触发方式怎么落地
三种触发的实现语义完全不一样,做得顺不顺手直接决定工具成败。
划词翻译听起来简单,实际上是整个项目里最复杂的一个功能。Windows 下“获取用户选中的文本”这件事并不统一,不同应用支持不同的机制:有的能通过 UI Automation 拿到选中内容,有的只能靠模拟 Ctrl+C 去读剪贴板,有的什么都不支持。我把这部分单列到第 3 节展开讲,因为它值得单独说。
截图翻译相对标准。用户按下快捷键后进入全屏遮罩模式,鼠标拖拽框选区域,框选确定后立刻执行 OCR 和翻译。框选交互要做得跟主流截图工具一致:ESC 取消、空格键拖动选区、滚轮微调范围。这里容易忽略的是框选结束后不要立刻翻译,而是先给用户一个短暂的确认期——否则手滑框错区域就直接出结果,体验会非常差。
剪贴板翻译的实现也很有讲究。它不能简单地在程序里循环读取剪贴板,因为剪贴板是被多进程共享的资源,如果你长期占用锁,其他程序的复制操作就会被卡住。我用的是AddClipboardFormatListener订阅系统剪贴板更新通知,收到WM_CLIPBOARDUPDATE消息后延迟 150 毫秒再去读数据。延迟是为了避免剪贴板内容还在写入时读到半截数据。读了之后还要做去重:如果新内容和上次内容一模一样,就不重复翻译。
剪贴板翻译还有个进阶配置:可以按应用进程名决定是否触发。比如用户在 IDEA 里复制代码时不希望弹翻译卡片,在浏览器里复制英文希望立刻翻译,这种规则在设置面板里加一个应用名单列表就能解决。
2.3 历史记录:一个容易被小看的核心功能
很多同类工具把翻译结果一闪而过当成设计理所当然,但真实使用中“刚才那个译文是什么来着”是高频需求。我坚持把历史记录做成一级功能而不是附属功能,所有翻译结果都会本地落盘,按原文、译文、来源类型、应用进程名、时间戳结构化存储。用户通过快捷键打开历史面板,可以按关键词检索过去的翻译记录。
这个设计在初期还被朋友吐槽“功能太小家子气”,但实际用起来价值非常大。历史记录天然形成一本个人的高频术语手册:比如你在做一个数据库项目,过去一个月反复翻译“sharding”“replica”“transaction isolation”这些词,翻看历史就能整理出自己常用的译法。后来我又加了收藏功能,用户可以手动修正某条译文并收藏,之后再次遇到完全相同的原文时,直接优先返回收藏版本。这其实就是个人术语表的雏形,不需要任何外部的术语服务也能积累出贴合自己工作领域的翻译资产。
另一个贴心细节是“翻译结果自动放回剪贴板”。当用户通过划词触发翻译时,原文在用户剪贴板里还是选中状态;翻译完成后程序把译文写入剪贴板,用户只需要多按一次 Ctrl+V 就能把译文粘贴到当前位置。整个过程只比原先多点了一次粘贴键,但省去了“切到翻译面板 → 复制结果 → 切回来”的三步操作。
3. 技术选型:OCR、翻译引擎和桌面壳子的取舍
3.1 桌面壳:为什么最后选了 WPF 而不是 WinUI 3 或 Tauri
框架选择我犹豫了挺久,候选包括 WPF、WinUI 3、Electron、Tauri。先说结论:我选了 WPF,理由可能和大家预想的不一样。
Electron 首先被排除。翻译工具要常驻后台,Chromium 内核跑起来动辄一两百兆内存,而且悬浮窗、全局快捷键、系统剪贴板交互这些能力都得绕一圈去调原生 API,体验并不省事。Tauri 的 Web 前端体验确实好,但关键问题在于窗口透明和异形窗的支持:要做到低延迟、无边框、半透明、不抢焦点的悬浮卡片,最终还是要直接调 Win32 层,绕路成本并不低。
WinUI 3 我很想用,它是 Windows 的未来,但是现阶段对单人维护的小工具不够友好。多显示器 DPI 适配、不同 Windows 版本下的行为差异,这些坑在 WinUI 3 上遇到了就要花一个晚上查 issue,而且组件生态和第三方库远不如 WPF 成熟。对一个常驻型工具来说,稳定性和可排查性比界面新潮重要得多。
WPF 胜在“老而稳”:XAML 写界面快,Win32 Interop 的例子一搜一大把,遇到问题几乎都能找到答案。性能和资源占用对它来说完全不是瓶颈,一个翻译卡片而已,不需要多强的渲染能力。这算是约束条件下的最优解:常驻 + 悬浮 + 深度系统集成 + 单人维护,WPF 是投入产出比最高的选择,而不是技术情怀的选择。
3.2 OCR 三选一:系统 OCR、Tesseract 还是 PaddleOCR
截图翻译的核心是 OCR,我对比了三个方案:Windows 系统自带的Windows.Media.Ocr、开源的 Tesseract、百度的 PaddleOCR。
Windows.Media.Ocr是 Win10 1809 之后系统内置的 OCR 引擎,支持几十种语言包,完全离线运行。在 WPF 里使用时需要借助 C#/WinRT 桥接(CsWinRT)去调 WinRT API,多了一层技术成本,但换来的是零模型体积、零授权成本、识别速度快。实测一张 600x300 像素的干净截图,CPU 识别耗时大约 80 到 150 毫秒,这个延迟对交互来说是足够理想的。
Tesseract 虽然免费开源,但中文识别准确率明显差一档,对加粗、斜体、图文混排、表格的鲁棒性都不足。PaddleOCR 的中文准确率是三者里最好的,PP-OCRv4 模型在 CPU 上也能跑进 200 毫秒,但代价是模型文件体积几十兆起步,而且部署链路复杂,对普通用户不友好。
我的取舍是第一版直接用系统 OCR,把复杂度藏起来;PaddleOCR 离线模型作为 v2 的高阶选项。实际操作中我总结出一个重要经验:OCR 前如果先把截图放大到 200% 再做灰度化和背景降噪,小字号文字的识别效果会天差地别。OCR 这个环节,预处理管线比引擎本身更影响最终体验。
3.3 翻译引擎:免费额度、付费 API 与本地缓存的三层架构
翻译引擎层我设计成了可插拔的多 Provider 架构。先用一个统一接口定义“翻译一个字符串”的语义,百度、腾讯、有道、DeepL 各自实现这个接口。请求发出时带 8 秒超时,如果某个 Provider 超时或返回异常,自动切换到下一个可用 Provider。用户可以在设置里填自己的 API Key,也可以切换默认引擎。
免费层我用过百度通用版标准版、有道智云、腾讯机器翻译的免费额度,个人使用基本够,但 QPS 限制低、偶尔会抽风。付费层主要是百度高级版、腾讯云和 DeepL API,DeepL 的翻译质量在长难句和专业术语上明显好,但它是按字符计费的,不适合免费开放给所有用户,所以默认不挂,用户填了自己的 Key 才激活。
架构之上我还加了一层本地缓存:对同一段文本,24 小时内的翻译结果直接命中缓存,不再发网络请求。这个设计一开始是出于省钱考虑,后来发现它大幅改善了体验——程序员看 GitHub 上多个 PR 讨论同一个模块时,大量重复句子会被瞬间命中,真正做到“秒出结果”而不是“接近一秒出结果”。隐私方面我也做了约束:所有请求走 HTTPS,原文和译文只在上文提到的 SQLite 里存一份文本,截图只在内存中处理,翻译完就释放,不落任何缓存图片。
3.4 划词的隐藏难点:Windows 的“选中文本”并不统一
划词翻译能难到什么程度?Windows 里“获取当前选中的文本”至少有三条完全不同的路,而且没有任何一条能覆盖所有程序。
第一条路是 UI Automation。通过System.Windows.Automation找到焦点元素,再尝试获取TextPattern的GetSelection()。这条路不碰剪贴板、不抢焦点、不需要用户额外操作,体验最优雅。但问题是支持情况参差不齐:记事本、Office、浏览器大部分时候可以,终端模拟器、远程桌面里的程序、某些自绘 UI 的软件就完全拿不到。
第二条路是模拟 Ctrl+C。用SendInput向前台窗口发送复制命令,然后读取剪贴板内容。这条路的兼容面广,几乎所有能选中的文本都能复制到,但副作用是它会真实地动用户的剪贴板。所以程序在复制前必须先保存当前剪贴板内容,读完再恢复,而且整个过程要小心加锁,避免和用户的复制操作并发冲突。更麻烦的是安全机制:如果目标窗口是以管理员权限运行,普通权限进程模拟的按键会被系统拦截,这条路直接失效。
第三条路是“悬浮按钮”。在检测到鼠标完成一次选区动作后,不立刻解析文本,而是在选区附近弹出一个小工具条,用户主动点击才去获取数据。这样最安全、最不越权,但多了一次点击,交互效率打折扣。
我的最终策略是三条路共存:优先走 UIA,失败后在下一个小工具条上提示“当前窗口无法读取选中内容”,用户可以点击让它走模拟 Ctrl+C 的兜底路径,也可以直接用截图翻译。原则就是“宁可多一步,不可打断用户”。选区的检测也不能做得太激进,我只在鼠标松开且判断可能产生文本选区时才触发判断,而不是拦截每一次点击事件去分析,否则 CPU 和干扰成本都太高。
4. 开发中踩过的坑:四个让我想砸键盘的问题
4.1 坑一:多显示器 + 不同 DPI,截图坐标全歪
第一个大坑出现在截图翻译的多显示器支持上。我的工作环境是 4K 主屏开 150% 缩放,副屏是 1080P 保持 100% 缩放。第一版截图翻译在副屏上框选时,识别内容总是和框选区域错位,有时候差一截,有时候完全指向另一块屏幕。
排查过程让我意识到问题的根子在“坐标系”上。WPF 里拿到的鼠标坐标默认是设备无关单位(DIP),而截图时用的CopyFromScreen等 Win32 API 需要的是物理像素。单屏环境下两者只差一个固定缩放系数,乘一下就行;多屏下每块屏幕的缩放比不一样,用一个全局系数去换算必然错位。
我的修复办法是封装了一个坐标换算类:先通过MonitorFromPoint找到鼠标所在的屏幕,再用GetDpiForMonitor获取该屏幕的实际 DPI,然后才做 DIP 到物理像素的换算。
// WPF 的 DIP 坐标换算成物理像素 var dpi = GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, out var dpiX, out var dpiY); double scaleX = dpiX / 96.0; double scaleY = dpiY / 96.0; int physX = (int)(dipX * scaleX); int physY = (int)(dipY * scaleY);同时监听WM_DPICHANGED消息,当屏幕分辨率或缩放比例变化时重新计算所有窗口布局。这件事给我的教训是:任何涉及截图的桌面工具,第一节课都是坐标系分离。只能用物理像素去截屏,只能用英寸换算后的比例去布局,两者之间的转换代码必须集中在一处,别散落在项目里到处乘 1.5 这种魔法数。
4.2 坑二:OCR 出来的文本顺序和人类阅读顺序不一样
第二个坑是 OCR 结果顺序混乱。Windows.Media.Ocr 返回的是一个按引擎识别顺序排列的 Line 集合,注意是“引擎识别顺序”,不是“人类阅读顺序”。遇到双栏 PDF 的时候,引擎可能先读右栏再读左栏;遇到图文混排的页面,正文行中间会夹着图注和小标题,翻译出来句子顺序完全是乱的。
我第一次遇到时以为是 OCR 引擎坏了,后来把每条 Line 的 BoundingRect 坐标打印出来,才看懂是排序策略的问题。修复方式是写了一个智能排序器:先把所有文本行的中心 X 坐标做聚类,聚成几类就代表有几栏;然后按栏从左到右排列,栏内再按 Y 从上到下、同 Y 按 X 从左到右排序。
这个排序器后来成为整个项目里复用价值最高的组件之一,PDF 页面识别、网页长截图识别都依赖它。对非常规排版,比如表格、代码块,我加了“保持引擎原始顺序”的开关让用户手动切换。踩了这个坑之后我才明白,OCR 翻译的难点从来不只是“认字”,而是“理解版面”。
4.3 坑三:全局快捷键被输入法和别的软件“借走”
我把全局快捷键默认设成了 Ctrl+Alt+T,结果装上某输入法之后频繁失灵,偶尔还会弹出输入法自带的剪贴板历史。排查后发现了两个独立问题。
第一,RegisterHotKey虽然注册成功,但WM_HOTKEY消息并没有被 WPF 主窗口收到。原因在于 WPF 的窗口消息处理需要手动通过HwndSource挂接消息过滤钩子,不能只靠注册 API 不管接收端。这件事其实不难解决,但很容易被忽略,我建了一张“Win32 消息与 WPF 对应处理方式”的对照表,之后凡是遇到 WPF 包不住的窗口消息,都统一进HwndSource的 hook 处理。
第二,Ctrl+Alt 这类组合键和输入法、系统热键冲突太常见了。仅仅换一个键并不能解决问题,最终方案是把快捷键全部交给用户自定义,注册时加上MOD_NOREPEAT标志避免按住时连续触发,注册失败时读取GetLastError,如果是 1409 就直接提示“该组合已被其他程序占用”而不是静默失败。
剪贴板监听也在这里联动踩了个类似的坑。用AddClipboardFormatListener时,必须把监听窗口的句柄和WM_CLIPBOARDUPDATE消息一起挂到HwndSource上,否则消息到了却无处处理。更稳妥的备用方案是轮询GetClipboardSequenceNumber,发现序号变化后稍微等 300 毫秒再读内容,这样能避免和用户正在进行的复制操作产生并发冲突。
4.4 坑四:UIA 拿不到管理员窗口和自绘程序的内容
第四个坑特别隐蔽。有开发者朋友反馈:Chrome 或者 VS Code 用“以管理员身份运行”打开后,SnapLingo 的划词解析竟然是空的。最开始我以为是 UIA 兼容性问题,后来用 UI Inspect 工具反复测试才发现,这不是软件 bug,而是 Windows 的安全机制在起作用——用户界面特权隔离(UIPI)会阻止普通权限进程对高权限窗口执行 UIA 访问和模拟按键。
开发环境的用户特别容易踩这个坑,因为大家经常顺手把 IDE 或终端以管理员身份打开。你要么也让自己的工具提权运行(这是一个很重的决定,对常驻工具来说会引入不可接受的安全风险),要么就只能优雅地降级。
第一版我选择的是产品层面降级:检测到前台窗口是管理员权限时,划词解析直接提示“当前窗口为管理员权限,请使用截图翻译或手动复制”。虽然多了一步,但至少用户明确知道发生了什么,不会以为软件坏了。对 UIA 完全拿不到内容的自绘程序,比如某些游戏引擎和特定聊天软件,就退回到模拟 Ctrl+C 的路径,但执行前要检查前台窗口所在进程的完整性级别,明确自己“惹不惹得起”。
这个坑也让我想明白一件事:桌面工具的很多“疑难杂症”,真正原因是 Windows 的安全模型,不是你的代码写得有问题。遇到这种情况,先确认是不是权限隔离,能绕就绕,不能绕就诚实告诉用户,而不是让用户面对一个“点了没反应”的玄学问题。
5. 实测数据:SnapLingo 把单次翻译成本降到了什么程度
5.1 三种场景的耗时对比
我用具体数据来回答“这个东西到底值不值得做”。测试环境是 i5-12400 + 16GB 内存,网络环境为普通宽带,同一段 200 词左右的英文技术文档,多次实测取中位数:
| 场景 | 手动方案耗时 | SnapLingo 耗时 | 主要耗时构成 |
|---|---|---|---|
| 选中一段英文划词翻译 | 8~12 秒 | 约 1.2 秒 | UIA 取词 0.2s + 翻译 API 0.8s + UI 展示 0.2s |
| PDF 扫描页截图翻译 | 15~25 秒 | 约 1.8 秒 | 框选 1s + OCR 0.15s + 翻译 API 0.8s |
| 聊天窗口复制英文自动翻译 | 8 秒左右 | 约 0.9 秒 | 剪贴板监听 0.15s + API 0.7s |
数据里最直观的一点是:三种场景下 SnapLingo 都把单次操作压缩到了 2 秒以内,而且这里的“2 秒”包含了用户主动框选的时间。翻译本身在网络通畅时基本稳定在 0.8 到 1.5 秒,这已经是考虑到免费 API 的合理水平。
延迟链路里最不可控的是翻译 API 的网络往返。所以我在本地缓存命中时能做到 0.3 秒内直接出结果。如果你用的是 DeepL API,质量会好一点,但延迟通常多 100 到 200 毫秒,这在交互上几乎感知不到。
5.2 识别与翻译准确率:哪些场景能用,哪些别指望
识别准确率方面,Windows.Media.Ocr 在干净的扫描件上英文接近 99%,中文印刷体大约 95% 以上,但手写体基本不要指望。放大预处理后的低分辨率小字也有明显提升,这部分经验我在第 3 节已经提过。
翻译质量这块我必须说公道话:百度、腾讯这类通用翻译在“英文→中文”的日常表达上完全够用,但长难句偶尔会有语序问题,专业术语和领域黑话时不时翻得离谱。比如 Rust 所有权相关的句子,DeepL 明显更好,但慢一点点。这就是为什么我把 Provider 做成可切换而不是锁死一家。
更重要的是,我加入了“原文对照 + 收藏校正”机制。遇到翻得不好的句子,用户可以手动编辑译文并收藏,之后再次遇到完全相同的原文时,程序直接返回收藏版本。这个机制和术语表雏形本质上是一回事,用得越久越准,这也是历史记录功能的价值延伸。
5.3 资源占用和七天挂机稳定性
资源占用方面,程序空闲时内存 110 到 130MB(包含 WPF 运行时和 OCR 引擎初始化后的常驻部分),CPU 基本为零。截图 OCR 高峰瞬间 CPU 会涨到 1% 到 5%,但持续过程不到 0.5 秒,对前台工作毫无感知影响。
稳定性方面,我做过一次七天连续挂机测试,期间没有明显的内存泄漏,主要风险出现在剪贴板监听的句柄管理上。每次收到剪贴板更新通知去OpenClipboard读取时,一定要在finally代码块里CloseClipboard。这个细节如果漏了,轻则句柄堆积,重则直接导致其他程序(包括 Excel、某些文档编辑器)复制失败,这是一个会让用户在朋友圈骂你的 bug。
启动到托盘可用的时间大约 2 秒,从托盘唤起悬浮窗到可以交互在 150 毫秒内。对常驻工具来说,这个启动速度基本可以做到用户无感知。
6. 几个当初没想明白、后来才想明白的事
6.1 免费接口不是零成本,而是不可控成本
项目初期我心态很轻松:反正有免费额度,翻译不花钱。用了一段时间才发现,免费接口的真正成本是“不可控”。免费额度低的时段请求会被排队,QPS 容易被瞬间打满,某家服务偶尔升级维护就直接中断。当软件开始被身边朋友使用后,撞限流的频率越来越高,我才意识到一开始就应该按“聚合 + 限速 + 自动降级”来设计,而不是等服务挂了再去补。
现在我的架构里哪怕只有一个 Provider,也预留了第二个 Provider 的切换位。这不是过度设计,这是对“翻译服务不可靠”这件事的最低成本保险。免费接口可以当默认,但永远要有一条备选路径。
6.2 做工具和做产品是两回事
最初版本的 SnapLingo 其实没那么克制,我加了配色主题、字体设置、发音朗读,甚至还有一堆用不上的设置项。后来做了一次减法,把功能砍到只剩划词、截图、剪贴板、历史记录这四块,测试反馈反而变好了。原因很朴素:工具型软件的用户要的是“完成任务”,不是“玩功能”。
我让三个非技术朋友各用两天,他们的使用习惯很有意思:划词翻译他们用得不多,截图翻译偶尔用,最常用的是剪贴板自动翻译和收藏历史。他们说“复制完自己就翻好了,不用想”,这句话让我意识到“结果可回溯”比“过程炫酷”重要得多。很多工具把精力花在让调用过程更炫,却忽略了结果出来之后用户想找却找不到的挫败感。
6.3 下一步计划,以及给同路的你一句话
v2 的计划里,我最想做的是 PaddleOCR 离线识别模式,这样用户在无网环境也能截图翻译。然后是术语表和翻译记忆库的导出功能,想把历史记录沉淀的术语表变成可迁移的个人资产。多语言输入自动检测也会加,现在用户必须手动指定源语言,体验还是有点糙。代码里已经预留了 Provider 接口,如果之后有更好的翻译引擎,接进去只是写一个类的事。
最后说句掏心窝的话:SnapLingo 没有用到任何别人做不到的黑科技,它的价值完全来自“把系统级集成做到位”。Windows 上真正缺的从来不是翻译引擎,而是愿意把全局快捷键、剪贴板、OCR、UIA、DPI 这些底层细节耐心盘好的人。我正在做下一个版本,你也完全可以去做一个属于你自己的版本——毕竟,工具最舒服的样子,就是按照你自己的工作方式长出来的样子。