From de3e34060c6dca60a807d3e2d6ef954b5626444f Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Wed, 15 Apr 2015 11:26:06 +1000 Subject: [PATCH] Fixed issue #226 - preferences don't crash. Use custom code rather than "Locale.forLanguageTag" (which is android-21 specific). Also fixed the actual setting of the language, by modifying the code in FDroidApp to respect the country code (rather than just the language code). --- F-Droid/res/values/no_trans.xml | 3 +- F-Droid/src/org/fdroid/fdroid/FDroidApp.java | 8 ++--- F-Droid/src/org/fdroid/fdroid/Utils.java | 30 +++++++++++++++++++ .../views/fragments/PreferencesFragment.java | 11 +++---- 4 files changed, 38 insertions(+), 14 deletions(-) diff --git a/F-Droid/res/values/no_trans.xml b/F-Droid/res/values/no_trans.xml index 7611e6951..7c033c2d0 100644 --- a/F-Droid/res/values/no_trans.xml +++ b/F-Droid/res/values/no_trans.xml @@ -38,8 +38,7 @@ cs de el - en-rGB - en-US + en-rUS eo es eu diff --git a/F-Droid/src/org/fdroid/fdroid/FDroidApp.java b/F-Droid/src/org/fdroid/fdroid/FDroidApp.java index f45674337..538bd041b 100644 --- a/F-Droid/src/org/fdroid/fdroid/FDroidApp.java +++ b/F-Droid/src/org/fdroid/fdroid/FDroidApp.java @@ -141,11 +141,9 @@ public class FDroidApp extends Application { } public static void updateLanguage(Context c, String lang) { - Configuration cfg = new Configuration(); - if (!TextUtils.isEmpty(lang)) - cfg.locale = new Locale(lang); - else - cfg.locale = Locale.getDefault(); + final Configuration cfg = new Configuration(); + final Locale newLocale = Utils.getLocaleFromAndroidLangTag(lang); + cfg.locale = newLocale == null ? Locale.getDefault() : newLocale; c.getResources().updateConfiguration(cfg, null); } diff --git a/F-Droid/src/org/fdroid/fdroid/Utils.java b/F-Droid/src/org/fdroid/fdroid/Utils.java index c7e7c7bd2..ca5c7c846 100644 --- a/F-Droid/src/org/fdroid/fdroid/Utils.java +++ b/F-Droid/src/org/fdroid/fdroid/Utils.java @@ -371,6 +371,36 @@ public final class Utils { return ret; } + /** + * There is a method {@link java.util.Locale#forLanguageTag(String)} which would be useful + * for this, however it doesn't deal with android-specific language tags, which are a little + * different. For example, android language tags may have an "r" before the country code, + * such as "zh-rHK", however {@link java.util.Locale} expects them to be "zr-HK". + */ + public static Locale getLocaleFromAndroidLangTag(String languageTag) { + if (TextUtils.isEmpty(languageTag)) { + return null; + } + + final String[] parts = languageTag.split("-"); + if (parts.length == 1) { + return new Locale(parts[0]); + } else if (parts.length == 2) { + String country = parts[1]; + // Some languages have an "r" before the country as per the values folders, such + // as "zh-rCN". As far as the Locale class is concerned, the "r" is + // not helpful, and this should be "zh-CN". Thus, we will + // strip the "r" when found. + if (country.charAt(0) == 'r' && country.length() == 3) { + country = country.substring(1); + } + return new Locale(parts[0], country); + } else { + Log.e(TAG, "Locale could not be parsed from language tag: " + languageTag); + return new Locale(languageTag); + } + } + public static class CommaSeparatedList implements Iterable { private final String value; diff --git a/F-Droid/src/org/fdroid/fdroid/views/fragments/PreferencesFragment.java b/F-Droid/src/org/fdroid/fdroid/views/fragments/PreferencesFragment.java index c7b1a9bd6..294733b0d 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/fragments/PreferencesFragment.java +++ b/F-Droid/src/org/fdroid/fdroid/views/fragments/PreferencesFragment.java @@ -14,6 +14,7 @@ import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.PreferencesActivity; import org.fdroid.fdroid.R; +import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.installer.CheckRootAsyncTask; import org.fdroid.fdroid.installer.Installer; @@ -293,17 +294,13 @@ public class PreferencesFragment extends PreferenceFragment } private void langSpinner(String key) { - ListPreference pref = (ListPreference)findPreference(key); + final ListPreference pref = (ListPreference)findPreference(key); final String[] langValues = getResources().getStringArray(R.array.languageValues); String[] langNames = new String[langValues.length]; langNames[0] = getString(R.string.pref_language_default); for (int i = 1; i < langValues.length; i++) { - try { - final Locale appLoc = Locale.forLanguageTag(langValues[i]); - langNames[i] = appLoc.getDisplayName(appLoc); - } catch (Exception e) { - langNames[i] = langValues[i]; - } + final Locale appLoc = Utils.getLocaleFromAndroidLangTag(langValues[i]); + langNames[i] = appLoc == null ? langValues[i] : appLoc.getDisplayName(appLoc); } pref.setEntries(langNames); }