OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 /** | 5 /** |
6 * @fileoverview 'settings-languages' provides convenient access to | 6 * @fileoverview 'settings-languages' provides convenient access to |
7 * Chrome's language and input method settings. | 7 * Chrome's language and input method settings. |
8 * | 8 * |
9 * Instances of this element have a 'languages' property, which reflects the | 9 * Instances of this element have a 'languages' property, which reflects the |
10 * current language settings. The 'languages' property is read-only, meaning | 10 * current language settings. The 'languages' property is read-only, meaning |
11 * hosts using this element cannot change it directly. Instead, changes to | 11 * hosts using this element cannot change it directly. Instead, changes to |
12 * language settings should be made using this element's public functions. | 12 * language settings should be made using the settings.LanguageHelper singleton. |
13 * | 13 * |
14 * Use two-way binding syntax to propagate changes from child to host, so that | 14 * Use upward binding syntax to propagate changes from child to host, so that |
15 * changes made internally to 'languages' propagate to your host element: | 15 * changes made internally to 'languages' propagate to your host element: |
16 * | 16 * |
17 * <template> | 17 * <template> |
18 * <settings-languages languages="{{languages}}"> | 18 * <settings-languages languages="{{languages}}"> |
19 * </settings-languages> | 19 * </settings-languages> |
20 * <div>[[languages.someProperty]]</div> | 20 * <div>[[languages.someProperty]]</div> |
21 * </template> | 21 * </template> |
22 * | 22 * |
23 * @group Chrome Settings Elements | 23 * @group Chrome Settings Elements |
24 * @element settings-languages | 24 * @element settings-languages |
25 */ | 25 */ |
26 | 26 |
27 /** @typedef {{spellCheckEnabled: boolean, translateEnabled: boolean}} */ | 27 cr.exportPath('settings'); |
michaelpg
2015/11/13 05:30:17
for closure
| |
28 var LanguageState; | |
29 | |
30 /** | |
31 * @typedef {{language: !chrome.languageSettingsPrivate.Language, | |
32 * state: !LanguageState}} | |
33 */ | |
34 var LanguageInfo; | |
35 | |
36 /** | |
37 * supportedLanguages: an array of languages, ordered alphabetically. | |
38 * enabledLanguages: an array of enabled language info and state, ordered by | |
39 * preference. | |
40 * @typedef {{ | |
41 * supportedLanguages: !Array<!chrome.languageSettingsPrivate.Language>, | |
42 * enabledLanguages: !Array<!LanguageInfo>, | |
43 * translateTarget: string | |
44 * }} | |
45 */ | |
46 var LanguagesModel; | |
47 | 28 |
48 (function() { | 29 (function() { |
49 'use strict'; | 30 'use strict'; |
50 | 31 |
51 // Translate server treats some language codes the same. | 32 // Translate server treats some language codes the same. |
52 // See also: components/translate/core/common/translate_util.cc. | 33 // See also: components/translate/core/common/translate_util.cc. |
53 var kLanguageCodeToTranslateCode = { | 34 var kLanguageCodeToTranslateCode = { |
54 'nb': 'no', | 35 'nb': 'no', |
55 'fil': 'tl', | 36 'fil': 'tl', |
56 'zh-HK': 'zh-TW', | 37 'zh-HK': 'zh-TW', |
57 'zh-MO': 'zh-TW', | 38 'zh-MO': 'zh-TW', |
58 'zh-SG': 'zh-CN', | 39 'zh-SG': 'zh-CN', |
59 }; | 40 }; |
60 | 41 |
61 // Some ISO 639 language codes have been renamed, e.g. "he" to "iw", but | 42 // Some ISO 639 language codes have been renamed, e.g. "he" to "iw", but |
62 // Translate still uses the old versions. TODO(michaelpg): Chrome does too. | 43 // Translate still uses the old versions. TODO(michaelpg): Chrome does too. |
63 // Follow up with Translate owners to understand the right thing to do. | 44 // Follow up with Translate owners to understand the right thing to do. |
64 var kTranslateLanguageSynonyms = { | 45 var kTranslateLanguageSynonyms = { |
65 'he': 'iw', | 46 'he': 'iw', |
66 'jv': 'jw', | 47 'jv': 'jw', |
67 }; | 48 }; |
68 | 49 |
69 /** | |
70 * This element has a reference to the singleton, exposing the singleton's | |
71 * language model to the host of this element as the 'languages' property. | |
72 */ | |
73 Polymer({ | |
74 is: 'settings-languages', | |
75 | |
76 properties: { | |
77 /** | |
78 * Singleton element created at startup which provides the languages model. | |
79 * @type {!Element} | |
80 */ | |
81 singleton_: { | |
82 type: Object, | |
83 value: document.createElement('settings-languages-singleton'), | |
84 }, | |
85 | |
86 /** | |
87 * A reference to the languages model from the singleton, exposed as a | |
88 * read-only property so hosts can bind to it, but not change it. | |
89 * @type {LanguagesModel|undefined} | |
90 */ | |
91 languages: { | |
92 type: Object, | |
93 notify: true, | |
94 readOnly: true, | |
95 }, | |
96 }, | |
97 | |
98 ready: function() { | |
99 // Set the 'languages' property to reference the singleton's model. | |
100 this._setLanguages(this.singleton_.languages); | |
101 // Listen for changes to the singleton's languages property, so we know | |
102 // when to notify hosts of changes to (our reference to) the property. | |
103 this.listen( | |
104 this.singleton_, 'languages-changed', 'singletonLanguagesChanged_'); | |
105 }, | |
106 | |
107 /** | |
108 * Takes changes reported by the singleton and forwards them to the host, | |
109 * manually sending a change notification for our 'languages' property (since | |
110 * it's the same object as the singleton's property, but isn't bound by | |
111 * Polymer). | |
112 * @private | |
113 */ | |
114 singletonLanguagesChanged_: function(e) { | |
115 // Forward the change notification to the host. | |
116 this.fire(e.type, e.detail, {bubbles: false}); | |
117 }, | |
118 | |
119 // Forward public methods to the singleton. | |
120 | |
121 /** @param {string} languageCode */ | |
122 setUILanguage: function(languageCode) { | |
123 if (cr.isWindows || cr.isChromeOS) | |
124 this.singleton_.setUILanguage(languageCode); | |
125 }, | |
126 | |
127 resetUILanguage: function() { | |
128 if (cr.isWindows || cr.isChromeOS) | |
129 this.singleton_.resetUILanguage(); | |
130 }, | |
131 | |
132 /** @return {string} */ | |
133 getProspectiveUILanguage: function() { | |
134 return this.singleton_.getProspectiveUILanguage(); | |
135 }, | |
136 | |
137 /** @param {string} languageCode */ | |
138 enableLanguage: function(languageCode) { | |
139 this.singleton_.enableLanguage(languageCode); | |
140 }, | |
141 | |
142 /** @param {string} languageCode */ | |
143 disableLanguage: function(languageCode) { | |
144 this.singleton_.disableLanguage(languageCode); | |
145 }, | |
146 | |
147 /** @param {string} languageCode */ | |
148 enableTranslateLanguage: function(languageCode) { | |
149 this.singleton_.enableTranslateLanguage(languageCode); | |
150 }, | |
151 | |
152 /** @param {string} languageCode */ | |
153 disableTranslateLanguage: function(languageCode) { | |
154 this.singleton_.disableTranslateLanguage(languageCode); | |
155 }, | |
156 | |
157 /** | |
158 * @param {string} languageCode | |
159 * @return {boolean} | |
160 */ | |
161 isEnabled: function(languageCode) { | |
162 return this.singleton_.isEnabled(languageCode); | |
163 }, | |
164 | |
165 /** | |
166 * @param {string} languageCode | |
167 * @param {boolean} enable | |
168 */ | |
169 toggleSpellCheck: function(languageCode, enable) { | |
170 this.singleton_.toggleSpellCheck(languageCode, enable); | |
171 }, | |
172 | |
173 /** | |
174 * @param {string} languageCode | |
175 * @return {string} | |
176 */ | |
177 convertLanguageCodeForTranslate: function(languageCode) { | |
178 return this.singleton_.convertLanguageCodeForTranslate(languageCode); | |
179 }, | |
180 }); | |
181 | |
182 var preferredLanguagesPrefName = cr.isChromeOS ? | 50 var preferredLanguagesPrefName = cr.isChromeOS ? |
183 'settings.language.preferred_languages' : 'intl.accept_languages'; | 51 'settings.language.preferred_languages' : 'intl.accept_languages'; |
184 | 52 |
185 /** | 53 /** |
186 * Singleton element created when settings-languages is registered. | 54 * Singleton element that generates the languages model on start-up and |
187 * Generates the languages model on start-up, and updates it whenever Chrome's | 55 * updates it whenever Chrome's pref store and other settings change. These |
188 * pref store and other settings change. These updates propagate to each | 56 * updates propagate to each <settings-language> instance so that their |
189 * <settings-language> instance so that their 'languages' property updates | 57 * 'languages' property updates like any other Polymer property. |
190 * like any other Polymer property. | 58 * @implements {LanguageSettingsHelper} |
191 */ | 59 */ |
192 Polymer({ | 60 var SettingsLanguagesSingletonElement = Polymer({ |
193 is: 'settings-languages-singleton', | 61 is: 'settings-languages-singleton', |
194 | 62 |
195 behaviors: [PrefsBehavior], | 63 behaviors: [PrefsBehavior], |
196 | 64 |
197 properties: { | 65 properties: { |
198 /** | 66 /** |
199 * @type {LanguagesModel|undefined} | 67 * @type {LanguagesModel|undefined} |
200 */ | 68 */ |
201 languages: { | 69 languages: { |
202 type: Object, | 70 type: Object, |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
260 resolve(); | 128 resolve(); |
261 }); | 129 }); |
262 }), | 130 }), |
263 ]).then(function() { | 131 ]).then(function() { |
264 this.createModel_(languageList, translateTarget); | 132 this.createModel_(languageList, translateTarget); |
265 this.initialized_ = true; | 133 this.initialized_ = true; |
266 }.bind(this)); | 134 }.bind(this)); |
267 }, | 135 }, |
268 | 136 |
269 /** | 137 /** |
138 * Updates the list of enabled languages from the preferred languages pref. | |
139 * @private | |
140 */ | |
141 preferredLanguagesPrefChanged_: function() { | |
142 if (!this.initialized_) | |
143 return; | |
144 var enabledLanguages = | |
145 this.getEnabledLanguages_(this.languages.translateTarget); | |
146 | |
147 // Reset the enabled language map before updating | |
148 // languages.enabledLanguages. | |
149 this.enabledLanguageMap_ = {}; | |
150 for (var i = 0; i < enabledLanguages.length; i++) { | |
151 var languageInfo = enabledLanguages[i]; | |
152 this.enabledLanguageMap_[languageInfo.language.code] = languageInfo; | |
153 } | |
154 this.set('languages.enabledLanguages', enabledLanguages); | |
155 }, | |
156 | |
157 /** | |
158 * Updates the spellCheckEnabled state of each enabled language. | |
159 * @private | |
160 */ | |
161 spellCheckDictionariesPrefChanged_: function() { | |
162 if (!this.initialized_) | |
163 return; | |
164 | |
165 var spellCheckMap = this.makeMapFromArray_(/** @type {!Array<string>} */( | |
166 this.getPref('spellcheck.dictionaries').value)); | |
167 for (var i = 0; i < this.languages.enabledLanguages.length; i++) { | |
168 var languageCode = this.languages.enabledLanguages[i].language.code; | |
169 this.set('languages.enabledLanguages.' + i + '.state.spellCheckEnabled', | |
170 !!spellCheckMap[languageCode]); | |
171 } | |
172 }, | |
173 | |
174 /** @private */ | |
175 translateLanguagesPrefChanged_: function() { | |
176 if (!this.initialized_) | |
177 return; | |
178 | |
179 var translateBlockedPref = this.getPref('translate_blocked_languages'); | |
180 var translateBlockedMap = this.makeMapFromArray_( | |
181 /** @type {!Array<string>} */(translateBlockedPref.value)); | |
182 | |
183 for (var i = 0; i < this.languages.enabledLanguages.length; i++) { | |
184 var translateCode = this.convertLanguageCodeForTranslate( | |
185 this.languages.enabledLanguages[i].language.code); | |
186 this.set( | |
187 'languages.enabledLanguages.' + i + '.state.translateEnabled', | |
188 !translateBlockedMap[translateCode]); | |
189 } | |
190 }, | |
191 | |
192 /** | |
270 * Constructs the languages model. | 193 * Constructs the languages model. |
271 * @param {!Array<!chrome.languageSettingsPrivate.Language>} | 194 * @param {!Array<!chrome.languageSettingsPrivate.Language>} |
272 * supportedLanguages | 195 * supportedLanguages |
273 * @param {string} translateTarget Language code of the default translate | 196 * @param {string} translateTarget Language code of the default translate |
274 * target language. | 197 * target language. |
198 * @private | |
275 */ | 199 */ |
276 createModel_: function(supportedLanguages, translateTarget) { | 200 createModel_: function(supportedLanguages, translateTarget) { |
277 // Populate the hash map of supported languages. | 201 // Populate the hash map of supported languages. |
278 for (var i = 0; i < supportedLanguages.length; i++) { | 202 for (var i = 0; i < supportedLanguages.length; i++) { |
279 var language = supportedLanguages[i]; | 203 var language = supportedLanguages[i]; |
280 language.supportsUI = !!language.supportsUI; | 204 language.supportsUI = !!language.supportsUI; |
281 language.supportsTranslate = !!language.supportsTranslate; | 205 language.supportsTranslate = !!language.supportsTranslate; |
282 language.supportsSpellcheck = !!language.supportsSpellcheck; | 206 language.supportsSpellcheck = !!language.supportsSpellcheck; |
283 this.supportedLanguageMap_[language.code] = language; | 207 this.supportedLanguageMap_[language.code] = language; |
284 } | 208 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
318 var spellCheckMap = this.makeMapFromArray_(/** @type {!Array<string>} */( | 242 var spellCheckMap = this.makeMapFromArray_(/** @type {!Array<string>} */( |
319 spellCheckPref.value)); | 243 spellCheckPref.value)); |
320 | 244 |
321 var translateBlockedPref = this.getPref('translate_blocked_languages'); | 245 var translateBlockedPref = this.getPref('translate_blocked_languages'); |
322 var translateBlockedMap = this.makeMapFromArray_( | 246 var translateBlockedMap = this.makeMapFromArray_( |
323 /** @type {!Array<string>} */(translateBlockedPref.value)); | 247 /** @type {!Array<string>} */(translateBlockedPref.value)); |
324 | 248 |
325 for (var i = 0; i < enabledLanguageCodes.length; i++) { | 249 for (var i = 0; i < enabledLanguageCodes.length; i++) { |
326 var code = enabledLanguageCodes[i]; | 250 var code = enabledLanguageCodes[i]; |
327 var language = this.supportedLanguageMap_[code]; | 251 var language = this.supportedLanguageMap_[code]; |
252 // Skip unsupported languages. | |
328 if (!language) | 253 if (!language) |
329 continue; | 254 continue; |
330 var state = {}; | 255 var state = /** @type {LanguageState} */({}); |
331 state.spellCheckEnabled = !!spellCheckMap[code]; | 256 state.spellCheckEnabled = !!spellCheckMap[code]; |
332 // Translate is considered disabled if this language maps to any translate | 257 // Translate is considered disabled if this language maps to any translate |
333 // language that is blocked. | 258 // language that is blocked. |
334 var translateCode = this.convertLanguageCodeForTranslate(code); | 259 var translateCode = this.convertLanguageCodeForTranslate(code); |
335 state.translateEnabled = language.supportsTranslate && | 260 state.translateEnabled = !!language.supportsTranslate && |
336 !translateBlockedMap[translateCode] && | 261 !translateBlockedMap[translateCode] && |
337 translateCode != translateTarget; | 262 translateCode != translateTarget; |
338 enabledLanguages.push({language: language, state: state}); | 263 enabledLanguages.push(/** @type {LanguageInfo} */( |
264 {language: language, state: state})); | |
339 } | 265 } |
340 return enabledLanguages; | 266 return enabledLanguages; |
341 }, | 267 }, |
342 | 268 |
343 /** | 269 /** |
344 * Creates an object whose keys are the elements of the list. | 270 * Creates an object whose keys are the elements of the list. |
345 * @param {!Array<string>} list | 271 * @param {!Array<string>} list |
346 * @return {!Object<boolean>} | 272 * @return {!Object<boolean>} |
273 * @private | |
347 */ | 274 */ |
348 makeMapFromArray_: function(list) { | 275 makeMapFromArray_: function(list) { |
349 var map = {}; | 276 var map = {}; |
350 for (var i = 0; i < list.length; i++) | 277 for (var i = 0; i < list.length; i++) |
351 map[list[i]] = true; | 278 map[list[i]] = true; |
352 return map; | 279 return map; |
353 }, | 280 }, |
354 | 281 |
355 /** | 282 // LanguageSettingsHelper implementation. |
356 * Updates the list of enabled languages from the preferred languages pref. | 283 // TODO(michaelpg): replace duplicate docs with @override once b/24294625 |
357 * @private | 284 // is fixed. |
358 * */ | |
359 preferredLanguagesPrefChanged_: function() { | |
360 if (!this.initialized_) | |
361 return; | |
362 | |
363 var enabledLanguages = | |
364 this.getEnabledLanguages_(this.languages.translateTarget); | |
365 // Reset the enabled language map. Do this before notifying of the change | |
366 // via languages.enabledLanguages. | |
367 this.enabledLanguageMap_ = {}; | |
368 for (var i = 0; i < enabledLanguages.length; i++) { | |
369 var languageInfo = enabledLanguages[i]; | |
370 this.enabledLanguageMap_[languageInfo.language.code] = languageInfo; | |
371 } | |
372 this.set('languages.enabledLanguages', enabledLanguages); | |
373 }, | |
374 | |
375 /** | |
376 * Updates the spellCheckEnabled state of each enabled language. | |
377 * @private | |
378 */ | |
379 spellCheckDictionariesPrefChanged_: function() { | |
380 if (!this.initialized_) | |
381 return; | |
382 | |
383 var spellCheckMap = this.makeMapFromArray_(/** @type {!Array<string>} */( | |
384 this.getPref('spellcheck.dictionaries').value)); | |
385 for (var i = 0; i < this.languages.enabledLanguages.length; i++) { | |
386 var languageCode = this.languages.enabledLanguages[i].language.code; | |
387 this.set('languages.enabledLanguages.' + i + '.state.spellCheckEnabled', | |
388 !!spellCheckMap[languageCode]); | |
389 } | |
390 }, | |
391 | |
392 translateLanguagesPrefChanged_: function() { | |
393 if (!this.initialized_) | |
394 return; | |
395 | |
396 var translateBlockedPref = this.getPref('translate_blocked_languages'); | |
397 var translateBlockedMap = this.makeMapFromArray_( | |
398 /** @type {!Array<string>} */(translateBlockedPref.value)); | |
399 | |
400 for (var i = 0; i < this.languages.enabledLanguages.length; i++) { | |
401 var translateCode = this.convertLanguageCodeForTranslate( | |
402 this.languages.enabledLanguages[i].language.code); | |
403 this.set( | |
404 'languages.enabledLanguages.' + i + '.state.translateEnabled', | |
405 !translateBlockedMap[translateCode]); | |
406 } | |
407 }, | |
408 | |
409 /** | |
410 * Deletes the given item from the pref at the given key if the item is found. | |
411 * Asserts if the pref itself is not found or is not an Array type. | |
412 * @param {string} key | |
413 * @param {*} item | |
414 */ | |
415 deletePrefItem_: function(key, item) { | |
416 assert(this.getPref(key).type == chrome.settingsPrivate.PrefType.LIST); | |
417 this.arrayDelete('prefs.' + key + '.value', item); | |
418 }, | |
419 | 285 |
420 /** | 286 /** |
421 * Windows and Chrome OS only: Sets the prospective UI language to the chosen | 287 * Windows and Chrome OS only: Sets the prospective UI language to the chosen |
422 * language. This dosen't affect the actual UI language until a restart. | 288 * language. This dosen't affect the actual UI language until a restart. |
423 * @param {string} languageCode | 289 * @param {string} languageCode |
424 */ | 290 */ |
425 setUILanguage: function(languageCode) { | 291 setUILanguage: function(languageCode) { |
292 assert(cr.isWindows || cr.isChromeOS); | |
426 chrome.send('setUILanguage', [languageCode]); | 293 chrome.send('setUILanguage', [languageCode]); |
427 }, | 294 }, |
428 | 295 |
429 /** | 296 /** |
430 * Windows and Chrome OS only: Resets the prospective UI language back to the | 297 * Windows and Chrome OS only: Resets the prospective UI language back to the |
431 * actual UI language. | 298 * actual UI language. |
432 */ | 299 */ |
433 resetUILanguage: function() { | 300 resetUILanguage: function() { |
301 assert(cr.isWindows || cr.isChromeOS); | |
434 chrome.send('setUILanguage', [navigator.language]); | 302 chrome.send('setUILanguage', [navigator.language]); |
435 }, | 303 }, |
436 | 304 |
437 /** | 305 /** |
438 * Returns the "prospective" UI language, i.e. the one to be used on next | 306 * Returns the "prospective" UI language, i.e. the one to be used on next |
439 * restart. If the pref is not set, the current UI language is also the | 307 * restart. If the pref is not set, the current UI language is also the |
440 * "prospective" language. | 308 * "prospective" language. |
441 * @return {string} Language code of the prospective UI language. | 309 * @return {string} Language code of the prospective UI language. |
442 * @private | |
443 */ | 310 */ |
444 getProspectiveUILanguage: function() { | 311 getProspectiveUILanguage: function() { |
445 return /** @type {string} */(this.getPref('intl.app_locale').value) || | 312 return /** @type {string} */(this.getPref('intl.app_locale').value) || |
446 navigator.language; | 313 navigator.language; |
447 }, | 314 }, |
448 | 315 |
449 /** | 316 /** |
317 * @param {string} languageCode | |
318 * @return {boolean} True if the language is enabled. | |
319 */ | |
320 isLanguageEnabled: function(languageCode) { | |
321 return !!this.enabledLanguageMap_[languageCode]; | |
322 }, | |
323 | |
324 /** | |
450 * Enables the language, making it available for spell check and input. | 325 * Enables the language, making it available for spell check and input. |
451 * @param {string} languageCode | 326 * @param {string} languageCode |
452 */ | 327 */ |
453 enableLanguage: function(languageCode) { | 328 enableLanguage: function(languageCode) { |
454 if (!CrSettingsPrefs.isInitialized) | 329 if (!CrSettingsPrefs.isInitialized) |
455 return; | 330 return; |
456 | 331 |
457 var languageCodes = | 332 var languageCodes = |
458 this.getPref(preferredLanguagesPrefName).value.split(','); | 333 this.getPref(preferredLanguagesPrefName).value.split(','); |
459 if (languageCodes.indexOf(languageCode) > -1) | 334 if (languageCodes.indexOf(languageCode) > -1) |
460 return; | 335 return; |
461 languageCodes.push(languageCode); | 336 languageCodes.push(languageCode); |
462 chrome.languageSettingsPrivate.setLanguageList(languageCodes); | 337 chrome.languageSettingsPrivate.setLanguageList(languageCodes); |
463 this.disableTranslateLanguage(languageCode); | 338 this.disableTranslateLanguage(languageCode); |
464 }, | 339 }, |
465 | 340 |
466 /** | 341 /** |
467 * Disables the language. | 342 * Disables the language. |
468 * @param {string} languageCode | 343 * @param {string} languageCode |
469 */ | 344 */ |
470 disableLanguage: function(languageCode) { | 345 disableLanguage: function(languageCode) { |
471 if (!CrSettingsPrefs.isInitialized) | 346 if (!CrSettingsPrefs.isInitialized) |
472 return; | 347 return; |
473 | 348 |
474 // Cannot disable the UI language. | 349 assert(this.canDisableLanguage(languageCode)); |
475 assert(languageCode != this.getProspectiveUILanguage()); | |
476 | 350 |
477 // Cannot disable the only enabled language. | 351 // Remove the language from spell check. |
352 this.arrayDelete('prefs.spellcheck.dictionaries.value', languageCode); | |
353 | |
354 // Remove the language from preferred languages. | |
478 var languageCodes = | 355 var languageCodes = |
479 this.getPref(preferredLanguagesPrefName).value.split(','); | 356 this.getPref(preferredLanguagesPrefName).value.split(','); |
480 assert(languageCodes.length > 1); | |
481 | |
482 // Remove the language from spell check. | |
483 this.deletePrefItem_('spellcheck.dictionaries', languageCode); | |
484 | |
485 var languageIndex = languageCodes.indexOf(languageCode); | 357 var languageIndex = languageCodes.indexOf(languageCode); |
486 if (languageIndex == -1) | 358 if (languageIndex == -1) |
487 return; | 359 return; |
488 languageCodes.splice(languageIndex, 1); | 360 languageCodes.splice(languageIndex, 1); |
489 chrome.languageSettingsPrivate.setLanguageList(languageCodes); | 361 chrome.languageSettingsPrivate.setLanguageList(languageCodes); |
490 this.enableTranslateLanguage(languageCode); | 362 this.enableTranslateLanguage(languageCode); |
491 }, | 363 }, |
492 | 364 |
493 /** | 365 /** |
494 * @param {string} languageCode | 366 * @param {string} languageCode Language code for an enabled language. |
495 * @return {boolean} True if the language is enabled. | 367 * @return {boolean} |
496 */ | 368 */ |
497 isEnabled: function(languageCode) { | 369 canDisableLanguage: function(languageCode) { |
498 return !!this.enabledLanguageMap_[languageCode]; | 370 // Cannot disable the prospective UI language. |
371 if (languageCode == this.getProspectiveUILanguage()) | |
372 return false; | |
373 | |
374 // Cannot disable the only enabled language. | |
375 if (this.languages.enabledLanguages.length == 1) | |
376 return false; | |
377 | |
378 return true; | |
499 }, | 379 }, |
500 | 380 |
501 /** | 381 /** |
502 * Enables translate for the given language by removing the translate | 382 * Enables translate for the given language by removing the translate |
503 * language from the blocked languages preference. | 383 * language from the blocked languages preference. |
504 * @param {string} languageCode | 384 * @param {string} languageCode |
505 */ | 385 */ |
506 enableTranslateLanguage: function(languageCode) { | 386 enableTranslateLanguage: function(languageCode) { |
507 languageCode = this.convertLanguageCodeForTranslate(languageCode); | 387 languageCode = this.convertLanguageCodeForTranslate(languageCode); |
508 this.arrayDelete('prefs.translate_blocked_languages.value', languageCode); | 388 this.arrayDelete('prefs.translate_blocked_languages.value', languageCode); |
(...skipping 29 matching lines...) Expand all Loading... | |
538 this.arrayDelete('prefs.spellcheck.dictionaries.value', languageCode); | 418 this.arrayDelete('prefs.spellcheck.dictionaries.value', languageCode); |
539 } | 419 } |
540 }, | 420 }, |
541 | 421 |
542 /** | 422 /** |
543 * Converts the language code for translate. There are some differences | 423 * Converts the language code for translate. There are some differences |
544 * between the language set the Translate server uses and that for | 424 * between the language set the Translate server uses and that for |
545 * Accept-Language. | 425 * Accept-Language. |
546 * @param {string} languageCode | 426 * @param {string} languageCode |
547 * @return {string} The converted language code. | 427 * @return {string} The converted language code. |
548 * @private | |
549 */ | 428 */ |
550 convertLanguageCodeForTranslate: function(languageCode) { | 429 convertLanguageCodeForTranslate: function(languageCode) { |
551 if (languageCode in kLanguageCodeToTranslateCode) | 430 if (languageCode in kLanguageCodeToTranslateCode) |
552 return kLanguageCodeToTranslateCode[languageCode]; | 431 return kLanguageCodeToTranslateCode[languageCode]; |
553 | 432 |
554 var main = languageCode.split('-')[0]; | 433 var main = languageCode.split('-')[0]; |
555 if (main == 'zh') { | 434 if (main == 'zh') { |
556 // In Translate, general Chinese is not used, and the sub code is | 435 // In Translate, general Chinese is not used, and the sub code is |
557 // necessary as a language code for the Translate server. | 436 // necessary as a language code for the Translate server. |
558 return languageCode; | 437 return languageCode; |
559 } | 438 } |
560 if (main in kTranslateLanguageSynonyms) | 439 if (main in kTranslateLanguageSynonyms) |
561 return kTranslateLanguageSynonyms[main]; | 440 return kTranslateLanguageSynonyms[main]; |
562 | 441 |
563 return main; | 442 return main; |
564 }, | 443 }, |
444 | |
445 /** | |
446 * @param {string} languageCode | |
447 * @return {!chrome.languageSettingsPrivate.Language|undefined} | |
448 */ | |
449 getLanguage: function(languageCode) { | |
450 return this.supportedLanguageMap_[languageCode]; | |
451 }, | |
452 }); | |
453 | |
454 /** | |
455 * A reference to the singleton under the guise of a LanguageSettingsHelper | |
456 * implementation. This provides a limited API but implies the singleton | |
457 * should not be used directly for data binding. | |
458 */ | |
459 settings.LanguageHelper = SettingsLanguagesSingletonElement; | |
Dan Beam
2015/11/18 18:06:01
why not cr.exportPath() here?
michaelpg
2015/11/22 00:22:40
Why cr.exportPath() here?
Dan Beam
2015/11/23 20:14:10
as low as possible
michaelpg
2015/11/23 20:26:56
Oh, I interpreted "why not cr.exportPath() here?"
Dan Beam
2015/11/23 20:59:50
yes
| |
460 cr.addSingletonGetter(settings.LanguageHelper); | |
Dan Beam
2015/11/18 18:06:01
do you need to addSingletonGetter() to the setting
michaelpg
2015/11/22 00:22:40
Not if we make settings.LanguageHelper point to th
Dan Beam
2015/11/23 20:14:10
why is this better than addSingletonGetter? why d
michaelpg
2015/11/23 20:26:56
Sorry, but: Huh? When you asked if I "needed" to a
Dan Beam
2015/11/23 20:59:50
You were doing this:
cr.addSingletonGetter(sett
michaelpg
2015/11/24 20:27:13
OK, I changed it to what you wanted originally. I
| |
461 | |
462 /** | |
463 * This element has a reference to the singleton, exposing the singleton's | |
464 * |languages| model to the host of this element. | |
465 */ | |
466 Polymer({ | |
467 is: 'settings-languages', | |
468 | |
469 properties: { | |
470 /** | |
471 * Singleton element created at startup which provides the languages model. | |
472 * @type {!Element} | |
473 */ | |
474 singleton_: { | |
475 type: Object, | |
476 value: settings.LanguageHelper.getInstance(), | |
477 }, | |
478 | |
479 /** | |
480 * A reference to the languages model from the singleton, exposed as a | |
481 * read-only property so hosts can bind to it, but not change it. | |
482 * @type {LanguagesModel|undefined} | |
483 */ | |
484 languages: { | |
485 type: Object, | |
486 notify: true, | |
487 readOnly: true, | |
488 }, | |
489 }, | |
490 | |
491 ready: function() { | |
492 // Set the 'languages' property to reference the singleton's model. | |
493 this._setLanguages(this.singleton_.languages); | |
Dan Beam
2015/11/18 18:06:01
why are you calling a private Polymer method?
michaelpg
2015/11/22 00:22:40
this is how you set a readOnly property.
Dan Beam
2015/11/23 20:14:10
Acknowledged. (though mildly odd to me, guess it's
| |
494 // Listen for changes to the singleton's languages property, so we know | |
495 // when to notify hosts of changes to (our reference to) the property. | |
496 this.listen( | |
497 this.singleton_, 'languages-changed', 'singletonLanguagesChanged_'); | |
498 }, | |
499 | |
500 /** | |
501 * Takes changes reported by the singleton and forwards them to the host, | |
502 * manually sending a change notification for our 'languages' property (since | |
503 * it's the same object as the singleton's property, but isn't bound by | |
504 * Polymer). | |
505 * @private | |
506 */ | |
507 singletonLanguagesChanged_: function(e) { | |
508 // Forward the change notification to the host. | |
509 this.fire(e.type, e.detail, {bubbles: false}); | |
510 }, | |
565 }); | 511 }); |
566 })(); | 512 })(); |
OLD | NEW |