Chromium Code Reviews| 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 |