mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 917480 - Part 2: add 'Language' section to top-level preferences, allowing for browser locale switching. r=nalexander
* * * Bug 917480 - Part 2d: compute locale list at build time.
This commit is contained in:
parent
6019732cbe
commit
fb4045eb34
@ -302,7 +302,6 @@
|
||||
|
||||
<activity android:name="org.mozilla.gecko.preferences.GeckoPreferences"
|
||||
android:theme="@style/Gecko.Preferences"
|
||||
android:label="@string/settings_title"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:excludeFromRecents="true"/>
|
||||
|
||||
|
@ -9,6 +9,7 @@ import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.json.JSONArray;
|
||||
@ -132,6 +133,10 @@ abstract public class BrowserApp extends GeckoApp
|
||||
private static final String STATE_ABOUT_HOME_TOP_PADDING = "abouthome_top_padding";
|
||||
|
||||
private static final String BROWSER_SEARCH_TAG = "browser_search";
|
||||
|
||||
// Request ID for startActivityForResult.
|
||||
private static final int ACTIVITY_REQUEST_PREFERENCES = 1001;
|
||||
|
||||
private BrowserSearch mBrowserSearch;
|
||||
private View mBrowserSearchContainer;
|
||||
|
||||
@ -1288,7 +1293,7 @@ abstract public class BrowserApp extends GeckoApp
|
||||
}
|
||||
Intent settingsIntent = new Intent(this, GeckoPreferences.class);
|
||||
GeckoPreferences.setResourceToOpen(settingsIntent, resource);
|
||||
startActivity(settingsIntent);
|
||||
startActivityForResult(settingsIntent, ACTIVITY_REQUEST_PREFERENCES);
|
||||
} else if (event.equals("Updater:Launch")) {
|
||||
handleUpdaterLaunch();
|
||||
} else if (event.equals("Prompt:ShowTop")) {
|
||||
@ -1754,6 +1759,7 @@ abstract public class BrowserApp extends GeckoApp
|
||||
|
||||
@Override
|
||||
public void onLocaleReady(final String locale) {
|
||||
Log.d(LOGTAG, "onLocaleReady: " + locale);
|
||||
super.onLocaleReady(locale);
|
||||
|
||||
HomePanelsManager.getInstance().onLocaleReady(locale);
|
||||
@ -1764,6 +1770,35 @@ abstract public class BrowserApp extends GeckoApp
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
Log.d(LOGTAG, "onActivityResult: " + requestCode + ", " + resultCode + ", " + data);
|
||||
switch (requestCode) {
|
||||
case ACTIVITY_REQUEST_PREFERENCES:
|
||||
// We just returned from preferences. If our locale changed,
|
||||
// we need to redisplay at this point, and do any other browser-level
|
||||
// bookkeeping that we associate with a locale change.
|
||||
if (resultCode != GeckoPreferences.RESULT_CODE_LOCALE_DID_CHANGE) {
|
||||
Log.d(LOGTAG, "No locale change returning from preferences; nothing to do.");
|
||||
return;
|
||||
}
|
||||
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final LocaleManager localeManager = BrowserLocaleManager.getInstance();
|
||||
final Locale locale = localeManager.getCurrentLocale(getApplicationContext());
|
||||
Log.d(LOGTAG, "Persisted locale was " + locale);
|
||||
onLocaleChanged(BrowserLocaleManager.getLanguageTag(locale));
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void showHomePager(String panelId) {
|
||||
showHomePagerWithAnimator(panelId, null);
|
||||
}
|
||||
@ -2420,7 +2455,10 @@ abstract public class BrowserApp extends GeckoApp
|
||||
|
||||
if (itemId == R.id.settings) {
|
||||
intent = new Intent(this, GeckoPreferences.class);
|
||||
startActivity(intent);
|
||||
|
||||
// We want to know when the Settings activity returns, because
|
||||
// we might need to redisplay based on a locale change.
|
||||
startActivityForResult(intent, ACTIVITY_REQUEST_PREFERENCES);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -14,10 +14,19 @@ import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.util.GeckoJarReader;
|
||||
|
||||
/**
|
||||
* This class manages persistence, application, and otherwise handling of
|
||||
* user-specified locales.
|
||||
@ -39,6 +48,8 @@ public class BrowserLocaleManager implements LocaleManager {
|
||||
private static final String EVENT_LOCALE_CHANGED = "Locale:Changed";
|
||||
private static final String PREF_LOCALE = "locale";
|
||||
|
||||
private static final String FALLBACK_LOCALE_TAG = "en-US";
|
||||
|
||||
// This is volatile because we don't impose restrictions
|
||||
// over which thread calls our methods.
|
||||
private volatile Locale currentLocale = null;
|
||||
@ -92,7 +103,7 @@ public class BrowserLocaleManager implements LocaleManager {
|
||||
return language + "-" + country;
|
||||
}
|
||||
|
||||
private static Locale parseLocaleCode(final String localeCode) {
|
||||
public static Locale parseLocaleCode(final String localeCode) {
|
||||
int index;
|
||||
if ((index = localeCode.indexOf('-')) != -1 ||
|
||||
(index = localeCode.indexOf('_')) != -1) {
|
||||
@ -244,7 +255,8 @@ public class BrowserLocaleManager implements LocaleManager {
|
||||
settings.edit().putString(PREF_LOCALE, localeCode).commit();
|
||||
}
|
||||
|
||||
private Locale getCurrentLocale(Context context) {
|
||||
@Override
|
||||
public Locale getCurrentLocale(Context context) {
|
||||
if (currentLocale != null) {
|
||||
return currentLocale;
|
||||
}
|
||||
@ -285,4 +297,67 @@ public class BrowserLocaleManager implements LocaleManager {
|
||||
|
||||
return locale.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Examines <code>multilocale.json</code>, returning the included list of
|
||||
* locale codes.
|
||||
*
|
||||
* If <code>multilocale.json</code> is not present, returns
|
||||
* <code>null</code>. In that case, consider {@link #getFallbackLocaleTag()}.
|
||||
*
|
||||
* multilocale.json currently looks like this:
|
||||
*
|
||||
* <code>
|
||||
* {"locales": ["en-US", "be", "ca", "cs", "da", "de", "en-GB",
|
||||
* "en-ZA", "es-AR", "es-ES", "es-MX", "et", "fi",
|
||||
* "fr", "ga-IE", "hu", "id", "it", "ja", "ko",
|
||||
* "lt", "lv", "nb-NO", "nl", "pl", "pt-BR",
|
||||
* "pt-PT", "ro", "ru", "sk", "sl", "sv-SE", "th",
|
||||
* "tr", "uk", "zh-CN", "zh-TW", "en-US"]}
|
||||
* </code>
|
||||
*/
|
||||
public static Collection<String> getPackagedLocaleTags(final Context context) {
|
||||
final String resPath = "res/multilocale.json";
|
||||
final String apkPath = context.getPackageResourcePath();
|
||||
|
||||
final String jarURL = "jar:jar:" + new File(apkPath).toURI() + "!/" +
|
||||
AppConstants.OMNIJAR_NAME + "!/" +
|
||||
resPath;
|
||||
|
||||
final String contents = GeckoJarReader.getText(jarURL);
|
||||
if (contents == null) {
|
||||
// GeckoJarReader logs and swallows exceptions.
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
final JSONObject multilocale = new JSONObject(contents);
|
||||
final JSONArray locales = multilocale.getJSONArray("locales");
|
||||
if (locales == null) {
|
||||
Log.e(LOG_TAG, "No 'locales' array in multilocales.json!");
|
||||
return null;
|
||||
}
|
||||
|
||||
final Set<String> out = new HashSet<String>(locales.length());
|
||||
for (int i = 0; i < locales.length(); ++i) {
|
||||
// If any item in the array is invalid, this will throw,
|
||||
// and the entire clause will fail, being caught below
|
||||
// and returning null.
|
||||
out.add(locales.getString(i));
|
||||
}
|
||||
|
||||
return out;
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOG_TAG, "Unable to parse multilocale.json.", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the single default locale baked into this application.
|
||||
* Applicable when there is no multilocale.json present.
|
||||
*/
|
||||
public static String getFallbackLocaleTag() {
|
||||
return FALLBACK_LOCALE_TAG;
|
||||
}
|
||||
}
|
||||
|
@ -2712,18 +2712,12 @@ public abstract class GeckoApp
|
||||
private static final String SESSION_END_LOCALE_CHANGED = "L";
|
||||
|
||||
/**
|
||||
* Use BrowserLocaleManager to change our persisted and current locales,
|
||||
* and poke HealthRecorder to tell it of our changed state.
|
||||
* This exists so that a locale can be applied in two places: when saved
|
||||
* in a nested activity, and then again when we get back up to GeckoApp.
|
||||
*
|
||||
* GeckoApp needs to do a bunch more stuff than, say, GeckoPreferences.
|
||||
*/
|
||||
private void setLocale(final String locale) {
|
||||
if (locale == null) {
|
||||
return;
|
||||
}
|
||||
final String resultant = BrowserLocaleManager.getInstance().setSelectedLocale(this, locale);
|
||||
if (resultant == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
protected void onLocaleChanged(final String locale) {
|
||||
final boolean startNewSession = true;
|
||||
final boolean shouldRestart = false;
|
||||
|
||||
@ -2732,7 +2726,7 @@ public abstract class GeckoApp
|
||||
// with the wrong locale.
|
||||
final HealthRecorder rec = mHealthRecorder;
|
||||
if (rec != null) {
|
||||
rec.onAppLocaleChanged(resultant);
|
||||
rec.onAppLocaleChanged(locale);
|
||||
rec.onEnvironmentChanged(startNewSession, SESSION_END_LOCALE_CHANGED);
|
||||
}
|
||||
|
||||
@ -2740,7 +2734,7 @@ public abstract class GeckoApp
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GeckoApp.this.onLocaleReady(resultant);
|
||||
GeckoApp.this.onLocaleReady(locale);
|
||||
}
|
||||
});
|
||||
return;
|
||||
@ -2757,6 +2751,24 @@ public abstract class GeckoApp
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Use BrowserLocaleManager to change our persisted and current locales,
|
||||
* and poke HealthRecorder to tell it of our changed state.
|
||||
*/
|
||||
protected void setLocale(final String locale) {
|
||||
Log.d(LOGTAG, "setLocale: " + locale);
|
||||
if (locale == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String resultant = BrowserLocaleManager.getInstance().setSelectedLocale(this, locale);
|
||||
if (resultant == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
onLocaleChanged(resultant);
|
||||
}
|
||||
|
||||
private void setSystemUiVisible(final boolean visible) {
|
||||
if (Build.VERSION.SDK_INT < 14) {
|
||||
return;
|
||||
|
@ -12,6 +12,7 @@ import android.content.res.Resources;
|
||||
|
||||
public interface LocaleManager {
|
||||
void initialize(Context context);
|
||||
Locale getCurrentLocale(Context context);
|
||||
String getAndApplyPersistedLocale(Context context);
|
||||
void correctLocale(Context context, Resources resources, Configuration newConfig);
|
||||
void updateConfiguration(Context context, Locale locale);
|
||||
|
@ -67,6 +67,18 @@
|
||||
<!ENTITY settings_title "Settings">
|
||||
<!ENTITY pref_category_advanced "Advanced">
|
||||
<!ENTITY pref_category_customize "Customize">
|
||||
|
||||
<!-- Localization note (pref_category_language) : This is the preferences
|
||||
section in which the user picks the locale in which to display Firefox
|
||||
UI. The locale includes both language and region concepts. -->
|
||||
<!ENTITY pref_category_language "Language">
|
||||
<!ENTITY pref_browser_locale "Browser language">
|
||||
|
||||
<!-- Localization note (locale_system_default) : This string indicates that
|
||||
Firefox will use the locale currently selected in Android's settings
|
||||
to display browser chrome. -->
|
||||
<!ENTITY locale_system_default "System default">
|
||||
|
||||
<!ENTITY pref_category_search3 "Search">
|
||||
<!ENTITY pref_category_search_summary "Customize your search providers">
|
||||
<!ENTITY pref_category_display "Display">
|
||||
|
@ -323,6 +323,7 @@ gbjar.sources += [
|
||||
'preferences/GeckoPreferenceFragment.java',
|
||||
'preferences/GeckoPreferences.java',
|
||||
'preferences/LinkPreference.java',
|
||||
'preferences/LocaleListPreference.java',
|
||||
'preferences/ModifiableHintPreference.java',
|
||||
'preferences/MultiChoicePreference.java',
|
||||
'preferences/PanelsPreference.java',
|
||||
|
@ -6,12 +6,18 @@
|
||||
package org.mozilla.gecko.preferences;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.mozilla.gecko.BrowserLocaleManager;
|
||||
import org.mozilla.gecko.GeckoSharedPrefs;
|
||||
import org.mozilla.gecko.PrefsHelper;
|
||||
import org.mozilla.gecko.R;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceFragment;
|
||||
@ -29,6 +35,7 @@ public class GeckoPreferenceFragment extends PreferenceFragment {
|
||||
|
||||
private static final String LOGTAG = "GeckoPreferenceFragment";
|
||||
private int mPrefsRequestId = 0;
|
||||
private Locale lastLocale = Locale.getDefault();
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@ -51,6 +58,64 @@ public class GeckoPreferenceFragment extends PreferenceFragment {
|
||||
mPrefsRequestId = ((GeckoPreferences)getActivity()).setupPreferences(screen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the title to use for this preference fragment. This allows
|
||||
* for us to redisplay this fragment in a different locale.
|
||||
*
|
||||
* We only return titles for the preference screens that are in the
|
||||
* flow for selecting a locale, and thus might need to be redisplayed.
|
||||
*/
|
||||
protected String getTitle() {
|
||||
final int res = getResource();
|
||||
if (res == R.xml.preferences_locale) {
|
||||
return getString(R.string.pref_category_language);
|
||||
}
|
||||
|
||||
if (res == R.xml.preferences) {
|
||||
return getString(R.string.settings_title);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void updateTitle() {
|
||||
final String newTitle = getTitle();
|
||||
if (newTitle != null) {
|
||||
final Activity activity = getActivity();
|
||||
|
||||
Log.v(LOGTAG, "Setting activity title to " + newTitle);
|
||||
activity.setTitle(newTitle);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 14) {
|
||||
final ActionBar actionBar = activity.getActionBar();
|
||||
actionBar.setTitle(newTitle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
final Locale currentLocale = Locale.getDefault();
|
||||
final Context context = getActivity().getApplicationContext();
|
||||
|
||||
BrowserLocaleManager.getInstance().updateConfiguration(context, currentLocale);
|
||||
|
||||
if (!currentLocale.equals(lastLocale)) {
|
||||
// Locales differ. Let's redisplay.
|
||||
Log.d(LOGTAG, "Locale changed: " + currentLocale);
|
||||
this.lastLocale = currentLocale;
|
||||
|
||||
// Rebuild the list to reflect the current locale.
|
||||
getPreferenceScreen().removeAll();
|
||||
addPreferencesFromResource(getResource());
|
||||
}
|
||||
|
||||
// Fix the parent title regardless.
|
||||
updateTitle();
|
||||
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the resource from Fragment arguments and return it.
|
||||
*
|
||||
@ -59,19 +124,21 @@ public class GeckoPreferenceFragment extends PreferenceFragment {
|
||||
private int getResource() {
|
||||
int resid = 0;
|
||||
|
||||
String resourceName = getArguments().getString("resource");
|
||||
final String resourceName = getArguments().getString("resource");
|
||||
final Activity activity = getActivity();
|
||||
|
||||
if (resourceName != null) {
|
||||
// Fetch resource id by resource name.
|
||||
resid = getActivity().getResources().getIdentifier(resourceName,
|
||||
"xml",
|
||||
getActivity().getPackageName());
|
||||
final Resources resources = activity.getResources();
|
||||
final String packageName = activity.getPackageName();
|
||||
resid = resources.getIdentifier(resourceName, "xml", packageName);
|
||||
}
|
||||
|
||||
if (resid == 0) {
|
||||
// The resource was invalid. Use the default resource.
|
||||
Log.e(LOGTAG, "Failed to find resource: " + resourceName + ". Displaying default settings.");
|
||||
|
||||
boolean isMultiPane = ((PreferenceActivity) getActivity()).onIsMultiPane();
|
||||
boolean isMultiPane = ((PreferenceActivity) activity).onIsMultiPane();
|
||||
resid = isMultiPane ? R.xml.preferences_customize_tablet : R.xml.preferences;
|
||||
}
|
||||
|
||||
|
@ -7,18 +7,21 @@ package org.mozilla.gecko.preferences;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
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.GeckoApp;
|
||||
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.LocaleManager;
|
||||
import org.mozilla.gecko.PrefsHelper;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.announcements.AnnouncementsConstants;
|
||||
@ -28,6 +31,7 @@ import org.mozilla.gecko.home.HomePanelPicker;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
@ -104,8 +108,79 @@ public class GeckoPreferences
|
||||
private static final int REQUEST_CODE_PREF_SCREEN = 5;
|
||||
private static final int RESULT_CODE_EXIT_SETTINGS = 6;
|
||||
|
||||
// Result code used when a locale preference changes.
|
||||
// Callers can recognize this code to refresh themselves to
|
||||
// accommodate a locale change.
|
||||
public static final int RESULT_CODE_LOCALE_DID_CHANGE = 7;
|
||||
|
||||
/**
|
||||
* Track the last locale so we know whether to redisplay.
|
||||
*/
|
||||
private Locale lastLocale = Locale.getDefault();
|
||||
|
||||
private void updateTitle(int title) {
|
||||
// Due to locale switching, we need to dynamically impose the title on
|
||||
// the default preferences view.
|
||||
|
||||
final String newTitle = getString(title);
|
||||
if (newTitle != null) {
|
||||
Log.v(LOGTAG, "Setting activity title to " + newTitle);
|
||||
setTitle(newTitle);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 14) {
|
||||
final ActionBar actionBar = getActionBar();
|
||||
actionBar.setTitle(newTitle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTitleForPrefsResource(int res) {
|
||||
// At present we only need to do this for the top-level prefs view
|
||||
// and the locale switcher itself.
|
||||
// The others don't allow you to change locales, and have their
|
||||
// titles set in their fragment descriptors.
|
||||
if (res == R.xml.preferences) {
|
||||
updateTitle(R.string.settings_title);
|
||||
return;
|
||||
}
|
||||
|
||||
if (res == R.xml.preferences_locale) {
|
||||
updateTitle(R.string.pref_category_language);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void onLocaleChanged(Locale newLocale) {
|
||||
Log.d(LOGTAG, "onLocaleChanged: " + newLocale);
|
||||
|
||||
BrowserLocaleManager.getInstance().updateConfiguration(getApplicationContext(), newLocale);
|
||||
this.lastLocale = newLocale;
|
||||
|
||||
// Cause the current fragment to redisplay, the hard way.
|
||||
// This avoids nonsense with trying to reach inside fragments and force them
|
||||
// to redisplay themselves.
|
||||
// We also don't need to update the title.
|
||||
final Intent intent = (Intent) getIntent().clone();
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||
startActivityForResult(intent, REQUEST_CODE_PREF_SCREEN);
|
||||
|
||||
setResult(RESULT_CODE_LOCALE_DID_CHANGE);
|
||||
finish();
|
||||
}
|
||||
|
||||
private void checkLocale() {
|
||||
final Locale currentLocale = Locale.getDefault();
|
||||
if (currentLocale.equals(lastLocale)) {
|
||||
return;
|
||||
}
|
||||
|
||||
onLocaleChanged(currentLocale);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
// Apply the current user-selected locale, if necessary.
|
||||
checkLocale();
|
||||
|
||||
// For Android v11+ where we use Fragments (v11+ only due to bug 866352),
|
||||
// check that PreferenceActivity.EXTRA_SHOW_FRAGMENT has been set
|
||||
@ -146,6 +221,9 @@ public class GeckoPreferences
|
||||
Log.e(LOGTAG, "Displaying default settings.");
|
||||
res = R.xml.preferences;
|
||||
}
|
||||
|
||||
// We don't include a title in the XML, so set it here, in a locale-aware fashion.
|
||||
updateTitleForPrefsResource(res);
|
||||
addPreferencesFromResource(res);
|
||||
}
|
||||
|
||||
@ -171,8 +249,14 @@ public class GeckoPreferences
|
||||
}
|
||||
});
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 14)
|
||||
getActionBar().setHomeButtonEnabled(true);
|
||||
if (Build.VERSION.SDK_INT >= 14) {
|
||||
final ActionBar actionBar = getActionBar();
|
||||
actionBar.setHomeButtonEnabled(true);
|
||||
}
|
||||
|
||||
// N.B., if we ever need to redisplay the locale selection UI without
|
||||
// just finishing and recreating the activity, right here we'll need to
|
||||
// capture EXTRA_SHOW_FRAGMENT_TITLE from the intent and store the title ID.
|
||||
|
||||
// If launched from notification, explicitly cancel the notification.
|
||||
if (intentExtras != null && intentExtras.containsKey(DataReportingNotification.ALERT_NAME_DATAREPORTING_NOTIFICATION)) {
|
||||
@ -182,7 +266,8 @@ public class GeckoPreferences
|
||||
}
|
||||
|
||||
/**
|
||||
* Set intent to display top-level settings fragment.
|
||||
* Set intent to display top-level settings fragment,
|
||||
* and show the correct title.
|
||||
*/
|
||||
private void setupTopLevelFragmentIntent() {
|
||||
Intent intent = getIntent();
|
||||
@ -205,6 +290,9 @@ public class GeckoPreferences
|
||||
// Build fragment intent.
|
||||
intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, GeckoPreferenceFragment.class.getName());
|
||||
intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS, fragmentArgs);
|
||||
|
||||
// Show the title for the top level.
|
||||
updateTitle(R.string.settings_title);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -267,6 +355,8 @@ public class GeckoPreferences
|
||||
@Override
|
||||
public void startWithFragment(String fragmentName, Bundle args,
|
||||
Fragment resultTo, int resultRequestCode, int titleRes, int shortTitleRes) {
|
||||
Log.v(LOGTAG, "Starting with fragment: " + fragmentName + ", title " + titleRes);
|
||||
|
||||
// Overriding because we want to use startActivityForResult for Fragment intents.
|
||||
Intent intent = onBuildStartFragmentIntent(fragmentName, args, titleRes, shortTitleRes);
|
||||
if (resultTo == null) {
|
||||
@ -278,6 +368,10 @@ public class GeckoPreferences
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
// We might have just returned from a settings activity that allows us
|
||||
// to switch locales, so reflect any change that occurred.
|
||||
checkLocale();
|
||||
|
||||
switch (requestCode) {
|
||||
case REQUEST_CODE_PREF_SCREEN:
|
||||
if (resultCode == RESULT_CODE_EXIT_SETTINGS) {
|
||||
@ -290,8 +384,8 @@ public class GeckoPreferences
|
||||
case HomePanelPicker.REQUEST_CODE_ADD_PANEL:
|
||||
switch (resultCode) {
|
||||
case Activity.RESULT_OK:
|
||||
// Panel installed, refresh panels list.
|
||||
mPanelsPreferenceCategory.refresh();
|
||||
// Panel installed, refresh panels list.
|
||||
mPanelsPreferenceCategory.refresh();
|
||||
break;
|
||||
case Activity.RESULT_CANCELED:
|
||||
// Dialog was cancelled, do nothing.
|
||||
@ -403,7 +497,8 @@ public class GeckoPreferences
|
||||
return true;
|
||||
}
|
||||
});
|
||||
} else if (PREFS_RESTORE_SESSION.equals(key)) {
|
||||
} else if (PREFS_RESTORE_SESSION.equals(key) ||
|
||||
PREFS_BROWSER_LOCALE.equals(key)) {
|
||||
// Set the summary string to the current entry. The summary
|
||||
// for other list prefs will be set in the PrefsHelper
|
||||
// callback, but since this pref doesn't live in Gecko, we
|
||||
@ -602,16 +697,74 @@ public class GeckoPreferences
|
||||
return prefs.getBoolean(name, def);
|
||||
}
|
||||
|
||||
/**
|
||||
* Immediately handle the user's selection of a browser locale.
|
||||
*
|
||||
* Earlier locale-handling code did this with centralized logic in
|
||||
* GeckoApp, delegating to LocaleManager for persistence and refreshing
|
||||
* the activity as necessary.
|
||||
*
|
||||
* We no longer handle this by sending a message to GeckoApp, for
|
||||
* several reasons:
|
||||
*
|
||||
* * GeckoApp might not be running. Activities don't always stick around.
|
||||
* A Java bridge message might not be handled.
|
||||
* * We need to adapt the preferences UI to the locale ourselves.
|
||||
* * The user might not hit Back (or Up) -- they might hit Home and never
|
||||
* come back.
|
||||
*
|
||||
* We handle the case of the user returning to the browser via the
|
||||
* onActivityResult mechanism: see {@link BrowserApp#onActivityResult(int, int, Intent)}.
|
||||
*/
|
||||
private boolean onLocaleSelected(final String newValue) {
|
||||
if (newValue.equals("")) {
|
||||
// TODO: reset our locale to match system.
|
||||
return false;
|
||||
}
|
||||
|
||||
final Context context = getApplicationContext();
|
||||
|
||||
// LocaleManager operations need to occur on the background thread.
|
||||
// ... but activity operations need to occur on the UI thread. So we
|
||||
// have nested runnables.
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final LocaleManager localeManager = BrowserLocaleManager.getInstance();
|
||||
if (null == localeManager.setSelectedLocale(context, newValue)) {
|
||||
localeManager.updateConfiguration(context, Locale.getDefault());
|
||||
}
|
||||
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onLocaleChanged(Locale.getDefault());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
String prefName = preference.getKey();
|
||||
final String prefName = preference.getKey();
|
||||
if (PREFS_MP_ENABLED.equals(prefName)) {
|
||||
showDialog((Boolean) newValue ? DIALOG_CREATE_MASTER_PASSWORD : DIALOG_REMOVE_MASTER_PASSWORD);
|
||||
|
||||
// We don't want the "use master password" pref to change until the
|
||||
// user has gone through the dialog.
|
||||
return false;
|
||||
} else if (PREFS_MENU_CHAR_ENCODING.equals(prefName)) {
|
||||
}
|
||||
|
||||
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((String) newValue);
|
||||
}
|
||||
|
||||
if (PREFS_MENU_CHAR_ENCODING.equals(prefName)) {
|
||||
setCharEncodingState(((String) newValue).equals("true"));
|
||||
} else if (PREFS_ANNOUNCEMENTS_ENABLED.equals(prefName)) {
|
||||
// Send a broadcast intent to the product announcements service, either to start or
|
||||
|
106
mobile/android/base/preferences/LocaleListPreference.java
Normal file
106
mobile/android/base/preferences/LocaleListPreference.java
Normal file
@ -0,0 +1,106 @@
|
||||
/* 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.preferences;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.mozilla.gecko.BrowserLocaleManager;
|
||||
import org.mozilla.gecko.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.preference.ListPreference;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
public class LocaleListPreference extends ListPreference {
|
||||
public LocaleListPreference(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public LocaleListPreference(Context context, AttributeSet attributes) {
|
||||
super(context, attributes);
|
||||
buildList();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public LocaleDescriptor(Locale locale, String tag) {
|
||||
this.nativeName = locale.getDisplayName(locale);
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
public String getTag() {
|
||||
return this.tag;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return this.nativeName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.nativeName;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int compareTo(LocaleDescriptor another) {
|
||||
// We sort by name, so we use Collator.
|
||||
return COLLATOR.compare(this.nativeName, another.nativeName);
|
||||
}
|
||||
}
|
||||
|
||||
private LocaleDescriptor[] getShippingLocales() {
|
||||
Collection<String> shippingLocales = BrowserLocaleManager.getPackagedLocaleTags(getContext());
|
||||
|
||||
// Future: single-locale builds should be specified, too.
|
||||
if (shippingLocales == null) {
|
||||
final String fallbackTag = BrowserLocaleManager.getFallbackLocaleTag();
|
||||
return new LocaleDescriptor[] { new LocaleDescriptor(fallbackTag) };
|
||||
}
|
||||
|
||||
final int count = shippingLocales.size();
|
||||
final LocaleDescriptor[] descriptors = new LocaleDescriptor[count];
|
||||
|
||||
int i = 0;
|
||||
for (String tag : shippingLocales) {
|
||||
descriptors[i++] = new LocaleDescriptor(tag);
|
||||
}
|
||||
|
||||
Arrays.sort(descriptors, 0, count);
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
private void buildList() {
|
||||
final LocaleDescriptor[] descriptors = getShippingLocales();
|
||||
final int count = descriptors.length;
|
||||
|
||||
// We leave room for "System default".
|
||||
final String[] entries = new String[count + 1];
|
||||
final String[] values = new String[count + 1];
|
||||
|
||||
entries[0] = getContext().getString(R.string.locale_system_default);
|
||||
values[0] = "";
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
entries[i + 1] = descriptors[i].getDisplayName();
|
||||
values[i + 1] = descriptors[i].getTag();
|
||||
}
|
||||
|
||||
setEntries(entries);
|
||||
setEntryValues(values);
|
||||
}
|
||||
}
|
@ -34,6 +34,11 @@
|
||||
android:value="preferences_privacy" />
|
||||
</PreferenceScreen>
|
||||
|
||||
<PreferenceScreen android:title="@string/pref_category_language"
|
||||
android:fragment="org.mozilla.gecko.preferences.GeckoPreferenceFragment" >
|
||||
<extra android:name="resource"
|
||||
android:value="preferences_locale" />
|
||||
</PreferenceScreen>
|
||||
|
||||
<PreferenceScreen android:title="@string/pref_category_vendor"
|
||||
android:fragment="org.mozilla.gecko.preferences.GeckoPreferenceFragment" >
|
||||
|
@ -45,6 +45,16 @@
|
||||
</intent>
|
||||
</PreferenceScreen>
|
||||
|
||||
<PreferenceScreen android:title="@string/pref_category_language" >
|
||||
<intent android:action="android.intent.action.VIEW"
|
||||
android:targetPackage="@string/android_package_name"
|
||||
android:targetClass="org.mozilla.gecko.preferences.GeckoPreferences" >
|
||||
<extra
|
||||
android:name="resource"
|
||||
android:value="preferences_locale" />
|
||||
</intent>
|
||||
</PreferenceScreen>
|
||||
|
||||
<PreferenceScreen android:title="@string/pref_category_vendor">
|
||||
<intent android:action="android.intent.action.VIEW"
|
||||
android:targetPackage="@string/android_package_name"
|
||||
|
19
mobile/android/base/resources/xml/preferences_locale.xml
Normal file
19
mobile/android/base/resources/xml/preferences_locale.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:gecko="http://schemas.android.com/apk/res-auto"
|
||||
android:title="@string/pref_category_language"
|
||||
android:enabled="false">
|
||||
<PreferenceCategory android:title="@string/pref_browser_locale">
|
||||
<!-- No title set here. We set the title to the current locale in
|
||||
GeckoPreferences. -->
|
||||
<org.mozilla.gecko.preferences.LocaleListPreference
|
||||
android:key="locale"
|
||||
android:persistent="true"
|
||||
android:defaultValue=""
|
||||
/>
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
@ -108,6 +108,10 @@
|
||||
<string name="pref_search_restore_defaults_summary">&pref_search_restore_defaults_summary;</string>
|
||||
<string name="pref_search_hint">&pref_search_hint;</string>
|
||||
|
||||
<string name="pref_category_language">&pref_category_language;</string>
|
||||
<string name="pref_browser_locale">&pref_browser_locale;</string>
|
||||
<string name="locale_system_default">&locale_system_default;</string>
|
||||
|
||||
<string name="pref_category_devtools">&pref_category_devtools;</string>
|
||||
<string name="pref_developer_remotedebugging">&pref_developer_remotedebugging;</string>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user