/* 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; }, };