emacs.d/elpa/google-translate-20190620.1416/google-translate-core.el

266 lines
9.7 KiB
EmacsLisp
Raw Normal View History

2020-02-14 23:09:34 +01:00
;;; google-translate-core.el --- google-translate core script.
;; 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 file is the core of `google-translate' package. It does contains
;; the most important and vital functions and variables for the
;; package functionality.
;;
;; The most important is the `google-translate-request' function which
;; is intended to be used by other scripts and packages, expecially by
;; the packages which provides UI.
;;
;; This, `google-translate-core', package doesn't provide any UI.
;;
;; `google-translate-request' function sends http request to the
;; google service and returns JSON response which contains translation
;; and other info.
;;
;; There are also a set of helper functions which are going to be
;; useful to retrieve data from the mentioned JSON response:
;;
;; `google-translate-json-text-phonetic' - retrieves text phonetic;
;;
;; `google-translate-json-translation' - retrieves translation;
;;
;; `google-translate-json-translation-phonetic' - retrieves
;; phonetic translation;
;;
;; `google-translate-json-detailed-translation' - retrieves
;; additional, detailed information which relates to the
;; translation.
;;
;;; Code:
(eval-when-compile (require 'cl))
(require 'json)
(require 'url)
(require 'google-translate-tk)
(defgroup google-translate-core nil
"Google Translate core script."
:group 'processes)
(defvar google-translate-base-url
"http://translate.google.com/translate_a/single")
(defvar google-translate-listen-url
"http://translate.google.com/translate_tts")
(defun google-translate--format-query-string (query-params)
"Format QUERY-PARAMS as a query string.
QUERY-PARAMS must be an alist of field-value pairs."
(mapconcat #'(lambda (p)
(format "%s=%s"
(url-hexify-string (car p))
(url-hexify-string (cdr p))))
query-params "&"))
(defun google-translate--format-request-url (query-params)
"Format QUERY-PARAMS as a Google Translate HTTP request URL.
QUERY-PARAMS must be an alist of field-value pairs."
(concat google-translate-base-url
"?"
(google-translate--format-query-string query-params)))
(defun google-translate--format-listen-url (query-params)
"Format QUERY-PARAMS as a Google Translate HTTP request URL for listen translation.
QUERY-PARAMS must be an alist of field-value pairs."
(concat google-translate-listen-url
"?"
(google-translate--format-query-string query-params)))
(defun google-translate-format-listen-url (text language)
"Format listen url for TEXT and TARGET-LANGUAGE."
(google-translate--format-listen-url `(("ie" . "UTF-8")
("q" . ,text)
("tl" . ,language)
("total" . "1")
("idx" . "0")
("textlen" . ,(number-to-string (length text)))
("client" . "t")
("prev" . "input")
("tk" . ,(google-translate--gen-tk text)))))
(defun google-translate--http-response-body (url &optional for-test-purposes)
"Retrieve URL and return the response body as a string."
(let ((google-translate-backend-debug (or for-test-purposes
google-translate-backend-debug)))
(with-temp-buffer
(save-excursion
(google-translate-backend-retrieve url))
(set-buffer-multibyte t)
(buffer-string))))
(defun google-translate--insert-nulls (string)
"Google Translate responses with an almost valid JSON string
respresentation except that the nulls appear to be dropped. In
particular the response may contain the substrings \"[,\",
\",,\", and \",]\". This function undoes that."
(with-temp-buffer
(set-buffer-multibyte t)
(insert string)
(goto-char (point-min))
(while (re-search-forward "\\(\\[,\\|,,\\|,\\]\\)" (point-max) t)
(backward-char)
(insert "null"))
(buffer-string)))
(defun google-translate--trim-string (string)
"Remove whitespaces in beginning and ending of STRING.
White space here is any of: space, tab, emacs newline (line feed, ASCII 10)."
(replace-regexp-in-string "\\`[ \t\n\r]*" ""
(replace-regexp-in-string "[ \t\n\r]*\\'" "" string)))
(defun google-translate--strip-string (string)
"Replace spaces, tabs, line feeds (ASCII 10) and carridge
returns (ASCII 13) by a single space symbol."
(replace-regexp-in-string "[[:space:]\n\r]+" " " string))
(defun google-translate-prepare-text-for-request (text)
"Make TEXT as clean as possible berofe sending it in the
request."
(google-translate--trim-string
(google-translate--strip-string text)))
(defun google-translate-request (source-language target-language text)
"Send to the Google Translate http request which consigned to
translate TEXT from SOURCE-LANGUAGE to TARGET-LANGUAGE. Returns
response in json format."
(let ((cleaned-text (google-translate-prepare-text-for-request text)))
(when (and
(stringp cleaned-text)
(> (length cleaned-text) 0))
(json-read-from-string
(google-translate--insert-nulls
(google-translate--request source-language target-language text))))))
(defun google-translate--request (source-language
target-language
text
&optional for-test-purposes)
"Send to the Google Translate http request which consigned to
translate TEXT from SOURCE-LANGUAGE to TARGET-LANGUAGE."
(google-translate--http-response-body
(google-translate--format-request-url
`(("client" . "t")
("ie" . "UTF-8")
("oe" . "UTF-8")
("sl" . ,source-language)
("tl" . ,target-language)
("q" . ,text)
("dt" . "bd")
("dt" . "ex")
("dt" . "ld")
("dt" . "md")
("dt" . "qc")
("dt" . "rw")
("dt" . "rm")
("dt" . "ss")
("dt" . "t")
("dt" . "at")
("pc" . "1")
("otf" . "1")
("srcrom" . "1")
("ssel" . "0")
("tsel" . "0")
("tk" . ,(google-translate--gen-tk text))))
for-test-purposes))
(defun google-translate-json-text-phonetic (json)
"Retrieve from the JSON (which returns by the
`google-translate-request' function) phonetic transcription of
the translating text."
(mapconcat (lambda (item) (if (> (length item) 3) (aref item 3) ""))
(aref json 0) ""))
(defun google-translate-json-translation (json)
"Retrieve from the JSON (which returns by the
`google-translate-request' function) translation of the
translating text."
(mapconcat #'(lambda (item) (aref item 0))
(aref json 0) ""))
(defun google-translate-json-translation-phonetic (json)
"Retrieve from the JSON (which returns by the
`google-translate-request' function) phonetic transcription of
the translating text."
(mapconcat #'(lambda (item) (if (> (length item) 2) (aref item 2) ""))
(aref json 0) ""))
(defun google-translate-json-detailed-translation (json)
"Retrieve from the JSON (which returns by the
`google-translate-request' function) a dictionary article
represented by a vector of items, where each item is a 2-element
vector whose zeroth element is the name of a part of speech and
whose first element is a vector of translations for that part of
speech."
(aref json 1))
(defun google-translate-json-detailed-definition (json)
"Retrieve the definition of translating text in source language from the JSON
which returned by the `google-translate-request' function.
This function returns the definition if it's included within the JSON as 12th
element, or returns nil if not included.
The definition is a dictionary article represented by a vector of items, where
each item is a 2-element vector whose zeroth element is the name of a part of
speech and whose first element is a vector of definitions for that part of
speech."
(if (> (length json) 12)
(aref json 12)))
(defun google-translate-json-suggestion (json)
"Retrieve from JSON (which returns by the
`google-translate-request' function) suggestion. This function
does matter when translating misspelled word. So instead of
translation it is possible to get suggestion."
(let ((info (aref json 7)))
(when info
(aref info 1))))
(defun google-translate-version ()
(interactive)
(message "Google Translate (version): %s" "0.11.18"))
(provide 'google-translate-core)
;;; google-translate-core.el ends here