Bug 1414390 - Add intl.locale.requested locale list to replace general.useragent.locale. r=jfkthame,mossop
authorZibi Braniecki <zbraniecki@mozilla.com>
Wed, 01 Nov 2017 20:16:21 -0700
changeset 395133 8d88b85d93be
parent 395132 d1f1e12af235
child 395134 99a274ffa701
push id33033
push userrgurzau@mozilla.com
push dateWed, 06 Dec 2017 09:53:01 +0000
treeherdermozilla-central@efc64c749b0f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame, mossop
bugs1414390
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1414390 - Add intl.locale.requested locale list to replace general.useragent.locale. r=jfkthame,mossop This patch moves us from using an old pref `general.useragent.locale`combined with `intl.locale.matchOS` for retrieving user requested locale, to use a new preference `intl.locale.requested` which stores a list of well-formed BCP47 language tags. If set to empty, the OS locales are used. If not set at all, default locale is used. We are also adding a piece of code to migrate from old to new system. MozReview-Commit-ID: 854yQ1kC6Ee
browser/app/profile/firefox.js
browser/components/newtab/tests/browser/browser_packaged_as_locales.js
browser/components/nsBrowserGlue.js
browser/locales/en-US/firefox-l10n.js
intl/locale/LocaleService.cpp
intl/locale/tests/unit/test_localeService.js
mobile/android/installer/mobile-l10n.js
mobile/android/locales/en-US/mobile-l10n.js
modules/libpref/init/all.js
toolkit/locales/en-US/chrome/global/intl.properties
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -219,17 +219,16 @@ pref("browser.uitour.requireSecure", tru
 pref("browser.uitour.themeOrigin", "https://addons.mozilla.org/%LOCALE%/firefox/themes/");
 pref("browser.uitour.url", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/tour/");
 // How long to show a Hearbeat survey (two hours, in seconds)
 pref("browser.uitour.surveyDuration", 7200);
 
 pref("keyword.enabled", true);
 pref("browser.fixup.domainwhitelist.localhost", true);
 
-pref("general.useragent.locale", "@AB_CD@");
 pref("general.skins.selectedSkin", "classic/1.0");
 
 pref("general.smoothScroll", true);
 #ifdef UNIX_BUT_NOT_MAC
 pref("general.autoScroll", false);
 #else
 pref("general.autoScroll", true);
 #endif
@@ -516,16 +515,18 @@ pref("browser.bookmarks.openInTabClosesM
 
 // Scripts & Windows prefs
 pref("dom.disable_open_during_load",              true);
 pref("javascript.options.showInConsole",          true);
 #ifdef DEBUG
 pref("general.warnOnAboutConfig",                 false);
 #endif
 
+pref("intl.locale.requested", "@AB_CD@");
+
 // This is the pref to control the location bar, change this to true to
 // force this - this makes the origin of popup windows more obvious to avoid
 // spoofing. We would rather not do it by default because it affects UE for web
 // applications, but without it there isn't a really good way to prevent chrome
 // spoofing, see bug 337344
 pref("dom.disable_window_open_feature.location",  true);
 // prevent JS from setting status messages
 pref("dom.disable_window_status_change",          true);
--- a/browser/components/newtab/tests/browser/browser_packaged_as_locales.js
+++ b/browser/components/newtab/tests/browser/browser_packaged_as_locales.js
@@ -1,25 +1,24 @@
-const LOCALE_PREF = "general.useragent.locale";
-
+Components.utils.import("resource://gre/modules/Services.jsm");
 XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
                                    "@mozilla.org/browser/aboutnewtab-service;1",
                                    "nsIAboutNewTabService");
 
 const DEFAULT_URL = "resource://activity-stream/prerendered/en-US/activity-stream-prerendered.html";
 async function getUrlForLocale(locale) {
-  await SpecialPowers.pushPrefEnv({set: [[LOCALE_PREF, locale]]});
+  Services.locale.setRequestedLocales([locale]);
   return aboutNewTabService.defaultURL;
 }
 
 /**
  * Test that an unknown locale defaults to en-US
  */
 add_task(async function test_unknown_locale() {
-  const url = await getUrlForLocale("foo-BAR");
+  const url = await getUrlForLocale("und");
   Assert.equal(url, DEFAULT_URL);
 });
 
 /**
  * Test that we at least have en-US
  */
 add_task(async function test_default_locale() {
   const url = await getUrlForLocale("en-US");
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -2203,16 +2203,37 @@ BrowserGlue.prototype = {
 
         if (currentEngine._loadPath.startsWith("[https]")) {
           Services.prefs.setCharPref("browser.search.reset.status", "pending");
         } else {
           Services.search.resetToOriginalDefaultEngine();
           Services.prefs.setCharPref("browser.search.reset.status", "silent");
         }
       });
+
+      // Migrate the old requested locales prefs to use the new model
+      const SELECTED_LOCALE_PREF = "general.useragent.locale";
+      const MATCHOS_LOCALE_PREF = "intl.locale.matchOS";
+
+      if (Services.prefs.prefHasUserValue(MATCHOS_LOCALE_PREF) ||
+          Services.prefs.prefHasUserValue(SELECTED_LOCALE_PREF)) {
+        if (Services.prefs.getBoolPref(MATCHOS_LOCALE_PREF, false)) {
+          Services.locale.setRequestedLocales([]);
+        } else {
+          let locale = Services.prefs.getComplexValue(SELECTED_LOCALE_PREF,
+            Ci.nsIPrefLocalizedString);
+          if (locale) {
+            try {
+              Services.locale.setRequestedLocales([locale.data]);
+            } catch (e) { /* Don't panic if the value is not a valid locale code. */ }
+          }
+        }
+        Services.prefs.clearUserPref(SELECTED_LOCALE_PREF);
+        Services.prefs.clearUserPref(MATCHOS_LOCALE_PREF);
+      }
     }
 
     // Update the migration version.
     Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
   },
 
   _checkForDefaultBrowser() {
     // Perform default browser checking.
--- a/browser/locales/en-US/firefox-l10n.js
+++ b/browser/locales/en-US/firefox-l10n.js
@@ -2,10 +2,8 @@
 # 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/.
 
 #filter substitution
 
 # LOCALIZATION NOTE: this preference is set to true for en-US specifically,
 # locales without this line have the setting set to false by default.
 pref("browser.search.geoSpecificDefaults", true);
-
-pref("general.useragent.locale", "@AB_CD@");
--- a/intl/locale/LocaleService.cpp
+++ b/intl/locale/LocaleService.cpp
@@ -16,22 +16,20 @@
 #include "nsStringEnumerator.h"
 #include "nsXULAppAPI.h"
 #include "nsZipArchive.h"
 
 #include "unicode/uloc.h"
 
 #define INTL_SYSTEM_LOCALES_CHANGED "intl:system-locales-changed"
 
-#define MATCH_OS_LOCALE_PREF "intl.locale.matchOS"
-#define SELECTED_LOCALE_PREF "general.useragent.locale"
+#define REQUESTED_LOCALES_PREF "intl.locale.requested"
 
 static const char* kObservedPrefs[] = {
-  MATCH_OS_LOCALE_PREF,
-  SELECTED_LOCALE_PREF,
+  REQUESTED_LOCALES_PREF,
   nullptr
 };
 
 using namespace mozilla::intl;
 using namespace mozilla;
 
 NS_IMPL_ISUPPORTS(LocaleService, mozILocaleService, nsIObserver,
                   nsISupportsWeakReference)
@@ -42,69 +40,84 @@ mozilla::StaticRefPtr<LocaleService> Loc
  * This function transforms a canonical Mozilla Language Tag, into it's
  * BCP47 compilant form.
  *
  * Example: "ja-JP-mac" -> "ja-JP-x-lvariant-mac"
  *
  * The BCP47 form should be used for all calls to ICU/Intl APIs.
  * The canonical form is used for all internal operations.
  */
-static void
-SanitizeForBCP47(nsACString& aLocale)
+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.
   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,
-                                   false, &err);
+                                   strict, &err);
   if (U_SUCCESS(err) && len > 0) {
     aLocale.Assign(langTag, len);
   }
+  return U_SUCCESS(err);
 }
 
 static bool
 ReadRequestedLocales(nsTArray<nsCString>& aRetVal)
 {
-  nsAutoCString locale;
-
-  // First, we'll try to check if the user has `matchOS` pref selected
-  bool matchOSLocale = Preferences::GetBool(MATCH_OS_LOCALE_PREF);
+  nsAutoCString str;
+  nsresult rv = Preferences::GetCString(REQUESTED_LOCALES_PREF, str);
 
-  if (matchOSLocale) {
-    // If he has, we'll pick the locale from the system
-    if (OSPreferences::GetInstance()->GetSystemLocales(aRetVal)) {
-      // If we succeeded, return.
-      return true;
+  // We handle three scenarios here:
+  //
+  // 1) The pref is not set - use default locale
+  // 2) The pref is set to "" - use OS locales
+  // 3) The pref is set to a value - parse the locale list and use it
+  if (NS_SUCCEEDED(rv)) {
+    if (str.Length() > 0) {
+      for (const nsACString& part : str.Split(',')) {
+        nsAutoCString locale(part);
+        if (SanitizeForBCP47(locale, true)) {
+          // This is a hack required for us to handle the special Mozilla `ja-JP-mac`
+          // locales. We sanitize the input to normalize the case etc. but in result
+          // the `ja-JP-mac` will get turned into a BCP47 tag. Here we're turning it
+          // back into the form expected by Gecko resources.
+          if (locale.EqualsLiteral("ja-JP-x-lvariant-mac")) {
+            locale.Assign("ja-JP-mac");
+          }
+          if (!aRetVal.Contains(locale)) {
+            aRetVal.AppendElement(locale);
+          }
+        }
+      }
+    } else {
+      // If the pref string is empty, we'll take requested locales
+      // from the OS.
+      OSPreferences::GetInstance()->GetSystemLocales(aRetVal);
     }
+  } else {
+    nsAutoCString defaultLocale;
+    LocaleService::GetInstance()->GetDefaultLocale(defaultLocale);
+    aRetVal.AppendElement(defaultLocale);
   }
 
-  // Otherwise, we'll try to get the requested locale from the prefs.
-  if (!NS_SUCCEEDED(Preferences::GetCString(SELECTED_LOCALE_PREF, locale))) {
-    return false;
-  }
-
-  // At the moment we just take a single locale, but in the future
-  // we'll want to allow user to specify a list of requested locales.
-  aRetVal.AppendElement(locale);
-
   // Last fallback locale is a locale for the requested locale chain.
   // In the future we'll want to make the fallback chain differ per-locale.
-  // For now, it'll always fallback on en-US.
   //
   // Notice: This is not the same as DefaultLocale,
   // which follows the default locale the build is in.
-  LocaleService::GetInstance()->GetLastFallbackLocale(locale);
-  if (!aRetVal.Contains(locale)) {
-    aRetVal.AppendElement(locale);
+  LocaleService::GetInstance()->GetLastFallbackLocale(str);
+  if (!aRetVal.Contains(str)) {
+    aRetVal.AppendElement(str);
   }
   return true;
 }
 
 static bool
 ReadAvailableLocales(nsTArray<nsCString>& aRetVal)
 {
   nsCOMPtr<nsIToolkitChromeRegistry> cr =
@@ -218,17 +231,17 @@ LocaleService::GetAppLocalesAsLangTags(n
 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);
+    SanitizeForBCP47(locale, false);
     aRetVal.AppendElement(locale);
   }
 }
 
 void
 LocaleService::GetRegionalPrefsLocales(nsTArray<nsCString>& aRetVal)
 {
   bool useOSLocales = Preferences::GetBool("intl.regional_prefs.use_os_locales", false);
@@ -293,17 +306,16 @@ LocaleService::AssignRequestedLocales(co
   }
 }
 
 bool
 LocaleService::GetRequestedLocales(nsTArray<nsCString>& aRetVal)
 {
   if (mRequestedLocales.IsEmpty()) {
     ReadRequestedLocales(mRequestedLocales);
-
   }
 
   aRetVal = mRequestedLocales;
   return true;
 }
 
 bool
 LocaleService::GetAvailableLocales(nsTArray<nsCString>& aRetVal)
@@ -567,18 +579,17 @@ LocaleService::Observe(nsISupports *aSub
   MOZ_ASSERT(mIsServer, "This should only be called in the server mode.");
 
   if (!strcmp(aTopic, INTL_SYSTEM_LOCALES_CHANGED)) {
     RequestedLocalesChanged();
   } else {
     NS_ConvertUTF16toUTF8 pref(aData);
     // At the moment the only thing we're observing are settings indicating
     // user requested locales.
-    if (pref.EqualsLiteral(MATCH_OS_LOCALE_PREF) ||
-        pref.EqualsLiteral(SELECTED_LOCALE_PREF)) {
+    if (pref.EqualsLiteral(REQUESTED_LOCALES_PREF)) {
       RequestedLocalesChanged();
     }
   }
 
   return NS_OK;
 }
 
 bool
@@ -688,17 +699,17 @@ LocaleService::GetAppLocaleAsLangTag(nsA
 NS_IMETHODIMP
 LocaleService::GetAppLocaleAsBCP47(nsACString& aRetVal)
 {
   if (mAppLocales.IsEmpty()) {
     NegotiateAppLocales(mAppLocales);
   }
   aRetVal = mAppLocales[0];
 
-  SanitizeForBCP47(aRetVal);
+  SanitizeForBCP47(aRetVal, false);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 LocaleService::GetRegionalPrefsLocales(uint32_t* aCount, char*** aOutArray)
 {
   AutoTArray<nsCString,10> rgLocales;
 
@@ -972,29 +983,36 @@ LocaleService::GetRequestedLocale(nsACSt
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 LocaleService::SetRequestedLocales(const char** aRequested,
                                    uint32_t aRequestedCount)
 {
-  nsAutoCString lastFallbackLocale;
-  GetLastFallbackLocale(lastFallbackLocale);
-  MOZ_ASSERT(aRequestedCount < 2 ||
-             (aRequestedCount == 2 && lastFallbackLocale.Equals(aRequested[1])),
-      "We can only handle one requested locale (optionally with last fallback)");
+  nsAutoCString str;
 
-  if (aRequestedCount == 0) {
-    Preferences::ClearUser(SELECTED_LOCALE_PREF);
-  } else {
-    Preferences::SetCString(SELECTED_LOCALE_PREF, aRequested[0]);
+  for (uint32_t i = 0; i < aRequestedCount; i++) {
+    nsAutoCString locale(aRequested[i]);
+    if (!SanitizeForBCP47(locale, true)) {
+      NS_ERROR("Invalid language tag provided to SetRequestedLocales!");
+      return NS_ERROR_INVALID_ARG;
+    }
+    if (locale.EqualsLiteral("ja-JP-x-lvariant-mac")) {
+      // This is a hack for our code to handle `ja-JP-mac` special case.
+      locale.Assign("ja-JP-mac");
+    }
+
+    if (i > 0) {
+      str.AppendLiteral(",");
+    }
+    str.Append(locale);
   }
+  Preferences::SetCString(REQUESTED_LOCALES_PREF, str);
 
-  Preferences::SetBool(MATCH_OS_LOCALE_PREF, aRequestedCount == 0);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 LocaleService::GetAvailableLocales(uint32_t* aCount, char*** aOutArray)
 {
   AutoTArray<nsCString, 100> availableLocales;
   bool res = GetAvailableLocales(availableLocales);
--- a/intl/locale/tests/unit/test_localeService.js
+++ b/intl/locale/tests/unit/test_localeService.js
@@ -44,19 +44,17 @@ add_test(function test_getAppLocalesAsLa
   do_check_true(appLocale == appLocales[0], "appLocale matches first entry in appLocales");
 
   const enUSLocales = appLocales.filter(loc => loc === "en-US");
   do_check_true(enUSLocales.length == 1, "en-US is present exactly one time");
 
   run_next_test();
 });
 
-const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS";
-const PREF_SELECTED_LOCALE = "general.useragent.locale";
-const PREF_OS_LOCALE       = "intl.locale.os";
+const PREF_REQUESTED_LOCALES = "intl.locale.requested";
 const REQ_LOC_CHANGE_EVENT = "intl:requested-locales-changed";
 
 add_test(function test_getRequestedLocales() {
   const requestedLocales = localeService.getRequestedLocales();
   do_check_true(Array.isArray(requestedLocales), "requestedLocales returns an array");
 
   run_next_test();
 });
@@ -67,104 +65,108 @@ add_test(function test_getRequestedLocal
  * pref for matchOS is set to true.
  *
  * Then, we test that when the matchOS is set to true, we will retrieve
  * OS locale from getRequestedLocales.
  */
 add_test(function test_getRequestedLocales_matchOS() {
   do_test_pending();
 
-  Services.prefs.setBoolPref(PREF_MATCH_OS_LOCALE, false);
-  Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "ar-IR");
-  Services.prefs.setCharPref(PREF_OS_LOCALE, "en-US");
+  Services.prefs.setCharPref(PREF_REQUESTED_LOCALES, "ar-IR");
 
   const observer = {
     observe: function (aSubject, aTopic, aData) {
       switch (aTopic) {
         case REQ_LOC_CHANGE_EVENT:
           const reqLocs = localeService.getRequestedLocales();
           do_check_true(reqLocs[0] === osPrefs.systemLocale);
           Services.obs.removeObserver(observer, REQ_LOC_CHANGE_EVENT);
           do_test_finished();
       }
     }
   };
 
   Services.obs.addObserver(observer, REQ_LOC_CHANGE_EVENT);
-  Services.prefs.setBoolPref(PREF_MATCH_OS_LOCALE, true);
+  Services.prefs.setCharPref(PREF_REQUESTED_LOCALES, "");
 
   run_next_test();
 });
 
 /**
  * In this test we verify that after we set an observer on the LocaleService
  * event for requested locales change, it will be fired when the
  * pref for browser UI locale changes.
  */
-add_test(function test_getRequestedLocales_matchOS() {
+add_test(function test_getRequestedLocales_onChange() {
   do_test_pending();
 
-  Services.prefs.setBoolPref(PREF_MATCH_OS_LOCALE, false);
-  Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "ar-IR");
+  Services.prefs.setCharPref(PREF_REQUESTED_LOCALES, "ar-IR");
 
   const observer = {
     observe: function (aSubject, aTopic, aData) {
       switch (aTopic) {
         case REQ_LOC_CHANGE_EVENT:
           const reqLocs = localeService.getRequestedLocales();
           do_check_true(reqLocs[0] === "sr-RU");
           Services.obs.removeObserver(observer, REQ_LOC_CHANGE_EVENT);
           do_test_finished();
       }
     }
   };
 
   Services.obs.addObserver(observer, REQ_LOC_CHANGE_EVENT);
-  Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "sr-RU");
+  Services.prefs.setCharPref(PREF_REQUESTED_LOCALES, "sr-RU");
 
   run_next_test();
 });
 
 add_test(function test_getRequestedLocale() {
-  Services.prefs.setBoolPref(PREF_MATCH_OS_LOCALE, false);
-  Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "tlh");
+  Services.prefs.setCharPref(PREF_REQUESTED_LOCALES, "tlh");
 
   let requestedLocale = localeService.getRequestedLocale();
   do_check_true(requestedLocale === "tlh", "requestedLocale returns the right value");
 
-  Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "");
-
-  requestedLocale = localeService.getRequestedLocale();
-  do_check_true(requestedLocale === "", "requestedLocale returns empty value value");
-
-  Services.prefs.clearUserPref(PREF_MATCH_OS_LOCALE);
-  Services.prefs.clearUserPref(PREF_SELECTED_LOCALE);
+  Services.prefs.clearUserPref(PREF_REQUESTED_LOCALES);
 
   run_next_test();
 });
 
 add_test(function test_setRequestedLocales() {
   localeService.setRequestedLocales([]);
 
-  let matchOS = Services.prefs.getBoolPref(PREF_MATCH_OS_LOCALE);
-  do_check_true(matchOS === true);
+  localeService.setRequestedLocales(['de-AT', 'de-DE', 'de-CH']);
 
-  localeService.setRequestedLocales(['de-AT']);
-
-  matchOS = Services.prefs.getBoolPref(PREF_MATCH_OS_LOCALE);
-  do_check_true(matchOS === false);
   let locales = localeService.getRequestedLocales();;
   do_check_true(locales[0] === 'de-AT');
+  do_check_true(locales[1] === 'de-DE');
+  do_check_true(locales[2] === 'de-CH');
 
   run_next_test();
 });
 
 add_test(function test_isAppLocaleRTL() {
   do_check_true(typeof localeService.isAppLocaleRTL === 'boolean');
 
   run_next_test();
 });
 
+/**
+ * This test verifies that all values coming from the pref are sanitized.
+ */
+add_test(function test_getRequestedLocales_sanitize() {
+  Services.prefs.setCharPref(PREF_REQUESTED_LOCALES, "de,2,#$@#,pl,!a2,DE-at,,;");
+
+  let locales = localeService.getRequestedLocales();
+  do_check_eq(locales[0], "de");
+  do_check_eq(locales[1], "pl");
+  do_check_eq(locales[2], "de-AT");
+  do_check_eq(locales[3], "und");
+  do_check_eq(locales[4], localeService.lastFallbackLocale);
+  do_check_eq(locales.length, 5);
+
+  Services.prefs.clearUserPref(PREF_REQUESTED_LOCALES);
+
+  run_next_test();
+});
+
 do_register_cleanup(() => {
-  Services.prefs.clearUserPref(PREF_SELECTED_LOCALE);
-  Services.prefs.clearUserPref(PREF_MATCH_OS_LOCALE);
-  Services.prefs.clearUserPref(PREF_OS_LOCALE, "en-US");
+  Services.prefs.clearUserPref(PREF_REQUESTED_LOCALES);
 });
--- a/mobile/android/installer/mobile-l10n.js
+++ b/mobile/android/installer/mobile-l10n.js
@@ -1,6 +1,6 @@
 /* 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/. */
 
 // Inherit locale from the OS, used for multi-locale builds
-pref("intl.locale.matchOS", true);
+pref("intl.locale.requested", "");
--- a/mobile/android/locales/en-US/mobile-l10n.js
+++ b/mobile/android/locales/en-US/mobile-l10n.js
@@ -1,7 +1,5 @@
 # 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/.
 
 #filter substitution
-
-pref("general.useragent.locale", "@AB_CD@");
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -17,17 +17,16 @@
  *  - Dashes are delimiters; use underscores instead.
  *  - The first character after a period must be alphabetic.
  *  - Computed values (e.g. 50 * 1024) don't work.
  */
 
 pref("preferences.allow.omt-write", true);
 
 pref("keyword.enabled", false);
-pref("general.useragent.locale", "chrome://global/locale/intl.properties");
 pref("general.useragent.compatMode.firefox", false);
 
 // This pref exists only for testing purposes. In order to disable all
 // overrides by default, don't initialize UserAgentOverrides.jsm.
 pref("general.useragent.site_specific_overrides", true);
 
 pref("general.config.obscure_value", 13); // for MCD .cfg files
 
@@ -2290,17 +2289,16 @@ pref("converter.html2txt.always_include_
 pref("intl.accept_languages",               "chrome://global/locale/intl.properties");
 pref("intl.menuitems.alwaysappendaccesskeys","chrome://global/locale/intl.properties");
 pref("intl.menuitems.insertseparatorbeforeaccesskeys","chrome://global/locale/intl.properties");
 pref("intl.charset.detector",               "chrome://global/locale/intl.properties");
 pref("intl.charset.fallback.override",      "");
 pref("intl.charset.fallback.tld",           true);
 pref("intl.charset.fallback.utf8_for_file", false);
 pref("intl.ellipsis",                       "chrome://global-platform/locale/intl.properties");
-pref("intl.locale.matchOS",                 false);
 // this pref allows user to request that all internationalization formatters
 // like date/time formatting, unit formatting, calendars etc. should use
 // OS locale set instead of the app locale set.
 pref("intl.regional_prefs.use_os_locales",  false);
 // fallback charset list for Unicode conversion (converting from Unicode)
 // currently used for mail send only to handle symbol characters (e.g Euro, trademark, smartquotes)
 // for ISO-8859-1
 pref("intl.fallbackCharsetList.ISO-8859-1", "windows-1252");
--- a/toolkit/locales/en-US/chrome/global/intl.properties
+++ b/toolkit/locales/en-US/chrome/global/intl.properties
@@ -1,26 +1,16 @@
 # 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/.
 
-# LOCALIZATION NOTE (general.useragent.locale):
-# This is the valid BCP 47 language tag representing your locale.
-#
-# In most cases, this will simply be your locale code. However, in rare cases
-# (such as 'jp-JP-mac'), you may need to modify your locale code in order to
-# make it a valid BCP 47 language tag. (If your locale code does not include a
-# region subtag, do not include one in the language tag representing your
-# locale.)
-general.useragent.locale=en-US
-
 # LOCALIZATION NOTE (intl.accept_languages):
 # This is a comma-separated list of valid BCP 47 language tags.
 #
-# Begin with the value of 'general.useragent.locale'. Next, include language
+# Begin with the language tag of your locale. Next, include language
 # tags for other languages that you expect most users of your locale to be
 # able to speak, so that their browsing experience degrades gracefully if
 # content is not available in their primary language.
 #
 # It is recommended that you include "en-US, en" at the end of the list as a
 # last resort. However, if you know that users of your locale would prefer a
 # different variety of English, or if they are not likely to understand
 # English at all, you may opt to include a different English language tag, or