| 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' handles Chrome's language and input |
| 7 * Chrome's language and input method settings. | 7 * method settings. The 'languages' property, which reflects the current |
| 8 * | 8 * language settings, must not be changed directly. Instead, changes to |
| 9 * Instances of this element have a 'languages' property, which reflects the | 9 * language settings should be made using the LanguageHelper APIs provided by |
| 10 * current language settings. The 'languages' property is read-only, meaning | 10 * this class via languageHelper. |
| 11 * hosts using this element cannot change it directly. Instead, changes to | |
| 12 * language settings should be made using the LanguageHelperImpl singleton. | |
| 13 * | |
| 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: | |
| 16 * | |
| 17 * <template> | |
| 18 * <settings-languages languages="{{languages}}"> | |
| 19 * </settings-languages> | |
| 20 * <div>[[languages.someProperty]]</div> | |
| 21 * </template> | |
| 22 */ | 11 */ |
| 23 | 12 |
| 24 var SettingsLanguagesSingletonElement; | |
| 25 | |
| 26 cr.exportPath('languageSettings'); | |
| 27 | |
| 28 (function() { | 13 (function() { |
| 29 'use strict'; | 14 'use strict'; |
| 30 | 15 |
| 16 cr.exportPath('settings'); |
| 17 |
| 31 // Translate server treats some language codes the same. | 18 // Translate server treats some language codes the same. |
| 32 // See also: components/translate/core/common/translate_util.cc. | 19 // See also: components/translate/core/common/translate_util.cc. |
| 33 var kLanguageCodeToTranslateCode = { | 20 var kLanguageCodeToTranslateCode = { |
| 34 'nb': 'no', | 21 'nb': 'no', |
| 35 'fil': 'tl', | 22 'fil': 'tl', |
| 36 'zh-HK': 'zh-TW', | 23 'zh-HK': 'zh-TW', |
| 37 'zh-MO': 'zh-TW', | 24 'zh-MO': 'zh-TW', |
| 38 'zh-SG': 'zh-CN', | 25 'zh-SG': 'zh-CN', |
| 39 }; | 26 }; |
| 40 | 27 |
| 41 // Some ISO 639 language codes have been renamed, e.g. "he" to "iw", but | 28 // Some ISO 639 language codes have been renamed, e.g. "he" to "iw", but |
| 42 // Translate still uses the old versions. TODO(michaelpg): Chrome does too. | 29 // Translate still uses the old versions. TODO(michaelpg): Chrome does too. |
| 43 // Follow up with Translate owners to understand the right thing to do. | 30 // Follow up with Translate owners to understand the right thing to do. |
| 44 var kTranslateLanguageSynonyms = { | 31 var kTranslateLanguageSynonyms = { |
| 45 'he': 'iw', | 32 'he': 'iw', |
| 46 'jv': 'jw', | 33 'jv': 'jw', |
| 47 }; | 34 }; |
| 48 | 35 |
| 49 var preferredLanguagesPrefName = cr.isChromeOS ? | 36 var preferredLanguagesPrefName = cr.isChromeOS ? |
| 50 'settings.language.preferred_languages' : 'intl.accept_languages'; | 37 'settings.language.preferred_languages' : 'intl.accept_languages'; |
| 51 | 38 |
| 52 /** | 39 /** |
| 53 * Singleton element that generates the languages model on start-up and | 40 * Singleton element that generates the languages model on start-up and |
| 54 * updates it whenever Chrome's pref store and other settings change. These | 41 * updates it whenever Chrome's pref store and other settings change. |
| 55 * updates propagate to each <settings-language> instance so that their | |
| 56 * 'languages' property updates like any other Polymer property. | |
| 57 * @implements {LanguageHelper} | 42 * @implements {LanguageHelper} |
| 58 */ | 43 */ |
| 59 SettingsLanguagesSingletonElement = Polymer({ | 44 Polymer({ |
| 60 is: 'settings-languages-singleton', | 45 is: 'settings-languages', |
| 61 | 46 |
| 62 behaviors: [PrefsBehavior], | 47 behaviors: [PrefsBehavior], |
| 63 | 48 |
| 64 properties: { | 49 properties: { |
| 65 /** | 50 /** |
| 66 * @type {!LanguagesModel|undefined} | 51 * @type {!LanguagesModel|undefined} |
| 67 */ | 52 */ |
| 68 languages: { | 53 languages: { |
| 69 type: Object, | 54 type: Object, |
| 70 notify: true, | 55 notify: true, |
| 56 readOnly: true, |
| 71 }, | 57 }, |
| 72 | 58 |
| 73 /** | 59 /** |
| 74 * Object containing all preferences. | 60 * Object containing all preferences. |
| 75 */ | 61 */ |
| 76 prefs: { | 62 prefs: { |
| 77 type: Object, | 63 type: Object, |
| 78 notify: true, | 64 notify: true, |
| 79 }, | 65 }, |
| 80 | 66 |
| 81 /** | 67 /** |
| 68 * This element, as a LanguageHelper instance for API usage. |
| 69 * @type {!LanguageHelper} |
| 70 */ |
| 71 languageHelper: { |
| 72 type: Object, |
| 73 notify: true, |
| 74 readOnly: true, |
| 75 value: function() { return /** @type {!LanguageHelper} */(this); }, |
| 76 }, |
| 77 |
| 78 /** |
| 82 * PromiseResolver to be resolved when the singleton has been initialized. | 79 * PromiseResolver to be resolved when the singleton has been initialized. |
| 83 * @private {!PromiseResolver} | 80 * @private {!PromiseResolver} |
| 84 */ | 81 */ |
| 85 resolver_: { | 82 resolver_: { |
| 86 type: Object, | 83 type: Object, |
| 87 value: function() { | 84 value: function() { |
| 88 return new PromiseResolver(); | 85 return new PromiseResolver(); |
| 89 }, | 86 }, |
| 90 }, | 87 }, |
| 91 | 88 |
| 92 /** @type {!LanguageSettingsPrivate} */ | 89 /** @type {!LanguageSettingsPrivate} */ |
| 93 languageSettingsPrivate: Object, | 90 languageSettingsPrivate: Object, |
| 94 | 91 |
| 95 /** @type {!InputMethodPrivate} */ | 92 /** @type {!InputMethodPrivate} */ |
| 96 inputMethodPrivate: Object, | 93 inputMethodPrivate: Object, |
| 94 |
| 95 /** |
| 96 * Hash map of supported languages by language codes for fast lookup. |
| 97 * @private {!Map<string, !chrome.languageSettingsPrivate.Language>} |
| 98 */ |
| 99 supportedLanguageMap_: { |
| 100 type: Object, |
| 101 value: function() { return new Map(); }, |
| 102 }, |
| 103 |
| 104 /** |
| 105 * Hash set of enabled language codes for membership testing. |
| 106 * @private {!Set<string>} |
| 107 */ |
| 108 enabledLanguageSet_: { |
| 109 type: Object, |
| 110 value: function() { return new Set(); }, |
| 111 }, |
| 112 |
| 113 /** |
| 114 * Hash map of supported input methods by ID for fast lookup. |
| 115 * @private {!Map<string, chrome.languageSettingsPrivate.InputMethod>} |
| 116 */ |
| 117 supportedInputMethodMap_: { |
| 118 type: Object, |
| 119 value: function() { return new Map(); }, |
| 120 }, |
| 121 |
| 122 /** |
| 123 * Hash map of input methods supported for each language. |
| 124 * @type {!Map<string, |
| 125 * !Array<!chrome.languageSettingsPrivate.InputMethod>>} |
| 126 * @private |
| 127 */ |
| 128 languageInputMethods_: { |
| 129 type: Object, |
| 130 value: function() { return new Map(); }, |
| 131 }, |
| 97 }, | 132 }, |
| 98 | 133 |
| 99 /** | |
| 100 * Hash map of supported languages by language codes for fast lookup. | |
| 101 * @private {!Map<string, !chrome.languageSettingsPrivate.Language>} | |
| 102 */ | |
| 103 supportedLanguageMap_: new Map(), | |
| 104 | |
| 105 /** | |
| 106 * Hash set of enabled language codes for membership testing. | |
| 107 * @private {!Set<string>} | |
| 108 */ | |
| 109 enabledLanguageSet_: new Set(), | |
| 110 | |
| 111 /** | |
| 112 * Hash map of supported input methods by ID for fast lookup. | |
| 113 * @private {!Map<string, chrome.languageSettingsPrivate.InputMethod>} | |
| 114 */ | |
| 115 supportedInputMethodMap_: new Map(), | |
| 116 | |
| 117 /** | |
| 118 * Hash map of input methods supported for each language. | |
| 119 * @type {!Map<string, !Array<!chrome.languageSettingsPrivate.InputMethod>>} | |
| 120 * @private | |
| 121 */ | |
| 122 languageInputMethods_: new Map(), | |
| 123 | |
| 124 observers: [ | 134 observers: [ |
| 125 'preferredLanguagesPrefChanged_(' + | 135 'preferredLanguagesPrefChanged_(' + |
| 126 'prefs.' + preferredLanguagesPrefName + '.value, languages)', | 136 'prefs.' + preferredLanguagesPrefName + '.value, languages)', |
| 127 'spellCheckDictionariesPrefChanged_(' + | 137 'spellCheckDictionariesPrefChanged_(' + |
| 128 'prefs.spellcheck.dictionaries.value.*, languages)', | 138 'prefs.spellcheck.dictionaries.value.*, languages)', |
| 129 'translateLanguagesPrefChanged_(' + | 139 'translateLanguagesPrefChanged_(' + |
| 130 'prefs.translate_blocked_languages.value.*, languages)', | 140 'prefs.translate_blocked_languages.value.*, languages)', |
| 131 'prospectiveUILanguageChanged_(' + | 141 'prospectiveUILanguageChanged_(' + |
| 132 'prefs.intl.app_locale.value, languages)', | 142 'prefs.intl.app_locale.value, languages)', |
| 133 // Observe Chrome OS prefs (ignored for non-Chrome OS). | 143 // Observe Chrome OS prefs (ignored for non-Chrome OS). |
| 134 'updateRemovableLanguages_(' + | 144 'updateRemovableLanguages_(' + |
| 135 'prefs.settings.language.preload_engines.value, ' + | 145 'prefs.settings.language.preload_engines.value, ' + |
| 136 'prefs.settings.language.enabled_extension_imes.value, ' + | 146 'prefs.settings.language.enabled_extension_imes.value, ' + |
| 137 'languages)', | 147 'languages)', |
| 138 ], | 148 ], |
| 139 | 149 |
| 140 /** @override */ | 150 /** @override */ |
| 141 created: function() { | 151 created: function() { |
| 142 this.languageSettingsPrivate = | 152 this.languageSettingsPrivate = |
| 143 languageSettings.languageSettingsPrivateApiForTest || | 153 settings.languageSettingsPrivateApiForTest || |
| 144 /** @type {!LanguageSettingsPrivate} */(chrome.languageSettingsPrivate); | 154 /** @type {!LanguageSettingsPrivate} */(chrome.languageSettingsPrivate); |
| 145 | 155 |
| 146 this.inputMethodPrivate = | 156 this.inputMethodPrivate = |
| 147 languageSettings.inputMethodPrivateApiForTest || | 157 settings.inputMethodPrivateApiForTest || |
| 148 /** @type {!InputMethodPrivate} */(chrome.inputMethodPrivate); | 158 /** @type {!InputMethodPrivate} */(chrome.inputMethodPrivate); |
| 149 | 159 |
| 150 var promises = []; | 160 var promises = []; |
| 151 | 161 |
| 152 // Wait until prefs are initialized before creating the model, so we can | 162 // Wait until prefs are initialized before creating the model, so we can |
| 153 // include information about enabled languages. | 163 // include information about enabled languages. |
| 154 promises[0] = CrSettingsPrefs.initialized; | 164 promises[0] = CrSettingsPrefs.initialized; |
| 155 | 165 |
| 156 // Get the language list. | 166 // Get the language list. |
| 157 promises[1] = new Promise(function(resolve) { | 167 promises[1] = new Promise(function(resolve) { |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 }); | 302 }); |
| 293 if (cr.isChromeOS) { | 303 if (cr.isChromeOS) { |
| 294 model.inputMethods = /** @type {!InputMethodsModel} */({ | 304 model.inputMethods = /** @type {!InputMethodsModel} */({ |
| 295 supported: supportedInputMethods, | 305 supported: supportedInputMethods, |
| 296 enabled: this.getEnabledInputMethods_(), | 306 enabled: this.getEnabledInputMethods_(), |
| 297 currentId: currentInputMethodId, | 307 currentId: currentInputMethodId, |
| 298 }); | 308 }); |
| 299 } | 309 } |
| 300 | 310 |
| 301 // Initialize the Polymer languages model. | 311 // Initialize the Polymer languages model. |
| 302 this.languages = model; | 312 this._setLanguages(model); |
| 303 }, | 313 }, |
| 304 | 314 |
| 305 /** | 315 /** |
| 306 * Returns a list of LanguageStates for each enabled language in the supported | 316 * Returns a list of LanguageStates for each enabled language in the supported |
| 307 * languages list. | 317 * languages list. |
| 308 * @param {string} translateTarget Language code of the default translate | 318 * @param {string} translateTarget Language code of the default translate |
| 309 * target language. | 319 * target language. |
| 310 * @return {!Array<!LanguageState>} | 320 * @return {!Array<!LanguageState>} |
| 311 * @private | 321 * @private |
| 312 */ | 322 */ |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 this.languageSettingsPrivate.removeInputMethod(id); | 689 this.languageSettingsPrivate.removeInputMethod(id); |
| 680 }, | 690 }, |
| 681 | 691 |
| 682 /** @param {string} id */ | 692 /** @param {string} id */ |
| 683 setCurrentInputMethod: function(id) { | 693 setCurrentInputMethod: function(id) { |
| 684 assert(cr.isChromeOS); | 694 assert(cr.isChromeOS); |
| 685 this.inputMethodPrivate.setCurrentInputMethod(id); | 695 this.inputMethodPrivate.setCurrentInputMethod(id); |
| 686 }, | 696 }, |
| 687 | 697 |
| 688 /** | 698 /** |
| 689 * param {string} languageCode | 699 * @param {string} languageCode |
| 690 * @return {!Array<!chrome.languageSettingsPrivate.InputMethod>} | 700 * @return {!Array<!chrome.languageSettingsPrivate.InputMethod>} |
| 691 */ | 701 */ |
| 692 getInputMethodsForLanguage: function(languageCode) { | 702 getInputMethodsForLanguage: function(languageCode) { |
| 693 return this.languageInputMethods_.get(languageCode) || []; | 703 return this.languageInputMethods_.get(languageCode) || []; |
| 694 }, | 704 }, |
| 695 | 705 |
| 696 /** | 706 /** |
| 697 * @param {!chrome.languageSettingsPrivate.InputMethod} inputMethod | 707 * @param {!chrome.languageSettingsPrivate.InputMethod} inputMethod |
| 698 * @return {boolean} | 708 * @return {boolean} |
| 699 */ | 709 */ |
| (...skipping 20 matching lines...) Expand all Loading... |
| 720 this.updateEnabledInputMethods_(); | 730 this.updateEnabledInputMethods_(); |
| 721 }, | 731 }, |
| 722 | 732 |
| 723 /** @param {string} id Removed input method ID. */ | 733 /** @param {string} id Removed input method ID. */ |
| 724 onInputMethodRemoved_: function(id) { | 734 onInputMethodRemoved_: function(id) { |
| 725 assert(cr.isChromeOS); | 735 assert(cr.isChromeOS); |
| 726 this.updateEnabledInputMethods_(); | 736 this.updateEnabledInputMethods_(); |
| 727 }, | 737 }, |
| 728 }); | 738 }); |
| 729 })(); | 739 })(); |
| 730 | |
| 731 /** | |
| 732 * A reference to the singleton under the guise of a LanguageHelper | |
| 733 * implementation. This provides a limited API but implies the singleton | |
| 734 * should not be used directly for data binding. | |
| 735 */ | |
| 736 var LanguageHelperImpl = SettingsLanguagesSingletonElement; | |
| 737 cr.addSingletonGetter(LanguageHelperImpl); | |
| 738 | |
| 739 /** | |
| 740 * This element has a reference to the singleton, exposing the singleton's | |
| 741 * |languages| model to the host of this element. | |
| 742 */ | |
| 743 Polymer({ | |
| 744 is: 'settings-languages', | |
| 745 | |
| 746 properties: { | |
| 747 /** | |
| 748 * A reference to the languages model from the singleton, exposed as a | |
| 749 * read-only property so hosts can bind to it, but not change it. | |
| 750 * @type {LanguagesModel|undefined} | |
| 751 */ | |
| 752 languages: { | |
| 753 type: Object, | |
| 754 notify: true, | |
| 755 readOnly: true, | |
| 756 }, | |
| 757 }, | |
| 758 | |
| 759 ready: function() { | |
| 760 var singleton = /** @type {!SettingsLanguagesSingletonElement} */ | |
| 761 (LanguageHelperImpl.getInstance()); | |
| 762 singleton.whenReady().then(function() { | |
| 763 // Set the 'languages' property to reference the singleton's model. | |
| 764 this._setLanguages(singleton.languages); | |
| 765 // Listen for changes to the singleton's languages property, so we know | |
| 766 // when to notify hosts of changes to (our reference to) the property. | |
| 767 this.listen(singleton, 'languages-changed', 'singletonLanguagesChanged_'); | |
| 768 }.bind(this)); | |
| 769 }, | |
| 770 | |
| 771 /** | |
| 772 * Takes changes reported by the singleton and forwards them to the host, | |
| 773 * manually sending a change notification for our 'languages' property (since | |
| 774 * it's the same object as the singleton's property, but isn't bound by | |
| 775 * Polymer). | |
| 776 * @private | |
| 777 */ | |
| 778 singletonLanguagesChanged_: function(e) { | |
| 779 // Forward the change notification to the host. | |
| 780 this.fire(e.type, e.detail, {bubbles: false}); | |
| 781 }, | |
| 782 }); | |
| OLD | NEW |