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}} */ | |
| 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 | |
| 48 (function() { | 27 (function() { |
| 49 'use strict'; | 28 'use strict'; |
| 50 | 29 |
| 51 // Translate server treats some language codes the same. | 30 // Translate server treats some language codes the same. |
| 52 // See also: components/translate/core/common/translate_util.cc. | 31 // See also: components/translate/core/common/translate_util.cc. |
| 53 var kLanguageCodeToTranslateCode = { | 32 var kLanguageCodeToTranslateCode = { |
| 54 'nb': 'no', | 33 'nb': 'no', |
| 55 'fil': 'tl', | 34 'fil': 'tl', |
| 56 'zh-HK': 'zh-TW', | 35 'zh-HK': 'zh-TW', |
| 57 'zh-MO': 'zh-TW', | 36 'zh-MO': 'zh-TW', |
| 58 'zh-SG': 'zh-CN', | 37 'zh-SG': 'zh-CN', |
| 59 }; | 38 }; |
| 60 | 39 |
| 61 // Some ISO 639 language codes have been renamed, e.g. "he" to "iw", but | 40 // 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. | 41 // Translate still uses the old versions. TODO(michaelpg): Chrome does too. |
| 63 // Follow up with Translate owners to understand the right thing to do. | 42 // Follow up with Translate owners to understand the right thing to do. |
| 64 var kTranslateLanguageSynonyms = { | 43 var kTranslateLanguageSynonyms = { |
| 65 'he': 'iw', | 44 'he': 'iw', |
| 66 'jv': 'jw', | 45 'jv': 'jw', |
| 67 }; | 46 }; |
| 68 | 47 |
| 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 ? | 48 var preferredLanguagesPrefName = cr.isChromeOS ? |
| 183 'settings.language.preferred_languages' : 'intl.accept_languages'; | 49 'settings.language.preferred_languages' : 'intl.accept_languages'; |
| 184 | 50 |
| 185 /** | 51 /** |
| 186 * Singleton element created when settings-languages is registered. | 52 * 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 | 53 * updates it whenever Chrome's pref store and other settings change. These |
| 188 * pref store and other settings change. These updates propagate to each | 54 * updates propagate to each <settings-language> instance so that their |
| 189 * <settings-language> instance so that their 'languages' property updates | 55 * 'languages' property updates like any other Polymer property. |
| 190 * like any other Polymer property. | 56 * @implements {LanguageSettingsHelper} |
| 191 */ | 57 */ |
| 192 Polymer({ | 58 var SettingsLanguagesSingletonElement = Polymer({ |
| 193 is: 'settings-languages-singleton', | 59 is: 'settings-languages-singleton', |
| 194 | 60 |
| 195 behaviors: [PrefsBehavior], | 61 behaviors: [PrefsBehavior], |
| 196 | 62 |
| 197 properties: { | 63 properties: { |
| 198 /** | 64 /** |
| 199 * @type {LanguagesModel|undefined} | 65 * @type {LanguagesModel|undefined} |
| 200 */ | 66 */ |
| 201 languages: { | 67 languages: { |
| 202 type: Object, | 68 type: Object, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 260 resolve(); | 126 resolve(); |
| 261 }); | 127 }); |
| 262 }), | 128 }), |
| 263 ]).then(function() { | 129 ]).then(function() { |
| 264 this.createModel_(languageList, translateTarget); | 130 this.createModel_(languageList, translateTarget); |
| 265 this.initialized_ = true; | 131 this.initialized_ = true; |
| 266 }.bind(this)); | 132 }.bind(this)); |
| 267 }, | 133 }, |
| 268 | 134 |
| 269 /** | 135 /** |
| 136 * Updates the list of enabled languages from the preferred languages pref. | |
| 137 * @private | |
| 138 */ | |
| 139 preferredLanguagesPrefChanged_: function() { | |
| 140 if (!this.initialized_) | |
| 141 return; | |
| 142 var enabledLanguages = | |
| 143 this.getEnabledLanguages_(this.languages.translateTarget); | |
| 144 | |
| 145 // Reset the enabled language map before updating | |
| 146 // languages.enabledLanguages. | |
| 147 this.enabledLanguageMap_ = {}; | |
| 148 for (var i = 0; i < enabledLanguages.length; i++) { | |
| 149 var languageInfo = enabledLanguages[i]; | |
| 150 this.enabledLanguageMap_[languageInfo.language.code] = languageInfo; | |
| 151 } | |
| 152 this.set('languages.enabledLanguages', enabledLanguages); | |
| 153 }, | |
| 154 | |
| 155 /** | |
| 156 * Updates the spellCheckEnabled state of each enabled language. | |
| 157 * @private | |
| 158 */ | |
| 159 spellCheckDictionariesPrefChanged_: function() { | |
| 160 if (!this.initialized_) | |
| 161 return; | |
| 162 | |
| 163 var spellCheckMap = this.makeMapFromArray_(/** @type {!Array<string>} */( | |
| 164 this.getPref('spellcheck.dictionaries').value)); | |
| 165 for (var i = 0; i < this.languages.enabledLanguages.length; i++) { | |
| 166 var languageCode = this.languages.enabledLanguages[i].language.code; | |
| 167 this.set('languages.enabledLanguages.' + i + '.state.spellCheckEnabled', | |
| 168 !!spellCheckMap[languageCode]); | |
| 169 } | |
| 170 }, | |
| 171 | |
| 172 /** @private */ | |
| 173 translateLanguagesPrefChanged_: function() { | |
| 174 if (!this.initialized_) | |
| 175 return; | |
| 176 | |
| 177 var translateBlockedPref = this.getPref('translate_blocked_languages'); | |
| 178 var translateBlockedMap = this.makeMapFromArray_( | |
| 179 /** @type {!Array<string>} */(translateBlockedPref.value)); | |
| 180 | |
| 181 for (var i = 0; i < this.languages.enabledLanguages.length; i++) { | |
| 182 var translateCode = this.convertLanguageCodeForTranslate( | |
| 183 this.languages.enabledLanguages[i].language.code); | |
| 184 this.set( | |
| 185 'languages.enabledLanguages.' + i + '.state.translateEnabled', | |
| 186 !translateBlockedMap[translateCode]); | |
| 187 } | |
| 188 }, | |
| 189 | |
| 190 /** | |
| 270 * Constructs the languages model. | 191 * Constructs the languages model. |
| 271 * @param {!Array<!chrome.languageSettingsPrivate.Language>} | 192 * @param {!Array<!chrome.languageSettingsPrivate.Language>} |
| 272 * supportedLanguages | 193 * supportedLanguages |
| 273 * @param {string} translateTarget Language code of the default translate | 194 * @param {string} translateTarget Language code of the default translate |
| 274 * target language. | 195 * target language. |
| 196 * @private | |
| 275 */ | 197 */ |
| 276 createModel_: function(supportedLanguages, translateTarget) { | 198 createModel_: function(supportedLanguages, translateTarget) { |
| 277 // Populate the hash map of supported languages. | 199 // Populate the hash map of supported languages. |
| 278 for (var i = 0; i < supportedLanguages.length; i++) { | 200 for (var i = 0; i < supportedLanguages.length; i++) { |
| 279 var language = supportedLanguages[i]; | 201 var language = supportedLanguages[i]; |
| 280 language.supportsUI = !!language.supportsUI; | 202 language.supportsUI = !!language.supportsUI; |
| 281 language.supportsTranslate = !!language.supportsTranslate; | 203 language.supportsTranslate = !!language.supportsTranslate; |
| 282 language.supportsSpellcheck = !!language.supportsSpellcheck; | 204 language.supportsSpellcheck = !!language.supportsSpellcheck; |
| 283 this.supportedLanguageMap_[language.code] = language; | 205 this.supportedLanguageMap_[language.code] = language; |
| 284 } | 206 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 318 var spellCheckMap = this.makeMapFromArray_(/** @type {!Array<string>} */( | 240 var spellCheckMap = this.makeMapFromArray_(/** @type {!Array<string>} */( |
| 319 spellCheckPref.value)); | 241 spellCheckPref.value)); |
| 320 | 242 |
| 321 var translateBlockedPref = this.getPref('translate_blocked_languages'); | 243 var translateBlockedPref = this.getPref('translate_blocked_languages'); |
| 322 var translateBlockedMap = this.makeMapFromArray_( | 244 var translateBlockedMap = this.makeMapFromArray_( |
| 323 /** @type {!Array<string>} */(translateBlockedPref.value)); | 245 /** @type {!Array<string>} */(translateBlockedPref.value)); |
| 324 | 246 |
| 325 for (var i = 0; i < enabledLanguageCodes.length; i++) { | 247 for (var i = 0; i < enabledLanguageCodes.length; i++) { |
| 326 var code = enabledLanguageCodes[i]; | 248 var code = enabledLanguageCodes[i]; |
| 327 var language = this.supportedLanguageMap_[code]; | 249 var language = this.supportedLanguageMap_[code]; |
| 250 // Skip unsupported languages. | |
| 328 if (!language) | 251 if (!language) |
| 329 continue; | 252 continue; |
| 330 var state = {}; | 253 var state = /** @type {LanguageState} */({}); |
| 331 state.spellCheckEnabled = !!spellCheckMap[code]; | 254 state.spellCheckEnabled = !!spellCheckMap[code]; |
| 332 // Translate is considered disabled if this language maps to any translate | 255 // Translate is considered disabled if this language maps to any translate |
| 333 // language that is blocked. | 256 // language that is blocked. |
| 334 var translateCode = this.convertLanguageCodeForTranslate(code); | 257 var translateCode = this.convertLanguageCodeForTranslate(code); |
| 335 state.translateEnabled = language.supportsTranslate && | 258 state.translateEnabled = !!language.supportsTranslate && |
| 336 !translateBlockedMap[translateCode] && | 259 !translateBlockedMap[translateCode] && |
| 337 translateCode != translateTarget; | 260 translateCode != translateTarget; |
| 338 enabledLanguages.push({language: language, state: state}); | 261 enabledLanguages.push(/** @type {LanguageInfo} */( |
| 262 {language: language, state: state})); | |
| 339 } | 263 } |
| 340 return enabledLanguages; | 264 return enabledLanguages; |
| 341 }, | 265 }, |
| 342 | 266 |
| 343 /** | 267 /** |
| 344 * Creates an object whose keys are the elements of the list. | 268 * Creates an object whose keys are the elements of the list. |
| 345 * @param {!Array<string>} list | 269 * @param {!Array<string>} list |
| 346 * @return {!Object<boolean>} | 270 * @return {!Object<boolean>} |
| 271 * @private | |
| 347 */ | 272 */ |
| 348 makeMapFromArray_: function(list) { | 273 makeMapFromArray_: function(list) { |
| 349 var map = {}; | 274 var map = {}; |
| 350 for (var i = 0; i < list.length; i++) | 275 for (var i = 0; i < list.length; i++) |
| 351 map[list[i]] = true; | 276 map[list[i]] = true; |
| 352 return map; | 277 return map; |
| 353 }, | 278 }, |
| 354 | 279 |
| 355 /** | 280 // LanguageSettingsHelper implementation. |
| 356 * Updates the list of enabled languages from the preferred languages pref. | 281 // TODO(michaelpg): replace duplicate docs with @inheritDoc once b/24294625 |
|
Dan Beam
2015/11/11 07:34:21
inheritDoc is dead, I think you mean @override
michaelpg
2015/11/13 05:30:17
Done.
| |
| 357 * @private | 282 // 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 | 283 |
| 420 /** | 284 /** |
| 421 * Windows and Chrome OS only: Sets the prospective UI language to the chosen | 285 * 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. | 286 * language. This dosen't affect the actual UI language until a restart. |
| 423 * @param {string} languageCode | 287 * @param {string} languageCode |
| 424 */ | 288 */ |
| 425 setUILanguage: function(languageCode) { | 289 setUILanguage: function(languageCode) { |
| 426 chrome.send('setUILanguage', [languageCode]); | 290 if (cr.isWindows || cr.isChromeOS) |
|
Dan Beam
2015/11/11 07:34:21
can this be assert(cr.isWindows || cr.isChromeOS)
michaelpg
2015/11/13 05:30:17
Done.
| |
| 291 chrome.send('setUILanguage', [languageCode]); | |
| 427 }, | 292 }, |
| 428 | 293 |
| 429 /** | 294 /** |
| 430 * Windows and Chrome OS only: Resets the prospective UI language back to the | 295 * Windows and Chrome OS only: Resets the prospective UI language back to the |
| 431 * actual UI language. | 296 * actual UI language. |
| 432 */ | 297 */ |
| 433 resetUILanguage: function() { | 298 resetUILanguage: function() { |
| 434 chrome.send('setUILanguage', [navigator.language]); | 299 if (cr.isWindows || cr.isChromeOS) |
| 300 chrome.send('setUILanguage', [navigator.language]); | |
| 435 }, | 301 }, |
| 436 | 302 |
| 437 /** | 303 /** |
| 438 * Returns the "prospective" UI language, i.e. the one to be used on next | 304 * 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 | 305 * restart. If the pref is not set, the current UI language is also the |
| 440 * "prospective" language. | 306 * "prospective" language. |
| 441 * @return {string} Language code of the prospective UI language. | 307 * @return {string} Language code of the prospective UI language. |
| 442 * @private | |
| 443 */ | 308 */ |
| 444 getProspectiveUILanguage: function() { | 309 getProspectiveUILanguage: function() { |
| 445 return /** @type {string} */(this.getPref('intl.app_locale').value) || | 310 return /** @type {string} */(this.getPref('intl.app_locale').value) || |
| 446 navigator.language; | 311 navigator.language; |
| 447 }, | 312 }, |
| 448 | 313 |
| 449 /** | 314 /** |
| 315 * @param {string} languageCode | |
| 316 * @return {boolean} True if the language is enabled. | |
| 317 */ | |
| 318 isLanguageEnabled: function(languageCode) { | |
| 319 return !!this.enabledLanguageMap_[languageCode]; | |
| 320 }, | |
| 321 | |
| 322 /** | |
| 450 * Enables the language, making it available for spell check and input. | 323 * Enables the language, making it available for spell check and input. |
| 451 * @param {string} languageCode | 324 * @param {string} languageCode |
| 452 */ | 325 */ |
| 453 enableLanguage: function(languageCode) { | 326 enableLanguage: function(languageCode) { |
| 454 if (!CrSettingsPrefs.isInitialized) | 327 if (!CrSettingsPrefs.isInitialized) |
| 455 return; | 328 return; |
| 456 | 329 |
| 457 var languageCodes = | 330 var languageCodes = |
| 458 this.getPref(preferredLanguagesPrefName).value.split(','); | 331 this.getPref(preferredLanguagesPrefName).value.split(','); |
| 459 if (languageCodes.indexOf(languageCode) > -1) | 332 if (languageCodes.indexOf(languageCode) > -1) |
| 460 return; | 333 return; |
| 461 languageCodes.push(languageCode); | 334 languageCodes.push(languageCode); |
| 462 chrome.languageSettingsPrivate.setLanguageList(languageCodes); | 335 chrome.languageSettingsPrivate.setLanguageList(languageCodes); |
| 463 this.disableTranslateLanguage(languageCode); | 336 this.disableTranslateLanguage(languageCode); |
| 464 }, | 337 }, |
| 465 | 338 |
| 466 /** | 339 /** |
| 467 * Disables the language. | 340 * Disables the language. |
| 468 * @param {string} languageCode | 341 * @param {string} languageCode |
| 469 */ | 342 */ |
| 470 disableLanguage: function(languageCode) { | 343 disableLanguage: function(languageCode) { |
| 471 if (!CrSettingsPrefs.isInitialized) | 344 if (!CrSettingsPrefs.isInitialized) |
| 472 return; | 345 return; |
| 473 | 346 |
| 474 // Cannot disable the UI language. | 347 assert(this.canDisableLanguage(languageCode)); |
| 475 assert(languageCode != this.getProspectiveUILanguage()); | |
| 476 | 348 |
| 477 // Cannot disable the only enabled language. | 349 // Remove the language from spell check. |
| 350 this.arrayDelete('prefs.spellcheck.dictionaries.value', languageCode); | |
| 351 | |
| 352 // Remove the language from preferred languages. | |
| 478 var languageCodes = | 353 var languageCodes = |
| 479 this.getPref(preferredLanguagesPrefName).value.split(','); | 354 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); | 355 var languageIndex = languageCodes.indexOf(languageCode); |
| 486 if (languageIndex == -1) | 356 if (languageIndex == -1) |
| 487 return; | 357 return; |
| 488 languageCodes.splice(languageIndex, 1); | 358 languageCodes.splice(languageIndex, 1); |
| 489 chrome.languageSettingsPrivate.setLanguageList(languageCodes); | 359 chrome.languageSettingsPrivate.setLanguageList(languageCodes); |
| 490 this.enableTranslateLanguage(languageCode); | 360 this.enableTranslateLanguage(languageCode); |
| 491 }, | 361 }, |
| 492 | 362 |
| 493 /** | 363 /** |
| 494 * @param {string} languageCode | 364 * @param {string} languageCode Language code for an enabled language. |
| 495 * @return {boolean} True if the language is enabled. | 365 * @return {boolean} |
| 496 */ | 366 */ |
| 497 isEnabled: function(languageCode) { | 367 canDisableLanguage: function(languageCode) { |
| 498 return !!this.enabledLanguageMap_[languageCode]; | 368 // Cannot disable the prospective UI language. |
| 369 if (languageCode == this.getProspectiveUILanguage()) | |
| 370 return false; | |
| 371 | |
| 372 // Cannot disable the only enabled language. | |
| 373 if (this.languages.enabledLanguages.length == 1) | |
| 374 return false; | |
| 375 | |
| 376 return true; | |
| 499 }, | 377 }, |
| 500 | 378 |
| 501 /** | 379 /** |
| 502 * Enables translate for the given language by removing the translate | 380 * Enables translate for the given language by removing the translate |
| 503 * language from the blocked languages preference. | 381 * language from the blocked languages preference. |
| 504 * @param {string} languageCode | 382 * @param {string} languageCode |
| 505 */ | 383 */ |
| 506 enableTranslateLanguage: function(languageCode) { | 384 enableTranslateLanguage: function(languageCode) { |
| 507 languageCode = this.convertLanguageCodeForTranslate(languageCode); | 385 languageCode = this.convertLanguageCodeForTranslate(languageCode); |
| 508 this.arrayDelete('prefs.translate_blocked_languages.value', languageCode); | 386 this.arrayDelete('prefs.translate_blocked_languages.value', languageCode); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 538 this.arrayDelete('prefs.spellcheck.dictionaries.value', languageCode); | 416 this.arrayDelete('prefs.spellcheck.dictionaries.value', languageCode); |
| 539 } | 417 } |
| 540 }, | 418 }, |
| 541 | 419 |
| 542 /** | 420 /** |
| 543 * Converts the language code for translate. There are some differences | 421 * Converts the language code for translate. There are some differences |
| 544 * between the language set the Translate server uses and that for | 422 * between the language set the Translate server uses and that for |
| 545 * Accept-Language. | 423 * Accept-Language. |
| 546 * @param {string} languageCode | 424 * @param {string} languageCode |
| 547 * @return {string} The converted language code. | 425 * @return {string} The converted language code. |
| 548 * @private | |
| 549 */ | 426 */ |
| 550 convertLanguageCodeForTranslate: function(languageCode) { | 427 convertLanguageCodeForTranslate: function(languageCode) { |
| 551 if (languageCode in kLanguageCodeToTranslateCode) | 428 if (languageCode in kLanguageCodeToTranslateCode) |
| 552 return kLanguageCodeToTranslateCode[languageCode]; | 429 return kLanguageCodeToTranslateCode[languageCode]; |
| 553 | 430 |
| 554 var main = languageCode.split('-')[0]; | 431 var main = languageCode.split('-')[0]; |
| 555 if (main == 'zh') { | 432 if (main == 'zh') { |
| 556 // In Translate, general Chinese is not used, and the sub code is | 433 // In Translate, general Chinese is not used, and the sub code is |
| 557 // necessary as a language code for the Translate server. | 434 // necessary as a language code for the Translate server. |
| 558 return languageCode; | 435 return languageCode; |
| 559 } | 436 } |
| 560 if (main in kTranslateLanguageSynonyms) | 437 if (main in kTranslateLanguageSynonyms) |
| 561 return kTranslateLanguageSynonyms[main]; | 438 return kTranslateLanguageSynonyms[main]; |
| 562 | 439 |
| 563 return main; | 440 return main; |
| 564 }, | 441 }, |
| 442 | |
| 443 /** | |
| 444 * @param {string} languageCode | |
| 445 * @return {!chrome.languageSettingsPrivate.Language|undefined} | |
| 446 */ | |
| 447 getLanguage: function(languageCode) { | |
| 448 return this.supportedLanguageMap_[languageCode]; | |
| 449 }, | |
| 450 }); | |
| 451 | |
| 452 cr.exportPath('settings'); | |
| 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 * @type {{getInstance: function(): LanguageSettingsHelper}} | |
|
Dan Beam
2015/11/11 07:34:21
this @type should not be necessary... ChromePass s
michaelpg
2015/11/13 05:30:17
Done. Weird, I was getting an error before.
| |
| 459 */ | |
| 460 settings.LanguageHelper = SettingsLanguagesSingletonElement; | |
|
Dan Beam
2015/11/11 07:34:21
why is this better than just defining the singleto
michaelpg
2015/11/13 05:30:17
I'll write up documentation, but having it as a Po
| |
| 461 cr.addSingletonGetter(settings.LanguageHelper); | |
| 462 | |
| 463 /** | |
| 464 * This element has a reference to the singleton, exposing the singleton's | |
| 465 * |languages| model to the host of this element. | |
| 466 */ | |
| 467 Polymer({ | |
| 468 is: 'settings-languages', | |
| 469 | |
| 470 properties: { | |
| 471 /** | |
| 472 * Singleton element created at startup which provides the languages model. | |
| 473 * @type {!Element} | |
| 474 */ | |
| 475 singleton_: { | |
| 476 type: Object, | |
| 477 value: settings.LanguageHelper.getInstance(), | |
| 478 }, | |
| 479 | |
| 480 /** | |
| 481 * A reference to the languages model from the singleton, exposed as a | |
| 482 * read-only property so hosts can bind to it, but not change it. | |
| 483 * @type {LanguagesModel|undefined} | |
| 484 */ | |
| 485 languages: { | |
| 486 type: Object, | |
| 487 notify: true, | |
| 488 readOnly: true, | |
| 489 }, | |
| 490 }, | |
| 491 | |
| 492 ready: function() { | |
| 493 // Set the 'languages' property to reference the singleton's model. | |
| 494 this._setLanguages(this.singleton_.languages); | |
| 495 // Listen for changes to the singleton's languages property, so we know | |
| 496 // when to notify hosts of changes to (our reference to) the property. | |
| 497 this.listen( | |
| 498 this.singleton_, 'languages-changed', 'singletonLanguagesChanged_'); | |
| 499 }, | |
| 500 | |
| 501 /** | |
| 502 * Takes changes reported by the singleton and forwards them to the host, | |
| 503 * manually sending a change notification for our 'languages' property (since | |
| 504 * it's the same object as the singleton's property, but isn't bound by | |
| 505 * Polymer). | |
| 506 * @private | |
| 507 */ | |
| 508 singletonLanguagesChanged_: function(e) { | |
| 509 // Forward the change notification to the host. | |
| 510 this.fire(e.type, e.detail, {bubbles: false}); | |
| 511 }, | |
| 565 }); | 512 }); |
| 566 })(); | 513 })(); |
| OLD | NEW |