Bug 1450656 - Canonicalize ja-JP-mac to ja-JP-macos and use BCP47 version in Fluent. r?jfkthame
MozReview-Commit-ID: 2UbD2T8yyGm
--- a/intl/l10n/L10nRegistry.jsm
+++ b/intl/l10n/L10nRegistry.jsm
@@ -320,16 +320,21 @@ class FileSource {
//
// If the `indexed` property is set to `true` it will be treated as the
// resource not being available. Otherwise, the resource may be
// available and we do not have any information about it yet.
this.cache = {};
}
getPath(locale, path) {
+ // This is a special case for the only not BCP47-conformant locale
+ // code we have resources for.
+ if (locale === "ja-JP-macos") {
+ locale = "ja-JP-mac";
+ }
return (this.prePath + path).replace(/\{locale\}/g, locale);
}
hasFile(locale, path) {
if (!this.locales.includes(locale)) {
return false;
}
--- a/intl/l10n/Localization.jsm
+++ b/intl/l10n/Localization.jsm
@@ -96,17 +96,17 @@ class CachedIterable {
* available in L10nRegistry, with locales requested by the user to
* generate the iterator over MessageContexts.
*
* In the future, we may want to allow certain modules to override this
* with a different negotitation strategy to allow for the module to
* be localized into a different language - for example DevTools.
*/
function defaultGenerateMessages(resourceIds) {
- const appLocales = Services.locale.getAppLocalesAsLangTags();
+ const appLocales = Services.locale.getAppLocalesAsBCP47();
return L10nRegistry.generateContexts(appLocales, resourceIds);
}
/**
* The `Localization` class is a central high-level API for vanilla
* JavaScript use of Fluent.
* It combines language negotiation, MessageContext and I/O to
* provide a scriptable API to format translations.
--- a/intl/locale/LocaleService.cpp
+++ b/intl/locale/LocaleService.cpp
@@ -39,27 +39,35 @@ NS_IMPL_ISUPPORTS(LocaleService, mozILoc
nsISupportsWeakReference)
mozilla::StaticRefPtr<LocaleService> LocaleService::sInstance;
/**
* This function transforms a canonical Mozilla Language Tag, into it's
* BCP47 compilant form.
*
- * Example: "ja-JP-mac" -> "ja-JP-x-lvariant-mac"
+ * Example: "ja-JP-mac" -> "ja-JP-macos"
*
* The BCP47 form should be used for all calls to ICU/Intl APIs.
* The canonical form is used for all internal operations.
*/
static bool
SanitizeForBCP47(nsACString& aLocale, bool strict)
{
// Currently, the only locale code we use that's not BCP47-conformant is
- // "ja-JP-mac" on OS X, but let's try to be more general than just
- // hard-coding that here.
+ // "ja-JP-mac" on OS X, and ICU canonicalizes it into a mouthfull
+ // "ja-JP-x-lvariant-mac", so instead we're hardcoding a conversion
+ // of it to "ja-JP-macos".
+ if (aLocale.LowerCaseEqualsASCII("ja-jp-mac")) {
+ aLocale.AssignLiteral("ja-JP-macos");
+ return true;
+ }
+
+ // The rest of this function will use ICU canonicalization for any other
+ // tag that may come this way.
const int32_t LANG_TAG_CAPACITY = 128;
char langTag[LANG_TAG_CAPACITY];
nsAutoCString locale(aLocale);
locale.Trim(" ");
UErrorCode err = U_ZERO_ERROR;
// This is a fail-safe method that will set langTag to "und" if it cannot
// match any part of the input locale code.
int32_t len = uloc_toLanguageTag(locale.get(), langTag, LANG_TAG_CAPACITY,
@@ -75,22 +83,17 @@ SanitizeForBCP47(nsACString& aLocale, bo
* language tags and returns them to the caller.
*/
static void
SplitLocaleListStringIntoArray(nsACString& str, nsTArray<nsCString>& aRetVal)
{
if (str.Length() > 0) {
for (const nsACString& part : str.Split(',')) {
nsAutoCString locale(part);
- if (locale.EqualsLiteral("ja-JP-mac")) {
- // This is a hack required to handle the special Mozilla `ja-JP-mac` locale.
- if (!aRetVal.Contains(locale)) {
- aRetVal.AppendElement(locale);
- }
- } else if (SanitizeForBCP47(locale, true)) {
+ if (SanitizeForBCP47(locale, true)) {
if (!aRetVal.Contains(locale)) {
aRetVal.AppendElement(locale);
}
}
}
}
}
@@ -209,30 +212,33 @@ LocaleService::~LocaleService()
}
void
LocaleService::GetAppLocalesAsLangTags(nsTArray<nsCString>& aRetVal)
{
if (mAppLocales.IsEmpty()) {
NegotiateAppLocales(mAppLocales);
}
- aRetVal = mAppLocales;
+ for (uint32_t i = 0; i < mAppLocales.Length(); i++) {
+ nsAutoCString locale(mAppLocales[i]);
+ if (locale.LowerCaseEqualsASCII("ja-jp-macos")) {
+ aRetVal.AppendElement("ja-JP-mac");
+ } else {
+ aRetVal.AppendElement(locale);
+ }
+ }
}
void
LocaleService::GetAppLocalesAsBCP47(nsTArray<nsCString>& aRetVal)
{
if (mAppLocales.IsEmpty()) {
NegotiateAppLocales(mAppLocales);
}
- for (uint32_t i = 0; i < mAppLocales.Length(); i++) {
- nsAutoCString locale(mAppLocales[i]);
- SanitizeForBCP47(locale, false);
- aRetVal.AppendElement(locale);
- }
+ aRetVal = mAppLocales;
}
void
LocaleService::GetRegionalPrefsLocales(nsTArray<nsCString>& aRetVal)
{
bool useOSLocales = Preferences::GetBool("intl.regional_prefs.use_os_locales", false);
// If the user specified that they want to use OS Regional Preferences locales,
@@ -685,25 +691,27 @@ LocaleService::GetPackagedLocales(nsTArr
*/
NS_IMETHODIMP
LocaleService::GetDefaultLocale(nsACString& aRetVal)
{
// We don't allow this to change during a session (it's set at build/package
// time), so we cache the result the first time we're called.
if (mDefaultLocale.IsEmpty()) {
+ nsAutoCString locale;
// Try to get the package locale from update.locale in omnijar. If the
// update.locale file is not found, item.len will remain 0 and we'll
// just use our hard-coded default below.
- GetGREFileContents("update.locale", &mDefaultLocale);
- mDefaultLocale.Trim(" \t\n\r");
+ GetGREFileContents("update.locale", &locale);
+ locale.Trim(" \t\n\r");
// This should never be empty.
- MOZ_ASSERT(!mDefaultLocale.IsEmpty());
- MOZ_ASSERT(mDefaultLocale.EqualsLiteral("ja-JP-mac")
- || SanitizeForBCP47(mDefaultLocale, true));
+ MOZ_ASSERT(!locale.IsEmpty());
+ if (SanitizeForBCP47(locale, true)) {
+ mDefaultLocale.Assign(locale);
+ }
// Hard-coded fallback to allow us to survive even if update.locale was
// missing/broken in some way.
if (mDefaultLocale.IsEmpty()) {
GetLastFallbackLocale(mDefaultLocale);
}
}
@@ -716,57 +724,54 @@ LocaleService::GetLastFallbackLocale(nsA
{
aRetVal.AssignLiteral("en-US");
return NS_OK;
}
NS_IMETHODIMP
LocaleService::GetAppLocalesAsLangTags(uint32_t* aCount, char*** aOutArray)
{
- if (mAppLocales.IsEmpty()) {
- NegotiateAppLocales(mAppLocales);
- }
-
- *aCount = mAppLocales.Length();
- *aOutArray = CreateOutArray(mAppLocales);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-LocaleService::GetAppLocalesAsBCP47(uint32_t* aCount, char*** aOutArray)
-{
AutoTArray<nsCString, 32> locales;
- GetAppLocalesAsBCP47(locales);
+ GetAppLocalesAsLangTags(locales);
*aCount = locales.Length();
*aOutArray = CreateOutArray(locales);
return NS_OK;
}
NS_IMETHODIMP
-LocaleService::GetAppLocaleAsLangTag(nsACString& aRetVal)
+LocaleService::GetAppLocalesAsBCP47(uint32_t* aCount, char*** aOutArray)
{
if (mAppLocales.IsEmpty()) {
NegotiateAppLocales(mAppLocales);
}
- aRetVal = mAppLocales[0];
+ *aCount = mAppLocales.Length();
+ *aOutArray = CreateOutArray(mAppLocales);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+LocaleService::GetAppLocaleAsLangTag(nsACString& aRetVal)
+{
+ AutoTArray<nsCString, 32> locales;
+ GetAppLocalesAsLangTags(locales);
+
+ aRetVal = locales[0];
return NS_OK;
}
NS_IMETHODIMP
LocaleService::GetAppLocaleAsBCP47(nsACString& aRetVal)
{
if (mAppLocales.IsEmpty()) {
NegotiateAppLocales(mAppLocales);
}
aRetVal = mAppLocales[0];
-
- SanitizeForBCP47(aRetVal, false);
return NS_OK;
}
NS_IMETHODIMP
LocaleService::GetRegionalPrefsLocales(uint32_t* aCount, char*** aOutArray)
{
AutoTArray<nsCString,10> rgLocales;
@@ -897,18 +902,17 @@ LocaleService::GetRequestedLocale(nsACSt
NS_IMETHODIMP
LocaleService::SetRequestedLocales(const char** aRequested,
uint32_t aRequestedCount)
{
nsAutoCString str;
for (uint32_t i = 0; i < aRequestedCount; i++) {
nsAutoCString locale(aRequested[i]);
- if (!locale.EqualsLiteral("ja-JP-mac") &&
- !SanitizeForBCP47(locale, true)) {
+ if (!SanitizeForBCP47(locale, true)) {
NS_ERROR("Invalid language tag provided to SetRequestedLocales!");
return NS_ERROR_INVALID_ARG;
}
if (i > 0) {
str.AppendLiteral(",");
}
str.Append(locale);
@@ -944,18 +948,17 @@ LocaleService::GetIsAppLocaleRTL(bool* a
NS_IMETHODIMP
LocaleService::SetAvailableLocales(const char** aAvailable,
uint32_t aAvailableCount)
{
nsTArray<nsCString> newLocales;
for (uint32_t i = 0; i < aAvailableCount; i++) {
nsAutoCString locale(aAvailable[i]);
- if (!locale.EqualsLiteral("ja-JP-mac") &&
- !SanitizeForBCP47(locale, true)) {
+ if (!SanitizeForBCP47(locale, true)) {
NS_ERROR("Invalid language tag provided to SetAvailableLocales!");
return NS_ERROR_INVALID_ARG;
}
newLocales.AppendElement(locale);
}
if (newLocales != mAvailableLocales) {
mAvailableLocales = Move(newLocales);
--- a/intl/locale/MozLocale.cpp
+++ b/intl/locale/MozLocale.cpp
@@ -78,21 +78,17 @@ Locale::Locale(const nsACString& aLocale
mScript = subTag;
ToLowerCase(mScript);
mScript.Replace(0, 1, ToUpperCase(mScript[0]));
position = 3;
} else if (position <= 3 && slen == 2) {
mRegion = subTag;
ToUpperCase(mRegion);
position = 4;
- } else if (position <= 4 && slen >= 3 && slen <= 8) {
- // we're quirky here because we allow for variant to be 3 char long.
- // BCP47 requires variants to be 5-8 char long at lest.
- //
- // We do this to support the `ja-JP-mac` quirk that we have.
+ } else if (position <= 4 && slen >= 5 && slen <= 8) {
nsAutoCString lcSubTag(subTag);
ToLowerCase(lcSubTag);
mVariants.InsertElementSorted(lcSubTag);
position = 4;
}
}
}
--- a/intl/locale/tests/unit/test_localeService.js
+++ b/intl/locale/tests/unit/test_localeService.js
@@ -184,23 +184,28 @@ add_test(function test_getRequestedLocal
add_test(function test_handle_ja_JP_mac() {
const bkpAvLocales = localeService.getAvailableLocales();
localeService.setAvailableLocales(["ja-JP-mac", "en-US"]);
localeService.setRequestedLocales(['ja-JP-mac']);
let reqLocales = localeService.getRequestedLocales();
- Assert.ok(reqLocales[0] === 'ja-JP-mac');
+ Assert.equal(reqLocales[0], 'ja-JP-macos');
let avLocales = localeService.getAvailableLocales();
- Assert.ok(avLocales[0] === 'ja-JP-mac');
+ Assert.equal(avLocales[0], 'ja-JP-macos');
+
+ let appLocales = localeService.getAppLocalesAsBCP47();
+ Assert.equal(appLocales[0], 'ja-JP-macos');
- let appLocales = localeService.getAppLocalesAsLangTags();
- Assert.ok(appLocales[0] === 'ja-JP-mac');
+ let appLocalesAsLT = localeService.getAppLocalesAsLangTags();
+ Assert.equal(appLocalesAsLT[0], 'ja-JP-mac');
+
+ Assert.equal(localeService.getAppLocaleAsLangTag(), "ja-JP-mac");
localeService.setAvailableLocales(bkpAvLocales);
run_next_test();
});
registerCleanupFunction(() => {