summaryrefslogtreecommitdiffstats
path: root/toolkit/modules/Locale.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/modules/Locale.jsm')
-rw-r--r--toolkit/modules/Locale.jsm93
1 files changed, 93 insertions, 0 deletions
diff --git a/toolkit/modules/Locale.jsm b/toolkit/modules/Locale.jsm
new file mode 100644
index 000000000..886de9e3a
--- /dev/null
+++ b/toolkit/modules/Locale.jsm
@@ -0,0 +1,93 @@
+/* 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/. */
+
+this.EXPORTED_SYMBOLS = ["Locale"];
+
+const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/Preferences.jsm");
+
+const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS";
+const PREF_SELECTED_LOCALE = "general.useragent.locale";
+
+this.Locale = {
+ /**
+ * Gets the currently selected locale for display.
+ * @return the selected locale or "en-US" if none is selected
+ */
+ getLocale() {
+ if (Preferences.get(PREF_MATCH_OS_LOCALE, false))
+ return Services.locale.getLocaleComponentForUserAgent();
+ try {
+ let locale = Preferences.get(PREF_SELECTED_LOCALE, null, Ci.nsIPrefLocalizedString);
+ if (locale)
+ return locale;
+ }
+ catch (e) {}
+ return Preferences.get(PREF_SELECTED_LOCALE, "en-US");
+ },
+
+ /**
+ * Selects the closest matching locale from a list of locales.
+ *
+ * @param aLocales
+ * An array of locales
+ * @return the best match for the currently selected locale
+ */
+ findClosestLocale(aLocales) {
+ let appLocale = this.getLocale();
+
+ // Holds the best matching localized resource
+ var bestmatch = null;
+ // The number of locale parts it matched with
+ var bestmatchcount = 0;
+ // The number of locale parts in the match
+ var bestpartcount = 0;
+
+ var matchLocales = [appLocale.toLowerCase()];
+ /* If the current locale is English then it will find a match if there is
+ a valid match for en-US so no point searching that locale too. */
+ if (matchLocales[0].substring(0, 3) != "en-")
+ matchLocales.push("en-us");
+
+ for (let locale of matchLocales) {
+ var lparts = locale.split("-");
+ for (let localized of aLocales) {
+ for (let found of localized.locales) {
+ found = found.toLowerCase();
+ // Exact match is returned immediately
+ if (locale == found)
+ return localized;
+
+ var fparts = found.split("-");
+ /* If we have found a possible match and this one isn't any longer
+ then we dont need to check further. */
+ if (bestmatch && fparts.length < bestmatchcount)
+ continue;
+
+ // Count the number of parts that match
+ var maxmatchcount = Math.min(fparts.length, lparts.length);
+ var matchcount = 0;
+ while (matchcount < maxmatchcount &&
+ fparts[matchcount] == lparts[matchcount])
+ matchcount++;
+
+ /* If we matched more than the last best match or matched the same and
+ this locale is less specific than the last best match. */
+ if (matchcount > bestmatchcount ||
+ (matchcount == bestmatchcount && fparts.length < bestpartcount)) {
+ bestmatch = localized;
+ bestmatchcount = matchcount;
+ bestpartcount = fparts.length;
+ }
+ }
+ }
+ // If we found a valid match for this locale return it
+ if (bestmatch)
+ return bestmatch;
+ }
+ return null;
+ },
+};