Bug 1109000 - Split statics out of BrowserLocaleManager. r=nalexander, a=java-only on a CLOSED TREE
authorRichard Newman <rnewman@mozilla.com>
Tue, 09 Dec 2014 18:07:07 +0000
changeset 244782 e2759f8d7232e1856d25f73a79b6bacaa85ca2de
parent 244720 383988745eb24d55eb2cd669769fc336211f4f3c
child 244783 f4627e74e39f06cc5cdf733173905cdfd8ac5f5e
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnalexander, java-only
bugs1109000
milestone37.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 1109000 - Split statics out of BrowserLocaleManager. r=nalexander, a=java-only on a CLOSED TREE
mobile/android/base/BrowserApp.java
mobile/android/base/BrowserLocaleManager.java
mobile/android/base/GeckoApp.java
mobile/android/base/LocaleAware.java
mobile/android/base/LocaleManager.java
mobile/android/base/Locales.java
mobile/android/base/db/SuggestedSites.java
mobile/android/base/fxa/activities/FxAccountAbstractActivity.java
mobile/android/base/fxa/activities/FxAccountGetStartedActivity.java
mobile/android/base/fxa/activities/FxAccountStatusActivity.java
mobile/android/base/home/TopSitesPanel.java
mobile/android/base/moz.build
mobile/android/base/overlays/ui/ShareDialog.java
mobile/android/base/preferences/GeckoPreferences.java
mobile/android/base/preferences/LocaleListPreference.java
mobile/android/base/sync/setup/activities/SendTabActivity.java
mobile/android/base/tabs/PrivateTabsPanel.java
mobile/android/base/tests/testOSLocale.java
mobile/android/search/java/org/mozilla/search/SearchActivity.java
mobile/android/search/java/org/mozilla/search/SearchPreferenceActivity.java
mobile/android/search/java/org/mozilla/search/providers/SearchEngineManager.java
mobile/android/tests/browser/junit3/src/TestSuggestedSites.java
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -2192,17 +2192,17 @@ public class BrowserApp extends GeckoApp
                     @Override
                     public void run() {
                         final LocaleManager localeManager = BrowserLocaleManager.getInstance();
                         final Locale locale = localeManager.getCurrentLocale(getApplicationContext());
                         Log.d(LOGTAG, "Read persisted locale " + locale);
                         if (locale == null) {
                             return;
                         }
-                        onLocaleChanged(BrowserLocaleManager.getLanguageTag(locale));
+                        onLocaleChanged(Locales.getLanguageTag(locale));
                     }
                 });
                 break;
             default:
                 super.onActivityResult(requestCode, resultCode, data);
         }
     }
 
@@ -2925,17 +2925,17 @@ public class BrowserApp extends GeckoApp
             // we might need to redisplay based on a locale change.
             startActivityForResult(intent, ACTIVITY_REQUEST_PREFERENCES);
             return true;
         }
 
         if (itemId == R.id.help) {
             final String VERSION = AppConstants.MOZ_APP_VERSION;
             final String OS = AppConstants.OS_TARGET;
-            final String LOCALE = BrowserLocaleManager.getLanguageTag(Locale.getDefault());
+            final String LOCALE = Locales.getLanguageTag(Locale.getDefault());
 
             final String URL = getResources().getString(R.string.help_link, VERSION, OS, LOCALE);
             Tabs.getInstance().loadUrlInTab(URL);
             return true;
         }
 
         if (itemId == R.id.addons) {
             Tabs.getInstance().loadUrlInTab(AboutPages.ADDONS);
--- a/mobile/android/base/BrowserLocaleManager.java
+++ b/mobile/android/base/BrowserLocaleManager.java
@@ -76,74 +76,16 @@ public class BrowserLocaleManager implem
     }
 
     @Override
     public boolean isEnabled() {
         return AppConstants.MOZ_LOCALE_SWITCHER;
     }
 
     /**
-     * Sometimes we want just the language for a locale, not the entire
-     * language tag. But Java's .getLanguage method is wrong.
-     *
-     * This method is equivalent to the first part of {@link #getLanguageTag(Locale)}.
-     *
-     * @return a language string, such as "he" for the Hebrew locales.
-     */
-    public static String getLanguage(final Locale locale) {
-        final String language = locale.getLanguage();  // Can, but should never be, an empty string.
-        // Modernize certain language codes.
-        if (language.equals("iw")) {
-            return "he";
-        }
-
-        if (language.equals("in")) {
-            return "id";
-        }
-
-        if (language.equals("ji")) {
-            return "yi";
-        }
-
-        return language;
-    }
-
-    /**
-     * Gecko uses locale codes like "es-ES", whereas a Java {@link Locale}
-     * stringifies as "es_ES".
-     *
-     * This method approximates the Java 7 method <code>Locale#toLanguageTag()</code>.
-     *
-     * @return a locale string suitable for passing to Gecko.
-     */
-    public static String getLanguageTag(final Locale locale) {
-        // If this were Java 7:
-        // return locale.toLanguageTag();
-
-        final String language = getLanguage(locale);
-        final String country = locale.getCountry();    // Can be an empty string.
-        if (country.equals("")) {
-            return language;
-        }
-        return language + "-" + country;
-    }
-
-    public static Locale parseLocaleCode(final String localeCode) {
-        int index;
-        if ((index = localeCode.indexOf('-')) != -1 ||
-            (index = localeCode.indexOf('_')) != -1) {
-            final String langCode = localeCode.substring(0, index);
-            final String countryCode = localeCode.substring(index + 1);
-            return new Locale(langCode, countryCode);
-        } else {
-            return new Locale(localeCode);
-        }
-    }
-
-    /**
      * Ensure that you call this early in your application startup,
      * and with a context that's sufficiently long-lived (typically
      * the application context).
      *
      * Calling multiple times is harmless.
      */
     @Override
     public void initialize(final Context context) {
@@ -270,17 +212,17 @@ public class BrowserLocaleManager implem
             return;
         }
 
         // Store the Java-native form.
         prefs.edit().putString("osLocale", osLocaleString).apply();
 
         // The value we send to Gecko should be a language tag, not
         // a Java locale string.
-        final String osLanguageTag = BrowserLocaleManager.getLanguageTag(osLocale);
+        final String osLanguageTag = Locales.getLanguageTag(osLocale);
         final GeckoEvent localeOSEvent = GeckoEvent.createBroadcastEvent("Locale:OS", osLanguageTag);
         GeckoAppShell.sendEventToGecko(localeOSEvent);
     }
 
     @Override
     public String getAndApplyPersistedLocale(Context context) {
         initialize(context);
 
@@ -316,17 +258,17 @@ public class BrowserLocaleManager implem
         // We always persist and notify Gecko, even if nothing seemed to
         // change. This might happen if you're picking a locale that's the same
         // as the current OS locale. The OS locale might change next time we
         // launch, and we need the Gecko pref and persisted locale to have been
         // set by the time that happens.
         persistLocale(context, localeCode);
 
         // Tell Gecko.
-        GeckoEvent ev = GeckoEvent.createBroadcastEvent(EVENT_LOCALE_CHANGED, BrowserLocaleManager.getLanguageTag(getCurrentLocale(context)));
+        GeckoEvent ev = GeckoEvent.createBroadcastEvent(EVENT_LOCALE_CHANGED, Locales.getLanguageTag(getCurrentLocale(context)));
         GeckoAppShell.sendEventToGecko(ev);
 
         return resultant;
     }
 
     @Override
     public void resetToSystemLocale(Context context) {
         // Wipe the pref.
@@ -384,17 +326,17 @@ public class BrowserLocaleManager implem
         if (currentLocale != null) {
             return currentLocale;
         }
 
         final String current = getPersistedLocale(context);
         if (current == null) {
             return null;
         }
-        return currentLocale = parseLocaleCode(current);
+        return currentLocale = Locales.parseLocaleCode(current);
     }
 
     /**
      * Updates the Java locale and the Android configuration.
      *
      * Returns the persisted locale if it differed.
      *
      * Does not notify Gecko.
@@ -404,17 +346,17 @@ public class BrowserLocaleManager implem
      */
     private String updateLocale(Context context, String localeCode) {
         // Fast path.
         final Locale defaultLocale = Locale.getDefault();
         if (defaultLocale.toString().equals(localeCode)) {
             return null;
         }
 
-        final Locale locale = parseLocaleCode(localeCode);
+        final Locale locale = Locales.parseLocaleCode(localeCode);
 
         return updateLocale(context, locale);
     }
 
     /**
      * @return the Java locale string: e.g., "en_US".
      */
     private String updateLocale(Context context, final Locale locale) {
@@ -490,12 +432,13 @@ public class BrowserLocaleManager implem
             return null;
         }
     }
 
     /**
      * @return the single default locale baked into this application.
      *         Applicable when there is no multilocale.json present.
      */
-    public static String getFallbackLocaleTag() {
+    @SuppressWarnings("static-method")
+    public String getFallbackLocaleTag() {
         return FALLBACK_LOCALE_TAG;
     }
 }
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -1378,17 +1378,17 @@ public abstract class GeckoApp
      * response to device changes.
      */
     @Override
     public void onLocaleReady(final String locale) {
         if (!ThreadUtils.isOnUiThread()) {
             throw new RuntimeException("onLocaleReady must always be called from the UI thread.");
         }
 
-        final Locale loc = BrowserLocaleManager.parseLocaleCode(locale);
+        final Locale loc = Locales.parseLocaleCode(locale);
         if (loc.equals(mLastLocale)) {
             Log.d(LOGTAG, "New locale same as old; onLocaleReady has nothing to do.");
         }
 
         // The URL bar hint needs to be populated.
         TextView urlBar = (TextView) findViewById(R.id.url_bar_title);
         if (urlBar != null) {
             final String hint = getResources().getString(R.string.url_bar_default_text);
@@ -2114,17 +2114,17 @@ public abstract class GeckoApp
 
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
         Log.d(LOGTAG, "onConfigurationChanged: " + newConfig.locale);
 
         final LocaleManager localeManager = BrowserLocaleManager.getInstance();
         final Locale changed = localeManager.onSystemConfigurationChanged(this, getResources(), newConfig, mLastLocale);
         if (changed != null) {
-            onLocaleChanged(BrowserLocaleManager.getLanguageTag(changed));
+            onLocaleChanged(Locales.getLanguageTag(changed));
         }
 
         // onConfigurationChanged is not called for 180 degree orientation changes,
         // we will miss such rotations and the screen orientation will not be
         // updated.
         if (GeckoScreenOrientation.getInstance().update(newConfig.orientation)) {
             if (mFormAssistPopup != null)
                 mFormAssistPopup.hide();
--- a/mobile/android/base/LocaleManager.java
+++ b/mobile/android/base/LocaleManager.java
@@ -33,9 +33,10 @@ public interface LocaleManager {
 
     /**
      * Call this in your onConfigurationChanged handler. This method is expected
      * to do the appropriate thing: if the user has selected a locale, it
      * corrects the incoming configuration; if not, it signals the new locale to
      * use.
      */
     Locale onSystemConfigurationChanged(Context context, Resources resources, Configuration configuration, Locale currentActivityLocale);
+    String getFallbackLocaleTag();
 }
rename from mobile/android/base/LocaleAware.java
rename to mobile/android/base/Locales.java
--- a/mobile/android/base/LocaleAware.java
+++ b/mobile/android/base/Locales.java
@@ -1,52 +1,116 @@
 /* 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/. */
 
 package org.mozilla.gecko;
 
+import java.util.Locale;
+
 import org.mozilla.gecko.BrowserLocaleManager;
 import org.mozilla.gecko.LocaleManager;
 
 import android.app.Activity;
 import android.content.Context;
 import android.os.Bundle;
 import android.os.StrictMode;
 import android.support.v4.app.FragmentActivity;
 
 /**
- * This is a helper class to do typical locale switching operations
- * without hitting StrictMode errors or adding boilerplate to common
- * activity subclasses.
+ * This is a helper class to do typical locale switching operations without
+ * hitting StrictMode errors or adding boilerplate to common activity
+ * subclasses.
  *
- * Either call {@link LocaleAware#initializeLocale(Context)} in your
- * <code>onCreate</code> method, or inherit from <code>LocaleAwareFragmentActivity</code>
- * or <code>LocaleAwareActivity</code>.
+ * Either call {@link Locales#initializeLocale(Context)} in your
+ * <code>onCreate</code> method, or inherit from
+ * <code>LocaleAwareFragmentActivity</code> or <code>LocaleAwareActivity</code>.
  */
-public class LocaleAware {
-  public static void initializeLocale(Context context) {
-    final LocaleManager localeManager = BrowserLocaleManager.getInstance();
-    final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
-    StrictMode.allowThreadDiskWrites();
-    try {
-      localeManager.getAndApplyPersistedLocale(context);
-    } finally {
-      StrictMode.setThreadPolicy(savedPolicy);
+public class Locales {
+    public static void initializeLocale(Context context) {
+        final LocaleManager localeManager = BrowserLocaleManager.getInstance();
+        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
+        StrictMode.allowThreadDiskWrites();
+        try {
+            localeManager.getAndApplyPersistedLocale(context);
+        } finally {
+            StrictMode.setThreadPolicy(savedPolicy);
+        }
+    }
+
+    public static class LocaleAwareFragmentActivity extends FragmentActivity {
+        @Override
+        protected void onCreate(Bundle savedInstanceState) {
+            Locales.initializeLocale(getApplicationContext());
+            super.onCreate(savedInstanceState);
+        }
+    }
+
+    public static class LocaleAwareActivity extends Activity {
+        @Override
+        protected void onCreate(Bundle savedInstanceState) {
+            Locales.initializeLocale(getApplicationContext());
+            super.onCreate(savedInstanceState);
+        }
     }
-  }
+
+    /**
+     * Sometimes we want just the language for a locale, not the entire language
+     * tag. But Java's .getLanguage method is wrong.
+     *
+     * This method is equivalent to the first part of
+     * {@link Locales#getLanguageTag(Locale)}.
+     *
+     * @return a language string, such as "he" for the Hebrew locales.
+     */
+    public static String getLanguage(final Locale locale) {
+        // Can, but should never be, an empty string.
+        final String language = locale.getLanguage();
 
-  public static class LocaleAwareFragmentActivity extends FragmentActivity {
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-      LocaleAware.initializeLocale(getApplicationContext());
-      super.onCreate(savedInstanceState);
+        // Modernize certain language codes.
+        if (language.equals("iw")) {
+            return "he";
+        }
+
+        if (language.equals("in")) {
+            return "id";
+        }
+
+        if (language.equals("ji")) {
+            return "yi";
+        }
+
+        return language;
     }
-  }
+
+    /**
+     * Gecko uses locale codes like "es-ES", whereas a Java {@link Locale}
+     * stringifies as "es_ES".
+     *
+     * This method approximates the Java 7 method
+     * <code>Locale#toLanguageTag()</code>.
+     *
+     * @return a locale string suitable for passing to Gecko.
+     */
+    public static String getLanguageTag(final Locale locale) {
+        // If this were Java 7:
+        // return locale.toLanguageTag();
 
-  public static class LocaleAwareActivity extends Activity {
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-      LocaleAware.initializeLocale(getApplicationContext());
-      super.onCreate(savedInstanceState);
+        final String language = getLanguage(locale);
+        final String country = locale.getCountry(); // Can be an empty string.
+        if (country.equals("")) {
+            return language;
+        }
+        return language + "-" + country;
     }
-  }
+
+    public static Locale parseLocaleCode(final String localeCode) {
+        int index;
+        if ((index = localeCode.indexOf('-')) != -1 ||
+            (index = localeCode.indexOf('_')) != -1) {
+            final String langCode = localeCode.substring(0, index);
+            final String countryCode = localeCode.substring(index + 1);
+            return new Locale(langCode, countryCode);
+        }
+
+        return new Locale(localeCode);
+    }
 }
--- a/mobile/android/base/db/SuggestedSites.java
+++ b/mobile/android/base/db/SuggestedSites.java
@@ -29,20 +29,19 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Scanner;
 import java.util.Set;
 
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
-
-import org.mozilla.gecko.BrowserLocaleManager;
 import org.mozilla.gecko.GeckoSharedPrefs;
 import org.mozilla.gecko.GeckoProfile;
+import org.mozilla.gecko.Locales;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.distribution.Distribution;
 import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.mozglue.RobocopTarget;
 import org.mozilla.gecko.preferences.GeckoPreferences;
 import org.mozilla.gecko.util.RawResource;
 import org.mozilla.gecko.util.ThreadUtils;
 
@@ -329,17 +328,17 @@ public class SuggestedSites {
      * current locale or with the fallback locale (en-US).
      *
      * It's assumed that the given distribution instance is ready to be
      * used and exists.
      */
     static Map<String, Site> loadFromDistribution(Distribution dist) {
         for (Locale locale : getAcceptableLocales()) {
             try {
-                final String languageTag = BrowserLocaleManager.getLanguageTag(locale);
+                final String languageTag = Locales.getLanguageTag(locale);
                 final String path = String.format("suggestedsites/locales/%s/%s",
                                                   languageTag, FILENAME);
 
                 final File f = dist.getDistributionFile(path);
                 if (f == null) {
                     Log.d(LOGTAG, "No suggested sites for locale: " + languageTag);
                     continue;
                 }
--- a/mobile/android/base/fxa/activities/FxAccountAbstractActivity.java
+++ b/mobile/android/base/fxa/activities/FxAccountAbstractActivity.java
@@ -4,17 +4,17 @@
 
 package org.mozilla.gecko.fxa.activities;
 
 import org.mozilla.gecko.background.common.log.Logger;
 import org.mozilla.gecko.background.fxa.FxAccountAgeLockoutHelper;
 import org.mozilla.gecko.fxa.FirefoxAccounts;
 import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
 import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
-import org.mozilla.gecko.LocaleAware.LocaleAwareActivity;
+import org.mozilla.gecko.Locales.LocaleAwareActivity;
 
 import android.accounts.Account;
 import android.app.Activity;
 import android.content.Intent;
 import android.os.SystemClock;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.TextView;
--- a/mobile/android/base/fxa/activities/FxAccountGetStartedActivity.java
+++ b/mobile/android/base/fxa/activities/FxAccountGetStartedActivity.java
@@ -8,17 +8,17 @@ import java.util.Locale;
 
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.background.common.log.Logger;
 import org.mozilla.gecko.background.fxa.FxAccountAgeLockoutHelper;
 import org.mozilla.gecko.background.fxa.FxAccountUtils;
 import org.mozilla.gecko.fxa.FirefoxAccounts;
 import org.mozilla.gecko.fxa.FxAccountConstants;
 import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
-import org.mozilla.gecko.LocaleAware;
+import org.mozilla.gecko.Locales;
 
 import android.accounts.AccountAuthenticatorActivity;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.TextView;
@@ -34,17 +34,17 @@ public class FxAccountGetStartedActivity
   /**
    * {@inheritDoc}
    */
   @Override
   public void onCreate(Bundle icicle) {
     Logger.setThreadLogTag(FxAccountConstants.GLOBAL_LOG_TAG);
     Logger.debug(LOG_TAG, "onCreate(" + icicle + ")");
 
-    LocaleAware.initializeLocale(getApplicationContext());
+    Locales.initializeLocale(getApplicationContext());
 
     super.onCreate(icicle);
 
     setContentView(R.layout.fxaccount_get_started);
 
     linkifyOldFirefoxLink();
 
     View button = findViewById(R.id.get_started_button);
--- a/mobile/android/base/fxa/activities/FxAccountStatusActivity.java
+++ b/mobile/android/base/fxa/activities/FxAccountStatusActivity.java
@@ -1,16 +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/. */
 
 package org.mozilla.gecko.fxa.activities;
 
 import org.mozilla.gecko.AppConstants;
-import org.mozilla.gecko.LocaleAware.LocaleAwareFragmentActivity;
+import org.mozilla.gecko.Locales.LocaleAwareFragmentActivity;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.background.common.log.Logger;
 import org.mozilla.gecko.fxa.FirefoxAccounts;
 import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
 import org.mozilla.gecko.sync.Utils;
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
--- a/mobile/android/base/home/TopSitesPanel.java
+++ b/mobile/android/base/home/TopSitesPanel.java
@@ -10,18 +10,18 @@ import static org.mozilla.gecko.db.URLMe
 
 import java.util.ArrayList;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 
-import org.mozilla.gecko.BrowserLocaleManager;
 import org.mozilla.gecko.GeckoProfile;
+import org.mozilla.gecko.Locales;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.Tab;
 import org.mozilla.gecko.Tabs;
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.gecko.db.BrowserContract.Thumbnails;
 import org.mozilla.gecko.db.BrowserContract.TopSites;
 import org.mozilla.gecko.db.BrowserDB;
@@ -233,17 +233,17 @@ public class TopSitesPanel extends HomeF
                             method = TelemetryContract.Method.GRID_ITEM;
                         }
                         Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, method, Integer.toString(position));
 
                         // Record tile click events on non-private tabs.
                         final Tab tab = Tabs.getInstance().getSelectedTab();
                         if (!tab.isPrivate()) {
                             final Locale locale = Locale.getDefault();
-                            final String localeTag = BrowserLocaleManager.getLanguageTag(locale);
+                            final String localeTag = Locales.getLanguageTag(locale);
                             mTilesRecorder.recordAction(tab, TilesRecorder.ACTION_CLICK, position, getTilesSnapshot(), localeTag);
                         }
 
                         mUrlOpenListener.onUrlOpen(url, EnumSet.noneOf(OnUrlOpenListener.Flags.class));
                     }
                 } else {
                     if (mEditPinnedSiteListener != null) {
                         mEditPinnedSiteListener.onEditPinnedSite(position, "");
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -321,18 +321,18 @@ gbjar.sources += [
     'home/TopSitesGridView.java',
     'home/TopSitesPanel.java',
     'home/TopSitesThumbnailView.java',
     'home/TransitionAwareCursorLoaderCallbacks.java',
     'home/TwoLinePageRow.java',
     'InputMethods.java',
     'IntentHelper.java',
     'JavaAddonManager.java',
-    'LocaleAware.java',
     'LocaleManager.java',
+    'Locales.java',
     'lwt/LightweightTheme.java',
     'lwt/LightweightThemeDrawable.java',
     'MediaCastingBar.java',
     'MemoryMonitor.java',
     'menu/GeckoMenu.java',
     'menu/GeckoMenuInflater.java',
     'menu/GeckoMenuItem.java',
     'menu/GeckoSubMenu.java',
--- a/mobile/android/base/overlays/ui/ShareDialog.java
+++ b/mobile/android/base/overlays/ui/ShareDialog.java
@@ -5,17 +5,17 @@
 
 package org.mozilla.gecko.overlays.ui;
 
 import java.net.URISyntaxException;
 
 import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.Assert;
 import org.mozilla.gecko.GeckoProfile;
-import org.mozilla.gecko.LocaleAware;
+import org.mozilla.gecko.Locales;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.gecko.db.LocalBrowserDB;
 import org.mozilla.gecko.overlays.OverlayConstants;
 import org.mozilla.gecko.overlays.service.OverlayActionService;
 import org.mozilla.gecko.overlays.service.sharemethods.ParcelableClientRecord;
 import org.mozilla.gecko.overlays.service.sharemethods.SendTab;
@@ -45,17 +45,17 @@ import android.view.animation.AnimationU
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 import android.widget.Toast;
 
 /**
  * A transparent activity that displays the share overlay.
  */
-public class ShareDialog extends LocaleAware.LocaleAwareActivity implements SendTabTargetSelectedListener {
+public class ShareDialog extends Locales.LocaleAwareActivity implements SendTabTargetSelectedListener {
     private static final String LOGTAG = "GeckoShareDialog";
 
     private String url;
     private String title;
 
     // The override intent specified by SendTab (if any). See SendTab.java.
     private Intent sendTabOverrideIntent;
 
--- a/mobile/android/base/preferences/GeckoPreferences.java
+++ b/mobile/android/base/preferences/GeckoPreferences.java
@@ -7,31 +7,33 @@ package org.mozilla.gecko.preferences;
 
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 
 import android.os.Build;
+
 import org.json.JSONObject;
 import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.AppConstants.Versions;
 import org.mozilla.gecko.BrowserApp;
 import org.mozilla.gecko.BrowserLocaleManager;
 import org.mozilla.gecko.DataReportingNotification;
 import org.mozilla.gecko.EventDispatcher;
 import org.mozilla.gecko.GeckoActivityStatus;
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoEvent;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.GeckoSharedPrefs;
 import org.mozilla.gecko.GuestSession;
 import org.mozilla.gecko.LocaleManager;
+import org.mozilla.gecko.Locales;
 import org.mozilla.gecko.NewTabletUI;
 import org.mozilla.gecko.PrefsHelper;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.RestrictedProfiles;
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.gecko.TelemetryContract.Method;
 import org.mozilla.gecko.background.common.GlobalConstants;
@@ -1009,17 +1011,17 @@ OnSharedPreferenceChangeListener
      *
      * Note that this listener is not always registered: we use it only on
      * tablets, Honeycomb and up, where we'll have a multi-pane view and prefs
      * changing multiple times.
      */
     @Override
     public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
         if (PREFS_BROWSER_LOCALE.equals(key)) {
-            onLocaleSelected(BrowserLocaleManager.getLanguageTag(lastLocale),
+            onLocaleSelected(Locales.getLanguageTag(lastLocale),
                              sharedPreferences.getString(key, null));
         } else if (PREFS_SUGGESTED_SITES.equals(key)) {
             refreshSuggestedSites();
         } else if (PREFS_NEW_TABLET_UI.equals(key)) {
             Toast.makeText(this, R.string.new_tablet_restart, Toast.LENGTH_SHORT).show();
         }
     }
 
@@ -1049,17 +1051,17 @@ OnSharedPreferenceChangeListener
             // We don't want the "use master password" pref to change until the
             // user has gone through the dialog.
             return false;
         }
 
         if (PREFS_BROWSER_LOCALE.equals(prefName)) {
             // Even though this is a list preference, we don't want to handle it
             // below, so we return here.
-            return onLocaleSelected(BrowserLocaleManager.getLanguageTag(lastLocale), (String) newValue);
+            return onLocaleSelected(Locales.getLanguageTag(lastLocale), (String) newValue);
         }
 
         if (PREFS_MENU_CHAR_ENCODING.equals(prefName)) {
             setCharEncodingState(((String) newValue).equals("true"));
         } else if (PREFS_UPDATER_AUTODOWNLOAD.equals(prefName)) {
             UpdateServiceHelper.registerForUpdates(this, (String) newValue);
         } else if (PREFS_HEALTHREPORT_UPLOAD_ENABLED.equals(prefName)) {
             // The healthreport pref only lives in Android, so we do not persist
--- a/mobile/android/base/preferences/LocaleListPreference.java
+++ b/mobile/android/base/preferences/LocaleListPreference.java
@@ -9,16 +9,17 @@ import java.text.Collator;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Locale;
 import java.util.Set;
 
 import org.mozilla.gecko.AppConstants.Versions;
 import org.mozilla.gecko.BrowserLocaleManager;
+import org.mozilla.gecko.Locales;
 import org.mozilla.gecko.R;
 
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.preference.ListPreference;
 import android.text.TextUtils;
@@ -112,17 +113,17 @@ public class LocaleListPreference extend
     private static final class LocaleDescriptor implements Comparable<LocaleDescriptor> {
         // We use Locale.US here to ensure a stable ordering of entries.
         private static final Collator COLLATOR = Collator.getInstance(Locale.US);
 
         public final String tag;
         private final String nativeName;
 
         public LocaleDescriptor(String tag) {
-            this(BrowserLocaleManager.parseLocaleCode(tag), tag);
+            this(Locales.parseLocaleCode(tag), tag);
         }
 
         public LocaleDescriptor(Locale locale, String tag) {
             this.tag = tag;
 
             final String displayName = locale.getDisplayName(locale);
             if (TextUtils.isEmpty(displayName)) {
                 // There's nothing sane we can do.
@@ -216,17 +217,17 @@ public class LocaleListPreference extend
      *
      * This method filters down the list before generating the descriptor array.
      */
     private LocaleDescriptor[] getUsableLocales() {
         Collection<String> shippingLocales = BrowserLocaleManager.getPackagedLocaleTags(getContext());
 
         // Future: single-locale builds should be specified, too.
         if (shippingLocales == null) {
-            final String fallbackTag = BrowserLocaleManager.getFallbackLocaleTag();
+            final String fallbackTag = BrowserLocaleManager.getInstance().getFallbackLocaleTag();
             return new LocaleDescriptor[] { new LocaleDescriptor(fallbackTag) };
         }
 
         final int initialCount = shippingLocales.size();
         final Set<LocaleDescriptor> locales = new HashSet<LocaleDescriptor>(initialCount);
         for (String tag : shippingLocales) {
             final LocaleDescriptor descriptor = new LocaleDescriptor(tag);
 
@@ -257,17 +258,17 @@ public class LocaleListPreference extend
         BrowserLocaleManager.getInstance().updateConfiguration(context, selectedLocale);
     }
 
     private Locale getSelectedLocale() {
         final String tag = getValue();
         if (tag == null || tag.equals("")) {
             return Locale.getDefault();
         }
-        return BrowserLocaleManager.parseLocaleCode(tag);
+        return Locales.parseLocaleCode(tag);
     }
 
     @Override
     public CharSequence getSummary() {
         final String value = getValue();
 
         if (TextUtils.isEmpty(value)) {
             return getContext().getString(R.string.locale_system_default);
--- a/mobile/android/base/sync/setup/activities/SendTabActivity.java
+++ b/mobile/android/base/sync/setup/activities/SendTabActivity.java
@@ -22,17 +22,17 @@ import org.mozilla.gecko.sync.CommandPro
 import org.mozilla.gecko.sync.CommandRunner;
 import org.mozilla.gecko.sync.GlobalSession;
 import org.mozilla.gecko.sync.SyncConfiguration;
 import org.mozilla.gecko.sync.SyncConstants;
 import org.mozilla.gecko.sync.repositories.NullCursorException;
 import org.mozilla.gecko.sync.repositories.android.ClientsDatabaseAccessor;
 import org.mozilla.gecko.sync.repositories.domain.ClientRecord;
 import org.mozilla.gecko.sync.setup.SyncAccounts;
-import org.mozilla.gecko.LocaleAware.LocaleAwareActivity;
+import org.mozilla.gecko.Locales.LocaleAwareActivity;
 import org.mozilla.gecko.sync.syncadapter.SyncAdapter;
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
--- a/mobile/android/base/tabs/PrivateTabsPanel.java
+++ b/mobile/android/base/tabs/PrivateTabsPanel.java
@@ -2,17 +2,17 @@
  * 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/. */
 
 package org.mozilla.gecko.tabs;
 
 import java.util.Locale;
 
-import org.mozilla.gecko.BrowserLocaleManager;
+import org.mozilla.gecko.Locales;
 import org.mozilla.gecko.NewTabletUI;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.Tabs;
 import org.mozilla.gecko.tabs.TabsPanel.CloseAllPanelView;
 import org.mozilla.gecko.tabs.TabsPanel.TabsLayout;
 
 import android.content.Context;
 import android.content.res.Resources;
@@ -53,17 +53,17 @@ class PrivateTabsPanel extends FrameLayo
 
         emptyTabsFrame = (LinearLayout) findViewById(R.id.private_tabs_empty);
         tabsLayout.setEmptyView(emptyTabsFrame);
 
         final View learnMore = findViewById(R.id.private_tabs_learn_more);
         learnMore.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
-                final String locale = BrowserLocaleManager.getLanguageTag(Locale.getDefault());
+                final String locale = Locales.getLanguageTag(Locale.getDefault());
                 final String url =
                         getResources().getString(R.string.private_tabs_panel_learn_more_link, locale);
                 Tabs.getInstance().loadUrlInTab(url);
                 if (tabsPanel != null) {
                     tabsPanel.autoHidePanel();
                 }
             }
         });
--- a/mobile/android/base/tests/testOSLocale.java
+++ b/mobile/android/base/tests/testOSLocale.java
@@ -5,16 +5,17 @@
 package org.mozilla.gecko.tests;
 
 import java.util.Locale;
 
 import org.mozilla.gecko.BrowserLocaleManager;
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.GeckoEvent;
 import org.mozilla.gecko.GeckoSharedPrefs;
+import org.mozilla.gecko.Locales;
 import org.mozilla.gecko.PrefsHelper;
 
 import android.content.SharedPreferences;
 
 
 public class testOSLocale extends BaseTest {
     @Override
     public void setUp() throws Exception {
@@ -85,17 +86,17 @@ public class testOSLocale extends BaseTe
         // If we cleared the pref above prior to BrowserApp's delayed init, or our Gecko
         // profile has been used before, then we're already going to be set up for en-US.
         //
         // If we cleared the pref after the initial broadcast, and our Android-side profile
         // has been used before but the Gecko profile is clean, then the Gecko prefs won't
         // have been set.
         //
         // Instead, we always send a new locale code, and see what we get.
-        final Locale fr = BrowserLocaleManager.parseLocaleCode("fr");
+        final Locale fr = Locales.parseLocaleCode("fr");
         BrowserLocaleManager.storeAndNotifyOSLocale(prefs, fr);
 
         state.fetch();
 
         mAsserter.is(state.osLocale, "fr", "We're in fr.");
 
         // Now we can see what the expected Accept-Languages header should be.
         // The OS locale is 'fr', so we have our app locale (en-US),
@@ -120,17 +121,17 @@ public class testOSLocale extends BaseTe
         // Expected, from es-ES's intl.properties:
         final String EXPECTED = SELECTED_LOCALES +
                                 (isMultiLocaleBuild ? "es,en-us,en" :  // Expected, from es-ES's intl.properties.
                                                       "en-us,en");     // Expected, from en-US (the default).
 
         mAsserter.is(state.acceptLanguages, EXPECTED, "We have the right es-ES+fr Accept-Languages for this build.");
 
         // And back to en-US.
-        final Locale en_US = BrowserLocaleManager.parseLocaleCode("en-US");
+        final Locale en_US = Locales.parseLocaleCode("en-US");
         BrowserLocaleManager.storeAndNotifyOSLocale(prefs, en_US);
         BrowserLocaleManager.getInstance().resetToSystemLocale(getActivity());
 
         state.fetch();
 
         mAsserter.is(state.osLocale, "en-US", "We're in en-US.");
         mAsserter.is(state.acceptLanguages, "en-us,en", "We have the default processed en-US Accept-Languages.");
     }
--- a/mobile/android/search/java/org/mozilla/search/SearchActivity.java
+++ b/mobile/android/search/java/org/mozilla/search/SearchActivity.java
@@ -1,16 +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/. */
 
 package org.mozilla.search;
 
 import org.mozilla.gecko.GeckoAppShell;
-import org.mozilla.gecko.LocaleAware;
+import org.mozilla.gecko.Locales;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.gecko.db.BrowserContract.SearchHistory;
 import org.mozilla.gecko.distribution.Distribution;
 import org.mozilla.gecko.health.BrowserHealthRecorder;
 import org.mozilla.search.autocomplete.SearchBar;
 import org.mozilla.search.autocomplete.SuggestionsFragment;
@@ -34,17 +34,17 @@ import com.nineoldandroids.animation.Ani
 import com.nineoldandroids.animation.ObjectAnimator;
 
 /**
  * The main entrance for the Android search intent.
  * <p/>
  * State management is delegated to child fragments. Fragments communicate
  * with each other by passing messages through this activity.
  */
-public class SearchActivity extends LocaleAware.LocaleAwareFragmentActivity
+public class SearchActivity extends Locales.LocaleAwareFragmentActivity
         implements AcceptsSearchQuery, SearchEngineCallback {
 
     private static final String LOGTAG = "GeckoSearchActivity";
 
     private static final String KEY_SEARCH_STATE = "search_state";
     private static final String KEY_EDIT_STATE = "edit_state";
     private static final String KEY_QUERY = "query";
 
--- a/mobile/android/search/java/org/mozilla/search/SearchPreferenceActivity.java
+++ b/mobile/android/search/java/org/mozilla/search/SearchPreferenceActivity.java
@@ -1,16 +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/. */
 
 package org.mozilla.search;
 
 import org.mozilla.gecko.GeckoSharedPrefs;
-import org.mozilla.gecko.LocaleAware;
+import org.mozilla.gecko.Locales;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.gecko.db.BrowserContract;
 
 import android.app.AlertDialog;
 import android.content.DialogInterface;
 import android.os.AsyncTask;
@@ -36,17 +36,17 @@ public class SearchPreferenceActivity ex
 
     private static final String LOG_TAG = "SearchPreferenceActivity";
 
     public static final String PREF_CLEAR_HISTORY_KEY = "search.not_a_preference.clear_history";
 
     @Override
     @SuppressWarnings("deprecation")
     protected void onCreate(Bundle savedInstanceState) {
-        LocaleAware.initializeLocale(getApplicationContext());
+        Locales.initializeLocale(getApplicationContext());
         super.onCreate(savedInstanceState);
 
         getPreferenceManager().setSharedPreferencesName(GeckoSharedPrefs.APP_PREFS_NAME);
 
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
             if (getActionBar() != null) {
                 getActionBar().setDisplayHomeAsUpEnabled(true);
             }
--- a/mobile/android/search/java/org/mozilla/search/providers/SearchEngineManager.java
+++ b/mobile/android/search/java/org/mozilla/search/providers/SearchEngineManager.java
@@ -7,19 +7,19 @@ package org.mozilla.search.providers;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.text.TextUtils;
 import android.util.Log;
 
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.mozilla.gecko.AppConstants;
-import org.mozilla.gecko.BrowserLocaleManager;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.GeckoSharedPrefs;
+import org.mozilla.gecko.Locales;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.util.FileUtils;
 import org.mozilla.gecko.util.GeckoJarReader;
 import org.mozilla.gecko.util.RawResource;
 import org.mozilla.gecko.util.ThreadUtils;
 import org.mozilla.gecko.distribution.Distribution;
 import org.mozilla.search.Constants;
 import org.xmlpull.v1.XmlPullParserException;
@@ -183,17 +183,17 @@ public class SearchEngineManager impleme
         if (prefFile == null) {
             return null;
         }
 
         try {
             final JSONObject all = new JSONObject(FileUtils.getFileContents(prefFile));
 
             // First, check to see if there's a locale-specific override.
-            final String languageTag = BrowserLocaleManager.getLanguageTag(Locale.getDefault());
+            final String languageTag = Locales.getLanguageTag(Locale.getDefault());
             final String overridesKey = "LocalizablePreferences." + languageTag;
             if (all.has(overridesKey)) {
                 final JSONObject overridePrefs = all.getJSONObject(overridesKey);
                 if (overridePrefs.has(PREF_GECKO_DEFAULT_ENGINE)) {
                     Log.d(LOG_TAG, "Found default engine name in distribution LocalizablePreferences override.");
                     return overridePrefs.getString(PREF_GECKO_DEFAULT_ENGINE);
                 }
             }
@@ -416,26 +416,26 @@ public class SearchEngineManager impleme
      *
      * @param fileName name of the file to read.
      * @return InputStream for file.
      */
     private InputStream getInputStreamFromSearchPluginsJar(String fileName) {
         final Locale locale = Locale.getDefault();
 
         // First, try a file path for the full locale.
-        final String languageTag = BrowserLocaleManager.getLanguageTag(locale);
+        final String languageTag = Locales.getLanguageTag(locale);
         String url = getSearchPluginsJarURL(languageTag, fileName);
 
         InputStream in = GeckoJarReader.getStream(url);
         if (in != null) {
             return in;
         }
 
         // If that doesn't work, try a file path for just the language.
-        final String language = BrowserLocaleManager.getLanguage(locale);
+        final String language = Locales.getLanguage(locale);
         if (!languageTag.equals(language)) {
             url = getSearchPluginsJarURL(language, fileName);
             in = GeckoJarReader.getStream(url);
             if (in != null) {
                 return in;
             }
         }
 
--- a/mobile/android/tests/browser/junit3/src/TestSuggestedSites.java
+++ b/mobile/android/tests/browser/junit3/src/TestSuggestedSites.java
@@ -91,17 +91,17 @@ public class TestSuggestedSites extends 
         public TestDistribution(Context context) {
             super(context);
             this.filesPerLocale = new HashMap<Locale, File>();
         }
 
         @Override
         public File getDistributionFile(String name) {
             for (Locale locale : filesPerLocale.keySet()) {
-                if (name.startsWith("suggestedsites/locales/" + BrowserLocaleManager.getLanguageTag(locale))) {
+                if (name.startsWith("suggestedsites/locales/" + Locales.getLanguageTag(locale))) {
                     return filesPerLocale.get(locale);
                 }
             }
 
             return null;
         }
 
         @Override