Bug 1409185 - Generalize language-matching for date/time patterns in OSPreferences. r?jfkthame draft
authorZibi Braniecki <zbraniecki@mozilla.com>
Mon, 16 Oct 2017 14:32:29 -0700
changeset 684751 b570e58151fae0a6ddecb9466f5414c1230f6109
parent 684481 8ccbd32831c7c7e9a253aaa35834f1d7b7244672
child 736956 d5d87735ae6f2546758ee4785ba98395dc7b8eeb
push id85716
push userbmo:gandalf@aviary.pl
push dateMon, 23 Oct 2017 14:23:25 +0000
reviewersjfkthame
bugs1409185
milestone58.0a1
Bug 1409185 - Generalize language-matching for date/time patterns in OSPreferences. r?jfkthame MozReview-Commit-ID: LF98Avi6egj
intl/locale/LocaleService.cpp
intl/locale/OSPreferences.cpp
intl/locale/windows/OSPreferences_win.cpp
--- a/intl/locale/LocaleService.cpp
+++ b/intl/locale/LocaleService.cpp
@@ -222,20 +222,49 @@ LocaleService::GetAppLocalesAsBCP47(nsTA
   }
 }
 
 void
 LocaleService::GetRegionalPrefsLocales(nsTArray<nsCString>& aRetVal)
 {
   bool useOSLocales = Preferences::GetBool("intl.regional_prefs.use_os_locales", false);
 
-  if (useOSLocales && OSPreferences::GetInstance()->GetRegionalPrefsLocales(aRetVal)) {
+  // If the user specified that they want to use OS Regional Preferences locales,
+  // try to retrieve them and use.
+  if (useOSLocales) {
+    if (OSPreferences::GetInstance()->GetRegionalPrefsLocales(aRetVal)) {
+      return;
+    }
+
+    // If we fail to retrieve them, return the app locales.
+    GetAppLocalesAsBCP47(aRetVal);
     return;
   }
 
+  // Otherwise, fetch OS Regional Preferences locales and compare the first one
+  // to the app locale. If the language subtag matches, we can safely use
+  // the OS Regional Preferences locale.
+  //
+  // This facilitates scenarios such as Firefox in "en-US" and User sets
+  // regional prefs to "en-GB".
+  nsAutoCString appLocale;
+  AutoTArray<nsCString, 10> regionalPrefsLocales;
+  LocaleService::GetInstance()->GetAppLocaleAsBCP47(appLocale);
+
+  if (!OSPreferences::GetInstance()->GetRegionalPrefsLocales(regionalPrefsLocales)) {
+    GetAppLocalesAsBCP47(aRetVal);
+    return;
+  }
+
+  if (LocaleService::LanguagesMatch(appLocale, regionalPrefsLocales[0])) {
+    aRetVal = regionalPrefsLocales;
+    return;
+  }
+
+  // Otherwise use the app locales.
   GetAppLocalesAsBCP47(aRetVal);
 }
 
 void
 LocaleService::AssignAppLocales(const nsTArray<nsCString>& aAppLocales)
 {
   MOZ_ASSERT(!mIsServer, "This should only be called for LocaleService in client mode.");
 
--- a/intl/locale/OSPreferences.cpp
+++ b/intl/locale/OSPreferences.cpp
@@ -165,17 +165,19 @@ OSPreferences::GetDateTimePatternForStyl
       break;
   }
 
   const int32_t kPatternMax = 160;
   UChar pattern[kPatternMax];
 
   nsAutoCString locale;
   if (aLocale.IsEmpty()) {
-    LocaleService::GetInstance()->GetAppLocaleAsBCP47(locale);
+    AutoTArray<nsCString, 10> regionalPrefsLocales;
+    LocaleService::GetInstance()->GetRegionalPrefsLocales(regionalPrefsLocales);
+    locale.Assign(regionalPrefsLocales[0]);
   } else {
     locale.Assign(aLocale);
   }
 
   UErrorCode status = U_ZERO_ERROR;
   UDateFormat* df = udat_open(timeStyle, dateStyle,
                               locale.get(),
                               nullptr, -1, nullptr, -1, &status);
--- a/intl/locale/windows/OSPreferences_win.cpp
+++ b/intl/locale/windows/OSPreferences_win.cpp
@@ -47,35 +47,16 @@ OSPreferences::ReadRegionalPrefsLocales(
 
   if (CanonicalizeLanguageTag(loc)) {
     aLocaleList.AppendElement(loc);
     return true;
   }
   return false;
 }
 
-/**
- * Windows distinguishes between System Locale (the locale OS is in), and
- * User Locale (the locale used for regional settings etc.).
- *
- * For DateTimePattern, we want to retrieve the User Locale.
- */
-static void
-ReadUserLocale(nsCString& aRetVal)
-{
-  WCHAR locale[LOCALE_NAME_MAX_LENGTH];
-  if (NS_WARN_IF(!LCIDToLocaleName(LOCALE_USER_DEFAULT, locale,
-                                   LOCALE_NAME_MAX_LENGTH, 0))) {
-    aRetVal.AssignLiteral("en-US");
-    return;
-  }
-
-  LossyCopyUTF16toASCII(locale, aRetVal);
-}
-
 static LCTYPE
 ToDateLCType(OSPreferences::DateTimeFormatStyle aFormatStyle)
 {
   switch (aFormatStyle) {
     case OSPreferences::DateTimeFormatStyle::None:
       return LOCALE_SLONGDATE;
     case OSPreferences::DateTimeFormatStyle::Short:
       return LOCALE_SSHORTDATE;
@@ -108,39 +89,16 @@ ToTimeLCType(OSPreferences::DateTimeForm
       return LOCALE_STIMEFORMAT;
     case OSPreferences::DateTimeFormatStyle::Invalid:
     default:
       MOZ_ASSERT_UNREACHABLE("invalid time format");
       return LOCALE_STIMEFORMAT;
   }
 }
 
-LPWSTR
-GetWindowsLocaleFor(const nsACString& aLocale, LPWSTR aBuffer)
-{
-  nsAutoCString reqLocale;
-  nsAutoCString userLocale;
-  ReadUserLocale(userLocale);
-
-  if (aLocale.IsEmpty()) {
-    LocaleService::GetInstance()->GetAppLocaleAsBCP47(reqLocale);
-  } else {
-    reqLocale.Assign(aLocale);
-  }
-
-  bool match = LocaleService::LanguagesMatch(reqLocale, userLocale);
-  if (match || reqLocale.Length() >= LOCALE_NAME_MAX_LENGTH) {
-    UTF8ToUnicodeBuffer(userLocale, (char16_t*)aBuffer);
-  } else {
-    UTF8ToUnicodeBuffer(reqLocale, (char16_t*)aBuffer);
-  }
-
-  return aBuffer;
-}
-
 /**
  * Windows API includes regional preferences from the user only
  * if we pass empty locale string or if the locale string matches
  * the current locale.
  *
  * Since Windows API only allows us to retrieve two options - short/long
  * we map it to our four options as:
  *
@@ -153,19 +111,18 @@ GetWindowsLocaleFor(const nsACString& aL
  * for combined date/time string, since Windows API does not provide an
  * option for this.
  */
 bool
 OSPreferences::ReadDateTimePattern(DateTimeFormatStyle aDateStyle,
                                    DateTimeFormatStyle aTimeStyle,
                                    const nsACString& aLocale, nsAString& aRetVal)
 {
-  WCHAR buffer[LOCALE_NAME_MAX_LENGTH];
-
-  LPWSTR localeName = GetWindowsLocaleFor(aLocale, buffer);
+  WCHAR localeName[LOCALE_NAME_MAX_LENGTH];
+  UTF8ToUnicodeBuffer(aLocale, (char16_t*)localeName);
 
   bool isDate = aDateStyle != DateTimeFormatStyle::None &&
                 aDateStyle != DateTimeFormatStyle::Invalid;
   bool isTime = aTimeStyle != DateTimeFormatStyle::None &&
                 aTimeStyle != DateTimeFormatStyle::Invalid;
 
   // If both date and time are wanted, we'll initially read them into a
   // local string, and then insert them into the overall date+time pattern;