1. 起因
经常需要阅读英文文档,冷不丁的会碰到一些不懂的单词,之前的做法是打开一个谷歌翻译的网页在一旁放着,有需要就切换过来查单词。但是来回的切换着实有点麻烦,就想着有没有一些Chrome翻译插件,一番搜寻,找了两款比较心仪的Chrome插件:一个是good word guide的Instant Dictionary,它的优点是直接显示英文的释义,因为很多时候直接看英文的释义更容易理解一个单词。例如对于a bank of memory might be assigned to each CPU
这句话,bank这单词,不管你套用“银行”、“湖畔”、“岸”等意思,感觉都怪怪的,而如果直接看它的英文释义a set or series of similar things, especially electrical or electronic devices, grouped together in rows
,一下子就能明白他说的是一组特性相同的内存;除了Instant Dictionary,另一个就是Google的Google Dictionary,因为我就比较中意谷歌翻译。可是心仪归心仪,这两款插件都有个致命的缺陷:由于众所周知的原因,他们俩都没法链接到他们的服务器。
对于Instant Dictionary,这显然已经没救了,但是对于Google Dictionary,我觉得还可以抢救一下。为什么呢?因为谷歌翻译在中国是可以直接打开的,对应的域名是translate.google.cn
,既然都是Google家的东西,连不上translate.google.com
,那是否可以让它去连translate.google.cn
?查看了Google Dictionary配置选项,并没有切换到国内服务器的选项,这样一来,想在国内用,就只能手动改一改了。
胡适曾经说过:大胆假设,小心求证。我们的假设就是最终单词翻译的请求是通过HTTP进行的,并且域名使用的是translate.google.com
。
2. 行动
好,说干就干,只要思想不滑坡,方法总比困难多。
2.1. 获取插件
Chrome插件的后缀名是.crx
,其实就是一个压缩包。常用的压缩软件一般都能解压,解压出来的是一堆JavaScript文件以及其他相关的一些文件。我有想过它为什么不直接用.zip
做后缀?最后得到了一个我自己比较信服的答案,使用.zip
等常用后缀就相当于在挑衅:“你来解压我啊!”。总会有好事者解压一探究竟,并且这样逼格也就不那么高了。当然,最后.crx
依旧没能阻挡好事者。
但是想解压,那也要先拿到。遗憾的是插件商店在中国正常情况下也是没法访问的,好在你不能访问,别人也不能访问。但是不能访问并不代表需求就消失了,需求始终都在,只有爱会消失。使用必应搜索chrome extension downloader
就能找到一堆下载插件的网站,例如https://crxdown.com/。紧接着,虽然我们不能直接访问到插件,但我们可以网上搜索该插件,得到它的确切地址,这样我们就能将它下载下来。例如在搜索Google dictionary后找到来源为Chrome Web Store的结果,右键选择复制链接地址就能得到对应的插件地址。
2.2. 找入口
得到了插件,下面我们要做的就是找到入口。正常情况下,出于安全的考虑Chrome是没法安装我们下载好了的插件的,即便是来源正经也不行,我们要进入开发者模式。在浏览器地址栏输入chrome://extensions/
,在打开的界面中勾选开发者模式。
然后,点击load unpacked
加载我们已经解压好了的插件,只需要选择包含manifest.json
这层的文件夹就行。
想要改代码,那就必须先理解代码,想要理解代码,首先要找到一个合适的切入点。理论上,manifest.json
是整个插件的元文件,里面肯定会有描述整个插件的入口文件之类的。但这个门槛有点高,使用这种方法应该是对Chrome插件的开发比较熟悉的,我这种门外汉算了。除此之外,还有另一个方法,那就是直接搜索我们能看到的东西。
运行该插件之后我们发现,触发翻译的条件是我们输入需要翻译的内容后回车或者点击蓝色按钮,正常情况下两种方法最终都会调用同一个函数。因为我们可以从这两个动作入手。通过在所有文件中搜索Define
这个单词,最终我们在browser_action.html
发现了这个按钮的标签。
<div id="form">
<input type="text" id="query-field"><button id="define-btn" class="btn btn-primary" value="Define">Define</button>
</div
从代码中看到,这里有个叫qeury-field
的输入以及一个叫define-btn
的按钮,和我们看到的一致。这个按钮标签定义了id属性却没有定义点击的回调函数,那么很大概率在JavaScript代码中会使用类似get_element_by_id()
这类的函数获取该标签并为其绑定回调函数,因此我们接着使用它的id define-btn
进行搜索。
一共搜索到三条内容,一条在html文件中,也就是我们刚看到的,一条位于css文件中,说明是设置显示样式的不用管,剩下一条在js文件中,果然和我们想的一样。打开该文件,返现代码已经经过混淆挤作一团了,正常人估计没几个能这么读代码,因此需要稍加处理。
处理方式很简单,随便找个JavaScript代码美化网站进行下格式调整,这里我使用的是https://beautifier.io/。进过美化,代码变成了下面的样子。
d = document.getElementById("define-btn");
e = document.getElementById("query-field");
f = document.getElementById("status-box");
g = document.getElementById("status-msg");
h = document.getElementById("status-search-link");
k = document.getElementById("usage-tip");
n = document.getElementById("meaning");
k.display = "block";
k.innerText = "Tip: Select text on any webpage, then click the Google Dictionary button to view the definition of your selection.";
document.getElementById("year"