Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(340)

Unified Diff: chrome/browser/resources/settings/languages_page/languages.js

Issue 1419033008: Extract language settings methods into a LanguageHelper interface (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@LanguagePage5InputMethodsAPI
Patch Set: nit Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/settings/languages_page/languages.js
diff --git a/chrome/browser/resources/settings/languages_page/languages.js b/chrome/browser/resources/settings/languages_page/languages.js
index bedacd7524846abf3e78be9fd8b78c0af980990a..fb15e44b0c08497eea698e38a5e5a8c7e112d90c 100644
--- a/chrome/browser/resources/settings/languages_page/languages.js
+++ b/chrome/browser/resources/settings/languages_page/languages.js
@@ -9,9 +9,9 @@
* Instances of this element have a 'languages' property, which reflects the
* current language settings. The 'languages' property is read-only, meaning
* hosts using this element cannot change it directly. Instead, changes to
- * language settings should be made using this element's public functions.
+ * language settings should be made using the LanguageHelperImpl singleton.
*
- * Use two-way binding syntax to propagate changes from child to host, so that
+ * Use upward binding syntax to propagate changes from child to host, so that
* changes made internally to 'languages' propagate to your host element:
*
* <template>
@@ -24,26 +24,7 @@
* @element settings-languages
*/
-/** @typedef {{spellCheckEnabled: boolean, translateEnabled: boolean}} */
-var LanguageState;
-
-/**
- * @typedef {{language: !chrome.languageSettingsPrivate.Language,
- * state: !LanguageState}}
- */
-var LanguageInfo;
-
-/**
- * supportedLanguages: an array of languages, ordered alphabetically.
- * enabledLanguages: an array of enabled language info and state, ordered by
- * preference.
- * @typedef {{
- * supportedLanguages: !Array<!chrome.languageSettingsPrivate.Language>,
- * enabledLanguages: !Array<!LanguageInfo>,
- * translateTarget: string
- * }}
- */
-var LanguagesModel;
+var SettingsLanguagesSingletonElement;
(function() {
'use strict';
@@ -66,130 +47,17 @@ var kTranslateLanguageSynonyms = {
'jv': 'jw',
};
-/**
- * This element has a reference to the singleton, exposing the singleton's
- * language model to the host of this element as the 'languages' property.
- */
-Polymer({
- is: 'settings-languages',
-
- properties: {
- /**
- * Singleton element created at startup which provides the languages model.
- * @type {!Element}
- */
- singleton_: {
- type: Object,
- value: document.createElement('settings-languages-singleton'),
- },
-
- /**
- * A reference to the languages model from the singleton, exposed as a
- * read-only property so hosts can bind to it, but not change it.
- * @type {LanguagesModel|undefined}
- */
- languages: {
- type: Object,
- notify: true,
- readOnly: true,
- },
- },
-
- ready: function() {
- // Set the 'languages' property to reference the singleton's model.
- this._setLanguages(this.singleton_.languages);
- // Listen for changes to the singleton's languages property, so we know
- // when to notify hosts of changes to (our reference to) the property.
- this.listen(
- this.singleton_, 'languages-changed', 'singletonLanguagesChanged_');
- },
-
- /**
- * Takes changes reported by the singleton and forwards them to the host,
- * manually sending a change notification for our 'languages' property (since
- * it's the same object as the singleton's property, but isn't bound by
- * Polymer).
- * @private
- */
- singletonLanguagesChanged_: function(e) {
- // Forward the change notification to the host.
- this.fire(e.type, e.detail, {bubbles: false});
- },
-
- // Forward public methods to the singleton.
-
- /** @param {string} languageCode */
- setUILanguage: function(languageCode) {
- if (cr.isWindows || cr.isChromeOS)
- this.singleton_.setUILanguage(languageCode);
- },
-
- resetUILanguage: function() {
- if (cr.isWindows || cr.isChromeOS)
- this.singleton_.resetUILanguage();
- },
-
- /** @return {string} */
- getProspectiveUILanguage: function() {
- return this.singleton_.getProspectiveUILanguage();
- },
-
- /** @param {string} languageCode */
- enableLanguage: function(languageCode) {
- this.singleton_.enableLanguage(languageCode);
- },
-
- /** @param {string} languageCode */
- disableLanguage: function(languageCode) {
- this.singleton_.disableLanguage(languageCode);
- },
-
- /** @param {string} languageCode */
- enableTranslateLanguage: function(languageCode) {
- this.singleton_.enableTranslateLanguage(languageCode);
- },
-
- /** @param {string} languageCode */
- disableTranslateLanguage: function(languageCode) {
- this.singleton_.disableTranslateLanguage(languageCode);
- },
-
- /**
- * @param {string} languageCode
- * @return {boolean}
- */
- isEnabled: function(languageCode) {
- return this.singleton_.isEnabled(languageCode);
- },
-
- /**
- * @param {string} languageCode
- * @param {boolean} enable
- */
- toggleSpellCheck: function(languageCode, enable) {
- this.singleton_.toggleSpellCheck(languageCode, enable);
- },
-
- /**
- * @param {string} languageCode
- * @return {string}
- */
- convertLanguageCodeForTranslate: function(languageCode) {
- return this.singleton_.convertLanguageCodeForTranslate(languageCode);
- },
-});
-
var preferredLanguagesPrefName = cr.isChromeOS ?
'settings.language.preferred_languages' : 'intl.accept_languages';
/**
- * Singleton element created when settings-languages is registered.
- * Generates the languages model on start-up, and updates it whenever Chrome's
- * pref store and other settings change. These updates propagate to each
- * <settings-language> instance so that their 'languages' property updates
- * like any other Polymer property.
+ * Singleton element that generates the languages model on start-up and
+ * updates it whenever Chrome's pref store and other settings change. These
+ * updates propagate to each <settings-language> instance so that their
+ * 'languages' property updates like any other Polymer property.
+ * @implements {LanguageHelper}
*/
-Polymer({
+SettingsLanguagesSingletonElement = Polymer({
is: 'settings-languages-singleton',
behaviors: [PrefsBehavior],
@@ -267,11 +135,68 @@ Polymer({
},
/**
+ * Updates the list of enabled languages from the preferred languages pref.
+ * @private
+ */
+ preferredLanguagesPrefChanged_: function() {
+ if (!this.initialized_)
+ return;
+
+ var enabledLanguages =
+ this.getEnabledLanguages_(this.languages.translateTarget);
+
+ // Reset the enabled language map before updating
+ // languages.enabledLanguages.
+ this.enabledLanguageMap_ = {};
+ for (var i = 0; i < enabledLanguages.length; i++) {
+ var languageInfo = enabledLanguages[i];
+ this.enabledLanguageMap_[languageInfo.language.code] = languageInfo;
+ }
+ this.set('languages.enabledLanguages', enabledLanguages);
+ },
+
+ /**
+ * Updates the spellCheckEnabled state of each enabled language.
+ * @private
+ */
+ spellCheckDictionariesPrefChanged_: function() {
+ if (!this.initialized_)
+ return;
+
+ var spellCheckMap = this.makeMapFromArray_(/** @type {!Array<string>} */(
+ this.getPref('spellcheck.dictionaries').value));
+ for (var i = 0; i < this.languages.enabledLanguages.length; i++) {
+ var languageCode = this.languages.enabledLanguages[i].language.code;
+ this.set('languages.enabledLanguages.' + i + '.state.spellCheckEnabled',
+ !!spellCheckMap[languageCode]);
+ }
+ },
+
+ /** @private */
+ translateLanguagesPrefChanged_: function() {
+ if (!this.initialized_)
+ return;
+
+ var translateBlockedPref = this.getPref('translate_blocked_languages');
+ var translateBlockedMap = this.makeMapFromArray_(
+ /** @type {!Array<string>} */(translateBlockedPref.value));
+
+ for (var i = 0; i < this.languages.enabledLanguages.length; i++) {
+ var translateCode = this.convertLanguageCodeForTranslate(
+ this.languages.enabledLanguages[i].language.code);
+ this.set(
+ 'languages.enabledLanguages.' + i + '.state.translateEnabled',
+ !translateBlockedMap[translateCode]);
+ }
+ },
+
+ /**
* Constructs the languages model.
* @param {!Array<!chrome.languageSettingsPrivate.Language>}
* supportedLanguages
* @param {string} translateTarget Language code of the default translate
* target language.
+ * @private
*/
createModel_: function(supportedLanguages, translateTarget) {
// Populate the hash map of supported languages.
@@ -325,17 +250,19 @@ Polymer({
for (var i = 0; i < enabledLanguageCodes.length; i++) {
var code = enabledLanguageCodes[i];
var language = this.supportedLanguageMap_[code];
+ // Skip unsupported languages.
if (!language)
continue;
- var state = {};
+ var state = /** @type {LanguageState} */({});
state.spellCheckEnabled = !!spellCheckMap[code];
// Translate is considered disabled if this language maps to any translate
// language that is blocked.
var translateCode = this.convertLanguageCodeForTranslate(code);
- state.translateEnabled = language.supportsTranslate &&
+ state.translateEnabled = !!language.supportsTranslate &&
!translateBlockedMap[translateCode] &&
translateCode != translateTarget;
- enabledLanguages.push({language: language, state: state});
+ enabledLanguages.push(/** @type {LanguageInfo} */(
+ {language: language, state: state}));
}
return enabledLanguages;
},
@@ -344,6 +271,7 @@ Polymer({
* Creates an object whose keys are the elements of the list.
* @param {!Array<string>} list
* @return {!Object<boolean>}
+ * @private
*/
makeMapFromArray_: function(list) {
var map = {};
@@ -352,84 +280,21 @@ Polymer({
return map;
},
- /**
- * Updates the list of enabled languages from the preferred languages pref.
- * @private
- * */
- preferredLanguagesPrefChanged_: function() {
- if (!this.initialized_)
- return;
-
- var enabledLanguages =
- this.getEnabledLanguages_(this.languages.translateTarget);
- // Reset the enabled language map. Do this before notifying of the change
- // via languages.enabledLanguages.
- this.enabledLanguageMap_ = {};
- for (var i = 0; i < enabledLanguages.length; i++) {
- var languageInfo = enabledLanguages[i];
- this.enabledLanguageMap_[languageInfo.language.code] = languageInfo;
- }
- this.set('languages.enabledLanguages', enabledLanguages);
- },
-
- /**
- * Updates the spellCheckEnabled state of each enabled language.
- * @private
- */
- spellCheckDictionariesPrefChanged_: function() {
- if (!this.initialized_)
- return;
-
- var spellCheckMap = this.makeMapFromArray_(/** @type {!Array<string>} */(
- this.getPref('spellcheck.dictionaries').value));
- for (var i = 0; i < this.languages.enabledLanguages.length; i++) {
- var languageCode = this.languages.enabledLanguages[i].language.code;
- this.set('languages.enabledLanguages.' + i + '.state.spellCheckEnabled',
- !!spellCheckMap[languageCode]);
- }
- },
-
- translateLanguagesPrefChanged_: function() {
- if (!this.initialized_)
- return;
-
- var translateBlockedPref = this.getPref('translate_blocked_languages');
- var translateBlockedMap = this.makeMapFromArray_(
- /** @type {!Array<string>} */(translateBlockedPref.value));
-
- for (var i = 0; i < this.languages.enabledLanguages.length; i++) {
- var translateCode = this.convertLanguageCodeForTranslate(
- this.languages.enabledLanguages[i].language.code);
- this.set(
- 'languages.enabledLanguages.' + i + '.state.translateEnabled',
- !translateBlockedMap[translateCode]);
- }
- },
-
- /**
- * Deletes the given item from the pref at the given key if the item is found.
- * Asserts if the pref itself is not found or is not an Array type.
- * @param {string} key
- * @param {*} item
- */
- deletePrefItem_: function(key, item) {
- assert(this.getPref(key).type == chrome.settingsPrivate.PrefType.LIST);
- this.arrayDelete('prefs.' + key + '.value', item);
- },
+ // LanguageHelper implementation.
+ // TODO(michaelpg): replace duplicate docs with @override once b/24294625
+ // is fixed.
+<if expr="chromeos or is_win">
/**
- * Windows and Chrome OS only: Sets the prospective UI language to the chosen
- * language. This dosen't affect the actual UI language until a restart.
+ * Sets the prospective UI language to the chosen language. This won't affect
+ * the actual UI language until a restart.
* @param {string} languageCode
*/
setUILanguage: function(languageCode) {
chrome.send('setUILanguage', [languageCode]);
},
- /**
- * Windows and Chrome OS only: Resets the prospective UI language back to the
- * actual UI language.
- */
+ /** Resets the prospective UI language back to the actual UI language. */
resetUILanguage: function() {
chrome.send('setUILanguage', [navigator.language]);
},
@@ -439,12 +304,20 @@ Polymer({
* restart. If the pref is not set, the current UI language is also the
* "prospective" language.
* @return {string} Language code of the prospective UI language.
- * @private
*/
getProspectiveUILanguage: function() {
return /** @type {string} */(this.getPref('intl.app_locale').value) ||
navigator.language;
},
+</if>
+
+ /**
+ * @param {string} languageCode
+ * @return {boolean} True if the language is enabled.
+ */
+ isLanguageEnabled: function(languageCode) {
+ return !!this.enabledLanguageMap_[languageCode];
+ },
/**
* Enables the language, making it available for spell check and input.
@@ -471,17 +344,14 @@ Polymer({
if (!CrSettingsPrefs.isInitialized)
return;
- // Cannot disable the UI language.
- assert(languageCode != this.getProspectiveUILanguage());
-
- // Cannot disable the only enabled language.
- var languageCodes =
- this.getPref(preferredLanguagesPrefName).value.split(',');
- assert(languageCodes.length > 1);
+ assert(this.canDisableLanguage(languageCode));
// Remove the language from spell check.
- this.deletePrefItem_('spellcheck.dictionaries', languageCode);
+ this.arrayDelete('prefs.spellcheck.dictionaries.value', languageCode);
+ // Remove the language from preferred languages.
+ var languageCodes =
+ this.getPref(preferredLanguagesPrefName).value.split(',');
var languageIndex = languageCodes.indexOf(languageCode);
if (languageIndex == -1)
return;
@@ -491,11 +361,21 @@ Polymer({
},
/**
- * @param {string} languageCode
- * @return {boolean} True if the language is enabled.
+ * @param {string} languageCode Language code for an enabled language.
+ * @return {boolean}
*/
- isEnabled: function(languageCode) {
- return !!this.enabledLanguageMap_[languageCode];
+ canDisableLanguage: function(languageCode) {
+ // Cannot disable the prospective UI language.
+ if ((cr.isChromeOS || cr.isWindows) &&
+ languageCode == this.getProspectiveUILanguage()) {
+ return false;
+ }
+
+ // Cannot disable the only enabled language.
+ if (this.languages.enabledLanguages.length == 1)
+ return false;
+
+ return true;
},
/**
@@ -545,7 +425,6 @@ Polymer({
* Accept-Language.
* @param {string} languageCode
* @return {string} The converted language code.
- * @private
*/
convertLanguageCodeForTranslate: function(languageCode) {
if (languageCode in kLanguageCodeToTranslateCode)
@@ -562,5 +441,72 @@ Polymer({
return main;
},
+
+ /**
+ * @param {string} languageCode
+ * @return {!chrome.languageSettingsPrivate.Language|undefined}
+ */
+ getLanguage: function(languageCode) {
+ return this.supportedLanguageMap_[languageCode];
+ },
});
})();
+
+/**
+ * A reference to the singleton under the guise of a LanguageHelper
+ * implementation. This provides a limited API but implies the singleton
+ * should not be used directly for data binding.
+ */
+var LanguageHelperImpl = SettingsLanguagesSingletonElement;
+cr.addSingletonGetter(LanguageHelperImpl);
+
+/**
+ * This element has a reference to the singleton, exposing the singleton's
+ * |languages| model to the host of this element.
+ */
+Polymer({
+ is: 'settings-languages',
+
+ properties: {
+ /**
+ * Singleton element created at startup which provides the languages model.
+ * @type {!SettingsLanguagesSingletonElement}
+ */
+ singleton_: {
+ type: Object,
+ value: LanguageHelperImpl.getInstance(),
+ },
+
+ /**
+ * A reference to the languages model from the singleton, exposed as a
+ * read-only property so hosts can bind to it, but not change it.
+ * @type {LanguagesModel|undefined}
+ */
+ languages: {
+ type: Object,
+ notify: true,
+ readOnly: true,
+ },
+ },
+
+ ready: function() {
+ // Set the 'languages' property to reference the singleton's model.
+ this._setLanguages(this.singleton_.languages);
+ // Listen for changes to the singleton's languages property, so we know
+ // when to notify hosts of changes to (our reference to) the property.
+ this.listen(
+ this.singleton_, 'languages-changed', 'singletonLanguagesChanged_');
+ },
+
+ /**
+ * Takes changes reported by the singleton and forwards them to the host,
+ * manually sending a change notification for our 'languages' property (since
+ * it's the same object as the singleton's property, but isn't bound by
+ * Polymer).
+ * @private
+ */
+ singletonLanguagesChanged_: function(e) {
+ // Forward the change notification to the host.
+ this.fire(e.type, e.detail, {bubbles: false});
+ },
+});

Powered by Google App Engine
This is Rietveld 408576698