OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This code is used in conjunction with the Google Translate Element script. | 5 // This code is used in conjunction with the Google Translate Element script. |
6 // It is executed in an isolated world of a page to translate it from one | 6 // It is executed in an isolated world of a page to translate it from one |
7 // language to another. | 7 // language to another. |
8 // It should be included in the page before the Translate Element script. | 8 // It should be included in the page before the Translate Element script. |
9 | 9 |
10 var cr = {}; | 10 var cr = {}; |
xiyuan
2013/09/06 16:16:41
nit: cr = cr || {};
Takashi Toyoshima
2013/09/09 04:02:29
This script is injected into the new isolated worl
| |
11 | 11 |
12 /** | 12 /** |
13 * An object to provide functions to interact with the Translate library. | 13 * An object to provide functions to interact with the Translate library. |
14 * @type {object} | 14 * @type {object} |
15 */ | 15 */ |
16 cr.googleTranslate = (function() { | 16 cr.googleTranslate = (function() { |
17 /** | 17 /** |
18 * The Translate Element library's instance. | 18 * The Translate Element library's instance. |
19 * @type {object} | 19 * @type {object} |
20 */ | 20 */ |
21 var lib; | 21 var lib; |
22 | 22 |
23 /** | 23 /** |
24 * A flag representing if the Translate Element library is initialized. | 24 * A flag representing if the Translate Element library is initialized. |
25 * @type {boolean} | 25 * @type {boolean} |
26 */ | 26 */ |
27 var libReady = false; | 27 var libReady = false; |
28 | 28 |
29 /** | 29 /** |
30 * A flag representing if the Translate Element library returns error while | 30 * Error definitions for |errorCode|. See chrome/common/translate_errors.h |
31 * performing translation. Also it is set to true when the Translate Element | 31 * to modify the definition. |
xiyuan
2013/09/06 16:16:41
nit: @const
Takashi Toyoshima
2013/09/09 04:02:29
Done.
| |
32 * library is not initialized in 600 msec from the library is loaded. | |
33 * @type {boolean} | |
34 */ | 32 */ |
35 var error = false; | 33 var error = { |
xiyuan
2013/09/06 16:16:41
nit: error -> ERROR for const var name.
Takashi Toyoshima
2013/09/09 04:02:29
Done.
| |
34 'NONE': 0, | |
35 'INITIALIZATION_ERROR': 2, | |
36 'UNSUPPORTED_LANGUAGE': 4, | |
37 'TRANSLATION_ERROR': 6, | |
38 'TRANSLATION_TIMEOUT': 7, | |
39 'UNEXPECTED_SCRIPT_ERROR': 8, | |
40 'BAD_ORIGIN': 9, | |
41 'SCRIPT_LOAD_ERROR': 10 | |
42 }; | |
43 | |
44 /** | |
45 * Error code map from te.dom.DomTranslator.Error to |errorCode|. | |
46 * See also go/dom_translator.js in google3. | |
xiyuan
2013/09/06 16:16:41
nit: @const
Takashi Toyoshima
2013/09/09 04:02:29
Done.
| |
47 */ | |
48 var mapTranslateErrorToErrorCode = { | |
xiyuan
2013/09/06 16:16:41
nit: mapTranslateErrorToErrorCode -> TRANSLATE_ERR
Takashi Toyoshima
2013/09/09 04:02:29
Done.
| |
49 0: error['NONE'], | |
50 1: error['TRANSLATION_ERROR'], | |
51 2: error['UNSUPPORTED_LANGUAGE'] | |
52 }; | |
53 | |
54 /** | |
55 * An error code happened in translate.js and the Translate Element library. | |
56 */ | |
57 var errorCode = error['NONE']; | |
36 | 58 |
37 /** | 59 /** |
38 * A flag representing if the Translate Element has finished a translation. | 60 * A flag representing if the Translate Element has finished a translation. |
39 * @type {boolean} | 61 * @type {boolean} |
40 */ | 62 */ |
41 var finished = false; | 63 var finished = false; |
42 | 64 |
43 /** | 65 /** |
44 * Counts how many times the checkLibReady function is called. The function | 66 * Counts how many times the checkLibReady function is called. The function |
45 * is called in every 100 msec and counted up to 6. | 67 * is called in every 100 msec and counted up to 6. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
78 */ | 100 */ |
79 var endTime = 0.0; | 101 var endTime = 0.0; |
80 | 102 |
81 function checkLibReady() { | 103 function checkLibReady() { |
82 if (lib.isAvailable()) { | 104 if (lib.isAvailable()) { |
83 readyTime = performance.now(); | 105 readyTime = performance.now(); |
84 libReady = true; | 106 libReady = true; |
85 return; | 107 return; |
86 } | 108 } |
87 if (checkReadyCount++ > 5) { | 109 if (checkReadyCount++ > 5) { |
88 error = true; | 110 errorCode = error['TRANSLATION_TIMEOUT']; |
89 return; | 111 return; |
90 } | 112 } |
91 setTimeout(checkLibReady, 100); | 113 setTimeout(checkLibReady, 100); |
92 } | 114 } |
93 | 115 |
94 function onTranslateProgress(progress, opt_finished, opt_error) { | 116 function onTranslateProgress(progress, opt_finished, opt_error) { |
95 finished = opt_finished; | 117 finished = opt_finished; |
96 // opt_error can be 'undefined'. | 118 // opt_error can be 'undefined'. |
97 if (typeof opt_error == 'boolean' && opt_error) { | 119 if (typeof opt_error == 'boolean' && opt_error) { |
98 error = true; | 120 // TODO(toyoshim): Remove boolean case once a server is updated. |
121 errorCode = error['TRANSLATION_ERROR']; | |
99 // We failed to translate, restore so the page is in a consistent state. | 122 // We failed to translate, restore so the page is in a consistent state. |
100 lib.restore(); | 123 lib.restore(); |
124 } else if (typeof opt_error == 'number' && opt_error != 0) { | |
125 errorCode = mapTranslateErrorToErrorCode[opt_error]; | |
126 lib.restore(); | |
101 } | 127 } |
102 if (finished) | 128 if (finished) |
103 endTime = performance.now(); | 129 endTime = performance.now(); |
104 } | 130 } |
105 | 131 |
106 // Public API. | 132 // Public API. |
107 return { | 133 return { |
108 /** | 134 /** |
109 * Whether the library is ready. | 135 * Whether the library is ready. |
110 * The translate function should only be called when |libReady| is true. | 136 * The translate function should only be called when |libReady| is true. |
(...skipping 10 matching lines...) Expand all Loading... | |
121 get finished() { | 147 get finished() { |
122 return finished; | 148 return finished; |
123 }, | 149 }, |
124 | 150 |
125 /** | 151 /** |
126 * Whether an error occured initializing the library of translating the | 152 * Whether an error occured initializing the library of translating the |
127 * page. | 153 * page. |
128 * @type {boolean} | 154 * @type {boolean} |
129 */ | 155 */ |
130 get error() { | 156 get error() { |
131 return error; | 157 return errorCode != error['NONE']; |
132 }, | 158 }, |
133 | 159 |
134 /** | 160 /** |
161 * Returns a number to represent error type. | |
162 * @type {number} | |
163 */ | |
164 get errorCode() { | |
165 return errorCode; | |
166 }, | |
167 | |
168 /** | |
135 * The language the page translated was in. Is valid only after the page | 169 * The language the page translated was in. Is valid only after the page |
136 * has been successfully translated and the original language specified to | 170 * has been successfully translated and the original language specified to |
137 * the translate function was 'auto'. Is empty otherwise. | 171 * the translate function was 'auto'. Is empty otherwise. |
138 * Some versions of Element library don't provide |getDetectedLanguage| | 172 * Some versions of Element library don't provide |getDetectedLanguage| |
139 * function. In that case, this function returns 'und'. | 173 * function. In that case, this function returns 'und'. |
140 * @type {boolean} | 174 * @type {boolean} |
141 */ | 175 */ |
142 get sourceLang() { | 176 get sourceLang() { |
143 if (!libReady || !finished || error) | 177 if (!libReady || !finished || errorCode != error['NONE']) |
144 return ''; | 178 return ''; |
145 if (!lib.getDetectedLanguage) | 179 if (!lib.getDetectedLanguage) |
146 return 'und'; // defined as chrome::kUnknownLanguageCode in C++ world. | 180 return 'und'; // defined as chrome::kUnknownLanguageCode in C++ world. |
147 return lib.getDetectedLanguage(); | 181 return lib.getDetectedLanguage(); |
148 }, | 182 }, |
149 | 183 |
150 /** | 184 /** |
151 * Time in msec from this script being injected to all server side scripts | 185 * Time in msec from this script being injected to all server side scripts |
152 * being loaded. | 186 * being loaded. |
153 * @type {number} | 187 * @type {number} |
(...skipping 20 matching lines...) Expand all Loading... | |
174 * @type {number} | 208 * @type {number} |
175 */ | 209 */ |
176 get translationTime() { | 210 get translationTime() { |
177 if (!finished) | 211 if (!finished) |
178 return 0; | 212 return 0; |
179 return endTime - startTime; | 213 return endTime - startTime; |
180 }, | 214 }, |
181 | 215 |
182 /** | 216 /** |
183 * Translate the page contents. Note that the translation is asynchronous. | 217 * Translate the page contents. Note that the translation is asynchronous. |
184 * You need to regularly check the state of |finished| and |error| to know | 218 * You need to regularly check the state of |finished| and |errorCode| to |
185 * if the translation finished or if there was an error. | 219 * know if the translation finished or if there was an error. |
186 * @param {string} originalLang The language the page is in. | 220 * @param {string} originalLang The language the page is in. |
187 * @param {string} targetLang The language the page should be translated to. | 221 * @param {string} targetLang The language the page should be translated to. |
188 * @return {boolean} False if the translate library was not ready, in which | 222 * @return {boolean} False if the translate library was not ready, in which |
189 * case the translation is not started. True otherwise. | 223 * case the translation is not started. True otherwise. |
190 */ | 224 */ |
191 translate: function(originalLang, targetLang) { | 225 translate: function(originalLang, targetLang) { |
192 finished = false; | 226 finished = false; |
193 error = false; | 227 errorCode = error['NONE']; |
194 if (!libReady) | 228 if (!libReady) |
195 return false; | 229 return false; |
196 startTime = performance.now(); | 230 startTime = performance.now(); |
197 try { | 231 try { |
198 lib.translatePage(originalLang, targetLang, onTranslateProgress); | 232 lib.translatePage(originalLang, targetLang, onTranslateProgress); |
199 } catch (err) { | 233 } catch (err) { |
200 console.error('Translate: ' + err); | 234 console.error('Translate: ' + err); |
201 // TODO(toyoshim): Check if it shows an error notification. | 235 errorCode = error['UNEXPECTED_SCRIPT_ERROR']; |
202 error = true; | |
203 return false; | 236 return false; |
204 } | 237 } |
205 return true; | 238 return true; |
206 }, | 239 }, |
207 | 240 |
208 /** | 241 /** |
209 * Reverts the page contents to its original value, effectively reverting | 242 * Reverts the page contents to its original value, effectively reverting |
210 * any performed translation. Does nothing if the page was not translated. | 243 * any performed translation. Does nothing if the page was not translated. |
211 */ | 244 */ |
212 revert: function() { | 245 revert: function() { |
213 lib.restore(); | 246 lib.restore(); |
214 }, | 247 }, |
215 | 248 |
216 /** | 249 /** |
217 * Entry point called by the Translate Element once it has been injected in | 250 * Entry point called by the Translate Element once it has been injected in |
218 * the page. | 251 * the page. |
219 */ | 252 */ |
220 onTranslateElementLoad: function() { | 253 onTranslateElementLoad: function() { |
221 loadedTime = performance.now(); | 254 loadedTime = performance.now(); |
222 try { | 255 try { |
223 lib = google.translate.TranslateService({ | 256 lib = google.translate.TranslateService({ |
224 // translateApiKey is predefined by translate_script.cc. | 257 // translateApiKey is predefined by translate_script.cc. |
225 'key': translateApiKey, | 258 'key': translateApiKey, |
226 'useSecureConnection': true | 259 'useSecureConnection': true |
227 }); | 260 }); |
228 translateApiKey = undefined; | 261 translateApiKey = undefined; |
229 } catch (err) { | 262 } catch (err) { |
230 error = true; | 263 errorCode = error['INITIALIZATION_ERROR']; |
231 translateApiKey = undefined; | 264 translateApiKey = undefined; |
232 return; | 265 return; |
233 } | 266 } |
234 // The TranslateService is not available immediately as it needs to start | 267 // The TranslateService is not available immediately as it needs to start |
235 // Flash. Let's wait until it is ready. | 268 // Flash. Let's wait until it is ready. |
236 checkLibReady(); | 269 checkLibReady(); |
237 }, | 270 }, |
238 | 271 |
239 /** | 272 /** |
240 * Entry point called by the Translate Element when it want to load an | 273 * Entry point called by the Translate Element when it want to load an |
(...skipping 10 matching lines...) Expand all Loading... | |
251 }, | 284 }, |
252 | 285 |
253 /** | 286 /** |
254 * Entry point called by the Translate Element when it want to load and run | 287 * Entry point called by the Translate Element when it want to load and run |
255 * an external JavaScript on the page. | 288 * an external JavaScript on the page. |
256 * @param {string} url URL of an external JavaScript to load. | 289 * @param {string} url URL of an external JavaScript to load. |
257 */ | 290 */ |
258 onLoadJavascript: function(url) { | 291 onLoadJavascript: function(url) { |
259 // securityOrigin is predefined by translate_script.cc. | 292 // securityOrigin is predefined by translate_script.cc. |
260 if (url.indexOf(securityOrigin) != 0) { | 293 if (url.indexOf(securityOrigin) != 0) { |
261 // TODO(toyoshim): Handle this error to show an error notification. | |
262 console.error('Translate: ' + url + ' is not allowed to load.'); | 294 console.error('Translate: ' + url + ' is not allowed to load.'); |
263 error = true; | 295 errorCode = error['BAD_ORIGIN']; |
264 return; | 296 return; |
265 } | 297 } |
266 var xhr = new XMLHttpRequest(); | 298 var xhr = new XMLHttpRequest(); |
267 xhr.open('GET', url, true); | 299 xhr.open('GET', url, true); |
268 xhr.onreadystatechange = function() { | 300 xhr.onreadystatechange = function() { |
269 if (this.readyState != this.DONE || this.status != 200) | 301 if (this.readyState != this.DONE) |
270 return; | 302 return; |
303 if (this.status != 200) { | |
304 errorCode = error['SCRIPT_LOAD_ERROR']; | |
305 return; | |
306 } | |
271 eval(this.responseText); | 307 eval(this.responseText); |
272 } | 308 } |
273 xhr.send(); | 309 xhr.send(); |
274 } | 310 } |
275 }; | 311 }; |
276 })(); | 312 })(); |
OLD | NEW |