首先介绍一下词典软件。
目前最流行的还是有道词典、金山词霸等app。但是这些app在专业性和权威性上又有所不足。而Mdcit系列词典可以添加各种自定义词库,而且很多网友已经制作好了很多权威词典对应的Mdict词库(见Pdawiki与FreeMdict)。
而对于自己最常使用的macOS,支持Mdict词库的GoldenDict开发进度缓慢,界面不太好看,有时会遇到Bug。而另一款欧路词典需要收费才能添加自定义词库,而且界面、操作也不令人满意。
更新:欧路词典用户体验还可以。目前是常用的词典转换成macOS Dictionary格式使用,其它词典在欧路词典使用。毕竟每本词典都转换的话太费时间了。
相反,macOS系统原生的Dictionary有着良好的操作体验,支持三指取词,阅读体验也很棒,却没有那么多自定义词库可以添加。
于是,就想着把两者的优点结合起来,将丰富的Mdict词库转换成macOS Dictionary支持的格式,而且支持图片显示、发音等等功能。
下面简要简要记录由Mdict词库文件转换成完美macOS Dictionary词库文件的过程。
所需环境
- 开源项目
PYGLOSSARY:最新Releases见ilius/pyglossary/releases
python-lzo:sudo pip3 install python-lzo
- Writing to AppleDict:
sudo pip3 install lxml beautifulsoup4 html5lib
- GNU make as part of Command Line Tools for Xcode
- Dictionary Development Kit as part of Auxillary Tools for Xcode. Extract to/Developer/Extras/Dictionary Development Kit
转换过程
- 用PYGLOSSARY进行转换
假设词典文件为~/Downloads/oald8/oald8.mdx, 图片、语音文件oald8.mdd也在同一文件夹下。
先将词典文件转换成xml文件,并将其他图片、音频等文件提取出来放在OtherResources文件夹下。
1 | cd ~/Downloads/oald8/ |
在PYGLOSSARY的说明中接下来是将xml文件中的相对链接中的”/“去掉以及替换spx为wav。
1 | sed -i "" 's:src="/:src=":g' oald8.xml |
其实这两步可以在之后用正则统一替换。
- 转换语音文件
如果是spx文件,先转换成wav(需安装speex)。若是wav文件则可跳过这一步。
1 | find OtherResources -name "*.spx" -execdir sh -c 'spx={};speexdec $spx ${spx%.*}.wav' \; |
然后用FFmpeg把wav文件转换成mp3文件(macOS中默认的iTunes与QuickTime均不支持wav格式)。
在当前目录新建Sounds文件夹,并新建sh脚本convert.sh文件如下。
1 | for x in ./OtherResources/*.wav; do ffmpeg -i "$x" "Sounds/`basename "$x" .wav`.mp3"; done |
然后执行sh脚本。
1 | sh ./convert.sh |
如果语音文件较多的话需等待较长时间。
- 编译
1 | make |
有时生成的词典包文件中并没有图片、音频文件。这时将OtherResources文件夹中除音频外的其他文件以及放置mp3文件的Sounds文件夹复制到xxx.dictionary/Contents目录下(右键dictionary文件,选择Show Package Contents)。
- 安装
将生成的dictionary文件复制到当前用户文件夹下的/Library/Dictionaries中(或者打开Dictionary App,选择菜单栏中的文件->打开词典文件夹,即可进入该文件夹),之后在Dictionary App的菜单栏中词典->偏好设置中启用一下就行。
修正词典文件的各种问题
以上方法生成的词典会有开头说到的词典内链接跳转不正常,不能发音、图片不能显示等种种小问题。下面修复这些问题。
- Dictionary的URI Scheme介绍
以下引自Dictionary Services Programming Guide。
x-dictionary: is an URI scheme that describes cross references between entries in dictionaries. It is used in tag such as <a href="x-dictionary:r:another_id">
.
The x-dictionary:URI contains three elements separated by colons as the general form—target selector, target text, and dictionary bundle ID. The target selector must be either d (for definition) or r (for reference). Use d if you want to search definitions of the following key text. Use r if you want to refer to the entry specified by the reference ID which must be unique to each dictionary.
1 | x-dictionary:d:key_text:dict_bundle_id |
The dictionary bundle ID can be omitted in both forms, as shown in the following lines. If it is omitted, Dictionary Services searches the target text in all active dictionaries.
1 | x-dictionary:d:key_text |
- 修复词典中的链接跳转问题。
举例来说,假设dict_bundle_id为Longman5。(dict_bundle_id可在生成的词典文件中的Info.plist中修改。)
假设xml文件中为:
1 | <a href="x-dictionary:d:entry://hour">hour</a> |
可替换为:
1 | <a href="x-dictionary:d:hour:Longman5">hour</a> |
可用正则表达式匹配然后处理。
- 修正词典中页面内的定位问题
例如点击apple1会跳转到同一个页面中的apple2处。
1 | <a href="x-dictionary:d:entry://#_hke1">apple1</a> |
将其替换为
1 | <a href="#_hke1">apple1</a> |
- 修复词典的发音问题
假设xml文件中为:
1 | <a href="x-dictionary:d:sound://1.spx"><img border="0" src="Br.gif"/></a> |
可替换为
1 | <audio id="1" src="Sounds/1.mp3"/><img border="0" src="Br.gif" onmousedown="document.getElementById('1').play(); return false;"/> |
onmousedown
可替换成onmouseover
,这样鼠标悬浮上发音图标就开始发音,而不用单击。
可用正则表达式匹配然后处理。
- Java正则替换代码示例
以Longman5_Activator为示例,假设只需要修复链接跳转问题和页面内的定位问题。写得比较随便,随意看一下就好。
当然挺多编辑器(比如Sublime Text、Visual Studio Code)直接支持正则表达式查找和替换,这样就不用写程序了。
1 | import java.io.*; |
其他注意事项
- 文本匹配的正则表达式需一一调试
以上每个词典文件中的具体模式均不太一样,而且有时会有与一般模式不同的个例(如多加了几个空格、标签间加了个<br/>
、中间换了一行、图片大多是png个别是gif等等),需要一一调试。推荐调试网站Regexr。
- 空格相关问题
连续两个粗体单词之间的空格会不显示。例如
1 | <b>apple</b> <b>pie</b> |
会显示为applepie。此时将其替换为
1 | <b>apple</b> <b>pie</b> |
注意xml中不能用
。
另外有时xml中会有&nbsp;
,原意应显示为空格,却显示为
。此时将其替换为 
就好。
- 取词小窗口修改大小
若取词小窗口中字体太小,可在词典包内容中的DefaultStyle.css文件中加上以下内容:
1 | .apple_client-panel body{margin: 0 0 15px;font-size: 16px;} |
- CSS样式文件
若OtherResources文件夹中有其它CSS文件,或者原来CSS文件就独立于MDict文件之外,将其内容复制到词典文件包中的DefaultStyle.css文件中。
- 深色模式
在深色模式中,转换的词典背景颜色依旧是白色,这可以通过修改词典包内容中的DefaultStyle.css文件解决。具体参考Make Mojave custom dictionaries work better。
- 其它问题
将@@@LINK=abc
替换成<a href="x-dictionary:d:abc:dict_bundle_id">abc</a>
。不过这样处理后显示的是指向另一个词条的链接,不是直接显示另一个词条。解决办法是扫描整个XML文件,将@@@LINK引用移动到正确的词条下。具体可以参考下述Python代码(引用自该链接)。
1 | #!/usr/bin/env python3 |
如果图片无法正常显示,将相对路径名最前面的/去掉,例如将<img src="/dir/abc.png"/>
替换成<img src="dir/abc.png"/>
.
由于macOS的Dictionary中鼠标悬浮于某一内容之上时会将其视作一个span,如果CSS中原本就有应用于所有span的样式,会把该样式应用于鼠标经过的区域。这样鼠标经过的区域会有很奇怪的样式。解决办法是在原有span中加一个class,并把原来span的样式归到新建的class中。
等等。
- 其他功能
Dictinary还支持高亮搜索关键词、家长控制功能等等,参考之前提到过的Dictionary Services Programming Guide。
与Alfred结合的一些功能
- 快捷键取词
虽然三指轻点取词很方便,但是有些软件并不支持三指取词。结合Alfed Workflow即可实现选中待查内容后快捷键取词。
1 | query="{query}" |
- 快捷键发音
下载韦氏142000单词发音库(密码:w4mw)后,假设解压至~/Voice文件夹下。同理即可实现选中待查内容后快捷键发音。
1 | query="{query}" |
当然系统中开启Speech功能,结合快捷键也能实现类似功能。缺点是这是合成的发音而非真人发音,优点是单词变形乃至句子段落都能发音。
这里附上快捷键取词和快捷键发音的Alfred Workflow下载地址。
更新:在单词中有空格或单引号时,原workflow失效。现在已修正。
Reference: