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

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_: {
stevenjb 2015/09/23 22:27:54 I like 'singleton' here.
michaelpg 2015/09/24 02:15:19 Acknowledged.
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: {
stevenjb 2015/09/23 22:27:54 Heh, so, FWIW, I was / would be fine with this bei
michaelpg 2015/09/24 02:15:20 Acknowledged.
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 preferredLanguagesPath;
136 if (cr.isChromeOS)
137 preferredLanguagesPath = 'prefs.settings.language.preferred_languages.value';
138 else
139 preferredLanguagesPath = 'prefs.intl.accept_languages.value';
stevenjb 2015/09/23 22:27:54 nit: I know that it would add a tiny bit of comple
Dan Beam 2015/09/23 23:28:17 can haz ternary?
michaelpg 2015/09/24 02:15:20 Done.
michaelpg 2015/09/24 02:15:20 Done.
140
141 /**
142 * Singleton element created when cr-settings-languages is registered.
143 * Generates the languages model on start-up, and updates it whenever Chrome's
144 * pref store and other settings change. These updates propagate to each
145 * <cr-settings-language> instance so that their 'languages' property updates
146 * like any other Polymer property.
147 */
148 Polymer({
149 is: 'cr-settings-languages-singleton',
150
151 properties: {
152 /**
153 * @type {LanguagesModel|undefined}
154 */
155 languages: {
stevenjb 2015/09/23 22:27:54 Same here, but it definitely makes sense to me to
michaelpg 2015/09/24 02:15:19 yep. If we don't match property names, we'd have t
156 type: Object,
157 notify: true,
158 },
159
160 /**
161 * Object containing all preferences.
162 */
163 prefs: {
164 type: Object,
165 notify: true,
166 },
167 },
168
169 /**
170 * Hash map of languages.supportedLanguages using language codes as keys for
171 * fast lookup.
172 * @private {!Object<!chrome.languageSettingsPrivate.Language>}
173 */
174 supportedLanguageMap_: {},
175
176 /**
177 * Hash map of languages.enabledLanguages using language codes as keys for
178 * fast lookup.
179 * @private {!Object<!LanguageInfo>}
180 */
181 enabledLanguageMap_: {},
182
183 observers: [
184 'preferredLanguagesPrefChanged_(' + preferredLanguagesPath + ')',
185 'spellCheckDictionariesPrefChanged_(prefs.spellcheck.dictionaries.value.*)',
186 ],
187
188 /** @override */
189 created: function() {
190 chrome.languageSettingsPrivate.getLanguageList(function(languageList) {
191 // Wait until prefs are initialized before creating the model, so we can
192 // include information about enabled languages.
193 CrSettingsPrefs.initialized.then(function() {
194 this.createModel_(languageList);
195 this.initialized_ = true;
196 }.bind(this));
197 }.bind(this));
198 },
199
200 /**
201 * Constructs the languages model from the given language list.
202 * @param {!Array<!chrome.languageSettingsPrivate.Language>}
203 * supportedLanguages
204 */
205 createModel_: function(supportedLanguages) {
206 // Populate the hash map of supported languages.
207 for (var i = 0; i < supportedLanguages.length; i++) {
208 this.supportedLanguageMap_[supportedLanguages[i].code] =
209 supportedLanguages[i];
210 }
211
212 // Create a list of enabled language info from the supported languages.
213 var enabledLanguages = this.getEnabledLanguages_();
214 // Populate the hash map of enabled languages.
215 for (var i = 0; i < enabledLanguages.length; i++) {
216 var languageInfo = enabledLanguages[i];
217 this.enabledLanguageMap_[languageInfo.language.code] = languageInfo;
218 }
219
220 // Initialize the Polymer languages model.
221 this.languages = {
222 supportedLanguages: supportedLanguages,
223 enabledLanguages: enabledLanguages,
224 };
225 },
226
227 /**
228 * Returns a list of LanguageInfos for each enabled language in the supported
229 * languages list.
230 * @private
231 * @return {!Array<!LanguageInfo>}
232 */
233 getEnabledLanguages_: function() {
234 assert(CrSettingsPrefs.isInitialized);
235
236 var languageCodes = this.get(preferredLanguagesPath).split(',');
stevenjb 2015/09/23 22:27:54 What do you think of: getPref_: function(path) {
michaelpg 2015/09/24 02:15:20 Done. It's not bad, but I'm not sure about the pre
stevenjb 2015/09/24 15:46:06 Yeah, I've been trying to think of a nice way we c
stevenjb 2015/09/24 15:46:06 Yeah, I've been trying to think of a nice way we c
michaelpg 2015/09/24 17:21:11 Yeah, a behavior would be a good way to make this
237 var enabledLanguages = [];
238 var spellCheckMap = this.getSpellCheckMap_();
239 for (var i = 0; i < languageCodes.length; i++) {
240 var code = languageCodes[i];
241 var language = this.supportedLanguageMap_[code];
242 if (!language)
243 continue;
244 var state = {spellCheckEnabled: !!spellCheckMap[code]};
Dan Beam 2015/09/23 23:28:17 why does this need to be a full dictionary?
michaelpg 2015/09/24 02:15:19 other properties are a'comin, like translateEnable
245 enabledLanguages.push({language: language, state: state});
246 }
247 return enabledLanguages;
248 },
249
250 /**
251 * Creates a map whose keys are languages enabled for spell check.
252 * @return {!Object<boolean>}
253 */
254 getSpellCheckMap_: function() {
255 assert(CrSettingsPrefs.isInitialized);
256
257 var spellCheckPref = /** @type {chrome.settingsPrivate.PrefObject} */(
258 this.get('prefs.spellcheck.dictionaries'));
259 var spellCheckCodes = spellCheckPref.value;
260 var spellCheckMap = {};
261 for (var i = 0; i < spellCheckCodes.length; i++)
262 spellCheckMap[spellCheckCodes[i]] = true;
263 return spellCheckMap;
264 },
265
266 /**
267 * Updates the list of enabled languages from the preferred languages pref.
268 * @private
269 * */
270 preferredLanguagesPrefChanged_: function() {
271 if (!this.initialized_)
272 return;
273
274 var enabledLanguages = this.getEnabledLanguages_();
275 // Reset the enabled language map. Do this before notifying of the change
276 // via languages.enabledLanguages.
277 this.enabledLanguageMap_ = {};
278 for (var i = 0; i < enabledLanguages.length; i++) {
279 var languageInfo = enabledLanguages[i];
280 this.enabledLanguageMap_[languageInfo.language.code] = languageInfo;
281 }
282 this.set('languages.enabledLanguages', enabledLanguages);
283 },
284
285 /**
286 * Updates the spellCheckEnabled state of each enabled language.
287 * @private
288 */
289 spellCheckDictionariesPrefChanged_: function() {
290 if (!this.initialized_)
291 return;
292
293 var spellCheckMap = this.getSpellCheckMap_();
294 for (var i = 0; i < this.languages.enabledLanguages.length; i++) {
295 var languageCode = this.languages.enabledLanguages[i].language.code;
296 this.set('languages.enabledLanguages.' + i + '.state.spellCheckEnabled',
297 !!spellCheckMap[languageCode]);
298 }
299 },
300
301 /**
302 * Windows and Chrome OS only: Sets the prospective UI language to the chosen
303 * language. This dosen't affect the actual UI language until a restart.
304 * @param {string} languageCode
305 */
306 setUILanguage: function(languageCode) {
307 chrome.send('setUILanguage', [languageCode]);
308 },
309
310 /**
311 * Enables the language, making it available for spell check and input.
312 * @param {string} languageCode
313 */
314 enableLanguage: function(languageCode) {
315 if (!CrSettingsPrefs.isInitialized)
316 return;
317
318 var languageCodes = this.get(preferredLanguagesPath);
319 var index = languageCodes.split(',').indexOf(languageCode);
320 if (index > -1)
321 return;
322 this.set(preferredLanguagesPath, languageCodes + ',' + languageCode);
323 },
324
325 /**
326 * Disables the language.
327 * @param {string} languageCode
328 */
329 disableLanguage: function(languageCode) {
330 if (!CrSettingsPrefs.isInitialized)
331 return;
332
333 // Don't disable the UI language.
334 var appLocale = this.get('prefs.intl.app_locale.value') ||
335 navigator.language;
336 if (languageCode == appLocale)
Dan Beam 2015/09/23 23:28:17 wait, how does this happen? can this be assert(la
michaelpg 2015/09/24 02:15:20 Done.
337 return;
338
339 // Don't disable the only enabled language.
Dan Beam 2015/09/23 23:28:17 same question: don't we prevent this in the UI (so
michaelpg 2015/09/24 02:15:20 Done.
340 var languageCodes = this.get(preferredLanguagesPath).split(',');
341 if (languageCodes.length == 1)
342 return;
343
344 // Remove the language from spell check.
345 this.arrayDelete('prefs.spellcheck.dictionaries.value', languageCode);
346
347 var languageIndex = languageCodes.indexOf(languageCode);
348 if (languageIndex == -1)
349 return;
350 languageCodes.splice(languageIndex, 1);
351 this.set(preferredLanguagesPath, languageCodes.join(','));
352 },
353
354 /**
355 * @param {string} languageCode
356 * @return {boolean} True if the language is enabled.
357 */
358 isEnabled: function(languageCode) {
359 return !!this.enabledLanguageMap_[languageCode];
360 },
361
362 /**
363 * Enables or disables spell check for the given language.
364 * @param {string} languageCode
365 * @param {boolean} enable
366 */
367 toggleSpellCheck: function(languageCode, enable) {
368 if (!this.initialized_)
369 return;
370
371 var spellCheckPref = /** @type {chrome.settingsPrivate.PrefObject} */(
372 this.get('prefs.spellcheck.dictionaries'));
373 if (enable) {
374 if (spellCheckPref.value.indexOf(languageCode) == -1)
375 this.push('prefs.spellcheck.dictionaries.value', languageCode);
376 } else {
377 // TODO: need update externs before committing
Dan Beam 2015/09/23 23:28:17 TODO(michaelpg): or actually do
michaelpg 2015/09/24 02:15:20 actually done (after four tries): https://coderevi
378 this.arrayDelete('prefs.spellcheck.dictionaries.value', languageCode);
379 }
380 },
381 });
382 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698