一个支持多词典的翻译插件(目前仅支持单词)

说一下为什么 melpa 上这么多词典了还会再次发明一个词典插件。个人初始的词典方案是用的本地的 ydcv, 但是有时候可能会在服务器上开发,而服务器上通常没有安装 ydcv 这个二进制,所以迫切的需要一个仅依赖网络的词典。

在 melpa 上搜索了一圈之后发现主要有:

  • chinese-yasdcv 依赖 sdcv, 不符合要求
  • sdcv 依赖 sdcv, 不符合要求
  • goldendict 依赖 goldendict, 不符合要求
  • bing-dict 但是它太简单了,而且只能显示在 echo arean 区域。在我个人使用的场景下有时候可能需要复制,所以这个插件不太符合要求
  • osx-dictionary 限定了 osx 平台且依赖 osx 自身的词典 app
  • youdao-dictionary 这个是目前最适合的,但是它需要申请个人 API key,不太想有道上注册一个新用户
  • dictionary 没有中文翻译,而且初次 tcp 连接是阻塞的
  • baidu-translate 需要申请 APPID 和秘钥,放弃
  • Google 翻译相关的包不考虑

在论坛上则发现了 multi-translate.el 用多个翻译服务翻译当前单词和选区 但是它依赖了太多包,不够轻量。

再尝试直接用 eww 打开,试用了一段时间过后发现效果太差了,非必要的干扰信息太多、主体不明确。于是就新写了一个

目前使用的服务是由:

这 2 个网站提供的。选用 dict.cn 的一个原因是它有提供单词的使用率分布图,而 etymonline 自然就是想知道这个单词是怎么演变的。如果本地有安装 mpv/mplayer/mpg123 的话,可以点击音量按键来播放单词对应的发音。目前这个插件比较适合我个人的使用场景,用的时候只需要 M-x fanyi-dwim 即可。

从代码上来看它的优点有:

  • 异步非阻塞
  • 使用了 eieio, 非常容易扩展
  • 用户实际使用的接口只有一个 fanyi-dwim
  • 不需要用户再申请 api key,直接解析 dom
16 个赞

话说可以同时支持本地和网络吗,而且这个是只能翻译单词不能翻译句子吗

海词 (dict.cn) 的“用度分布”很棒,曾想过给它写客户端。

写 multi-translate.el 的初衷主要是为了方便查看&比较各个平台的长句翻译,免得浏览器开多个 tab 不停切换,仅此而已(sdcv 的支持是后来增加的,现在想来是个不明智的决定,因为我自己都是直接用 sdcv 查单词,而不透过 multi-translate.el),在使用体验上欠缺更多考虑。

由于各个平台的差异巨大,无力从头写,所以直接用了现成的包。然而,长句翻译最好的 deepl.com 至今没有客户端,也是 multi-translate.el 的遗憾。

另,你这个包集成到 multi-translate.el 也不违和。

最好的方式:

  1. 有网的时候用网络服务
  2. 没网的时候用 sdcv
  3. 类似EAF的技术,提供一个支持Vue.js绘制界面的无边框弹出小窗口

作为顽固的终端派,我还在用 20190610.732 版的 sdcv.el:

(unless (assoc 'pos-tip (package-desc-reqs (cadr (assoc 'sdcv package-alist))))
    (warn "[sdcv] Current version %s is not terminal friendly. Last stable version is %s"
          (package-desc-version (cadr (assoc 'sdcv package-alist)))
          '(20190610.732)))

免费的有上限,似乎是日调用次数 1000

不太想支持本地,因为多数情况下都是有网的(面向云原生时代,翻译服务是不可变的基础设施,直接依赖就行! 其实是我懒,不想配置本地词典

1 个赞

好像有点问题,GNU Emacs 27.2 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.27, cairo version 1.16.0)

Debugger entered--Lisp error: (wrong-number-of-arguments get-buffer-create 2)
  (get-buffer-create fanyi-buffer-name :inhibit-buffer-hooks)
  (let ((buf (get-buffer-create fanyi-buffer-name :inhibit-buffer-hooks))) (save-current-buffer (set-buffer buf) (let ((inhibit-read-only t) (inhibit-point-motion-hooks t)) (erase-buffer) (fanyi-mode))) (let ((instances (seq-map #'clone fanyi-providers))) (seq-do #'(lambda (i) (eieio-oset i ':word (url-hexify-string word)) (fanyi--spawn i)) instances)) (pop-to-buffer buf))
  fanyi-dwim("introduce")
  funcall-interactively(fanyi-dwim "introduce")
  call-interactively(fanyi-dwim nil nil)
  command-execute(fanyi-dwim)

get-buffer-create 的文档如下

get-buffer-create is a built-in function in ‘C source code’.

(get-buffer-create BUFFER-OR-NAME)

  Probably introduced at or before Emacs version 19.29.

Return the buffer specified by BUFFER-OR-NAME, creating a new one if needed.
If BUFFER-OR-NAME is a string and a live buffer with that name exists,
return that buffer.  If no such buffer exists, create a new buffer with
that name and return it.  If BUFFER-OR-NAME starts with a space, the new
buffer does not keep undo information.

If BUFFER-OR-NAME is a buffer instead of a string, return it as given,
even if it is dead.  The return value is never nil.

看了一下 emacs 的代码,这个好像是 28 才有的特性。

melpa那个版本都不知是谁上传的,但是离线版是有意义的,我经常出差,火车上看会材料,特别是专山洞的时候,sdcv还是很有用的。

Orz,感谢提醒

咦,melpa为啥没有这个包啊?

还未提交,只是先暂时写了 melpa 而已…

请问能有德语翻译吗 :joy:

看了一下,调用的服务不支持德语

melpa 上的版本是 @stardiviner 提交的:melpa/sdcv at master · melpa/melpa · GitHub

length> 也是 28 新加的

P.S. 把这个用 (> (length lst) len) 替换后,看起来没有其它兼容问题了

1 个赞

已经用电纸书看英文资料的路过,表示电脑只用来写东西、跑东西和浏览网页了…

我倒觉得离线更好,速度快、省心。 sdcv 可以自己下载英语、法语、日语、德语等各种词典,可以满足日常需求。

我试了一下 deepl,发现如果是免费用户的话非常容易会触发 too many requests 上限……

页面上显示是这个的,而直接用 API 调用的话则是

{
    "jsonrpc": "2.0",
    "error": {
        "code": 1042901,
        "message": "Too many requests."
    }
}

MELPA 现在在 melpa 上可以搜到啦!

2 个赞

太好了,我一会去试试。