From 5b6c98e884cda6ba83164ab3708f4535e2d96167 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Fri, 17 Jan 2020 23:36:51 +0100 Subject: [PATCH] Fixes #2670 Language fixes (#2672) * Fix for Pico Taiwanese Chinese locale * Language fixes * Fallback to en-US for Display/Voice when OS language is not supported --- .../vrbrowser/browser/SettingsStore.java | 7 -- .../settings/ContentLanguageOptionsView.java | 13 ++- .../settings/DisplayLanguageOptionsView.java | 2 + .../widgets/settings/LanguageOptionsView.java | 4 +- .../VoiceSearchLanguageOptionsView.java | 27 +++-- .../mozilla/vrbrowser/utils/LocaleUtils.java | 107 ++++++++++++++---- 6 files changed, 115 insertions(+), 45 deletions(-) diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/SettingsStore.java b/app/src/common/shared/org/mozilla/vrbrowser/browser/SettingsStore.java index 8332c067d..c6840b87d 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/SettingsStore.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/SettingsStore.java @@ -17,7 +17,6 @@ import org.mozilla.vrbrowser.telemetry.GleanMetricsService; import org.mozilla.vrbrowser.telemetry.TelemetryWrapper; import org.mozilla.vrbrowser.utils.DeviceType; -import org.mozilla.vrbrowser.utils.LocaleUtils; import org.mozilla.vrbrowser.utils.StringUtils; import org.mozilla.vrbrowser.utils.SystemUtils; @@ -419,9 +418,6 @@ public void setAudioEnabled(boolean isEnabled) { public String getVoiceSearchLocale() { String language = mPrefs.getString( mContext.getString(R.string.settings_key_voice_search_language), null); - if (language == null) { - return LocaleUtils.getDefaultSupportedLocale(); - } return language; } @@ -434,9 +430,6 @@ public void setVoiceSearchLocale(String language) { public String getDisplayLocale() { String language = mPrefs.getString( mContext.getString(R.string.settings_key_display_language), null); - if (language == null) { - return LocaleUtils.getDefaultSupportedLocale(); - } return language; } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/ContentLanguageOptionsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/ContentLanguageOptionsView.java index aeb30096f..a3ac3e156 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/ContentLanguageOptionsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/ContentLanguageOptionsView.java @@ -25,6 +25,7 @@ import org.mozilla.vrbrowser.utils.LocaleUtils; import java.util.Collections; +import java.util.List; public class ContentLanguageOptionsView extends SettingsView { @@ -129,10 +130,14 @@ private void refreshLanguages() { @Override protected boolean reset() { - SettingsStore.getInstance(getContext()).setContentLocales(Collections.singletonList(LocaleUtils.getDeviceLanguage().getId())); - SessionStore.get().setLocales(Collections.singletonList(LocaleUtils.getDeviceLanguage().getId())); - LocaleUtils.resetLanguages(); - refreshLanguages(); + String systemLocale = LocaleUtils.getClosestAvailableLocale(LocaleUtils.getDeviceLanguage().getId()); + List preferredLanguages = LocaleUtils.getPreferredLanguages(getContext()); + if (preferredLanguages.size() > 1 || !preferredLanguages.get(0).getId().equals(systemLocale)) { + SettingsStore.getInstance(getContext()).setContentLocales(Collections.emptyList()); + SessionStore.get().setLocales(Collections.emptyList()); + LocaleUtils.resetLanguages(); + refreshLanguages(); + } return false; } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/DisplayLanguageOptionsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/DisplayLanguageOptionsView.java index 617051064..7e98119e7 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/DisplayLanguageOptionsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/DisplayLanguageOptionsView.java @@ -12,6 +12,7 @@ import androidx.databinding.DataBindingUtil; import org.mozilla.vrbrowser.R; +import org.mozilla.vrbrowser.browser.SettingsStore; import org.mozilla.vrbrowser.browser.engine.SessionStore; import org.mozilla.vrbrowser.databinding.OptionsLanguageDisplayBinding; import org.mozilla.vrbrowser.ui.views.settings.RadioGroupSetting; @@ -65,6 +66,7 @@ protected boolean reset() { } else { setLanguage(LocaleUtils.getIndexForSupportedLocale(systemLocale), true); + SettingsStore.getInstance(getContext()).setDisplayLocale(null); return true; } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/LanguageOptionsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/LanguageOptionsView.java index 2925bceda..8e8ada86d 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/LanguageOptionsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/LanguageOptionsView.java @@ -92,7 +92,7 @@ protected void onDismiss() { }; private void setVoiceLanguage() { - mBinding.voiceSearchLanguageDescription.setText(getSpannedLanguageText(LocaleUtils.getVoiceSearchLanguage(getContext())), TextView.BufferType.SPANNABLE); + mBinding.voiceSearchLanguageDescription.setText(getSpannedLanguageText(LocaleUtils.getVoiceSearchLanguage(getContext()).getName()), TextView.BufferType.SPANNABLE); } private void setContentLanguage() { @@ -105,7 +105,7 @@ private void setContentLanguage() { } private void setDisplayLanguage() { - mBinding.displayLanguageDescription.setText(getSpannedLanguageText(LocaleUtils.getDisplayLanguage())); + mBinding.displayLanguageDescription.setText(getSpannedLanguageText(LocaleUtils.getDisplayLanguage(getContext()).getName())); } private int getLanguageIndex(@NonNull String text) { diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/VoiceSearchLanguageOptionsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/VoiceSearchLanguageOptionsView.java index 256dcf6a8..e45159c19 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/VoiceSearchLanguageOptionsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/VoiceSearchLanguageOptionsView.java @@ -12,6 +12,7 @@ import androidx.databinding.DataBindingUtil; import org.mozilla.vrbrowser.R; +import org.mozilla.vrbrowser.browser.SettingsStore; import org.mozilla.vrbrowser.browser.engine.SessionStore; import org.mozilla.vrbrowser.databinding.OptionsLanguageVoiceBinding; import org.mozilla.vrbrowser.ui.views.settings.RadioGroupSetting; @@ -58,16 +59,25 @@ private void initialize(Context aContext) { @Override protected boolean reset() { String systemLocale = LocaleUtils.getClosestSupportedLocale(getContext(), LocaleUtils.getDeviceLanguage().getId()); - String value = LocaleUtils.getSupportedLocaleForIndex(mBinding.languageRadio.getCheckedRadioButtonId()); - if (!value.equals(systemLocale)) { - setLanguage(LocaleUtils.getIndexForSupportedLocale(LocaleUtils.getSystemLocale()), true); + String currentLocale = LocaleUtils.getCurrentLocale(); + if (currentLocale.equalsIgnoreCase(systemLocale)) { + setLanguage(LocaleUtils.getIndexForSupportedLocale(systemLocale), false); + return false; + + } else { + setLanguage(LocaleUtils.getIndexForSupportedLocale(systemLocale), true); + SettingsStore.getInstance(getContext()).setVoiceSearchLocale(null); + return true; } - - return false; } private RadioGroupSetting.OnCheckedChangeListener mLanguageListener = (radioGroup, checkedId, doApply) -> { - setLanguage(checkedId, true); + String currentLocale = LocaleUtils.getCurrentLocale(); + String locale = LocaleUtils.getSupportedLocaleForIndex(mBinding.languageRadio.getCheckedRadioButtonId()); + + if (!locale.equalsIgnoreCase(currentLocale)) { + setLanguage(checkedId, true); + } }; private OnClickListener mResetListener = (view) -> { @@ -79,7 +89,10 @@ private void setLanguage(int checkedId, boolean doApply) { mBinding.languageRadio.setChecked(checkedId, doApply); mBinding.languageRadio.setOnCheckedChangeListener(mLanguageListener); - LocaleUtils.setVoiceSearchLocale(getContext(), LocaleUtils.getSupportedLocaleForIndex(checkedId)); + if (doApply) { + String locale = LocaleUtils.getSupportedLocaleForIndex(checkedId); + LocaleUtils.setVoiceSearchLocale(getContext(), locale); + } } @Override diff --git a/app/src/common/shared/org/mozilla/vrbrowser/utils/LocaleUtils.java b/app/src/common/shared/org/mozilla/vrbrowser/utils/LocaleUtils.java index 154a38aaf..7561aa15c 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/utils/LocaleUtils.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/utils/LocaleUtils.java @@ -37,8 +37,8 @@ public static void saveSystemLocale() { } @NonNull - public static String getSystemLocale() { - return mSystemLocale.toLanguageTag(); + public static Locale getSystemLocale() { + return mSystemLocale; } @NonNull @@ -60,6 +60,14 @@ private static HashMap getAllLanguages() { mLanguagesCache.put(languageId, locale); } + Locale locale = Locale.forLanguageTag(getDeviceLocale().toLanguageTag()); + String languageId = locale.toLanguageTag(); + if (!mLanguagesCache.containsKey(languageId)) { + String displayName = locale.getDisplayName().substring(0, 1).toUpperCase() + locale.getDisplayName().substring(1); + Language language = new Language(languageId, displayName + " [" + languageId + "]"); + mLanguagesCache.put(languageId, language); + } + return mLanguagesCache; } @@ -75,7 +83,11 @@ public static void resetLanguages() { } public static Language getDeviceLanguage() { - return mLanguagesCache.get(Resources.getSystem().getConfiguration().getLocales().get(0).toLanguageTag()); + return mLanguagesCache.get(getDeviceLocale().toLanguageTag()); + } + + public static Locale getDeviceLocale() { + return Resources.getSystem().getConfiguration().getLocales().get(0); } public static List getLocalesFromLanguages(@NonNull final List languages) { @@ -97,15 +109,21 @@ public static List getPreferredLanguages(@NonNull Context aContext) { List preferredLanguages = new ArrayList<>(); if (savedLanguages != null) { for (String language : savedLanguages) { - Language lang = languages.get(language); + Language lang = languages.get(getClosestAvailableLocale(language)); + if (lang != null) { + lang.setPreferred(true); + preferredLanguages.add(lang); + } + } + + } + + if (savedLanguages == null || savedLanguages.isEmpty()) { + Language lang = languages.get(getClosestAvailableLocale(getDeviceLocale().toLanguageTag())); + if (lang != null) { lang.setPreferred(true); preferredLanguages.add(lang); } - - } else { - Language currentLanguage = getDeviceLanguage(); - currentLanguage.setPreferred(true); - preferredLanguages.add(currentLanguage); } return preferredLanguages; @@ -118,9 +136,47 @@ public static List getAvailableLanguages() { .collect(Collectors.toList()); } + @NonNull + public static String getClosestAvailableLocale(@NonNull String languageTag) { + List locales = Stream.of(Locale.getAvailableLocales()).collect(Collectors.toList()); + Locale inputLocale = Locale.forLanguageTag(languageTag); + Optional outputLocale = locales.stream().filter(item -> + item.equals(inputLocale) + ).findFirst(); + + if (!outputLocale.isPresent()) { + outputLocale = locales.stream().filter(item -> + item.getLanguage().equals(inputLocale.getLanguage()) && + item.getScript().equals(inputLocale.getScript()) && + item.getCountry().equals(inputLocale.getCountry()) + ).findFirst(); + } + if (!outputLocale.isPresent()) { + outputLocale = locales.stream().filter(item -> + item.getLanguage().equals(inputLocale.getLanguage()) && + item.getCountry().equals(inputLocale.getCountry()) + ).findFirst(); + } + if (!outputLocale.isPresent()) { + outputLocale = locales.stream().filter(item -> + item.getLanguage().equals(inputLocale.getLanguage()) + ).findFirst(); + } + + if (outputLocale.isPresent()) { + return outputLocale.get().toLanguageTag(); + } + + return getDeviceLocale().toLanguageTag(); + } + @NonNull public static String getVoiceSearchLocale(@NonNull Context aContext) { - return SettingsStore.getInstance(aContext).getVoiceSearchLocale(); + String locale = SettingsStore.getInstance(aContext).getVoiceSearchLocale(); + if (locale == null) { + locale = LocaleUtils.getDefaultSupportedLocale(aContext); + } + return locale; } public static void setVoiceSearchLocale(@NonNull Context context, @NonNull String locale) { @@ -128,14 +184,16 @@ public static void setVoiceSearchLocale(@NonNull Context context, @NonNull Strin } @NonNull - public static String getVoiceSearchLanguage(@NonNull Context aContext) { - String language = LocaleUtils.getVoiceSearchLocale(aContext); - return getAllLanguages().get(language).getName(); + public static Language getVoiceSearchLanguage(@NonNull Context aContext) { + return mLanguagesCache.get(getClosestAvailableLocale(getVoiceSearchLocale(aContext))); } @NonNull public static String getDisplayLocale(Context context) { String locale = SettingsStore.getInstance(context).getDisplayLocale(); + if (locale == null) { + locale = LocaleUtils.getDefaultSupportedLocale(context); + } return mapOldLocaleToNew((locale)); } @@ -144,12 +202,16 @@ public static void setDisplayLocale(@NonNull Context context, @NonNull String lo } @NonNull - public static String getDisplayLanguage() { - return getAllLanguages().get(getCurrentLocale()).getName(); + public static Language getDisplayLanguage(@NonNull Context aContext) { + return mLanguagesCache.get(getClosestAvailableLocale(getDisplayLocale(aContext))); } public static Context setLocale(@NonNull Context context) { - return updateResources(context, SettingsStore.getInstance(context).getDisplayLocale()); + String locale = SettingsStore.getInstance(context).getDisplayLocale(); + if (locale == null) { + locale = LocaleUtils.getDefaultSupportedLocale(context); + } + return updateResources(context, locale); } private static Context updateResources(@NonNull Context context, @NonNull String language) { @@ -256,14 +318,8 @@ public static String getSupportedLocaleForIndex(int index) { return localizedSupportedLanguages.get(index).locale.toLanguageTag(); } - public static String getDefaultSupportedLocale() { - String locale = getCurrentLocale(); - List supportedLocales = getSupportedLocales(); - if (!supportedLocales.contains(locale)) { - return supportedLocales.get(0); - } - - return locale; + public static String getDefaultSupportedLocale(@NonNull Context context) { + return getClosestSupportedLocale(context, getDeviceLocale().toLanguageTag()); } public static String getClosestSupportedLocale(@NonNull Context context, @NonNull String languageTag) { @@ -295,7 +351,8 @@ public static String getClosestSupportedLocale(@NonNull Context context, @NonNul return language.get().locale.toLanguageTag(); } else { - return getDisplayLocale(context); + // If there is no closest supported locale we fallback to en-US + return "en-US"; } }