diff options
Diffstat (limited to 'toolkit/modules/Locale.jsm')
-rw-r--r-- | toolkit/modules/Locale.jsm | 93 |
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; + }, +}; |