Gt.el
Translator on Emacs. Support multiple engines such as Google, Bing, deepL, StarDict and Youdao, also support LLMs like ChatGPT, DeepSeek and so on.
Install / Use
/learn @lorniu/Gt.elREADME
[[https://melpa.org/#/gt][file:https://melpa.org/packages/gt-badge.svg]] [[https://stable.melpa.org/#/gt][file:https://stable.melpa.org/packages/gt-badge.svg]]
I have renamed this package from =go-translate= to =gt=. You should change the config to fit it.
- gt.el
This is a translation framework on Emacs, with high configurability and extensibility.
[[README-zh.org][点击查看《中文版文档》]]
As a translation framework, it offers many advantages:
- Supports multiple translation engines, including Bing, Google, DeepL, YoudaoDict, StarDict, LibreTranslate, also LLMs like ChatGPT, DeepSeek and so on.
- Rich rendering components, such as rendering to Buffer, Posframe, Overlay, Kill Ring, and others. With stream output support.
- Flexible retrieval of content and language for translation, with the help of the built-in Taker component.
- Support for word and sentence translation, as well as translation of multiple paragraphs. It can use multiple engines concurrently to translate multiple paragraphs into multiple languages.
- Support for different HTTP backends (url.el, curl) with asynchronous and non-blocking requests, providing a smooth user experience.
- Implemented based on eieio (CLOS), allowing users to flexibly configure and extend the various components.
It's more than just a translation framework.It's flexible, and can easily be extended to various Text-to-Text conversion scenarios:
- For example, the built-in Text-Utility component integrates text encryption/decryption, hashing, QR code generation, etc.
- For example, it can be extended as a client for ChatGPT (WIP)
** Table of Content
- [[#basic-usage-as-a-translator][Basic Usage]] | [[#gt-http-backend][HTTP Client Config (url vs curl, proxy)]]
- [[#deep-into-core-components][The Components (Learn them → Use them → Extend them)]]
- ([[#component-gt-taker-for-capturing][Taker]]) [[#gt-taker-with-prompt][gt-taker with prompt]]
- ([[#component-gt-engine-for-translatingtransforming][Engine]]) [[#gt-stardict-engine][gt-stardict-engine]] | [[#gt-deepl-engine][gt-deepl-engine]] | [[#gt-chatgpt-engine][gt-chatgpt-engine]]
- ([[#component-gt-render-for-rendering][Render]]) [[#gt-buffer-render][gt-buffer-render]] | [[#gt-posframe-pop-rendergt-posframe-pin-render][gt-posframe-render]] | [[#gt-insert-render][gt-insert-render]] | [[#gt-overlay-render][gt-overlay-render]]
- [[#gt-text-utility][gt-text-utility]] | [[#gt-valid-trait-if][gt-valid-trait (the syntax of :if)]]
- [[#gt-chatgpt-engine-1][Interact with Various Models: The Evolution of gt-chatgpt-engine]]
- [[#integrate-tts-to-emacs][Integrate TTS (Text-to-Speech) to Emacs]]
- [[#customization-and-extension-the-framework][How to Extend the Framework or Components]]
** Installation
Download and load this package via MELPA or other ways.
#+begin_src emacs-lisp (use-package gt :ensure t) #+end_src
** Basic Usage (as a Translator)
For the most basic use, add the following code to the configuration file: #+begin_src emacs-lisp (setq gt-langs '(en fr)) (setq gt-default-translator (gt-translator :engines (gt-google-engine)))
;; This configuration means: ;; Initialize the default translator, let it translate between en and fr via Google Translate, ;; and the result will be displayed in the Echo Area. #+end_src
Then select a certain text, and start translation with command =gt-translate=.
Of course, it is possible to specify more options for the translator, such as: #+begin_src emacs-lisp (setq gt-default-translator (gt-translator :taker (gt-taker :text 'buffer :pick 'paragraph) ; config the Taker :engines (list (gt-bing-engine) (gt-google-engine)) ; specify the Engines :render (gt-buffer-render))) ; config the Render
;; This configuration means: ;; Initialize the default translator, let it send all paragraphs in the buffer to Bing and Google, ;; and output the results with a new Buffer. #+end_src
Except config default translator with =gt-default-translator=, you can define several preset translators with =gt-preset-translators=: #+begin_src emacs-lisp (setq gt-preset-translators `((ts-1 . ,(gt-translator :taker (gt-taker :langs '(en fr) :text 'word) :engines (gt-bing-engine) :render (gt-overlay-render))) (ts-2 . ,(gt-translator :taker (gt-taker :langs '(en fr ru) :text 'sentence) :engines (gt-google-engine) :render (gt-insert-render))) (ts-3 . ,(gt-translator :taker (gt-taker :langs '(en fr) :text 'buffer :pick 'word :pick-pred (lambda (w) (length> w 6))) :engines (gt-google-engine) :render (gt-overlay-render :type 'help-echo))))) #+end_src
This configuration presets three translators:
- ts-1: translate word or selected region near the cursor between =en= and =fr= via Bing, display the translated result with Overlay
- ts-2: translate sentence or selected region near the cursor between =en=, =fr= and =ru= via Google, insert the translated result into current buffer
- ts-3: translate all words with length more than 6 in buffer between =en= and =fr= via Google, display the translated result with help echo
The first translator in =gt-preset-translators= will act as the default translator if =gt-default-translator= is nil. So, translate with command =gt-translate= and switch between preset translators with command =gt-setup=.
See more configuration options via =M-x customize-group gt=, and read the following chapters for more configuration details.
** Deep into Core Components
The core component of the translation framework is =gt-translator=, which contains the following components:
- =gt-taker=: used to capture user input, including text and languages to be translated
- =gt-engine=: used to translate the content captured by the taker into the corresponding target text
- =gt-render=: used to aggregate results from engines and output them to the user
The flow of translation is =[Input] -> [Translate/Transform] -> [Output]=, corresponding to the components =[Taker] -> [Engine] -> [Render]= above. Executing the method =gt-start= on the translator will complete a full translation flow.
Therefore, the essence of configuration is to create a translator instance and specify different components according to needs: #+begin_src emacs-lisp ;; specify components with ':taker' ':engines' and ':render'; run translation with 'gt-start' (gt-start (gt-translator :taker ... :engines ... :render ...))
;; command 'gt-translate' use the translator defined in 'gt-default-translator' to do its job (setq gt-default-translator (gt-translator :taker ... :engines ... :render ..)) (call-interactively #'gt-translate) #+end_src
So, one needs to understand these components first for better configuration.
*** component =gt-taker= for capturing
| slot | desc | value | |-----------+-------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------| | text | Initial text | String or a function that returns a string, it can also be symbol like 'buffer 'word 'paragraph 'sentence etc | | langs | Translate languages | List as '(en fr), '(en ru it fr), if empty, use the value of gt-langs instead | | prompt | Interactive Confirm | If t, confirm by minibuffer. If 'buffer, confirm by opening a new buffer | | pick | Pick paragraphs, sentences or words from initial text | Function or a symbol like 'word 'paragraph 'sentence etc | | pick-pred | Used to filter the text picked | Pass in a string and output a Boolean type | | then | The logic to be executed after take. Hook | A function that takes the current translator as argument. The final modification can be made to the content captured by Taker | | if | Validate | Function or literal symbol, used to determine whether taker is available for current translation task |
Currently there is only one built-in Taker implementation, which can be used in most scenarios: : Determine the initial text with 'text', : determine the translation languages with 'langs', : confirm with 'prompt', : and extract certain paragraphs, sentences, or words with 'pick'.
If no Taker is specified or if Taker is specified but lacks options, the values of the following variables will be used as default: #+begin_src emacs-lisp (setq gt-langs '(en fr)) ; Default translation languages, at least two must be specified (setq gt-taker-text 'word) ; By default, the initial text is the word under the cursor. If there is active region, the selected text will be used first (setq gt-taker-pick 'paragraph) ; By default, the initial text will be split by paragraphs. If you don't want to use multi-parts translation, set it to nil (setq gt-taker-prompt nil) ; By default, there is no confirm step. Set it to t or 'buffer if needed #+end_src
It's better to use =:taker= to explicitly specify a Taker for the translator: #+begin_src emacs-lisp (gt-translator :taker (gt-taker)) (gt-translator :taker (gt-taker :langs '(en fr) :text 'word :pick 'paragraph :prompt nil)) (gt-translator :
