summaryrefslogtreecommitdiffstats
path: root/browser/components/preferences/languages.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/preferences/languages.js')
-rw-r--r--browser/components/preferences/languages.js312
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;
+ }
+ }
+};
+