Bug 1378501 - Tell Gecko when the OS locale changes, even when backgrounded. r=mcomella,gandalf
This ensures that `intl.locale.os` is always set, even if the system locale changes
while Fennec is in the background.
This commit also restores `Strings.flush()` calls that are necessary to have Fennec's
non-Java UI reflect locale changes.
With this commit, the geolocation popup still doesn't behave correctly: when the
locale system is set to match OS locale, although the pref is set the locale doesn't
change. This applies in two scenarios: on first run (the popup is always English)
and when the locale changes at runtime (the popup uses an earlier OS locale).
Bug 1397925 should complete the fix.
MozReview-Commit-ID: 8zeZuYXFYdy
--- a/mobile/android/base/java/org/mozilla/gecko/BrowserLocaleManager.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserLocaleManager.java
@@ -101,16 +101,20 @@ public class BrowserLocaleManager implem
// habit of mutating it! Use the one Android supplies, because
// that gets regularly reset.
// The default value of systemLocale is fine, because we haven't
// yet swizzled Locale during static initialization.
systemLocale = context.getResources().getConfiguration().locale;
systemLocaleDidChange = true;
Log.d(LOG_TAG, "System locale changed from " + current + " to " + systemLocale);
+
+ // If the OS locale changed, we need to tell Gecko.
+ final SharedPreferences prefs = GeckoSharedPrefs.forProfile(context);
+ BrowserLocaleManager.storeAndNotifyOSLocale(prefs, systemLocale);
}
};
context.registerReceiver(receiver, new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
}
@Override
public boolean systemLocaleDidChange() {
return systemLocaleDidChange;
@@ -203,26 +207,28 @@ public class BrowserLocaleManager implem
if (osLocale == null) {
return;
}
final String lastOSLocale = prefs.getString("osLocale", null);
final String osLocaleString = osLocale.toString();
if (osLocaleString.equals(lastOSLocale)) {
+ Log.d(LOG_TAG, "Previous locale " + lastOSLocale + " same as new. Doing nothing.");
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 GeckoBundle data = new GeckoBundle(1);
data.putString("languageTag", Locales.getLanguageTag(osLocale));
+
EventDispatcher.getInstance().dispatch("Locale:OS", data);
}
@Override
public String getAndApplyPersistedLocale(Context context) {
initialize(context);
final long t1 = android.os.SystemClock.uptimeMillis();
@@ -299,16 +305,20 @@ public class BrowserLocaleManager implem
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
config.setLayoutDirection(locale);
}
res.updateConfiguration(config, null);
}
private SharedPreferences getSharedPreferences(Context context) {
+ // We should be using per-profile prefs here, because we're tracking against
+ // a Gecko pref. The same applies to the locale switcher!
+ // Bug 940575, Bug 873166 are relevant, and see Bug 1378501 for the commit
+ // that added this comment.
return GeckoSharedPrefs.forApp(context);
}
/**
* @return the persisted locale in Java format: "en_US".
*/
private String getPersistedLocale(Context context) {
final SharedPreferences settings = getSharedPreferences(context);
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -1737,26 +1737,34 @@ var BrowserApp = {
// Ensure that this choice is immediately persisted, because
// Gecko won't be told again if it forgets.
Services.prefs.setCharPref("intl.locale.os", languageTag);
Services.prefs.savePrefFile(null);
let appLocale = this.getUALocalePref();
this.computeAcceptLanguages(languageTag, appLocale);
+
+ // Rebuild strings, in case we're mirroring OS locale.
+ Strings.flush();
break;
}
case "Locale:Changed": {
if (data) {
Services.locale.setRequestedLocales([data.languageTag]);
} else {
Services.locale.setRequestedLocales([]);
}
+ console.log("Gecko display locale: " + this.getUALocalePref());
+
+ // Rebuild strings to reflect the new locale.
+ Strings.flush();
+
// Make sure we use the right Accept-Language header.
let osLocale;
try {
// This should never not be set at this point, but better safe than sorry.
osLocale = Services.prefs.getCharPref("intl.locale.os");
} catch (e) {
}