848 lines
33 KiB
EmacsLisp
848 lines
33 KiB
EmacsLisp
;;; google-translate-core-ui.el --- google translate core UI
|
|
|
|
;; Copyright (C) 2012 Oleksandr Manzyuk <manzyuk@gmail.com>
|
|
|
|
;; Author: Oleksandr Manzyuk <manzyuk@gmail.com>
|
|
;; Maintainer: Andrey Tykhonov <atykhonov@gmail.com>
|
|
;; URL: https://github.com/atykhonov/google-translate
|
|
;; Version: 0.11.18
|
|
;; Keywords: convenience
|
|
|
|
;; Contributors:
|
|
;; Tassilo Horn <tsdh@gnu.org>
|
|
;; Bernard Hurley <bernard@marcade.biz>
|
|
;; Chris Bilson <cbilson@pobox.com>
|
|
;; Takumi Kinjo <takumi.kinjo@gmail.com>
|
|
;; momomo5717 <momomo5717@gmail.com>
|
|
|
|
;; This file is NOT part of GNU Emacs.
|
|
|
|
;; This is free software; you can redistribute it and/or modify it
|
|
;; under the terms of the GNU General Public License as published by
|
|
;; the Free Software Foundation; either version 2, or (at your option)
|
|
;; any later version.
|
|
|
|
;; This file is distributed in the hope that it will be useful, but
|
|
;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
;; General Public License for more details.
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
;;; Commentary:
|
|
|
|
;; This script provides the most common functions and variables for
|
|
;; UI. It does not contain any interactive functions and overall is
|
|
;; not going to be used directly by means of
|
|
;; `execute-extended-command' (M-x). Its purpose to provide the most
|
|
;; valuable and useful functionality for packages and scripts which
|
|
;; provide UI.
|
|
;;
|
|
;; The most important functions are the following:
|
|
;;
|
|
;; - `google-translate-translate'
|
|
;;
|
|
;; - `google-translate-read-source-language'
|
|
;;
|
|
;; - `google-translate-read-target-language'
|
|
;;
|
|
;; `google-translate-translate' translates the given text from source
|
|
;; language to target language and shows a translation.
|
|
;;
|
|
;; `google-translate-read-source-language' reads source language from
|
|
;; minibuffer and returns language
|
|
;; abbreviation. `google-translate-read-target-language' reads target
|
|
;; language from minibuffer and returns language abbreviation.
|
|
|
|
;; Customization:
|
|
|
|
;; You can customize the following variables:
|
|
;;
|
|
;; - `google-translate-output-destination'
|
|
;;
|
|
;; - `google-translate-enable-ido-completion'
|
|
;;
|
|
;; - `google-translate-show-phonetic'
|
|
;;
|
|
;; - `google-translate-listen-program'
|
|
;;
|
|
;; - `google-translate-pop-up-buffer-set-focus'
|
|
;;
|
|
;; - `google-translate-preferable-input-methods-alist'
|
|
;;
|
|
;; `google-translate-output-destination' determines translation output
|
|
;; destination. If `nil' the translation output will be displayed in
|
|
;; the pop up buffer. If value equal to `echo-area' then translation
|
|
;; outputs in the Echo Area. In case of `popup' the translation
|
|
;; outputs to the popup tooltip using `popup' package. In case of
|
|
;; `kill-ring' the translation outputs to the kill ring. And in case
|
|
;; of `current-buffer' the translation outputs to the current
|
|
;; buffer. If you would like output translation to the Echo Area you
|
|
;; would probably like to increase it because only part of translation
|
|
;; could visible there with the default settings. To increase Echo
|
|
;; Area you could increase the value of `max-mini-window-height'
|
|
;; variable, for example: `(setq max-mini-window-height 0.5)'.
|
|
;;
|
|
;; If `google-translate-enable-ido-completion' is non-NIL, the input
|
|
;; will be read with ido-style completion.
|
|
;;
|
|
;; The variable `google-translate-show-phonetic' controls whether the
|
|
;; phonetic spelling of the original text and its translation is
|
|
;; displayed if available. If you want to see the phonetics, set this
|
|
;; variable to t.
|
|
;;
|
|
;; The variable `google-translate-listen-program' determines the
|
|
;; program to use to listen translations. By default the program looks
|
|
;; for `mplayer' in the PATH, if `mplayer' is found then listening
|
|
;; function will be available and you'll see `Listen' button in the
|
|
;; buffer with the translation. You can use any other suitable
|
|
;; program. If you use Windows please download and unpack `mplayer'
|
|
;; and add its path (directory) to the system PATH variable. Please
|
|
;; note that translation listening is not available if
|
|
;; `google-translate-output-destination' is set to `echo-area' or
|
|
;; `popup'.
|
|
;;
|
|
;; The variable `google-translate-pop-up-buffer-set-focus' determines
|
|
;; whether window (buffer) with translation gets focus when it pop
|
|
;; ups. If `nil', it doesn't get focus and focus remains in the same
|
|
;; window as was before translation. If `t', window (buffer with
|
|
;; translation) gets focus. Please note that that setting works only
|
|
;; for pop up buffer, i.e. when `google-translate-output-destination'
|
|
;; is `nil'.
|
|
;;
|
|
;; The `google-translate-input-method-auto-toggling' variable
|
|
;; determines whether input method auto toggling is enabled or not.
|
|
;;
|
|
;; While switching among languages I noticed that I change input
|
|
;; method quite often. Input method auto toggling allows switch on
|
|
;; appropriate input method while switching among languages. Auto
|
|
;; toggling will work in case of
|
|
;; `google-translate-input-method-auto-toggling' is set to `t' and
|
|
;; `google-translate-preferable-input-methods-alist' is defined
|
|
;; properly.
|
|
;;
|
|
;; This variable may be defined as follow (just for example):
|
|
;;
|
|
;; (setq google-translate-preferable-input-methods-alist '((nil . ("en"))
|
|
;; (ukrainian-programmer-dvorak . ("ru" "uk"))))
|
|
;;
|
|
;; In this way, input method is disabled (because of nil) for the
|
|
;; minibuffer when source language is English. And
|
|
;; "ukrainian-programmer-dvorak" input method is enabled when source
|
|
;; language is Russian or Ukrainian.
|
|
|
|
;; Customization of faces:
|
|
|
|
;; - `google-translate-text-face', used to display the original text
|
|
;; (defaults to `default')
|
|
;;
|
|
;; - `google-translate-phonetic-face', used to display the phonetics
|
|
;; (defaults to `shadow')
|
|
;;
|
|
;; - `google-translate-translation-face', used to display the highest
|
|
;; ranking translation (defaults to `default' with the `weight'
|
|
;; attribute set to `bold')
|
|
;;
|
|
;; - `google-translate-suggestion-label-face' used to display the
|
|
;; label for suggestion (defaults to `default' with the `foreground'
|
|
;; attribute set to `red')
|
|
;;
|
|
;; - `google-translate-suggestion-face' used to display the suggestion
|
|
;; in case of word is misspelled (defaults to `default' with the
|
|
;; `slant' attribute set to `italic' and `underline' attribute set
|
|
;; to `t')
|
|
;;
|
|
;; - `google-translate-listen-button-face' used to display the "Listen"
|
|
;; button (defaults to `height' 0.8).
|
|
;;
|
|
;; For example, to show the translation in a larger font change the
|
|
;; `height' attribute of the face `google-translate-translation-face'
|
|
;; like so:
|
|
;;
|
|
;; (set-face-attribute 'google-translate-translation-face nil :height 1.4)
|
|
;;
|
|
;;
|
|
;;; Code:
|
|
;;
|
|
|
|
(eval-when-compile (require 'cl))
|
|
(require 'google-translate-core)
|
|
(require 'ido)
|
|
|
|
|
|
(defvar google-translate-supported-languages-alist
|
|
'(("Afrikaans" . "af")
|
|
("Albanian" . "sq")
|
|
("Amharic" . "am")
|
|
("Arabic" . "ar")
|
|
("Armenian" . "hy")
|
|
("Azerbaijani" . "az")
|
|
("Basque" . "eu")
|
|
("Belarusian" . "be")
|
|
("Bengali" . "bn")
|
|
("Bosnian" . "bs")
|
|
("Bulgarian" . "bg")
|
|
("Catalan" . "ca")
|
|
("Cebuano" . "ceb")
|
|
("Chichewa" . "ny")
|
|
("Chinese Simplified" . "zh-CN")
|
|
("Chinese Traditional" . "zh-TW")
|
|
("Corsican" . "co")
|
|
("Croatian" . "hr")
|
|
("Czech" . "cs")
|
|
("Danish" . "da")
|
|
("Dutch" . "nl")
|
|
("English" . "en")
|
|
("Esperanto" . "eo")
|
|
("Estonian" . "et")
|
|
("Filipino" . "tl")
|
|
("Finnish" . "fi")
|
|
("French" . "fr")
|
|
("Frisian" . "fy")
|
|
("Galician" . "gl")
|
|
("Georgian" . "ka")
|
|
("German" . "de")
|
|
("Greek" . "el")
|
|
("Gujarati" . "gu")
|
|
("Haitian Creole" . "ht")
|
|
("Hausa" . "ha")
|
|
("Hawaiian" . "haw")
|
|
("Hebrew" . "iw")
|
|
("Hindi" . "hi")
|
|
("Hmong" . "hmn")
|
|
("Hungarian" . "hu")
|
|
("Icelandic" . "is")
|
|
("Igbo" . "ig")
|
|
("Indonesian" . "id")
|
|
("Irish" . "ga")
|
|
("Italian" . "it")
|
|
("Japanese" . "ja")
|
|
("Javanese" . "jw")
|
|
("Kannada" . "kn")
|
|
("Kazakh" . "kk")
|
|
("Khmer" . "km")
|
|
("Korean" . "ko")
|
|
("Kurdish (Kurmanji)" . "ku")
|
|
("Kyrgyz" . "ky")
|
|
("Lao" . "lo")
|
|
("Latin" . "la")
|
|
("Latvian" . "lv")
|
|
("Lithuanian" . "lt")
|
|
("Luxembourgish" . "lb")
|
|
("Macedonian" . "mk")
|
|
("Malagasy" . "mg")
|
|
("Malay" . "ms")
|
|
("Malayalam" . "ml")
|
|
("Maltese" . "mt")
|
|
("Maori" . "mi")
|
|
("Marathi" . "mr")
|
|
("Mongolian" . "mn")
|
|
("Myanmar (Burmese)" . "my")
|
|
("Nepali" . "ne")
|
|
("Norwegian" . "no")
|
|
("Pashto" . "ps")
|
|
("Persian" . "fa")
|
|
("Polish" . "pl")
|
|
("Portuguese" . "pt")
|
|
("Punjabi" . "pa")
|
|
("Romanian" . "ro")
|
|
("Russian" . "ru")
|
|
("Samoan" . "sm")
|
|
("Scots Gaelic" . "gd")
|
|
("Serbian" . "sr")
|
|
("Sesotho" . "st")
|
|
("Shona" . "sn")
|
|
("Sindhi" . "sd")
|
|
("Sinhala" . "si")
|
|
("Slovak" . "sk")
|
|
("Slovenian" . "sl")
|
|
("Somali" . "so")
|
|
("Spanish" . "es")
|
|
("Sundanese" . "su")
|
|
("Swahili" . "sw")
|
|
("Swedish" . "sv")
|
|
("Tajik" . "tg")
|
|
("Tamil" . "ta")
|
|
("Telugu" . "te")
|
|
("Thai" . "th")
|
|
("Turkish" . "tr")
|
|
("Ukrainian" . "uk")
|
|
("Urdu" . "ur")
|
|
("Uzbek" . "uz")
|
|
("Vietnamese" . "vi")
|
|
("Welsh" . "cy")
|
|
("Xhosa" . "xh")
|
|
("Yiddish" . "yi")
|
|
("Yoruba" . "yo")
|
|
("Zulu" . "zu"))
|
|
"Alist of the languages supported by Google Translate.
|
|
|
|
Each element is a cons-cell of the form (NAME . CODE), where NAME
|
|
is a human-readable language name and CODE is its code used as a
|
|
query parameter in HTTP requests.")
|
|
|
|
(defvar google-translate-translation-listening-debug nil
|
|
"For debug translation listening purposes.")
|
|
|
|
(defstruct gtos
|
|
"google translate output structure contains miscellaneous
|
|
information which intended to be outputed to the buffer, echo
|
|
area or popup tooltip."
|
|
source-language target-language text
|
|
auto-detected-language text-phonetic translation
|
|
translation-phonetic detailed-translation suggestion detailed-definition)
|
|
|
|
(defgroup google-translate-core-ui nil
|
|
"Emacs core UI script for the Google Translate package."
|
|
:group 'processes)
|
|
|
|
(defcustom google-translate-enable-ido-completion nil
|
|
"If non-NIL, use `ido-completing-read' rather than
|
|
`completing-read' for reading input."
|
|
:group 'google-translate-core-ui
|
|
:type '(choice (const :tag "No" nil)
|
|
(other :tag "Yes" t)))
|
|
|
|
(defcustom google-translate-show-phonetic nil
|
|
"If non-NIL, try to show the phonetic spelling."
|
|
:group 'google-translate-core-ui
|
|
:type '(choice (const :tag "No" nil)
|
|
(const :tag "Yes" t)))
|
|
|
|
(defcustom google-translate-listen-program
|
|
(executable-find "mplayer")
|
|
"The program to use to listen translations. By default the
|
|
program looks for `mplayer' in the PATH, if `mplayer' is found
|
|
then listening function will be available and you'll see `Listen'
|
|
button in the buffer with the translation. You can use any other
|
|
suitable program."
|
|
:group 'google-translate-core-ui
|
|
:type '(string))
|
|
|
|
(defcustom google-translate-output-destination
|
|
nil
|
|
"Determines where translation output will be displayed. If
|
|
`nil' the translation output will be displayed in the pop up
|
|
buffer (default). If value equals to `echo-area' then translation
|
|
outputs in the Echo Area. And in case of `popup' the translation
|
|
outputs to the popup tooltip using `popup' package."
|
|
:group 'google-translate-core-ui
|
|
:type '(symbol))
|
|
|
|
(defcustom google-translate-pop-up-buffer-set-focus
|
|
nil
|
|
"Determines whether window (buffer) with translation gets focus
|
|
when it pop ups. If `nil', it doesn't get focus and focus remains
|
|
in the same window as was before translation. If `t',
|
|
window (buffer with translation) gets focus.")
|
|
|
|
(defcustom google-translate-listen-button-label
|
|
"[Listen]"
|
|
"Label of the 'Listen' button."
|
|
:group 'google-translate-core-ui
|
|
:type 'string)
|
|
|
|
(defface google-translate-text-face
|
|
'((t (:inherit default)))
|
|
"Face used to display the original text."
|
|
:group 'google-translate-core-ui)
|
|
|
|
(defface google-translate-phonetic-face
|
|
'((t (:inherit shadow)))
|
|
"Face used to display the phonetic spelling."
|
|
:group 'google-translate-core-ui)
|
|
|
|
(defface google-translate-translation-face
|
|
'((t (:weight bold)))
|
|
"Face used to display the probable translation."
|
|
:group 'google-translate-core-ui)
|
|
|
|
(defface google-translate-suggestion-label-face
|
|
'((t (:foreground "red")))
|
|
"Face used to display the suggestion label."
|
|
:group 'google-translate-core-ui)
|
|
|
|
(defface google-translate-suggestion-face
|
|
'((t (:slant italic :underline t)))
|
|
"Face used to display the suggestion."
|
|
:group 'google-translate-core-ui)
|
|
|
|
(defface google-translate-listen-button-face
|
|
'((t (:inherit button :height 0.8)))
|
|
"Face used to display button \"Listen\"."
|
|
:group 'google-translate-core-ui)
|
|
|
|
(defvar google-translate-input-method-auto-toggling nil
|
|
"When `t' the current source language is compared with the
|
|
values from `google-translate-preferable-input-methods-alist' and
|
|
enables appropriate input method for the minibuffer. So this
|
|
feature may allow to avoid switching between input methods while
|
|
translating using different languages.")
|
|
|
|
(defvar google-translate-preferable-input-methods-alist
|
|
'((nil . nil))
|
|
"Alist of preferable input methods for certain languages.
|
|
|
|
Each element is a cons-cell of the form (INPUT-METHOD
|
|
. LANGUAGES-LIST), where INPUT-METHOD is the input method which
|
|
will be switched on, when translation source language equals to
|
|
one of the language from the LANGUAGE-LIST.
|
|
|
|
INPUT-METHOD could be specified as nil. In such case input method
|
|
disables.
|
|
|
|
As example, this alist could looks like the following:
|
|
|
|
'((nil . \"en\")
|
|
(ukrainian-programmer-dvorak . (\"ru\" \"uk\")))
|
|
|
|
In this way, `ukrainian-programmer-dvorak' will be auto enabled
|
|
for the minibuffer when Russian or Ukrainian (as source language)
|
|
is active.")
|
|
|
|
(defun google-translate-supported-languages ()
|
|
"Return a list of names of languages supported by Google Translate."
|
|
(mapcar #'car google-translate-supported-languages-alist))
|
|
|
|
(defun google-translate-language-abbreviation (language)
|
|
"Return the abbreviation of LANGUAGE."
|
|
(if (string-equal language "Detect language")
|
|
"auto"
|
|
(cdr (assoc language google-translate-supported-languages-alist))))
|
|
|
|
(defun google-translate-language-display-name (abbreviation)
|
|
"Return a name suitable for use in prompts of the language whose
|
|
abbreviation is ABBREVIATION."
|
|
(if (string-equal abbreviation "auto")
|
|
"unspecified language"
|
|
(car (rassoc abbreviation google-translate-supported-languages-alist))))
|
|
|
|
(defun google-translate-paragraph (text face &optional output-format)
|
|
"Return TEXT as a filled paragraph into the current buffer and
|
|
apply FACE to it. Optionally use OUTPUT-FORMAT."
|
|
(let ((beg (point))
|
|
(output-format
|
|
(if output-format output-format "\n%s\n")))
|
|
(with-temp-buffer
|
|
(insert (format output-format text))
|
|
(facemenu-set-face face beg (point))
|
|
(fill-region beg (point))
|
|
(buffer-substring (point-min) (point-max)))))
|
|
|
|
(defun google-translate-setup-preferable-input-method (source-language)
|
|
"Set input method which takes from the value of
|
|
`google-translate-preferable-input-methods-alist' variable."
|
|
(interactive)
|
|
(let* ((preferable-input-method
|
|
(google-translate-find-preferable-input-method source-language)))
|
|
(set-input-method preferable-input-method)))
|
|
|
|
(defun google-translate-find-preferable-input-method (source-language)
|
|
"Look for the SOURCE-LANGUAGE in the
|
|
`google-translate-preferable-input-methods-alist' and return
|
|
input method for it."
|
|
(let ((input-method nil))
|
|
(dolist (item google-translate-preferable-input-methods-alist)
|
|
(dolist (language (cdr item))
|
|
(when (string-equal source-language language)
|
|
(setq input-method (car item)))))
|
|
input-method))
|
|
|
|
(defun google-translate--translation-title (gtos format)
|
|
"Return translation title which contains information about used
|
|
source and target languages."
|
|
(let ((source-language (gtos-source-language gtos))
|
|
(target-language (gtos-target-language gtos))
|
|
(auto-detected-language (gtos-auto-detected-language gtos)))
|
|
(format format
|
|
(if (string-equal source-language "auto")
|
|
(format "%s (detected)"
|
|
(google-translate-language-display-name
|
|
auto-detected-language))
|
|
(google-translate-language-display-name
|
|
source-language))
|
|
(google-translate-language-display-name
|
|
target-language))))
|
|
|
|
(defun google-translate--translating-text (gtos format)
|
|
"Outputs in buffer translating text."
|
|
(let ((text (gtos-text gtos)))
|
|
(let ((output-format format))
|
|
(google-translate-paragraph
|
|
text
|
|
'google-translate-text-face
|
|
output-format))))
|
|
|
|
(defun google-translate--text-phonetic (gtos format)
|
|
"Outputs in buffer text phonetic in case of
|
|
`google-translate-show-phonetic' is set to t."
|
|
(let ((text-phonetic (gtos-text-phonetic gtos)))
|
|
(if (and google-translate-show-phonetic
|
|
(not (string-equal text-phonetic "")))
|
|
(google-translate-paragraph
|
|
text-phonetic
|
|
'google-translate-phonetic-face
|
|
format)
|
|
"")))
|
|
|
|
(defun google-translate--translated-text (gtos format)
|
|
"Output in buffer translation."
|
|
(let ((translation (gtos-translation gtos)))
|
|
(google-translate-paragraph
|
|
translation
|
|
'google-translate-translation-face
|
|
format)))
|
|
|
|
(defun google-translate--translation-phonetic (gtos format)
|
|
"Output in buffer translation phonetic in case of
|
|
`google-translate-show-phonetic' is set to t."
|
|
(let ((translation-phonetic (gtos-translation-phonetic gtos)))
|
|
(if (and google-translate-show-phonetic
|
|
(not (string-equal translation-phonetic "")))
|
|
(google-translate-paragraph
|
|
translation-phonetic
|
|
'google-translate-phonetic-face
|
|
format)
|
|
"")))
|
|
|
|
(defun google-translate--detailed-translation (detailed-translation translation
|
|
format1
|
|
format2)
|
|
"Return detailed translation."
|
|
(with-temp-buffer
|
|
(loop for item across detailed-translation do
|
|
(let ((index 0)
|
|
(label (aref item 0)))
|
|
(unless (string-equal label "")
|
|
(put-text-property 0 (length label)
|
|
'font-lock-face
|
|
'google-translate-translation-face
|
|
label)
|
|
(insert (format format1 label))
|
|
(loop for translation across (aref item 2) do
|
|
(let ((content
|
|
(format "%s (%s)"
|
|
(aref translation 0)
|
|
(mapconcat 'identity
|
|
(aref translation 1)
|
|
", "))))
|
|
(insert (format format2
|
|
(incf index)
|
|
content)))))))
|
|
(buffer-substring (point-min) (point-max))))
|
|
|
|
(defun google-translate--detailed-definition (detailed-definition definition
|
|
format1
|
|
format2)
|
|
"Return detailed definition."
|
|
(with-temp-buffer
|
|
(let ((section "DEFINITION"))
|
|
(put-text-property 0 (length section)
|
|
'font-lock-face
|
|
'google-translate-translation-face
|
|
section)
|
|
(insert (format "\n%s\n" section)))
|
|
(loop for item across detailed-definition do
|
|
(let ((index 0)
|
|
(label (aref item 0)))
|
|
(unless (string-equal label "")
|
|
(put-text-property 0 (length label)
|
|
'font-lock-face
|
|
'google-translate-translation-face
|
|
label)
|
|
(insert (format format1 label))
|
|
(loop for definition across (aref item 1) do
|
|
(insert (format format2
|
|
(incf index)
|
|
(if (> (length definition) 2)
|
|
(format "%s\n \"%s\""
|
|
(aref definition 0)
|
|
(aref definition 2))
|
|
(format "%s" (aref definition 0)))))))))
|
|
(buffer-substring (point-min) (point-max))))
|
|
|
|
(defun google-translate--suggestion (gtos)
|
|
"Return suggestion."
|
|
(let ((source-language (gtos-source-language gtos))
|
|
(target-language (gtos-target-language gtos))
|
|
(suggestion (gtos-suggestion gtos)))
|
|
(if suggestion
|
|
(with-temp-buffer
|
|
(insert "\n")
|
|
(let ((beg (point)))
|
|
(insert "Did you mean: ")
|
|
(facemenu-set-face 'google-translate-suggestion-label-face
|
|
beg (point)))
|
|
(goto-char (+ (point) 1))
|
|
(let ((beg (point)))
|
|
(insert-text-button suggestion
|
|
'action 'google-translate--suggestion-action
|
|
'follow-link t
|
|
'suggestion suggestion
|
|
'source-language source-language
|
|
'target-language target-language)
|
|
(facemenu-set-face 'google-translate-suggestion-face
|
|
beg (point))
|
|
(insert "\n"))
|
|
(buffer-substring (point-min) (point-max)))
|
|
"")))
|
|
|
|
(defun google-translate--suggestion-action (button)
|
|
"Suggestion action which occur when suggestion button is
|
|
clicked."
|
|
(interactive)
|
|
(let ((suggestion (button-get button 'suggestion))
|
|
(source-language (button-get button 'source-language))
|
|
(target-language (button-get button 'target-language)))
|
|
(google-translate-translate source-language
|
|
target-language
|
|
suggestion)))
|
|
|
|
(defun google-translate--listen-button (language text)
|
|
"Return listen button."
|
|
(with-temp-buffer
|
|
(insert " ")
|
|
(insert-text-button google-translate-listen-button-label
|
|
'action 'google-translate--listen-action
|
|
'face 'google-translate-listen-button-face
|
|
'follow-link t
|
|
'text text
|
|
'language language)
|
|
(insert "\n")
|
|
(buffer-substring (point-min) (point-max))))
|
|
|
|
(defun google-translate--listen-action (button)
|
|
"Do translation listening."
|
|
(interactive)
|
|
(let ((text (button-get button 'text))
|
|
(language (button-get button 'language)))
|
|
(google-translate-listen-translation language text)))
|
|
|
|
(defun google-translate-listen-translation (language text)
|
|
(let ((buf "*mplayer output*"))
|
|
(message "Retrieving audio message...")
|
|
(if google-translate-translation-listening-debug
|
|
(with-current-buffer (get-buffer-create buf)
|
|
(insert (format "Listen program: %s\r\n" google-translate-listen-program))
|
|
(insert (format "Listen URL: %s\r\n" (google-translate-format-listen-url text language)))
|
|
(call-process google-translate-listen-program nil t nil
|
|
(format "%s" (google-translate-format-listen-url text language)))
|
|
(switch-to-buffer buf))
|
|
(call-process google-translate-listen-program nil nil nil
|
|
(format "%s" (google-translate-format-listen-url text language))))))
|
|
|
|
(defun google-translate-translate (source-language target-language text &optional output-destination)
|
|
"Translate TEXT from SOURCE-LANGUAGE to TARGET-LANGUAGE.
|
|
|
|
In case of `google-translate-output-destination' is nil pops up a
|
|
buffer named *Google Translate* with available translations of
|
|
TEXT. In case of `google-translate-output-destination' is
|
|
`echo-area' outputs translation in the echo area. If
|
|
`google-translate-output-destination' is `popup' outputs
|
|
translation in the popup tooltip using `popup' package.
|
|
|
|
To deal with multi-line regions, sequences of white space
|
|
are replaced with a single space. If the region contains not text, a
|
|
message is printed."
|
|
(let* ((json (google-translate-request source-language
|
|
target-language
|
|
text)))
|
|
(if (null json)
|
|
(message "Nothing to translate.")
|
|
(let* ((detailed-translation
|
|
(google-translate-json-detailed-translation json))
|
|
(detailed-definition
|
|
(google-translate-json-detailed-definition json))
|
|
(gtos
|
|
(make-gtos
|
|
:source-language source-language
|
|
:target-language target-language
|
|
:auto-detected-language (aref json 2)
|
|
:text text
|
|
:text-phonetic (google-translate-json-text-phonetic json)
|
|
:translation (google-translate-json-translation json)
|
|
:translation-phonetic (google-translate-json-translation-phonetic json)
|
|
:detailed-translation detailed-translation
|
|
:detailed-definition detailed-definition
|
|
:suggestion (when (null detailed-translation)
|
|
(google-translate-json-suggestion json))))
|
|
(output-destination (if (null output-destination)
|
|
google-translate-output-destination
|
|
output-destination)))
|
|
(cond
|
|
((null output-destination)
|
|
(google-translate-buffer-output-translation gtos))
|
|
((equal output-destination 'echo-area)
|
|
(google-translate-echo-area-output-translation gtos))
|
|
((equal output-destination 'popup)
|
|
(google-translate-popup-output-translation gtos))
|
|
((equal output-destination 'kill-ring)
|
|
(google-translate-kill-ring-output-translation gtos))
|
|
((equal output-destination 'current-buffer)
|
|
(google-translate-current-buffer-output-translation gtos))
|
|
((equal output-destination 'help)
|
|
(let ((describe-func
|
|
(function
|
|
(lambda (gtos)
|
|
(google-translate-help-buffer-output-translation gtos)))))
|
|
(help-setup-xref (list 'google-translate-translate source-language target-language text) nil)
|
|
(with-help-window (help-buffer)
|
|
(funcall describe-func gtos)))))))))
|
|
|
|
(defun google-translate-popup-output-translation (gtos)
|
|
"Output translation to the popup tooltip using `popup'
|
|
package."
|
|
(require 'popup)
|
|
(popup-tip
|
|
(with-temp-buffer
|
|
(google-translate-insert-translation gtos)
|
|
(google-translate--trim-string
|
|
(buffer-substring (point-min) (point-max))))))
|
|
|
|
(defun google-translate-echo-area-output-translation (gtos)
|
|
"Output translation to the echo area (See
|
|
http://www.gnu.org/software/emacs/manual/html_node/elisp/The-Echo-Area.html)"
|
|
(message
|
|
(with-temp-buffer
|
|
(google-translate-insert-translation gtos)
|
|
(google-translate--trim-string
|
|
(buffer-substring (point-min) (point-max))))))
|
|
|
|
(defun google-translate-kill-ring-output-translation (gtos)
|
|
"Output translation to the kill ring."
|
|
(kill-new
|
|
(with-temp-buffer
|
|
(insert
|
|
(gtos-translation gtos))
|
|
(google-translate--trim-string
|
|
(buffer-substring (point-min) (point-max)))))
|
|
(message "Translated text was added to the kill ring."))
|
|
|
|
(defun google-translate-current-buffer-output-translation (gtos)
|
|
"Output translation to current buffer."
|
|
(insert
|
|
(gtos-translation gtos))
|
|
(message "Translated text was added to current buffer."))
|
|
|
|
(defun google-translate-insert-translation (gtos)
|
|
"Insert translation to the current buffer."
|
|
(let ((translation (gtos-translation gtos))
|
|
(detailed-translation (gtos-detailed-translation gtos)))
|
|
(insert
|
|
(google-translate--translation-title gtos "%s -> %s:")
|
|
(google-translate--translating-text gtos " %s")
|
|
(google-translate--text-phonetic gtos " [%s]")
|
|
" - "
|
|
(google-translate--translated-text gtos "%s")
|
|
(google-translate--translation-phonetic gtos " [%s]")
|
|
(if detailed-translation
|
|
(google-translate--detailed-translation
|
|
detailed-translation translation
|
|
"\n* %s " "%d. %s ")
|
|
(google-translate--suggestion gtos)))))
|
|
|
|
(defun google-translate-buffer-output-translation (gtos)
|
|
"Output translation to the temp buffer."
|
|
(let ((buffer-name "*Google Translate*"))
|
|
(with-output-to-temp-buffer buffer-name
|
|
(if google-translate-pop-up-buffer-set-focus
|
|
(select-window (display-buffer buffer-name))
|
|
(set-buffer buffer-name))
|
|
(google-translate-buffer-insert-translation gtos))))
|
|
|
|
(defun google-translate-help-buffer-output-translation (gtos)
|
|
"Output translation to the help buffer."
|
|
(and google-translate-pop-up-buffer-set-focus
|
|
(select-window (display-buffer "*Help*")))
|
|
(google-translate-buffer-insert-translation gtos))
|
|
|
|
(defun google-translate-buffer-insert-translation (gtos)
|
|
"Insert translation to the current temp buffer."
|
|
(let ((translation (gtos-translation gtos))
|
|
(detailed-translation (gtos-detailed-translation gtos))
|
|
(detailed-definition (gtos-detailed-definition gtos))
|
|
(source-language (gtos-source-language gtos))
|
|
(target-language (gtos-target-language gtos))
|
|
(auto-detected-language (gtos-auto-detected-language gtos))
|
|
(text (gtos-text gtos)))
|
|
(insert
|
|
(google-translate--translation-title gtos "Translate from %s to %s:\n")
|
|
"\n"
|
|
(google-translate--translating-text
|
|
gtos
|
|
(if (null google-translate-listen-program)
|
|
"%s\n"
|
|
"%s"))
|
|
(if google-translate-listen-program
|
|
(google-translate--listen-button
|
|
(if (string-equal source-language "auto")
|
|
auto-detected-language
|
|
source-language) text) "")
|
|
(google-translate--text-phonetic gtos "\n%s\n")
|
|
"\n"
|
|
(google-translate--translated-text
|
|
gtos
|
|
(if (null google-translate-listen-program)
|
|
"%s\n"
|
|
"%s"))
|
|
(if google-translate-listen-program
|
|
(google-translate--listen-button target-language translation) "")
|
|
(google-translate--translation-phonetic gtos "\n%s\n")
|
|
(if detailed-translation
|
|
(google-translate--detailed-translation
|
|
detailed-translation translation
|
|
"\n%s\n" "%2d. %s\n")
|
|
(google-translate--suggestion gtos))
|
|
(if detailed-definition
|
|
(google-translate--detailed-definition
|
|
detailed-definition translation
|
|
"\n%s\n" "%2d. %s\n")
|
|
""))))
|
|
|
|
(defun google-translate-read-source-language (&optional prompt)
|
|
"Read a source language, with completion, and return its abbreviation.
|
|
|
|
The null input is equivalent to \"Detect language\"."
|
|
(let ((completion-ignore-case t)
|
|
(prompt
|
|
(if (null prompt)
|
|
"Translate from: "
|
|
prompt)))
|
|
(google-translate-language-abbreviation
|
|
(google-translate-completing-read
|
|
prompt
|
|
(google-translate-supported-languages)
|
|
"Detect language"))))
|
|
|
|
(defun google-translate-read-target-language (&optional prompt)
|
|
"Read a target language, with completion, and return its abbreviation.
|
|
|
|
The input is guaranteed to be non-null."
|
|
(let ((completion-ignore-case t)
|
|
(prompt
|
|
(if (null prompt)
|
|
"Translate to: "
|
|
prompt)))
|
|
(cl-flet ((read-language ()
|
|
(google-translate-completing-read
|
|
prompt
|
|
(google-translate-supported-languages))))
|
|
(let ((target-language (read-language)))
|
|
(while (string-equal target-language "")
|
|
(setq target-language (read-language)))
|
|
(google-translate-language-abbreviation target-language)))))
|
|
|
|
(defun google-translate-completing-read (prompt choices &optional def)
|
|
"Read a string in the minibuffer with completion.
|
|
|
|
If `google-translate-enable-ido-completion' is non-NIL, use
|
|
ido-style completion."
|
|
(funcall (if google-translate-enable-ido-completion
|
|
#'ido-completing-read
|
|
#'completing-read)
|
|
prompt choices nil t nil nil def))
|
|
|
|
(provide 'google-translate-core-ui)
|
|
|
|
;;; google-translate-core-ui.el ends here
|