Translation In Emacs
逛 Emacs China 的时候看到了一些在 Emacs 中翻译的插件1,我也跟着配置了一些。得益于 LLM(Large Language Model),翻译的质量也好了很多。这篇文章记录一下我都使用了什么插件,怎么配置的以及是如何使用的。
插件使用
插件我主要使用这几个:
- Elilif/emacs-immersive-translate
- Immersive-translate provides bilingual simultaneous display and translation of any text in Emacs.
- lorniu/gt.el
- Translator on Emacs. Supports multiple engines such as Google, Bing, deepL, ChatGPT, StarDict, Youdao and so on.
- condy0919/fanyi.el
- Not only English-Chinese translator for Emacs.
- karthink/gptel
- A simple LLM client for Emacs.
我使用最多的是 emacs-immersive-translate,它的灵感是 Immersive Translate,是我使用频率极高的一个浏览器翻译插件。
emacs-immersive-translate 给我的体验和 Immersive Translate 很接近,我主要是用来查看 Emacs 中的 Info,它还有 immersive-translate-auto-mode ,可以在 buffer 变化的时候自动翻译,很方便。
emacs-immersive-translate 针对 Emacs 中的 Info,elfeed 等做了适配,总体效果看起来是不错的,每次我看 Info 都会用到。
gt.el 的灵活度会更高一些,我主要用来选中文本之后进行翻译。
fanyi 则是当作字典使用,碰到一两个单词不熟悉,就使用 fanyi 进行查询。我很喜欢 fanyi 里面的 海词,它可以生成图表,呈现单词含义的使用频率,让我了解这个单词最常见的含义。
最后,我还会用到 gptel,它实际上不是专门用来翻译的,但是作为 LLM,我可以在任何地方调用它,帮我完成一些翻译任务。
插件配置
你可以在 init-translate.el 中查看翻译的相关配置。
emacs-immersive-translate
你可以在 MELPA 上直接安装 emacs-immersive-translate。
不过我修改了源码,调整了翻译文字颜色,所以我是作为 git submodules 安装的。
然后我配置了使用 OpenRouter 作为翻译服务:
;;; immersive-translate (require 'immersive-translate) (add-hook 'elfeed-show-mode-hook #'immersive-translate-setup) ;; need to api key with user `apikey` in `.authinfo` (setq immersive-translate-backend 'chatgpt immersive-translate-chatgpt-host "openrouter.ai/api" immersive-translate-chatgpt-model "google/gemini-2.5-flash" immersive-translate-pending-message "(≖ᴗ≖๑)" immersive-translate-failed-message "(つд⊂) ")
API Key 在 ~/.authinfo 中配置,由于 emacs-immersive-translate 是查找 user 为 apikey 的配置,因此 user 这里需要设置为 apikey 。
machine openrouter.ai/api login apikey password ********************************
关于 .authinfo 你可以参考:
gt.el
gt.el 也是可以在 MELPA 上直接安装。
我将它配置成使用 OpenRouter 作为翻译服务,翻译显示在一个新的 buffer 中。
;; @see: https://github.com/lorniu/gt.el (maybe-require-package 'gt) (maybe-require-package 'plz) (with-eval-after-load 'init-auth (with-eval-after-load 'gt (setq gt-langs '(en zh) gt-chatgpt-key (spike-leung/get-openrouter-api-key) gt-chatgpt-host "https://openrouter.ai/api" gt-chatgpt-model "google/gemini-2.5-flash" gt-default-translator (gt-translator :taker (gt-taker :pick nil :prompt t) :engines (gt-chatgpt-engine :stream t) :render (gt-buffer-render :name "gt-translator" :window-config '((display-buffer-at-bottom)) :then (lambda (_) (pop-to-buffer "gt-translator")))))))
API Key 也是配置在 ~/.authinfo ,使用 spike-leung/get-openrouter-api-key 这个方法从文件中查找对应的密钥。
spike-leung/get-openrouter-api-key
Source: init-auth.el
;;; init-auth --- config for auth related -*- lexical-binding: t -*- ;;; Commentary: ;;; Code: (setq epa-pinentry-mode 'loopback) ;; input pass in minibuffer ;; (auth-source-pass-enable) ;;; use pass to manage auth-source ;;; function to get api-key from authinfo (defun spike-leung/get-api-key (service &optional host) "Retrieve the API key for SERVICE from authinfo. if HOST exist, retrieve by HOST." (let* ((host (or host (format "api.%s.com" service))) (creds (car (auth-source-search :host host :port 443)))) (if creds (let ((api-key (plist-get creds :secret ))) (if (functionp api-key) (funcall api-key) api-key (error "API key not found for %s" service))) (error "No credentials found for %s" service)))) (defun spike-leung/get-deepseek-api-key () "Retrieve the DeepSeek API key from authinfo." (spike-leung/get-api-key "deepseek")) (defun spike-leung/get-openrouter-api-key () "Retrieve the OpenRouter API key from authinfo." (spike-leung/get-api-key "openrouter" "openrouter.ai")) (provide 'init-auth) ;;; init-auth.el ends here.
fanyi
fanyi 从 MELPA 上直接安装使用即可。
gptel
gptel 也是从 MELPA 上直接安装,然后配置 OpenRouter,具体配置见 init-gptel.el。
gptel 就是当 LLM 用,需要翻译的时候就复制文字和它对话。此外,在日常开发中,gptel 还能用来重构代码,完成一些重复任务,给我一些初始代码逻辑等,也是我用的很频繁的插件。
快捷键
为了方便使用,我将这几个插件绑定到了相同的快捷键入口。
;;; keybindings (defvar spike-leung/my-translate-keymap (make-sparse-keymap) "Keymap for translation commands.") (define-key spike-leung/my-translate-keymap (kbd "i") 'immersive-translate-buffer) (define-key spike-leung/my-translate-keymap (kbd "p") 'immersive-translate-paragraph) (define-key spike-leung/my-translate-keymap (kbd "c") 'immersive-translate-clear) (define-key spike-leung/my-translate-keymap (kbd "f") 'fanyi-dwim2) (define-key spike-leung/my-translate-keymap (kbd "g") 'gt-translate) (with-eval-after-load 'init-my-keybindings (define-key spike-leung/meta-o-keymap (kbd "t") spike-leung/my-translate-keymap))
写在最后
有了翻译插件,在阅读 info 等文档上真的帮助很大,极大地提高阅读效率。集成了 LLM 后,翻译的质量也好了很多。但依赖翻译插件也有个问题,就是原文会看的比较少,不利于增进英语学习。
如果你还有更好的插件,欢迎推荐啦 (ノ>ω<)ノ