「边打字边开挂」:一个 AutoHotkey 实时翻译输入器的诞生记

当你还在中英来回切换、复制粘贴发疯的时候,有人已经一边敲中文一边在全球队友面前流利输出英文 trash talk 了——而且手都没离开键盘。
这篇文章,讲的就是这样一个小而精但极具实用价值的项目:Real-time-translation-typing —— 一个基于 AutoHotkey 的实时打字翻译工具,支持键盘输入、语音输入、LOL 游戏内聊天联动,还能自由切换多种在线翻译服务。
别看项目体量不算大,里面藏着的技术思路却一点不简单:
- 前端界面用 Direct2D 自绘输入框和提示气泡,轻量却灵活。
- 与翻译引擎之间通过 ZeroMQ 做进程间通信,主进程负责 UI 和输入捕获,子线程/子进程专职翻译。
- 支持多家翻译 API 和「网页翻译爬取」,做了一个小型的「翻译聚合器」。
- 利用 Windows 原生 API(IMM、UIAutomation 等)精确获取光标位置、控制输入法候选框。
- 集成 WebView2 做语音识别输入,并为 LOL 这种特殊场景做了专门适配和协议封装。
如果你对下面这些场景有共鸣:
- 写英文邮件时一边想一边切翻译工具,思路被打断;
- 和老外打游戏,别人打字如飞,你还在「复制→翻译→复制→粘贴」;
- 想语音说中文,电脑自动帮你变成英文发出去;
那这个小工具,值得你认真看完这篇文章。
接下来,我们从背景、架构、核心实现、使用方式和应用场景,一步步拆开这个项目,看看作者到底玩了多少「骚操作」。
一、项目背景:为什么要造一个「实时打字翻译器」?
先把话说直白一点,这个项目要解决的问题,其实就是:
打字用中文思考,输出却要是英文(或其他外语),而且要尽量不中断当前操作。
很多人多少都经历过这种体验:
- 聊天软件里:你写中文 → 复制 → 打开浏览器 → 粘贴 → 翻译 → 再复制 → 回聊天框 → 粘贴 → 发送。
- 写英文邮件:要在中文和英文、各类翻译网站之间频繁切换,效率感人。
- 游戏里:节奏飞快,你还在窗口间来回切换,队友已经团灭两波了。
这种流程有几个明显痛点:
- 打断思路:每一次 Alt+Tab,都是对专注度的一次谋杀。
- 操作繁琐:明明只是想翻译一句话,却像在做多任务操作练习题。
- 不够「实时」:翻译和输入是两个完全割裂的动作,很难做到边打边看结果。
于是,这个项目的核心立意就很清晰:
把「翻译」这一动作,彻底嵌进「打字」本身,让翻译像输入法一样无感存在。
这也是为什么项目名字叫 Real-time-translation-typing——不是「翻译工具」,而是一个更偏「输入方式增强」的小系统。
项目目前主要有两种形态:
- API 版本(
实时打字翻译.ahk + thread.ah2): - 主进程捕获输入、绘制界面;
- 子线程/子进程负责调用翻译 API,返回结果后展示并写入剪贴板。
- 网页版/WebView2 版本(
实时打字翻译-API.ah2): - 通过 WebView2 直接控制在线翻译页面,模拟输入、读取结果;
- 同时集成语音识别 HTML 页面(
lib/语音.html),支持语音转文字再翻译; - 对 LOL 等游戏场景做了专门快捷键和逻辑适配。
API 版结构更清晰、逻辑更偏「后端 + 客户端」,网页版则更贴近「浏览器自动化 +富交互 UI」。两者都围绕一个核心目标:尽量减少翻译这件事本身的存在感。
二、总体技术架构:一个轻量级「输入增强系统」
先用一句话概括这个项目的架构:
一个基于 AutoHotkey 的桌面输入增强层,上层对接各种应用(聊天工具、游戏、编辑器),下层对接多种翻译服务,中间用 ZeroMQ 做异步通信,辅以 Direct2D 和 WebView2 提供 UI 和网页能力。
从代码结构看,大致可以分成以下几个模块:
- 输入捕获与 UI 展示(前台)
- 文件:
实时打字翻译.ahk、实时打字翻译-API.ah2 - 技术点:
- 键盘钩子、全局热键(
Hotkey、OnMessage)。 - 通过
GetCaretPosEx获取当前文本光标位置或鼠标位置。 - 使用
Direct2DRender绘制自定义输入框(Edit_box类),并根据文本长度调整大小。 - 通过
ToolTip/btt显示当前翻译 API 名称和翻译结果。 - 翻译请求发送与结果接收(消息层)
- API 版:
- 使用
zmq作为通信库,主进程持有ZMQ_PUBsocket,子线程/进程持有ZMQ_SUB。 - 主进程把当前文本、光标坐标、是否 IME 输入、当前翻译 API 等信息打包为 JSON,发送给
thread.ah2。 - Web 版:
- 通过各个
Sougou_web_cd/Youdao_web_cd/Deepl_web_cd的包装类,直接向 WebView2 容器中的翻译网页注入 JS,实现「模拟输入 → 监听输出」。 - 翻译执行模块(后台)
- API 版:
- 文件:
thread.ah2 - 根据 config 中选中的 API,执行对应翻译逻辑:
- 有道:HTTP POST + JSON 解析。
- 谷歌:调用公开接口
https://translate.googleapis.com/translate_a/single。 - 搜狗:请求网页,解析 HTML DOM 提取翻译结果。
- 百度:签名 + 请求官方开放平台接口。
- Edge:调用
api-edge.cognitive.microsofttranslator.com的接口。 - 翻译完成后通过
ToolTip显示,并覆盖剪贴板,方便粘贴。 - Web 版:
- 翻译完全由网页自身负责;AHK 只负责把输入丢给页面、把结果抓回来。
- 配置与扩展
- 配置文件:
config/setting.json - 内容包括:
- 当前主用翻译源
cd。 - 可用 API 列表
all_api。 - 每个 API 是否开启、是否支持实时翻译、以及必要的秘钥信息(如百度)。
- 通过
tab或~tab快捷键实现在不同 API 之间切换。 - 语音输入与游戏集成(主要在 Web 版)
- 语音输入:
lib/语音.html使用浏览器的 Web Speech API(或同类方案),实时识别语音为文字。- AHK 监控该页面输出,并把结果回填到
Edit_box。 - LOL 集成:
- 利用
XButton1/XButton2作为语音触发和结束键。 - 检测
RiotWindowClass窗口,把翻译后的结果通过模拟键盘输入发送到游戏内聊天框。 - 支持
/all模式,并通过 ZeroMQ 将消息发送到一个后端服务进行进一步处理(如转发到其他渠道)。
可以看到,这个项目虽然基于 AutoHotkey,但其设计思路已经远超「几个热键脚本」的范畴,更像是一个 小型输入系统:
- 它有 UI 层(Direct2D + ToolTip)。
- 有通信层(ZeroMQ)。
- 有服务层(翻译 API/Web 端)。
- 有配置层(
setting.json决定策略)。 - 还有针对具体应用的适配层(LOL、任意窗口、剪贴板模式等)。
三、核心实现拆解:从按下 ALT+Y 到翻译结果出现
理解一个工具,最好的方式就是跟着一次完整的调用链走一遍。我们以 API 版 为例,看下从用户按下快捷键到看到翻译结果,中间具体发生了什么。
3.1 热键与输入入口:fanyi()
在 实时打字翻译.ahk 里,入口函数 main() 中设定了多组热键:
Alt+Y:打开输入框,进入翻译输入模式;Alt+Enter:对当前翻译结果发音;Enter:输出翻译结果文本;Ctrl+Enter:输出原始文本;Tab:切换翻译 API;Esc:关闭输入框。
以 Alt+Y 为例,它绑定了 fanyi():
fanyi() 的主要逻辑:
- 通过
GetCaretPosEx(&x, &y, &w, &h)尝试获取当前文本光标位置; - 如果失败,则回退到当前鼠标位置
MouseGetPos(&x, &y); - 记录当前坐标为全局
g_cursor_x / g_cursor_y; - 根据当前 API 的实时配置,弹出一个 ToolTip 提示当前翻译源;
- 在光标附近
g_eb.show(x, y)显示自绘输入框; - 调用
g_eb.draw()进行初次绘制。
体验上的感觉就是:
- 不用切窗口,不用切输入法,在任何文本输入位置,按下 Alt+Y,一个悬浮输入框就出现在光标下方。
3.2 自绘输入框:Edit_box 类
输入框并不是普通 Windows 控件,而是基于 Direct2DRender 的自绘组件。这么设计有几个好处:
- 完全不依赖目标应用的 UI 风格;
- 可以精确控制尺寸、位置、颜色、字体和透明度;
- 可以实现一些小功能,比如绘制插入位置、背景高亮等。
构造函数大致如下:
绘制方法 draw(flag := 0) 的关键逻辑:
- 调用
GetTextWidthHeight(this.text, 20)计算当前文本的绘制宽高; - 根据内容动态调整窗口大小:
this.move(x, y, wh.width + 100, wh.height + 100); - 绘制背景矩形和边框:
- 深色半透明背景
0xcc1E1E1E; - 红色描边
0xffff0000; - 绘制文本本身,颜色
0xFFC9E47E(偏黄的高亮色,非常符合「工具提示」那种感觉)。
在 Web 版中,输入框还多了一条绿色的竖线,用于表示当前插入位置:
这段逻辑结合 insert_pos(从文本末尾往回的偏移量)实现了简单但相当实用的「光标定位」。
3.3 输入捕获和 IME 适配:ON_MESSAGE_WM_CHAR / ON_MESSAGE_WM_IME_CHAR
为了让输入框真正像一个「迷你输入法」,项目监听了 WM_CHAR 和 WM_IME_CHAR 消息:
WM_CHAR:主要用来处理普通键盘字符;WM_IME_CHAR:处理输入法候选确定后的字符(比如中文拼音选字后回填的汉字)。
二者最终都会调用 g_eb.set_imm(a[1]),而 set_imm() 中:
- 调用
ImmGetContext、ImmSetCompositionWindow、ImmSetCandidateWindow等 API,重定向输入法候选框位置到自定义输入框区域; - 把输入字符转换成 UTF-16 字符串,通过
push()拼接到当前文本; - 调用
draw()重新渲染输入框。
换句话说,不论你是英文键盘直接敲,还是用中文输入法,都被统一纳入到这个自绘输入框里处理。
这一步是整个项目的「体验关键点」之一:
- 不劫持全局输入法,不强改系统行为;
- 只是临时在当前激活窗口旁边开了一个虚拟输入层。
3.4 何时触发翻译:实时 vs 空格触发
Edit_box.draw() 在每次更新时,会根据当前 API 的策略决定是否立即调用翻译:
- 如果是
youdao,基本是实时触发; - 对于有调用配额限制的百度、可能需要翻墙的谷歌,是否实时则由配置项
is_real_time_translate决定; sougou这种网页爬虫型翻译,因为延迟较高,一般更适合非实时触发;- 还有一种是「空格触发」模式:
- 当最后一个字符是空格时,才把整段文本发送给后台翻译。
触发的方式很简单:
- API 版:调用
cd(this.text, x, y)将文本和光标位置打包成 JSON,通过 ZeroMQ PUB socket 发送; - Web 版:调用对应翻译页面封装类:
this.sg.set_input_box(input_text)/this.yd.set_input_box(...)/this.dp.set_input_box(...)。
这个设计有一个非常实用的点:
不同翻译源的「成本」不同,策略也不同。
比如:
- 有道:速度快、成本低,可以实时;
- 百度:有配额限制,不适合每个字都发;
- 搜狗:网页爬虫,速度慢,不实时也更自然。
这些策略都被统一收敛到了 setting.json / 内部逻辑中,对用户来说只表现为:
- 你切到不同 API,体验会有细微差别,但行为都在预期之内。
3.5 后台翻译执行:thread.ah2
thread.ah2 的结构也很清晰:
- 从
A_Args[1]中取到 ZeroMQ 上下文ctx; - 创建
ZMQ_SUBsocket,连接到inproc://main; - 周期性
zmq_recv_string收取消息; - JSON 解析出
text、api、坐标等信息; - 根据
api调用对应的翻译函数: youdaocd(text)baiducd(text, appid, appsec, from, to)googlecd(text)sougoucd(text)edgecd(text)- 最后通过
ToolTip在原先位置显示翻译结果,并把结果写入A_Clipboard。
例如 Google 翻译函数:
搜狗翻译则比较「接地气」,走的是 HTML 解析路线:
- GET 请求
https://fanyi.sogou.com/text?keyword=...; - 把 ResponseText 写入
htmlfileCOM 对象; - 用
querySelector找到#trans-result或#trans-result > span.trans-sentence; - 读取
innerHTML作为翻译结果。
这种实现方式虽然不是最「正规」、最 API 化的方案,但在桌面工具场景里,非常实用且好维护。如果有一天搜狗改了页面结构,改下选择器就能继续用。
3.6 输出阶段:发音、粘贴、原文/译文切换
当翻译结果准备就绪后,用户有几种常见操作路线:
- 直接粘贴翻译结果:
Enter⇒ 调用send_command('translate'):- 把
g_eb.fanyi_result写入剪贴板; - 激活目标窗口(比如之前光标所在窗口);
- 模拟
{RShift Down}{Insert}{RShift Up}即「Shift+Insert」粘贴。 - 粘贴原始文本(不翻译):
Ctrl+Enter⇒send_command('Primitive'):- 用原文填充剪贴板,再粘贴。
- 发音:
Alt+Enter⇒sound_play():- 判断文本是否包含汉字;
- 英文用有道发音接口
https://dict.youdao.com/dictvoice?audio=...; - 中文用另一个 TTS API
https://api.oick.cn/txt/apiz.php?text=...&spd=10; - 通过
PlayMedia封装的 WinRTMediaPlayer自行播放,不依赖外部播放器。
整个过程下来,用户只感觉到:
- 打了一段中文;
- 输入框里出现了翻译结果;
- 按下 Enter;
- 目标应用中就像你亲手打出那段英文一样。
而在背后,已经经历了:输入捕获 → 自绘渲染 → 进程间通信 → HTTP 请求 → JSON/HTML 解析 → 结果回传 → 剪贴板设置 → 模拟输入。
四、Web 版与语音输入:当翻译器开始「听你说话」
如果说 API 版更像「程序员型工具」,那么 Web 版则是把「能用就行」发挥到了极致。
4.1 WebView2:让翻译页面成为你的「内嵌引擎」
在 实时打字翻译-API.ah2(实际上是 Web 版主脚本)中,可以看到项目引用了:
网页翻译集合.ah2 里封装了对搜狗、有道、百度、Deepl 等网页的自动化控制逻辑,整体思路是:
- 用 WebView2 加载相应的在线翻译网站;
- 找到页面中的输入框和输出区域;
- 通过 JS 注入/执行,设置输入框的值、模拟输入事件;
- 监听输出区域文本变化,通过回调通知 AHK 主脚本。
在 Edit_box.__New() 中,可以看到类似这样的初始化:
这表示:
- 如果当前全局可用翻译源中包含
sougou,就构造一个搜狗翻译控制器; - 设置输出变更回调
on_change; - 初始化时塞一句「我来自搜狗」,方便在 WebView2 界面中验证联通情况。
只要实现若干个 {xxx}_web_cd() 类,就能无缝把新的网页翻译源接入系统,完全不改主流程,扩展性非常好。
4.2 语音输入:lib/语音.html + SoundINput
语音输入是 Web 版的亮点之一:
配套的回调:
流程很简单:
- 打开内嵌 WebView2,加载
语音.html; - HTML 内部通过浏览器的语音识别能力,把语音转成文本;
- 每次文本更新时,通过某种桥接机制(通常是 WebView2 的 postMessage 或 URL 协议)把内容回推给 AHK;
- AHK 接到回调后,更新输入框内容并触发翻译。
用户体验层面就是:
- 按下
Alt+I:弹出输入框并开启语音识别; - 开始说中文 → 输入框文字变化 → 触发翻译 → 结果准备好;
- 按 Enter:翻译后的内容被送进当前窗口或游戏。
4.3 LOL 专属适配:玩游戏也要优雅地「发言」
在 Web 版脚本中还有一块专为 LOL 准备的逻辑:
配合 SendCn 和 sendcmd2game 两种模式:
- 一种是模拟用户在游戏里逐字键入(防止部分游戏对粘贴行为的限制);
- 另一种是通过 ZeroMQ 把聊天内容发送给外部服务,用于记录或延展功能。
这部分逻辑细节很多,但总体目标只有一个:
让你在游戏中也可以像在聊天软件里一样自然地用中文思考、用英文输出,而且操作尽量不打断游戏节奏。
五、配置与使用:从「能跑」到「好用」的细节
项目的配置主要集中在 config/setting.json:
5.1 API 管理与切换
cd:当前主用翻译源,例如edge、youdao等;all_api:允许参与轮换的翻译源;- 每个翻译源都可以配置:
is_open:是否启用;is_real_time_translate:是否每次输入变化就立即翻译。
键盘上只需要记住一个操作:
Tab/~tab:在当前启用的翻译源之间轮换。
项目内部是这样做的:
逻辑很直观:
在all_api里按顺序找下一个is_open == 1的 API,作为当前翻译源。
5.2 常用快捷键一览
从 README 和代码里可以整理出一组「日常够用」的快捷键:
Alt + Y:打开输入框(键盘输入模式)。Alt + I:打开输入框并开启语音输入(Web 版)。Enter:输出翻译文本到当前窗口。Ctrl + Enter:输出原始文本(不翻译)。Alt + Enter:朗读翻译结果。Tab:切换翻译 API。Esc:关闭输入框。- Web 版额外:
Ctrl + C:复制当前翻译结果。Ctrl + V:将剪贴板文本填入输入框。Ctrl + Alt + Y:直接翻译剪贴板内容。XButton1/XButton2:在 LOL 中启动/结束语音输入或发送内容。
5.3 运行环境与启动方式
根据 README:
- Web 版推荐环境:
- Windows 10 或安装了 WebView2 Runtime。
- AutoHotkey v2H 版本(用于支持增强特性)。
- 启动方式之一:
- 把
实时打字翻译-网页版(推荐).ah2拖到AutoHotkey.exe上执行; - 或者重命名为
.ahk,再配合改名后的AutoHotkey.exe直接双击运行。
API 版相对更偏折腾,适合对 AHK 有一定基础的用户:
- 确保依赖库(
zmq、Direct2DRender等)可用; - 启动主脚本
实时打字翻译.ahk,确保thread.ah2能正常被Worker执行。
六、典型应用场景:从工作到游戏,全面提效
这个工具的「适用面」其实比初看时要广得多,这里列几个典型场景,方便你对号入座。
6.1 写英文邮件/文档:
场景:
- 在 Outlook、浏览器邮件客户端、Word、VS Code 甚至记事本里,都可以直接用这个输入框辅助写作。
玩法:
- 在任何编辑区域按
Alt+Y; - 中文思考 → 中文输入;
- 一边打字一边看悬浮输入框里的英文翻译;
- 合适时按 Enter,翻译结果被填入正文;
- 对于反复出现的专有名词,可以用
Ctrl+Enter保留原文。
这比切换到浏览器找翻译网站要顺滑得多,特别适合「半熟练」的英文用户。
6.2 实时聊天:
场景:
- 和海外同事/朋友在微信 PC、QQ、Telegram、Discord 等各种 IM 里聊天。
玩法:
- 对话框中光标就绪;
- 按
Alt+Y; - 中文输入 → 实时翻译;
- 按 Enter 把翻译结果填充进去,再按一次 Enter 发送。
没有频繁窗口切换,没有待办遗失感,只有顺畅的沟通体验。
6.3 游戏场景(LOL 等):
场景:
- 和外国队友一起排位,又想表达清楚信息,又不想拖队友节奏。
玩法:
- 游戏中按
XButton1(鼠标侧键)启动语音输入; - 说中文:「小心对面打野在上路草丛」;
- 语音转文字 → 翻译 →
XButton2发送; - 队友收到的是一条流畅的英语提示。
你可以像队内指挥一样说中文,电脑帮你把它变成别人的母语。
6.4 编程辅助:变量命名小助手
项目顺手还塞了一个很实用的小功能:
流程:
- 输入框内先写中文描述,比如「用户注册时间」;
- 翻译成英文(比如
user registration time); - 按
Shift+Alt+Enter或Ctrl+Alt+Enter生成: - 驼峰:
UserRegistrationTime; - 蛇形:
user_registration_time; - 结果自动放入剪贴板并输入到编辑器中。
说白了,这是一个 「中→英→规范变量名」的快速通道,非常适合写业务代码时使用。
七、从这个项目里能学到什么?
如果你只是想「用」,看到这里基本已经够用了。但从开发者角度来看,这个项目还种下了好几个值得借鉴的思路。
7.1 不要小看「脚本语言」做桌面增强的力量
很多人提到 AutoHotkey,会下意识觉得它只是:
- 映射个快捷键;
- 做点窗口自动化;
- 写点小宏脚本。
但这个项目告诉你:
当你把 AHK 当作「桌面应用框架」用时,它也能写出结构清晰、可扩展的工具。
关键点包括:
- 自定义类、模块化拆分(
Edit_box、Zmq_send2plug等); - 与 C/C++ DLL、Win32 API 深度交互(IMM、UIAutomation);
- 单独的配置层(
setting.json),让功能和策略解耦; - 借助 ZeroMQ 等外部库实现跨进程通信。
这种组合拳,使得 AHK 不再是「简单脚本」,而是一个可以快速原型化桌面工具的平台。
7.2 输入法级别的工具,核心是「不打扰」
整个项目设计里,有一个贯穿始终的哲学:
让用户尽可能少地感知到工具的存在,但又实打实地提高效率。
比如:
- 不抢输入焦点,只在附近开一个小输入框;
- 不替代系统输入法,而是临时包裹一层;
- 翻译结果直接进入剪贴板,然后模拟输入,就像你自己打出来一样;
- 关闭时自动清空状态、隐藏 Tooltip,不留下「视觉残留」。
这类设计非常值得做工具产品的人借鉴。
7.3 多翻译源聚合的扩展思路
项目用了一套非常轻量的「翻译聚合」模式:
- 每个翻译源有自己的配置块;
- 选择和轮换逻辑与翻译具体实现解耦;
- 新增翻译源的步骤大致是:
- 增加配置项;
- 写一个
{api_name}cd函数(API 版)或{ApiName}_web_cd类(Web 版); - 在切换逻辑里加入相应 case 即可。
这种模式也很适合作为其他「聚合型工具」的参考,比如:
- 聚合搜索;
- 聚合 AI 模型调用;
- 聚合字典/百科等。
八、未来可以怎么进化?
最后,稍微展开想象一下,这个项目在现有基础上,很容易拓展出不少有趣方向。
8.1 引入本地/大模型翻译
目前项目主要依赖在线翻译:有道、谷歌、Edge、搜狗、百度等。如果结合现在的大模型生态,可以考虑:
- 支持调用本地或云端大模型(如 GPT 系列、国内大模型 API),执行:
- 上下文感知翻译;
- 语气润色;
- 简历/邮件的专业表达优化。
只要保持 ZeroMQ 这层通信接口不变,翻译后端就可以从「多家翻译 REST 接口」升级成「统一的智能语言服务」。
8.2 自定义翻译风格与术语库
在技术、产品、游戏等细分领域,专有名词和表达风格尤为重要。可以在现有配置体系上扩展:
- 支持用户维护自己的术语词典;
- 支持「翻译后自动替换部分短语」;
- 支持「正式/口语/幽默/严谨」等风格偏好,从而让输出更贴合不同场景。
8.3 更丰富的 UI 与状态反馈
现在界面已经比较克制了,但仍可以考虑:
- 在输入框里同步显示原文与译文;
- 支持多行翻译上下文;
- 对翻译失败、网络异常给出更明确提示;
- 给每种翻译 API 设置不同的配色或小图标,切换时更直观。
8.4 插件化架构
目前翻译源、特定应用(如 LOL)都是以「硬编码」的形式集成在工程里。长期看,也可以升级为:
- 定义一套插件协议:
- 输入:原文、上下文、目标语言;
- 输出:译文、可选解释信息;
- 插件通过某种 IPC/HTTP 协议跟主程序通信;
- 这样任何人都可以开发自己的翻译/处理插件,比如:
- 翻译后自动检查语法;
- 翻译后顺便生成反问句、延伸表达;
- 专门进行术语审核。
九、结语:把翻译,悄悄变成「输入体验升级」
回到一开始的问题:
为什么要造这么一个「实时打字翻译器」?
看完代码你会发现,作者其实不是单纯地想做一个「给你翻译结果」的工具,而是更在意:
- 你在写东西时的流畅感;
- 你在游戏里沟通时的节奏感;
- 你在中英文世界间切换时的自然度。
它做的事情,说白了就一句话:
帮你用中文思考,用英文(或其他外语)表达,而且尽量不打扰你原本的操作节奏。
从工程角度,这个项目不是什么「高大上架构」,也不是动辄几万行代码的大工程,但它用:
- 恰到好处的技术选型;
- 细腻的交互设计;
- 对真实使用场景的充分理解;
打造出了一个足够「贴身」的小工具。
如果你经常在中英文之间来回奔波,或者喜欢和全球玩家一起开黑,那不妨试试把这个项目跑起来,让它悄悄住进你的键盘,替你承担那些无聊又机械的操作。
毕竟,在这个时代,能帮你省下 Alt+Tab 的工具,都值得认真对待。
