gecko-dev/toolkit/modules/Locale.jsm
Zibi Braniecki a1a4f0b7c9 Bug 1346616 - Migrate callsites that are retrieving requested locale from pref, to use LocaleService::GetRequestedLocales. r=jfkthame,Pike
I'm adding a helper function mozILocaleService::GetRequestedLocale to simplify
most of the callsites that are looking for the first of the requested locales.

In most cases, I'm just matching the behavior of the code with reusing
LocaleService API instead of direct manipulation on the prefs.
That includes how I handle error case scenarios.

In case of sdk/l10n/locale.js I am reusing LocaleService heuristics over
the custom one from the file since the ones in LocaleService are just
more correct and unified accross the whole platform.

In case of FallbackEncoding I have to turn it into a nsIObserver to listen
to intl:requested-locales-changed.

MozReview-Commit-ID: 7rOr2CovLK

--HG--
extra : rebase_source : 883a91b249b6953b7872bfb9a8851e8be7257c7b
2017-03-11 18:43:11 -08:00

83 lines
2.8 KiB
JavaScript

/* 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");
this.Locale = {
/**
* Gets the currently selected locale for display.
* @return the selected locale or "en-US" if none is selected
*/
getLocale() {
return Services.locale.getRequestedLocale() || "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;
},
};