Moldable Emacs: translate string at point in multiple languages!
Too long; didn't read
Have you ever needed to translate text to multiple languages? Select
To multiple languages mold with
me-mold to translate your text
At my current job, I release mobile apps. One release step is to make sure to keep the list of changes accessible to our clients. We support 4-5 languages, so I provide the release notes in many (foreign) languages. That requires me to click around in the translator tab of my browser a few times. This kind of stuff becomes boring pretty soon. Would it not be nice to view a string in many different languages? Even just to see how translations differ from each other! This sounds a job for a mold!
And there is a solution
For this mold we rely on the useful google-translate Emacs extension. This mode makes translation as simple as they should be.
For my use case, I like to translate the string at point or a selection. Usually I translate from English to other languages. That is why I define the following variable like so.
(defcustom me-languages (list :from "en" :to '("fr" "de" "it" "no" "pt" "es" "sv")) "Languages to translate to.")
This is just defining the source and target languages. You can
redefine this as you need. And you can also redefine them
programmatically, should you need that (by binding the variable in a
With such a selection, the string "How are you?", produces the following Org buffer.
* How are you? ** fr #Comment ca va? ** de #Wie geht es Ihnen? ** it #Come stai? ** no #Hvordan har du det? ** pt #Como você está? ** es #¿Cómo estás? ** sv #Hur mår du?
I use the # as a separator because it makes searching the next hit easier for me.
The core of the mold is the function
This does the actual translation. By default this function displays
the translation in a dedicated buffer. In our case, we want it as an
Elisp string. You can redefine where to send the output of
google-translate-translate, but there is no option to return just a
string. Still, it comes with the target
kill-ring. That is what we
use in the following mold.
(me-register-mold :key "To multiple languages" :let ((sentence (or (me-get-region) (sentence-at-point t)))) :given (:fn (and sentence (me-require 'google-translate))) :then (:fn (let* ((translations (-map (lambda (language) (google-translate-translate (plist-get me-languages :from) language sentence 'kill-ring) (list :language language :translation n(car kill-ring))) (plist-get me-languages :to))) (tree (--map (append (list :sentence sentence) it) translations))) (with-current-buffer buffername (org-mode) (erase-buffer) (insert (format "* %s\n\n" sentence)) (--each translations (insert (format "** %s #%s\n\n" (plist-get it :language) (plist-get it :translation) ))) (setq-local self tree)))) :docs "You can translate text to multiple languages." :examples nil)
As you can see the mold is simple. With
(car kill-ring) we grab the
google-translate-translate. We make a translation
for each language in the
:to of our
me-languages variable. The
rest of the mold is about formatting the translations in a buffer.
Note that the
self variable will contain a plist like the following.
((:sentence "How are you?" :language "fr" :translation "Comment ca va?") (:sentence "How are you?" :language "de" :translation "Wie geht es Ihnen?") (:sentence "How are you?" :language "it" :translation "Come stai?") (:sentence "How are you?" :language "no" :translation "Hvordan har du det?") (:sentence "How are you?" :language "pt" :translation "Como você está?") (:sentence "How are you?" :language "es" :translation "¿Cómo estás?") (:sentence "How are you?" :language "sv" :translation "Hur mår du?"))
And in a few lines, I made the translation step of my release pretty quick! Now I just have to automate the input of translations on the app website via Nyxt and... Oh well that is for another time!
Even translations are views! All you need for that is to install
google-translate from Melpa and grab a copy of moldable-emacs. Then
you will be able to translate to your favourite languages in batches!