diff options
Diffstat (limited to 'browser/components/preferences/languages.js')
-rw-r--r-- | browser/components/preferences/languages.js | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/browser/components/preferences/languages.js b/browser/components/preferences/languages.js new file mode 100644 index 000000000..16ca257f7 --- /dev/null +++ b/browser/components/preferences/languages.js @@ -0,0 +1,312 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var gLanguagesDialog = { + + _availableLanguagesList : [], + _acceptLanguages : { }, + + _selectedItemID : null, + + init: function () + { + if (!this._availableLanguagesList.length) + this._loadAvailableLanguages(); + }, + + // Ugly hack used to trigger extra reflow in order to work around XUL bug 1194844; + // see bug 1194346. + forceReflow: function () + { + this._activeLanguages.style.fontKerning = "none"; + setTimeout("gLanguagesDialog._activeLanguages.style.removeProperty('font-kerning')", 0); + }, + + get _activeLanguages() + { + return document.getElementById("activeLanguages"); + }, + + get _availableLanguages() + { + return document.getElementById("availableLanguages"); + }, + + _loadAvailableLanguages: function () + { + // This is a parser for: resource://gre/res/language.properties + // The file is formatted like so: + // ab[-cd].accept=true|false + // ab = language + // cd = region + var bundleAccepted = document.getElementById("bundleAccepted"); + var bundleRegions = document.getElementById("bundleRegions"); + var bundleLanguages = document.getElementById("bundleLanguages"); + var bundlePreferences = document.getElementById("bundlePreferences"); + + function LanguageInfo(aName, aABCD, aIsVisible) + { + this.name = aName; + this.abcd = aABCD; + this.isVisible = aIsVisible; + } + + // 1) Read the available languages out of language.properties + var strings = bundleAccepted.strings; + while (strings.hasMoreElements()) { + var currString = strings.getNext(); + if (!(currString instanceof Components.interfaces.nsIPropertyElement)) + break; + + var property = currString.key.split("."); // ab[-cd].accept + if (property[1] == "accept") { + var abCD = property[0]; + var abCDPairs = abCD.split("-"); // ab[-cd] + var useABCDFormat = abCDPairs.length > 1; + var ab = useABCDFormat ? abCDPairs[0] : abCD; + var cd = useABCDFormat ? abCDPairs[1] : ""; + if (ab) { + var language = ""; + try { + language = bundleLanguages.getString(ab); + } + catch (e) { continue; } + + var region = ""; + if (useABCDFormat) { + try { + region = bundleRegions.getString(cd); + } + catch (e) { continue; } + } + + var name = ""; + if (useABCDFormat) + name = bundlePreferences.getFormattedString("languageRegionCodeFormat", + [language, region, abCD]); + else + name = bundlePreferences.getFormattedString("languageCodeFormat", + [language, abCD]); + + if (name && abCD) { + var isVisible = currString.value == "true" && + (!(abCD in this._acceptLanguages) || !this._acceptLanguages[abCD]); + var li = new LanguageInfo(name, abCD, isVisible); + this._availableLanguagesList.push(li); + } + } + } + } + this._buildAvailableLanguageList(); + }, + + _buildAvailableLanguageList: function () + { + var availableLanguagesPopup = document.getElementById("availableLanguagesPopup"); + while (availableLanguagesPopup.hasChildNodes()) + availableLanguagesPopup.removeChild(availableLanguagesPopup.firstChild); + + // Sort the list of languages by name + this._availableLanguagesList.sort(function (a, b) { + return a.name.localeCompare(b.name); + }); + + // Load the UI with the data + for (var i = 0; i < this._availableLanguagesList.length; ++i) { + var abCD = this._availableLanguagesList[i].abcd; + if (this._availableLanguagesList[i].isVisible && + (!(abCD in this._acceptLanguages) || !this._acceptLanguages[abCD])) { + var menuitem = document.createElement("menuitem"); + menuitem.id = this._availableLanguagesList[i].abcd; + availableLanguagesPopup.appendChild(menuitem); + menuitem.setAttribute("label", this._availableLanguagesList[i].name); + } + } + }, + + readAcceptLanguages: function () + { + while (this._activeLanguages.hasChildNodes()) + this._activeLanguages.removeChild(this._activeLanguages.firstChild); + + var selectedIndex = 0; + var preference = document.getElementById("intl.accept_languages"); + if (preference.value == "") + return undefined; + var languages = preference.value.toLowerCase().split(/\s*,\s*/); + for (var i = 0; i < languages.length; ++i) { + var name = this._getLanguageName(languages[i]); + if (!name) + name = "[" + languages[i] + "]"; + var listitem = document.createElement("listitem"); + listitem.id = languages[i]; + if (languages[i] == this._selectedItemID) + selectedIndex = i; + this._activeLanguages.appendChild(listitem); + listitem.setAttribute("label", name); + + // Hash this language as an "Active" language so we don't + // show it in the list that can be added. + this._acceptLanguages[languages[i]] = true; + } + + if (this._activeLanguages.childNodes.length > 0) { + this._activeLanguages.ensureIndexIsVisible(selectedIndex); + this._activeLanguages.selectedIndex = selectedIndex; + } + + return undefined; + }, + + writeAcceptLanguages: function () + { + return undefined; + }, + + onAvailableLanguageSelect: function () + { + var addButton = document.getElementById("addButton"); + addButton.disabled = false; + + this._availableLanguages.removeAttribute("accesskey"); + }, + + addLanguage: function () + { + var selectedID = this._availableLanguages.selectedItem.id; + var preference = document.getElementById("intl.accept_languages"); + var arrayOfPrefs = preference.value.toLowerCase().split(/\s*,\s*/); + for (var i = 0; i < arrayOfPrefs.length; ++i ) { + if (arrayOfPrefs[i] == selectedID) + return; + } + + this._selectedItemID = selectedID; + + if (preference.value == "") + preference.value = selectedID; + else { + arrayOfPrefs.unshift(selectedID); + preference.value = arrayOfPrefs.join(","); + } + + this._acceptLanguages[selectedID] = true; + this._availableLanguages.selectedItem = null; + + // Rebuild the available list with the added item removed... + this._buildAvailableLanguageList(); + + this._availableLanguages.setAttribute("label", this._availableLanguages.getAttribute("label2")); + }, + + removeLanguage: function () + { + // Build the new preference value string. + var languagesArray = []; + for (var i = 0; i < this._activeLanguages.childNodes.length; ++i) { + var item = this._activeLanguages.childNodes[i]; + if (!item.selected) + languagesArray.push(item.id); + else + this._acceptLanguages[item.id] = false; + } + var string = languagesArray.join(","); + + // Get the item to select after the remove operation completes. + var selection = this._activeLanguages.selectedItems; + var lastSelected = selection[selection.length-1]; + var selectItem = lastSelected.nextSibling || lastSelected.previousSibling; + selectItem = selectItem ? selectItem.id : null; + + this._selectedItemID = selectItem; + + // Update the preference and force a UI rebuild + var preference = document.getElementById("intl.accept_languages"); + preference.value = string; + + this._buildAvailableLanguageList(); + }, + + _getLanguageName: function (aABCD) + { + if (!this._availableLanguagesList.length) + this._loadAvailableLanguages(); + for (var i = 0; i < this._availableLanguagesList.length; ++i) { + if (aABCD == this._availableLanguagesList[i].abcd) + return this._availableLanguagesList[i].name; + } + return ""; + }, + + moveUp: function () + { + var selectedItem = this._activeLanguages.selectedItems[0]; + var previousItem = selectedItem.previousSibling; + + var string = ""; + for (var i = 0; i < this._activeLanguages.childNodes.length; ++i) { + var item = this._activeLanguages.childNodes[i]; + string += (i == 0 ? "" : ","); + if (item.id == previousItem.id) + string += selectedItem.id; + else if (item.id == selectedItem.id) + string += previousItem.id; + else + string += item.id; + } + + this._selectedItemID = selectedItem.id; + + // Update the preference and force a UI rebuild + var preference = document.getElementById("intl.accept_languages"); + preference.value = string; + }, + + moveDown: function () + { + var selectedItem = this._activeLanguages.selectedItems[0]; + var nextItem = selectedItem.nextSibling; + + var string = ""; + for (var i = 0; i < this._activeLanguages.childNodes.length; ++i) { + var item = this._activeLanguages.childNodes[i]; + string += (i == 0 ? "" : ","); + if (item.id == nextItem.id) + string += selectedItem.id; + else if (item.id == selectedItem.id) + string += nextItem.id; + else + string += item.id; + } + + this._selectedItemID = selectedItem.id; + + // Update the preference and force a UI rebuild + var preference = document.getElementById("intl.accept_languages"); + preference.value = string; + }, + + onLanguageSelect: function () + { + var upButton = document.getElementById("up"); + var downButton = document.getElementById("down"); + var removeButton = document.getElementById("remove"); + switch (this._activeLanguages.selectedCount) { + case 0: + upButton.disabled = downButton.disabled = removeButton.disabled = true; + break; + case 1: + upButton.disabled = this._activeLanguages.selectedIndex == 0; + downButton.disabled = this._activeLanguages.selectedIndex == this._activeLanguages.childNodes.length - 1; + removeButton.disabled = false; + break; + default: + upButton.disabled = true; + downButton.disabled = true; + removeButton.disabled = false; + } + } +}; + |