rev |
line source |
domcox@8451
|
1 ;;; text-translator.el --- Text Translator
|
domcox@8451
|
2
|
domcox@8451
|
3 ;; Copyright (C) 2007-2010 khiker
|
domcox@8451
|
4
|
domcox@8451
|
5 ;; Author: khiker <khiker.mail+elisp@gmail.com>
|
domcox@8451
|
6 ;; plus <MLB33828@nifty.com>
|
domcox@8451
|
7
|
domcox@8451
|
8 ;; This file is free software; you can redistribute it and/or modify
|
domcox@8451
|
9 ;; it under the terms of the GNU General Public License as published by
|
domcox@8451
|
10 ;; the Free Software Foundation; either version 2, or (at your option)
|
domcox@8451
|
11 ;; any later version.
|
domcox@8451
|
12
|
domcox@8451
|
13 ;; This file is distributed in the hope that it will be useful,
|
domcox@8451
|
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
domcox@8451
|
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
domcox@8451
|
16 ;; GNU General Public License for more details.
|
domcox@8451
|
17
|
domcox@8451
|
18 ;; You should have received a copy of the GNU General Public License
|
domcox@8451
|
19 ;; along with GNU Emacs; see the file COPYING. If not, write to
|
domcox@8451
|
20 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
domcox@8451
|
21 ;; Boston, MA 02110-1301, USA.
|
domcox@8451
|
22
|
domcox@8451
|
23 ;;; Commentary:
|
domcox@8451
|
24
|
domcox@8451
|
25 ;; Translates character strings on Emacs.
|
domcox@8451
|
26 ;; This package use the text translation service that exists on the internet.
|
domcox@8451
|
27
|
domcox@8451
|
28 ;; Read README.en (English) or README.ja (Japanese).
|
domcox@8451
|
29
|
domcox@8451
|
30 ;;; Code:
|
domcox@8451
|
31
|
domcox@8451
|
32 (require 'text-translator-vars)
|
domcox@8451
|
33
|
domcox@8451
|
34 (defun text-translator (arg &optional last engine-or-func)
|
domcox@8451
|
35 "The function which does text translation.
|
domcox@8451
|
36 Use Excite, Google and so translation site.
|
domcox@8451
|
37 1. Mark is active
|
domcox@8451
|
38 - Prefix was supplied.
|
domcox@8451
|
39 1. Choose translation site which you use.
|
domcox@8451
|
40 2. Translate by type which you selected.
|
domcox@8451
|
41 - Prefix was not supplied.
|
domcox@8451
|
42 Translate range of region that you selected by
|
domcox@8451
|
43 first element of `text-translator-engine-history'.
|
domcox@8451
|
44 (If `text-translator-engine-history' is nil,
|
domcox@8451
|
45 use `text-translator-default-engine'.)
|
domcox@8451
|
46 2. Mark is deactive
|
domcox@8451
|
47 - Prefix was supplied.
|
domcox@8451
|
48 1. Choose translation site which you use.
|
domcox@8451
|
49 2. Translate value which you input from minibuffer by type you selected.
|
domcox@8451
|
50 - Prefix was not supplied.
|
domcox@8451
|
51 Translate value which you input from minibuffer by
|
domcox@8451
|
52 first element of `text-translator-engine-history'.
|
domcox@8451
|
53 (If `text-translator-engine-history' is nil,
|
domcox@8451
|
54 use `text-translator-default-engine'.)"
|
domcox@8451
|
55 (interactive "P")
|
domcox@8451
|
56 (add-to-list 'text-translator-engine-history text-translator-default-engine)
|
domcox@8451
|
57 (let ((minibuffer-history text-translator-engine-history)
|
domcox@8451
|
58 (engine (text-translator-check-valid-translation-engine
|
domcox@8451
|
59 engine-or-func (car text-translator-engine-history)))
|
domcox@8451
|
60 str)
|
domcox@8451
|
61 ;; If prefix-arg is non-nil, change translation type.
|
domcox@8451
|
62 (when (or arg last)
|
domcox@8451
|
63 (setq engine (completing-read
|
domcox@8451
|
64 (format "Select translation engine (default %s): " engine)
|
domcox@8451
|
65 text-translator-site-data-alist nil t nil nil engine)))
|
domcox@8451
|
66 (setq str
|
domcox@8451
|
67 (cond
|
domcox@8451
|
68 (last
|
domcox@8451
|
69 text-translator-last-string)
|
domcox@8451
|
70 (t
|
domcox@8451
|
71 (text-translator-region-or-read-string
|
domcox@8451
|
72 (format "Enter string translated by %s: " engine)))))
|
domcox@8451
|
73 (text-translator-client
|
domcox@8451
|
74 (text-translator-check-valid-translation-engine
|
domcox@8451
|
75 (and (functionp engine-or-func) (funcall engine-or-func engine str))
|
domcox@8451
|
76 engine)
|
domcox@8451
|
77 str)))
|
domcox@8451
|
78
|
domcox@8451
|
79 (defun text-translator-translate-by-auto-selection (arg)
|
domcox@8451
|
80 "Function that translates by auto selection of translation engine.
|
domcox@8451
|
81 Function that select automatically is value of `text-translator-auto-selection-func'."
|
domcox@8451
|
82 (interactive "P")
|
domcox@8451
|
83 (text-translator arg nil text-translator-auto-selection-func))
|
domcox@8451
|
84
|
domcox@8451
|
85 (defun text-translator-translate-by-auto-selection-enja (engine str)
|
domcox@8451
|
86 "Automatic selection function for English to Japanese(or Japanese to English)
|
domcox@8451
|
87 translation.
|
domcox@8451
|
88 If alphabet ratio is over 40%, select engine which is translating from English to Japanese.
|
domcox@8451
|
89 Otherwise, from Japanese to English."
|
domcox@8451
|
90 (setq str (or str ""))
|
domcox@8451
|
91 (format
|
domcox@8451
|
92 "%s_%s"
|
domcox@8451
|
93 (text-translator-get-engine-type-or-site engine t)
|
domcox@8451
|
94 (if (> (/ (* (length (replace-regexp-in-string "[^A-Za-z]+" "" str)) 100)
|
domcox@8451
|
95 (length str))
|
domcox@8451
|
96 40)
|
domcox@8451
|
97 "enja" "jaen")))
|
domcox@8451
|
98
|
domcox@8451
|
99 (defun text-translator-translate-last-string ()
|
domcox@8451
|
100 "The function to translate in the translation site that
|
domcox@8451
|
101 I choose with the character string that I translated in the last time."
|
domcox@8451
|
102 (interactive)
|
domcox@8451
|
103 (text-translator nil t))
|
domcox@8451
|
104
|
domcox@8451
|
105
|
domcox@8451
|
106 (defun text-translator-region-or-read-string (&optional prompt)
|
domcox@8451
|
107 "If mark is active, return the region, otherwise, read string with PROMPT."
|
domcox@8451
|
108 (cond
|
domcox@8451
|
109 (mark-active
|
domcox@8451
|
110 (buffer-substring-no-properties (region-beginning) (region-end)))
|
domcox@8451
|
111 (t
|
domcox@8451
|
112 (read-string (or prompt "Enter string: ")))))
|
domcox@8451
|
113
|
domcox@8451
|
114 (defun text-translator-all (arg &optional key str)
|
domcox@8451
|
115 "The function to translate in all of translate sites that matches
|
domcox@8451
|
116 the selected type."
|
domcox@8451
|
117 (interactive "P")
|
domcox@8451
|
118 (let ((hash text-translator-sitedata-hash)
|
domcox@8451
|
119 keys)
|
domcox@8451
|
120 (setq str (or str (text-translator-region-or-read-string)))
|
domcox@8451
|
121 (when (or (null hash)
|
domcox@8451
|
122 arg)
|
domcox@8451
|
123 (setq text-translator-sitedata-hash
|
domcox@8451
|
124 (text-translator-update-hashtable))
|
domcox@8451
|
125 (setq hash text-translator-sitedata-hash))
|
domcox@8451
|
126 (maphash '(lambda (x y)
|
domcox@8451
|
127 (setq keys (cons x keys)))
|
domcox@8451
|
128 hash)
|
domcox@8451
|
129 (setq key (or key (completing-read "Select type: " keys nil t)))
|
domcox@8451
|
130 (when key
|
domcox@8451
|
131 (save-selected-window
|
domcox@8451
|
132 (pop-to-buffer text-translator-buffer)
|
domcox@8451
|
133 (setq buffer-read-only nil)
|
domcox@8451
|
134 (erase-buffer)
|
domcox@8451
|
135 (text-translator-mode))
|
domcox@8451
|
136 (let ((sites (gethash key hash)))
|
domcox@8451
|
137 (setq text-translator-last-string str)
|
domcox@8451
|
138 (setq text-translator-search-regexp-or-func
|
domcox@8451
|
139 (concat "_" key))
|
domcox@8451
|
140 (dolist (i sites)
|
domcox@8451
|
141 (text-translator-client i str t))))))
|
domcox@8451
|
142
|
domcox@8451
|
143 (defun text-translator-all-by-auto-selection (arg)
|
domcox@8451
|
144 "The function to translate in all of translate sites, whose translation engine is selected automatically.
|
domcox@8451
|
145 The selection function is the value of `text-translator-auto-selection-func'."
|
domcox@8451
|
146 (interactive "P")
|
domcox@8451
|
147 (let ((str (text-translator-region-or-read-string)))
|
domcox@8451
|
148 (text-translator-all
|
domcox@8451
|
149 arg
|
domcox@8451
|
150 (substring (funcall text-translator-auto-selection-func "" str) 1)
|
domcox@8451
|
151 str)))
|
domcox@8451
|
152
|
domcox@8451
|
153 (defun text-translator-client (engine str &optional all)
|
domcox@8451
|
154 "Function that throws out words and phrases that want to translate into
|
domcox@8451
|
155 specified site, and receives translation result."
|
domcox@8451
|
156 (let* ((history-delete-duplicates t)
|
domcox@8451
|
157 (buf (cond (all
|
domcox@8451
|
158 (concat text-translator-work-buffer
|
domcox@8451
|
159 (replace-regexp-in-string "_.*"
|
domcox@8451
|
160 ""
|
domcox@8451
|
161 engine)))
|
domcox@8451
|
162 (t
|
domcox@8451
|
163 text-translator-work-buffer)))
|
domcox@8451
|
164 (alist
|
domcox@8451
|
165 (cond
|
domcox@8451
|
166 ((not text-translator-do-fill-region)
|
domcox@8451
|
167 text-translator-pre-string-replace-alist)
|
domcox@8451
|
168 ;; for example, if engine is "excite.co.jp_enja",
|
domcox@8451
|
169 ;; this code returns "en".
|
domcox@8451
|
170 ((member (substring
|
domcox@8451
|
171 (text-translator-get-engine-type-or-site engine) 0 2)
|
domcox@8451
|
172 text-translator-space-division-languages)
|
domcox@8451
|
173 ;; replace "\n" to " ".
|
domcox@8451
|
174 (append '(("\n" . " ") ("\r" . ""))
|
domcox@8451
|
175 text-translator-pre-string-replace-alist))
|
domcox@8451
|
176 (t
|
domcox@8451
|
177 ;; replace "\n" to "".
|
domcox@8451
|
178 (append '(("\n" . "") ("\r" . ""))
|
domcox@8451
|
179 text-translator-pre-string-replace-alist))))
|
domcox@8451
|
180 (str (text-translator-replace-string str alist))
|
domcox@8451
|
181 (type (assoc engine text-translator-site-data-alist))
|
domcox@8451
|
182 (proc (open-network-stream "Web Connection" buf
|
domcox@8451
|
183 (or text-translator-proxy-server
|
domcox@8451
|
184 (nth 1 type))
|
domcox@8451
|
185 (or (and text-translator-proxy-server
|
domcox@8451
|
186 text-translator-proxy-port)
|
domcox@8451
|
187 80)))
|
domcox@8451
|
188 ;;(process-connection-type nil)
|
domcox@8451
|
189 (enc-str (text-translator-url-encode-string str (nth 4 type)))
|
domcox@8451
|
190 (post-str (if (nth 3 type) (format (nth 3 type) enc-str) nil))
|
domcox@8451
|
191 (truncate-partial-width-windows nil))
|
domcox@8451
|
192 (unless all
|
domcox@8451
|
193 (add-to-history 'text-translator-engine-history engine)
|
domcox@8451
|
194 (setq text-translator-search-regexp-or-func (nth 5 type))
|
domcox@8451
|
195 (setq text-translator-last-string str))
|
domcox@8451
|
196 (with-current-buffer (get-buffer-create buf)
|
domcox@8451
|
197 (erase-buffer)
|
domcox@8451
|
198 (set-process-coding-system proc (nth 4 type) 'binary)
|
domcox@8451
|
199 (set-process-filter proc 'text-translator-client-filter)
|
domcox@8451
|
200 (process-send-string
|
domcox@8451
|
201 proc
|
domcox@8451
|
202 (concat
|
domcox@8451
|
203 (cond
|
domcox@8451
|
204 (post-str
|
domcox@8451
|
205 ;; use POST method
|
domcox@8451
|
206 (concat "POST " (nth 2 type) "\r\n"))
|
domcox@8451
|
207 (t
|
domcox@8451
|
208 ;; use GET method
|
domcox@8451
|
209 (concat "GET " (format (nth 2 type) enc-str) "\r\n")))
|
domcox@8451
|
210 (and text-translator-proxy-server
|
domcox@8451
|
211 text-translator-proxy-user
|
domcox@8451
|
212 text-translator-proxy-password
|
domcox@8451
|
213 (format "Proxy-Authorization: Basic %s \r\n"
|
domcox@8451
|
214 (base64-encode-string
|
domcox@8451
|
215 (concat text-translator-proxy-user ":"
|
domcox@8451
|
216 text-translator-proxy-password))))
|
domcox@8451
|
217 "HOST: " (nth 1 type) "\r\n"
|
domcox@8451
|
218 "User-Agent: " text-translator-user-agent "\r\n"
|
domcox@8451
|
219 ;; "Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5" "\r\n"
|
domcox@8451
|
220 ;; "Accept-Language: ja,en-us;q=0.7,en;q=0.3" "\r\n"
|
domcox@8451
|
221 "Accept-Encoding: identity\r\n"
|
domcox@8451
|
222 "Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7\r\n"
|
domcox@8451
|
223 "Keep-Alive: 300" "\r\n"
|
domcox@8451
|
224 "Connection: keep-alive" "\r\n"
|
domcox@8451
|
225 (when post-str
|
domcox@8451
|
226 (concat
|
domcox@8451
|
227 "Content-Type: application/x-www-form-urlencoded\r\n"
|
domcox@8451
|
228 "Content-Length: "
|
domcox@8451
|
229 (number-to-string (string-bytes post-str)) "\r\n"
|
domcox@8451
|
230 "\r\n"
|
domcox@8451
|
231 post-str "\r\n"))
|
domcox@8451
|
232 "\r\n"))
|
domcox@8451
|
233 (message "Translating...")
|
domcox@8451
|
234 (unless (or all
|
domcox@8451
|
235 text-translator-display-popup)
|
domcox@8451
|
236 (save-selected-window
|
domcox@8451
|
237 (pop-to-buffer text-translator-buffer)
|
domcox@8451
|
238 (setq buffer-read-only nil)
|
domcox@8451
|
239 (erase-buffer)
|
domcox@8451
|
240 (text-translator-mode)
|
domcox@8451
|
241 (setq mode-line-buffer-identification
|
domcox@8451
|
242 `("%b [" ,(car text-translator-engine-history) "]")))))))
|
domcox@8451
|
243
|
domcox@8451
|
244 (defun text-translator-client-filter (proc str)
|
domcox@8451
|
245 (let ((regex-or-func text-translator-search-regexp-or-func)
|
domcox@8451
|
246 bname all-flag)
|
domcox@8451
|
247 (with-current-buffer (process-buffer proc)
|
domcox@8451
|
248 (goto-char (process-mark proc))
|
domcox@8451
|
249 (insert (format "%s" str))
|
domcox@8451
|
250 (set-marker (process-mark proc) (point))
|
domcox@8451
|
251 (setq bname (buffer-name))
|
domcox@8451
|
252 (setq all-flag (not (string= bname text-translator-work-buffer)))
|
domcox@8451
|
253 (when all-flag
|
domcox@8451
|
254 (setq regex-or-func
|
domcox@8451
|
255 (nth 5
|
domcox@8451
|
256 (assoc (concat
|
domcox@8451
|
257 (substring bname
|
domcox@8451
|
258 (length text-translator-work-buffer)
|
domcox@8451
|
259 (length bname))
|
domcox@8451
|
260 regex-or-func)
|
domcox@8451
|
261 text-translator-site-data-alist))))
|
domcox@8451
|
262 (setq str (text-translator-replace-string
|
domcox@8451
|
263 (or (cond
|
domcox@8451
|
264 ((functionp regex-or-func)
|
domcox@8451
|
265 (funcall regex-or-func))
|
domcox@8451
|
266 ((re-search-backward regex-or-func nil t)
|
domcox@8451
|
267 (match-string 1)))
|
domcox@8451
|
268 "")
|
domcox@8451
|
269 text-translator-post-string-replace-alist))
|
domcox@8451
|
270 (unless (string= "" str)
|
domcox@8451
|
271 (delete-process proc)
|
domcox@8451
|
272 (setq bname (buffer-name))
|
domcox@8451
|
273 (setq all-flag (not (string= bname text-translator-work-buffer)))
|
domcox@8451
|
274 (when (or all-flag
|
domcox@8451
|
275 (not text-translator-display-popup))
|
domcox@8451
|
276 (text-translator-display-window str bname all-flag))))
|
domcox@8451
|
277 ;; To display in popup-tip, buffer is out of with-current-buffer.
|
domcox@8451
|
278 (when (and (not (string= "" str))
|
domcox@8451
|
279 (not all-flag)
|
domcox@8451
|
280 (fboundp 'popup-tip)
|
domcox@8451
|
281 (eq text-translator-display-popup t))
|
domcox@8451
|
282 (text-translator-display-popup str))))
|
domcox@8451
|
283
|
domcox@8451
|
284 (defun text-translator-display-window (str buf all-flag)
|
domcox@8451
|
285 (let ((window (get-buffer-window text-translator-buffer))
|
domcox@8451
|
286 (window-min-height
|
domcox@8451
|
287 (if (> text-translator-window-min-height (/ (frame-height) 2))
|
domcox@8451
|
288 (/ (frame-height) 2)
|
domcox@8451
|
289 (1+ text-translator-window-min-height))))
|
domcox@8451
|
290 (set-buffer text-translator-buffer)
|
domcox@8451
|
291 (setq buffer-read-only nil)
|
domcox@8451
|
292 (cond
|
domcox@8451
|
293 (all-flag
|
domcox@8451
|
294 (insert (concat
|
domcox@8451
|
295 (propertize
|
domcox@8451
|
296 (format "----- %s -----\n"
|
domcox@8451
|
297 (substring buf
|
domcox@8451
|
298 (length text-translator-work-buffer)
|
domcox@8451
|
299 (length buf)))
|
domcox@8451
|
300 'face font-lock-keyword-face)
|
domcox@8451
|
301 str "\n\n")))
|
domcox@8451
|
302 (t (when text-translator-leave-string
|
domcox@8451
|
303 (insert
|
domcox@8451
|
304 (concat
|
domcox@8451
|
305 (propertize "----- Original -----\n"
|
domcox@8451
|
306 'face font-lock-keyword-face)
|
domcox@8451
|
307 text-translator-last-string
|
domcox@8451
|
308 "\n\n"
|
domcox@8451
|
309 (propertize "***** Translation *****\n"
|
domcox@8451
|
310 'face font-lock-keyword-face))))
|
domcox@8451
|
311 (insert (concat str "\n"))
|
domcox@8451
|
312 (when text-translator-do-fill-region
|
domcox@8451
|
313 (goto-char (- (point) (/ (length str) 2)))
|
domcox@8451
|
314 (call-interactively 'fill-paragraph))
|
domcox@8451
|
315 (set-buffer-modified-p nil)
|
domcox@8451
|
316 ;; adjust window height
|
domcox@8451
|
317 (when (and text-translator-auto-window-adjust
|
domcox@8451
|
318 (window-live-p window))
|
domcox@8451
|
319 (balance-windows)
|
domcox@8451
|
320 (shrink-window-if-larger-than-buffer window))
|
domcox@8451
|
321 (message "") ; prevent minibuffer from becoming two line.
|
domcox@8451
|
322 (ding)
|
domcox@8451
|
323 (message "Translating...done")))))
|
domcox@8451
|
324
|
domcox@8451
|
325 (defun text-translator-display-popup (str)
|
domcox@8451
|
326 (let ((read-only-p buffer-read-only))
|
domcox@8451
|
327 (setq str (with-temp-buffer
|
domcox@8451
|
328 (insert str)
|
domcox@8451
|
329 (when text-translator-do-fill-region
|
domcox@8451
|
330 (goto-char (- (point) (/ (length str) 2)))
|
domcox@8451
|
331 (call-interactively 'fill-paragraph))
|
domcox@8451
|
332 (buffer-string)))
|
domcox@8451
|
333 (ding)
|
domcox@8451
|
334 (message "Translating...done")
|
domcox@8451
|
335 (if read-only-p
|
domcox@8451
|
336 ;; temporay cancel buffer-read-only
|
domcox@8451
|
337 (unwind-protect (progn
|
domcox@8451
|
338 (setq buffer-read-only nil)
|
domcox@8451
|
339 (popup-tip str :margin t))
|
domcox@8451
|
340 (setq buffer-read-only t))
|
domcox@8451
|
341 (popup-tip str :margin t))))
|
domcox@8451
|
342
|
domcox@8451
|
343 (defun text-translator-update-hashtable ()
|
domcox@8451
|
344 (let ((hash (make-hash-table :test 'equal)))
|
domcox@8451
|
345 (mapc '(lambda (x)
|
domcox@8451
|
346 (let ((matched (replace-regexp-in-string "\\([^_]*\\)_"
|
domcox@8451
|
347 ""
|
domcox@8451
|
348 (car x))))
|
domcox@8451
|
349 (unless (or (string= (car x) matched)
|
domcox@8451
|
350 (eq ?* (aref matched 0)))
|
domcox@8451
|
351 (cond
|
domcox@8451
|
352 ((gethash matched hash)
|
domcox@8451
|
353 (puthash matched
|
domcox@8451
|
354 (cons (car x) (gethash matched hash))
|
domcox@8451
|
355 hash))
|
domcox@8451
|
356 (t
|
domcox@8451
|
357 (puthash matched (list (car x)) hash))))))
|
domcox@8451
|
358 text-translator-site-data-alist)
|
domcox@8451
|
359 hash))
|
domcox@8451
|
360
|
domcox@8451
|
361 (defun text-translator-replace-string (str replace)
|
domcox@8451
|
362 "Function that converts character string specified for argument STR
|
domcox@8451
|
363 according to rule REPLACE."
|
domcox@8451
|
364 (with-temp-buffer
|
domcox@8451
|
365 (insert str)
|
domcox@8451
|
366 ;; convert unusable string
|
domcox@8451
|
367 (format-replace-strings replace)
|
domcox@8451
|
368 (buffer-string)))
|
domcox@8451
|
369
|
domcox@8451
|
370 (defun text-translator-extract-tag-exclusion-string (regex &optional dont-convert-br)
|
domcox@8451
|
371 ;; (when (re-search-backward regex nil t)
|
domcox@8451
|
372 (when (re-search-backward regex nil t)
|
domcox@8451
|
373 ;; first: convert <br> tag to '\n' (when variable dont-convert-br is nil)
|
domcox@8451
|
374 ;; second: convert any another tags to empty string.
|
domcox@8451
|
375 (let ((matchstr (match-string 1)))
|
domcox@8451
|
376 (setq matchstr
|
domcox@8451
|
377 (text-translator-replace-string
|
domcox@8451
|
378 matchstr
|
domcox@8451
|
379 text-translator-post-string-replace-alist))
|
domcox@8451
|
380 (replace-regexp-in-string
|
domcox@8451
|
381 "<.*?>" "" (if dont-convert-br
|
domcox@8451
|
382 matchstr
|
domcox@8451
|
383 (replace-regexp-in-string
|
domcox@8451
|
384 "<[bB][rR]\\( /\\)?>" "\n" matchstr))))))
|
domcox@8451
|
385
|
domcox@8451
|
386 ;;;; major-mode text-translator-mode
|
domcox@8451
|
387
|
domcox@8451
|
388 ;; variables for major mode
|
domcox@8451
|
389 (defvar text-translator-mode nil)
|
domcox@8451
|
390 (defvar text-translator-mode-map nil)
|
domcox@8451
|
391 (defvar text-translator-mode-pkey-map nil)
|
domcox@8451
|
392 (defvar text-translator-mode-syntax-table nil)
|
domcox@8451
|
393 (defvar text-translator-mode-abbrev-table nil)
|
domcox@8451
|
394 (define-abbrev-table 'text-translator-mode-abbrev-table ())
|
domcox@8451
|
395
|
domcox@8451
|
396 ;; keymap definition
|
domcox@8451
|
397 (unless text-translator-mode-map
|
domcox@8451
|
398 (setq text-translator-mode-map (make-sparse-keymap))
|
domcox@8451
|
399 (define-prefix-command 'text-translator-mode-pkey-map)
|
domcox@8451
|
400 (let ((map text-translator-mode-pkey-map))
|
domcox@8451
|
401 (define-key map "\C-q" 'text-translator-quit)
|
domcox@8451
|
402 (define-key map "\C-a" 'text-translator-translate-recent-type)
|
domcox@8451
|
403 (define-key map "\C-l" 'text-translator-display-last-string)
|
domcox@8451
|
404 (define-key map "\C-d" 'text-translator-translate-default)
|
domcox@8451
|
405 (define-key map "\C-s" 'text-translator-toggle-leave-string)))
|
domcox@8451
|
406
|
domcox@8451
|
407 ;; major-mode
|
domcox@8451
|
408 (defun text-translator-mode ()
|
domcox@8451
|
409 "Major mode for text-translator."
|
domcox@8451
|
410 (kill-all-local-variables)
|
domcox@8451
|
411 (setq local-abbrev-table text-translator-mode-abbrev-table)
|
domcox@8451
|
412 (set-syntax-table text-translator-mode-syntax-table)
|
domcox@8451
|
413 (setq mode-name text-translator-mode-name)
|
domcox@8451
|
414 (setq major-mode 'text-translator-mode)
|
domcox@8451
|
415 (define-key text-translator-mode-map
|
domcox@8451
|
416 text-translator-prefix-key text-translator-mode-pkey-map)
|
domcox@8451
|
417 (use-local-map text-translator-mode-map)
|
domcox@8451
|
418 (run-hooks 'text-translator-mode-hook))
|
domcox@8451
|
419
|
domcox@8451
|
420 ;; syntax-table
|
domcox@8451
|
421 (unless text-translator-mode-syntax-table
|
domcox@8451
|
422 (setq text-translator-mode-syntax-table (make-syntax-table)))
|
domcox@8451
|
423
|
domcox@8451
|
424 ;; functions for major-mode
|
domcox@8451
|
425 (defun text-translator-quit ()
|
domcox@8451
|
426 "Function that closes buffer for text-translator.
|
domcox@8451
|
427 If window only have *translated* buffer, change another buffer."
|
domcox@8451
|
428 (interactive)
|
domcox@8451
|
429 (bury-buffer)
|
domcox@8451
|
430 (unless (one-window-p)
|
domcox@8451
|
431 (delete-window)))
|
domcox@8451
|
432
|
domcox@8451
|
433 (defun text-translator-toggle-leave-string ()
|
domcox@8451
|
434 "Function that change value of `text-translator-leave-string'.
|
domcox@8451
|
435 Toggle to display a translation result buffer of character
|
domcox@8451
|
436 string that used last time."
|
domcox@8451
|
437 (interactive)
|
domcox@8451
|
438 (setq text-translator-leave-string (not text-translator-leave-string))
|
domcox@8451
|
439 (message "Pretranslational string switched %s to leave."
|
domcox@8451
|
440 (if text-translator-leave-string "" " not")))
|
domcox@8451
|
441
|
domcox@8451
|
442 (defun text-translator-display-last-string (arg)
|
domcox@8451
|
443 "Function that displays translated character string last time.
|
domcox@8451
|
444 Default display to minibuffer.
|
domcox@8451
|
445 With prefix-arg, insert buffer."
|
domcox@8451
|
446 (interactive "P")
|
domcox@8451
|
447 (if arg
|
domcox@8451
|
448 (insert text-translator-last-string)
|
domcox@8451
|
449 (message "%s" text-translator-last-string)))
|
domcox@8451
|
450
|
domcox@8451
|
451 (defun text-translator-translate-recent-type ()
|
domcox@8451
|
452 "Function that translates by type corresponding to the language
|
domcox@8451
|
453 that used last time.
|
domcox@8451
|
454 For example, last time, if you have used excite.co.jp_enja,
|
domcox@8451
|
455 this time select from **_enja, and, translates."
|
domcox@8451
|
456 (interactive)
|
domcox@8451
|
457 (let* ((minibuffer-history text-translator-engine-history)
|
domcox@8451
|
458 (engine (car text-translator-engine-history))
|
domcox@8451
|
459 (last-type
|
domcox@8451
|
460 (concat "_" (text-translator-get-engine-type-or-site engine)))
|
domcox@8451
|
461 (type (completing-read
|
domcox@8451
|
462 (format "Select translation engine (last %s): " engine)
|
domcox@8451
|
463 (delq nil
|
domcox@8451
|
464 (mapcar
|
domcox@8451
|
465 (lambda (x)
|
domcox@8451
|
466 (when (string-match last-type (car x))
|
domcox@8451
|
467 x))
|
domcox@8451
|
468 text-translator-site-data-alist))
|
domcox@8451
|
469 nil t)))
|
domcox@8451
|
470 (unless (string= "" type)
|
domcox@8451
|
471 (text-translator-client type text-translator-last-string))))
|
domcox@8451
|
472
|
domcox@8451
|
473 (defun text-translator-translate-default ()
|
domcox@8451
|
474 "Function that translates by default type only.
|
domcox@8451
|
475 Default is value of `text-translator-default-engine'."
|
domcox@8451
|
476 (interactive)
|
domcox@8451
|
477 (text-translator nil nil text-translator-default-engine))
|
domcox@8451
|
478
|
domcox@8451
|
479 (defun text-translator-check-valid-translation-engine (engine valid-engine)
|
domcox@8451
|
480 "Check ENGINE that is registered in `text-translator-site-data-alist'.
|
domcox@8451
|
481 Return ENGINE if it is already registered, otherwise return VALID-ENGINE."
|
domcox@8451
|
482 (or (car (member engine (mapcar 'car text-translator-site-data-alist)))
|
domcox@8451
|
483 valid-engine))
|
domcox@8451
|
484
|
domcox@8451
|
485 (defun text-translator-get-engine-type-or-site (engine &optional get-site)
|
domcox@8451
|
486 "Get a translation engine type or site name.
|
domcox@8451
|
487 If optional argument GET-SITE is nil, return a translation engine type.
|
domcox@8451
|
488 Otherwise return a translation site name."
|
domcox@8451
|
489 (nth (if get-site 0 1) (split-string engine "_")))
|
domcox@8451
|
490
|
domcox@8451
|
491 ;; by google2.el
|
domcox@8451
|
492 (defun text-translator-url-encode-string (str &optional coding)
|
domcox@8451
|
493 (apply (function concat)
|
domcox@8451
|
494 (mapcar
|
domcox@8451
|
495 (lambda (ch)
|
domcox@8451
|
496 (cond
|
domcox@8451
|
497 ((eq ch ?\n) ; newline
|
domcox@8451
|
498 "%0D%0A")
|
domcox@8451
|
499 ((string-match "[-a-zA-Z0-9_:/]" (char-to-string ch)) ; xxx?
|
domcox@8451
|
500 (char-to-string ch)) ; printable
|
domcox@8451
|
501 ((char-equal ch ?\x20) ; space
|
domcox@8451
|
502 "+")
|
domcox@8451
|
503 (t
|
domcox@8451
|
504 (format "%%%02X" ch)))) ; escape
|
domcox@8451
|
505 ;; Coerce a string to a list of chars.
|
domcox@8451
|
506 (append (encode-coding-string (or str "") (or coding 'iso-2022-jp))
|
domcox@8451
|
507 nil))))
|
domcox@8451
|
508
|
domcox@8451
|
509 ;; initialization function
|
domcox@8451
|
510 (defun text-translator-site-data-init ()
|
domcox@8451
|
511 ;; initialize
|
domcox@8451
|
512 (setq text-translator-site-data-alist nil)
|
domcox@8451
|
513 (setq text-translator-site-data-alist
|
domcox@8451
|
514 text-translator-site-data-minimum-alist)
|
domcox@8451
|
515 (dolist (site text-translator-site-data-template-alist)
|
domcox@8451
|
516 (let ((tt-convert-name '(lambda (lang)
|
domcox@8451
|
517 (let ((match-lang (assoc lang
|
domcox@8451
|
518 (nth 7 site))))
|
domcox@8451
|
519 (if match-lang
|
domcox@8451
|
520 (cdr match-lang)
|
domcox@8451
|
521 lang))))
|
domcox@8451
|
522 (tt-replace-string '(lambda (pstr olang tlang)
|
domcox@8451
|
523 (when olang
|
domcox@8451
|
524 (setq pstr
|
domcox@8451
|
525 (replace-regexp-in-string "%o"
|
domcox@8451
|
526 olang
|
domcox@8451
|
527 pstr)))
|
domcox@8451
|
528 (when tlang
|
domcox@8451
|
529 (setq pstr
|
domcox@8451
|
530 (replace-regexp-in-string "%t"
|
domcox@8451
|
531 tlang
|
domcox@8451
|
532 pstr))
|
domcox@8451
|
533 pstr)))
|
domcox@8451
|
534 tt-alist)
|
domcox@8451
|
535 (dolist (i (nth 6 site))
|
domcox@8451
|
536 (add-to-list 'text-translator-site-data-alist
|
domcox@8451
|
537 (list (format "%s"
|
domcox@8451
|
538 (concat (nth 0 site)
|
domcox@8451
|
539 "_"
|
domcox@8451
|
540 (funcall tt-convert-name (car i))
|
domcox@8451
|
541 (funcall tt-convert-name (cdr i))))
|
domcox@8451
|
542 (nth 1 site)
|
domcox@8451
|
543 (nth 2 site)
|
domcox@8451
|
544 (funcall tt-replace-string
|
domcox@8451
|
545 (nth 3 site) (car i) (cdr i))
|
domcox@8451
|
546 (nth 4 site)
|
domcox@8451
|
547 (nth 5 site)))))))
|
domcox@8451
|
548 (text-translator-site-data-init) ; init
|
domcox@8451
|
549
|
domcox@8451
|
550 (provide 'text-translator)
|
domcox@8451
|
551 ;;; text-translator.el ends here
|
domcox@8451
|
552
|
domcox@8451
|
553 ;; Local Variables:
|
domcox@8451
|
554 ;; Coding: utf-8
|
domcox@8451
|
555 ;; End:
|