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

Side by Side Diff: chrome/browser/resources/settings/languages_page/languages.js

Issue 1351623008: MD Settings: Languages model for language pages (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@SingletonPrefs
Patch Set: Created 5 years, 2 months 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 unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 /**
6 * @fileoverview 'cr-settings-languages' provides convenient access to
7 * Chrome's language and input method settings.
8 *
9 * Instances of this element have a 'languages' property, which reflects the
10 * current language settings. The 'languages' property is read-only, meaning
11 * hosts using this element cannot change it directly. Instead, changes to
12 * language settings should be made using this element's public functions.
13 *
14 * Use two-way 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 * <cr-settings-languages languages="{{languages}}">
19 * </cr-settings-languages>
20 * <div>[[languages.someProperty]]</div>
21 * </template>
22 *
23 * @group Chrome Settings Elements
24 * @element cr-settings-languages
25 */
26
27 /** @typedef {{spellCheckEnabled: 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 * }}
44 */
45 var LanguagesModel;
46
47 (function() {
48 'use strict';
49
50 /**
51 * This element has a reference to the singleton, exposing the singleton's
52 * language model to the host of this element as the 'languages' property.
53 */
54 Polymer({
55 is: 'cr-settings-languages',
56
57 properties: {
58 /**
59 * Singleton element created at startup which provides the languages model.
60 * @type {!Element}
61 */
62 singleton_: {
63 type: Object,
64 value: document.createElement('cr-settings-languages-singleton'),
65 },
66
67 /**
68 * A reference to the languages model from the singleton, exposed as a
69 * read-only property so hosts can bind to it, but not change it.
70 * @type {LanguagesModel|undefined}
71 */
72 languages: {
73 type: Object,
74 notify: true,
75 readOnly: true,
76 },
77 },
78
79 ready: function() {
80 // Set the 'languages' property to reference the singleton's model.
81 this._setLanguages(this.singleton_.languages);
82 // Listen for changes to the singleton's languages property, so we know
83 // when to notify hosts of changes to (our reference to) the property.
84 this.listen(
85 this.singleton_, 'languages-changed', 'singletonLanguagesChanged_');
86 },
87
88 /**
89 * Takes changes reported by the singleton and forwards them to the host,
90 * manually sending a change notification for our 'languages' property (since
91 * it's the same object as the singleton's property, but isn't bound by
92 * Polymer).
93 * @private
94 */
95 singletonLanguagesChanged_: function(e) {
96 // Forward the change notification to the host.
97 this.fire(e.type, e.detail, {bubbles: false});
98 },
99
100 // Forward public methods to the singleton.
101
102 /** @param {string} languageCode */
103 setUILanguage: function(languageCode) {
104 if (cr.isWindows || cr.isChromeOS)
105 this.singleton_.setUILanguage(languageCode);
106 },
107
108 /** @param {string} languageCode */
109 enableLanguage: function(languageCode) {
110 this.singleton_.enableLanguage(languageCode);
111 },
112
113 /** @param {string} languageCode */
114 disableLanguage: function(languageCode) {
115 this.singleton_.disableLanguage(languageCode);
116 },
117
118 /**
119 * @param {string} languageCode
120 * @return {boolean}
121 */
122 isEnabled: function(languageCode) {
123 return this.singleton_.isEnabled(languageCode);
124 },
125
126 /**
127 * @param {string} languageCode
128 * @param {boolean} enable
129 */
130 toggleSpellCheck: function(languageCode, enable) {
131 this.singleton_.toggleSpellCheck(languageCode, enable);
132 },
133 });
134
135 var preferredLanguagesPrefName = cr.isChromeOS ?
136 'settings.language.preferred_languages' : 'intl.accept_languages';
137
138 /**
139 * Singleton element created when cr-settings-languages is registered.
140 * Generates the languages model on start-up, and updates it whenever Chrome's
141 * pref store and other settings change. These updates propagate to each
142 * <cr-settings-language> instance so that their 'languages' property updates
143 * like any other Polymer property.
144 */
145 Polymer({
146 is: 'cr-settings-languages-singleton',
147
148 properties: {
149 /**
150 * @type {LanguagesModel|undefined}
151 */
152 languages: {
153 type: Object,
154 notify: true,
155 },
156
157 /**
158 * Object containing all preferences.
159 */
160 prefs: {
161 type: Object,
162 notify: true,
163 },
164 },
165
166 /**
167 * Hash map of languages.supportedLanguages using language codes as keys for
168 * fast lookup.
169 * @private {!Object<!chrome.languageSettingsPrivate.Language>}
170 */
171 supportedLanguageMap_: {},
172
173 /**
174 * Hash map of languages.enabledLanguages using language codes as keys for
175 * fast lookup.
176 * @private {!Object<!LanguageInfo>}
177 */
178 enabledLanguageMap_: {},
179
180 observers: [
181 'preferredLanguagesPrefChanged_(prefs.' +
182 preferredLanguagesPrefName + '.value)',
183 'spellCheckDictionariesPrefChanged_(prefs.spellcheck.dictionaries.value.*)',
184 ],
185
186 /** @override */
187 created: function() {
188 chrome.languageSettingsPrivate.getLanguageList(function(languageList) {
189 // Wait until prefs are initialized before creating the model, so we can
190 // include information about enabled languages.
191 CrSettingsPrefs.initialized.then(function() {
192 this.createModel_(languageList);
193 this.initialized_ = true;
194 }.bind(this));
195 }.bind(this));
196 },
197
198 /**
199 * Constructs the languages model from the given language list.
200 * @param {!Array<!chrome.languageSettingsPrivate.Language>}
201 * supportedLanguages
202 */
203 createModel_: function(supportedLanguages) {
204 // Populate the hash map of supported languages.
205 for (var i = 0; i < supportedLanguages.length; i++) {
206 this.supportedLanguageMap_[supportedLanguages[i].code] =
207 supportedLanguages[i];
208 }
209
210 // Create a list of enabled language info from the supported languages.
211 var enabledLanguages = this.getEnabledLanguages_();
212 // Populate the hash map of enabled languages.
213 for (var i = 0; i < enabledLanguages.length; i++) {
214 var languageInfo = enabledLanguages[i];
215 this.enabledLanguageMap_[languageInfo.language.code] = languageInfo;
216 }
217
218 // Initialize the Polymer languages model.
219 this.languages = {
220 supportedLanguages: supportedLanguages,
221 enabledLanguages: enabledLanguages,
222 };
223 },
224
225 /**
226 * Returns a list of LanguageInfos for each enabled language in the supported
227 * languages list.
228 * @return {!Array<!LanguageInfo>}
229 * @private
230 */
231 getEnabledLanguages_: function() {
232 assert(CrSettingsPrefs.isInitialized);
233
234 var pref = this.getPref_(preferredLanguagesPrefName);
235 var enabledLanguageCodes = pref.value.split(',');
236 var enabledLanguages = [];
237 var spellCheckMap = this.getSpellCheckMap_();
238 for (var i = 0; i < enabledLanguageCodes.length; i++) {
239 var code = enabledLanguageCodes[i];
240 var language = this.supportedLanguageMap_[code];
241 if (!language)
242 continue;
243 var state = {spellCheckEnabled: !!spellCheckMap[code]};
244 enabledLanguages.push({language: language, state: state});
245 }
246 return enabledLanguages;
247 },
248
249 /**
250 * Creates a map whose keys are languages enabled for spell check.
251 * @return {!Object<boolean>}
252 */
253 getSpellCheckMap_: function() {
254 assert(CrSettingsPrefs.isInitialized);
255
256 var spellCheckCodes = this.getPref_('spellcheck.dictionaries').value;
257 var spellCheckMap = {};
258 for (var i = 0; i < spellCheckCodes.length; i++)
259 spellCheckMap[spellCheckCodes[i]] = true;
260 return spellCheckMap;
261 },
262
263 /**
264 * Updates the list of enabled languages from the preferred languages pref.
265 * @private
266 * */
267 preferredLanguagesPrefChanged_: function() {
268 if (!this.initialized_)
269 return;
270
271 var enabledLanguages = this.getEnabledLanguages_();
272 // Reset the enabled language map. Do this before notifying of the change
273 // via languages.enabledLanguages.
274 this.enabledLanguageMap_ = {};
275 for (var i = 0; i < enabledLanguages.length; i++) {
276 var languageInfo = enabledLanguages[i];
277 this.enabledLanguageMap_[languageInfo.language.code] = languageInfo;
278 }
279 this.set('languages.enabledLanguages', enabledLanguages);
280 },
281
282 /**
283 * Updates the spellCheckEnabled state of each enabled language.
284 * @private
285 */
286 spellCheckDictionariesPrefChanged_: function() {
287 if (!this.initialized_)
288 return;
289
290 var spellCheckMap = this.getSpellCheckMap_();
291 for (var i = 0; i < this.languages.enabledLanguages.length; i++) {
292 var languageCode = this.languages.enabledLanguages[i].language.code;
293 this.set('languages.enabledLanguages.' + i + '.state.spellCheckEnabled',
294 !!spellCheckMap[languageCode]);
295 }
296 },
297
298 /**
299 * Gets the pref at the given key. Asserts if the pref is not found.
300 * @param {string} key
301 * @return {!chrome.settingsPrivate.PrefObject}
302 */
303 getPref_: function(key) {
304 var pref = /** @type {!chrome.settingsPrivate.PrefObject} */(
305 this.get(key, this.prefs));
306 assert(typeof pref != 'undefined', 'Pref is missing: ' + key);
307 return pref;
308 },
309
310 /**
311 * Sets the value of the pref at the given key. Asserts if the pref is not
312 * found.
313 * @param {string} key
314 * @param {*} value
315 */
316 setPrefValue_: function(key, value) {
317 this.getPref_(key);
318 this.set('prefs.' + key + '.value', value);
319 },
320
321 /**
322 * Windows and Chrome OS only: Sets the prospective UI language to the chosen
323 * language. This dosen't affect the actual UI language until a restart.
324 * @param {string} languageCode
325 */
326 setUILanguage: function(languageCode) {
327 chrome.send('setUILanguage', [languageCode]);
328 },
329
330 /**
331 * Enables the language, making it available for spell check and input.
332 * @param {string} languageCode
333 */
334 enableLanguage: function(languageCode) {
335 if (!CrSettingsPrefs.isInitialized)
336 return;
337
338 var languageCodes = this.getPref_(preferredLanguagesPrefName).value;
339 var index = languageCodes.split(',').indexOf(languageCode);
340 if (index > -1)
341 return;
342 this.setPrefValue_(preferredLanguagesPrefName,
343 languageCodes + ',' + languageCode);
344 },
345
346 /**
347 * Disables the language.
348 * @param {string} languageCode
349 */
350 disableLanguage: function(languageCode) {
351 if (!CrSettingsPrefs.isInitialized)
352 return;
353
354 // Cannot disable the UI language.
355 var appLocale = this.getPref_('intl.app_locale').value ||
356 navigator.language;
357 assert(languageCode != appLocale);
358
359 // Cannot disable the only enabled language.
360 var pref = this.getPref_(preferredLanguagesPrefName);
361 var languageCodes = pref.value.split(',');
362 assert(languageCodes.length > 1);
363
364 // Remove the language from spell check.
365 this.arrayDelete('prefs.spellcheck.dictionaries.value', languageCode);
366
367 var languageIndex = languageCodes.indexOf(languageCode);
368 if (languageIndex == -1)
369 return;
370 languageCodes.splice(languageIndex, 1);
371 this.setPrefValue_(preferredLanguagesPrefName, languageCodes.join(','));
372 },
373
374 /**
375 * @param {string} languageCode
376 * @return {boolean} True if the language is enabled.
377 */
378 isEnabled: function(languageCode) {
379 return !!this.enabledLanguageMap_[languageCode];
380 },
381
382 /**
383 * Enables or disables spell check for the given language.
384 * @param {string} languageCode
385 * @param {boolean} enable
386 */
387 toggleSpellCheck: function(languageCode, enable) {
388 if (!this.initialized_)
389 return;
390
391 if (enable) {
392 var spellCheckPref = this.getPref_('spellcheck.dictionaries');
393 if (spellCheckPref.value.indexOf(languageCode) == -1)
394 this.push('prefs.spellcheck.dictionaries.value', languageCode);
395 } else {
396 this.arrayDelete('prefs.spellcheck.dictionaries.value', languageCode);
397 }
398 },
399 });
400 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698