improvements to Locale changing in app
This commit is contained in:
parent
9af00fe263
commit
6eb0a93dd8
|
@ -1,10 +1,14 @@
|
||||||
|
|
||||||
package info.guardianproject.util;
|
package info.guardianproject.util;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.annotation.TargetApi;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.content.ContextWrapper;
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.res.AssetManager;
|
import android.content.res.AssetManager;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
import android.os.Build;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
|
|
||||||
|
@ -16,11 +20,9 @@ import java.util.Set;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
public class Languages {
|
public class Languages {
|
||||||
private static final String TAG = "Languages";
|
public static final String TAG = "Languages";
|
||||||
private static Languages singleton;
|
|
||||||
private static Map<String, String> tmpMap = new TreeMap<String, String>();
|
public static final Locale defaultLocale;
|
||||||
private static Map<String, String> nameMap;
|
|
||||||
public static final String USE_SYSTEM_DEFAULT = "";
|
|
||||||
public static final Locale TIBETAN = new Locale("bo");
|
public static final Locale TIBETAN = new Locale("bo");
|
||||||
static final Locale localesToTest[] = {
|
static final Locale localesToTest[] = {
|
||||||
Locale.ENGLISH, Locale.FRENCH, Locale.GERMAN,
|
Locale.ENGLISH, Locale.FRENCH, Locale.GERMAN,
|
||||||
|
@ -50,68 +52,142 @@ public class Languages {
|
||||||
new Locale("uz"), new Locale("vi"), new Locale("zu"),
|
new Locale("uz"), new Locale("vi"), new Locale("zu"),
|
||||||
};
|
};
|
||||||
|
|
||||||
private Languages(Activity activity, int resId, String defaultString) {
|
private static final String USE_SYSTEM_DEFAULT = "";
|
||||||
|
private static final String defaultString = "Use System Default";
|
||||||
|
|
||||||
|
private static Locale locale;
|
||||||
|
private static Languages singleton;
|
||||||
|
private static Class<?> clazz;
|
||||||
|
private static int resId;
|
||||||
|
private static Map<String, String> tmpMap = new TreeMap<String, String>();
|
||||||
|
private static Map<String, String> nameMap;
|
||||||
|
|
||||||
|
static {
|
||||||
|
defaultLocale = Locale.getDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Languages(Activity activity) {
|
||||||
AssetManager assets = activity.getAssets();
|
AssetManager assets = activity.getAssets();
|
||||||
Configuration config = activity.getResources().getConfiguration();
|
Configuration config = activity.getResources().getConfiguration();
|
||||||
DisplayMetrics metrics = new DisplayMetrics();
|
// Resources() requires DisplayMetrics, but they are only needed for drawables
|
||||||
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
|
DisplayMetrics ignored = new DisplayMetrics();
|
||||||
|
activity.getWindowManager().getDefaultDisplay().getMetrics(ignored);
|
||||||
Resources resources;
|
Resources resources;
|
||||||
Set<Locale> localeSet = new LinkedHashSet<Locale>();
|
Set<Locale> localeSet = new LinkedHashSet<Locale>();
|
||||||
for (Locale locale : localesToTest) {
|
for (Locale locale : localesToTest) {
|
||||||
config.locale = locale;
|
config.locale = locale;
|
||||||
resources = new Resources(assets, metrics, config);
|
resources = new Resources(assets, ignored, config);
|
||||||
if (!TextUtils.equals(defaultString, resources.getString(resId))
|
if (!TextUtils.equals(defaultString, resources.getString(resId))
|
||||||
|| locale.equals(Locale.ENGLISH))
|
|| locale.equals(Locale.ENGLISH))
|
||||||
localeSet.add(locale);
|
localeSet.add(locale);
|
||||||
}
|
}
|
||||||
for (Locale locale : localeSet) {
|
for (Locale locale : localeSet) {
|
||||||
if (locale.equals(TIBETAN)) {
|
if (locale.equals(TIBETAN)) {
|
||||||
// include English name for devices that don't support Tibetan
|
// include English name for devices without Tibetan font support
|
||||||
// font
|
|
||||||
tmpMap.put(TIBETAN.getLanguage(), "Tibetan བོད་སྐད།"); // Tibetan
|
tmpMap.put(TIBETAN.getLanguage(), "Tibetan བོད་སྐད།"); // Tibetan
|
||||||
} else if (locale.equals(Locale.SIMPLIFIED_CHINESE)) {
|
} else if (locale.equals(Locale.SIMPLIFIED_CHINESE)) {
|
||||||
tmpMap.put(Locale.SIMPLIFIED_CHINESE.toString(), "中文 (中国)"); // Chinese
|
tmpMap.put(Locale.SIMPLIFIED_CHINESE.toString(), "中文 (中国)"); // Chinese (China)
|
||||||
// (China)
|
|
||||||
} else if (locale.equals(Locale.TRADITIONAL_CHINESE)) {
|
} else if (locale.equals(Locale.TRADITIONAL_CHINESE)) {
|
||||||
tmpMap.put(Locale.TRADITIONAL_CHINESE.toString(), "中文 (台灣)"); // Chinese
|
tmpMap.put(Locale.TRADITIONAL_CHINESE.toString(), "中文 (台灣)"); // Chinese (Taiwan)
|
||||||
// (Taiwan)
|
|
||||||
} else {
|
} else {
|
||||||
tmpMap.put(locale.getLanguage(), locale.getDisplayLanguage(locale));
|
tmpMap.put(locale.getLanguage(), locale.getDisplayLanguage(locale));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO implement this completely, the menu item works, but doesn't work
|
|
||||||
// properly
|
|
||||||
/* USE_SYSTEM_DEFAULT is a fake one for displaying in a chooser menu. */
|
/* USE_SYSTEM_DEFAULT is a fake one for displaying in a chooser menu. */
|
||||||
// localeSet.add(null);
|
localeSet.add(null);
|
||||||
// tmpMap.put(USE_SYSTEM_DEFAULT,
|
tmpMap.put(USE_SYSTEM_DEFAULT, activity.getString(resId));
|
||||||
// activity.getString(R.string.use_system_default));
|
|
||||||
nameMap = Collections.unmodifiableMap(tmpMap);
|
nameMap = Collections.unmodifiableMap(tmpMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the instance of {@link Languages} to work with, providing the
|
* Get the instance of {@link Languages} to work with, providing the
|
||||||
* {@link Activity} that is will be working as part of. This uses the
|
* {@link Activity} that is will be working as part of, as well as the
|
||||||
* provided string resource {@code resId} find the supported translations:
|
* {@code resId} that has the exact string "Use System Default",
|
||||||
* if an included translation has a translated string that matches that
|
* i.e. {@code R.string.use_system_default}.
|
||||||
* {@code resId}, i.e. {@code R.string.menu_settings}, then that language
|
* <p/>
|
||||||
* will be included as a supported language.
|
* That string resource {@code resId} is also used to find the supported
|
||||||
*
|
* translations: if an included translation has a translated string that
|
||||||
* @param activity the {@link Activity} this is working as part of
|
* matches that {@code resId}, then that language will be included as a
|
||||||
* @param resId the string resource ID to test, e.g.
|
* supported language.
|
||||||
* {@code R.string.menu_settings}
|
*
|
||||||
* @param defaultString the string resource in the default language, e.g.
|
* @param clazz the {@link Class} of the default {@code Activity},
|
||||||
* {@code "Settings"}
|
* usually the main {@code Activity} from where the
|
||||||
|
* Settings is launched from.
|
||||||
|
* @param resId the string resource ID to for the string "Use System Default",
|
||||||
|
* e.g. {@code R.string.use_system_default}
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static Languages get(Activity activity, int resId, String defaultString) {
|
public static void setup(Class<?> clazz, int resId) {
|
||||||
if (singleton == null)
|
if (Languages.clazz == null) {
|
||||||
singleton = new Languages(activity, resId, defaultString);
|
Languages.clazz = clazz;
|
||||||
|
Languages.resId = resId;
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Languages singleton was already initialized, duplicate call to Languages.setup()!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the singleton to work with.
|
||||||
|
*
|
||||||
|
* @param activity the {@link Activity} this is working as part of
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Languages get(Activity activity) {
|
||||||
|
if (singleton == null) {
|
||||||
|
singleton = new Languages(activity);
|
||||||
|
}
|
||||||
return singleton;
|
return singleton;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||||
|
@SuppressLint("NewApi")
|
||||||
|
public static void setLanguage(final ContextWrapper contextWrapper, String language, boolean refresh) {
|
||||||
|
if (locale != null && TextUtils.equals(locale.getLanguage(), language) && (!refresh)) {
|
||||||
|
return; // already configured
|
||||||
|
} else if (language == null || language == USE_SYSTEM_DEFAULT) {
|
||||||
|
locale = defaultLocale;
|
||||||
|
} else {
|
||||||
|
/* handle locales with the country in it, i.e. zh_CN, zh_TW, etc */
|
||||||
|
String localeSplit[] = language.split("_");
|
||||||
|
if (localeSplit.length > 1) {
|
||||||
|
locale = new Locale(localeSplit[0], localeSplit[1]);
|
||||||
|
} else {
|
||||||
|
locale = new Locale(language);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Resources resources = contextWrapper.getBaseContext().getResources();
|
||||||
|
Configuration config = resources.getConfiguration();
|
||||||
|
if (Build.VERSION.SDK_INT >= 17) {
|
||||||
|
config.setLocale(locale);
|
||||||
|
} else {
|
||||||
|
config.locale = locale;
|
||||||
|
}
|
||||||
|
resources.updateConfiguration(config, resources.getDisplayMetrics());
|
||||||
|
Locale.setDefault(locale);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force reload the {@link Activity to make language changes take effect.}
|
||||||
|
*
|
||||||
|
* @param activity the {@code Activity} to force reload
|
||||||
|
*/
|
||||||
|
public static void forceChangeLanguage(Activity activity) {
|
||||||
|
Intent intent = activity.getIntent();
|
||||||
|
if (intent == null) // when launched as LAUNCHER
|
||||||
|
return;
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||||
|
activity.finish();
|
||||||
|
activity.overridePendingTransition(0, 0);
|
||||||
|
activity.startActivity(intent);
|
||||||
|
activity.overridePendingTransition(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the name of the language based on the locale.
|
* Return the name of the language based on the locale.
|
||||||
*
|
*
|
||||||
* @param locale
|
* @param locale
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@ -127,7 +203,7 @@ public class Languages {
|
||||||
/**
|
/**
|
||||||
* Return an array of the names of all the supported languages, sorted to
|
* Return an array of the names of all the supported languages, sorted to
|
||||||
* match what is returned by {@link Languages#getSupportedLocales()}.
|
* match what is returned by {@link Languages#getSupportedLocales()}.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public String[] getAllNames() {
|
public String[] getAllNames() {
|
||||||
|
@ -147,7 +223,7 @@ public class Languages {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get sorted list of supported locales.
|
* Get sorted list of supported locales.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public String[] getSupportedLocales() {
|
public String[] getSupportedLocales() {
|
||||||
|
|
|
@ -39,7 +39,8 @@ public class OrbotApp extends Application implements OrbotConstants
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
Prefs.setContext(this);
|
Prefs.setContext(this);
|
||||||
|
|
||||||
setNewLocale(Prefs.getDefaultLocale());
|
Languages.setup(OrbotMainActivity.class, R.string.menu_settings);
|
||||||
|
Languages.setLanguage(this, Prefs.getDefaultLocale(), true);
|
||||||
|
|
||||||
appBinHome = getDir(TorServiceConstants.DIRECTORY_TOR_BINARY,Application.MODE_PRIVATE);
|
appBinHome = getDir(TorServiceConstants.DIRECTORY_TOR_BINARY,Application.MODE_PRIVATE);
|
||||||
appCacheHome = getDir(TorServiceConstants.DIRECTORY_TOR_DATA,Application.MODE_PRIVATE);
|
appCacheHome = getDir(TorServiceConstants.DIRECTORY_TOR_DATA,Application.MODE_PRIVATE);
|
||||||
|
@ -60,40 +61,9 @@ public class OrbotApp extends Application implements OrbotConstants
|
||||||
public void onConfigurationChanged(Configuration newConfig) {
|
public void onConfigurationChanged(Configuration newConfig) {
|
||||||
super.onConfigurationChanged(newConfig);
|
super.onConfigurationChanged(newConfig);
|
||||||
Log.i(TAG, "onConfigurationChanged " + newConfig.locale.getLanguage());
|
Log.i(TAG, "onConfigurationChanged " + newConfig.locale.getLanguage());
|
||||||
setNewLocale(Prefs.getDefaultLocale());
|
Languages.setLanguage(this, Prefs.getDefaultLocale(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
|
||||||
public void setNewLocale(String language) {
|
|
||||||
if (TextUtils.isEmpty(language))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (locale != null && TextUtils.equals(locale.getLanguage(), language))
|
|
||||||
return; // already configured
|
|
||||||
|
|
||||||
/* handle locales with the country in it, i.e. zh_CN, zh_TW, etc */
|
|
||||||
String localeSplit[] = language.split("_");
|
|
||||||
if (localeSplit.length > 1)
|
|
||||||
locale = new Locale(localeSplit[0], localeSplit[1]);
|
|
||||||
else
|
|
||||||
locale = new Locale(language);
|
|
||||||
Configuration config = getResources().getConfiguration();
|
|
||||||
if (Build.VERSION.SDK_INT >= 17)
|
|
||||||
config.setLocale(locale);
|
|
||||||
else
|
|
||||||
config.locale = locale;
|
|
||||||
getResources().updateConfiguration(config, getResources().getDisplayMetrics());
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the preference after setting the locale in case something goes
|
|
||||||
* wrong. If setting the locale causes an Exception, it should be set in
|
|
||||||
* the preferences, otherwise ChatSecure will be stuck in a crash loop.
|
|
||||||
*/
|
|
||||||
Prefs.setDefaultLocale(language);
|
|
||||||
Log.i(TAG, "setNewLocale complete: locale: " + locale.getLanguage()
|
|
||||||
+ " Locale.getDefault: " + Locale.getDefault().getLanguage());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void forceChangeLanguage(Activity activity) {
|
public static void forceChangeLanguage(Activity activity) {
|
||||||
Intent intent = activity.getIntent();
|
Intent intent = activity.getIntent();
|
||||||
if (intent == null) // when launched as LAUNCHER
|
if (intent == null) // when launched as LAUNCHER
|
||||||
|
@ -106,6 +76,6 @@ public class OrbotApp extends Application implements OrbotConstants
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Languages getLanguages(Activity activity) {
|
public static Languages getLanguages(Activity activity) {
|
||||||
return Languages.get(activity, R.string.menu_settings, "Settings");
|
return Languages.get(activity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class SettingsPreferences
|
||||||
|
|
||||||
prefLocale = (ListPreference) findPreference("pref_default_locale");
|
prefLocale = (ListPreference) findPreference("pref_default_locale");
|
||||||
prefLocale.setOnPreferenceClickListener(this);
|
prefLocale.setOnPreferenceClickListener(this);
|
||||||
Languages languages = Languages.get(this, R.string.menu_settings, "Settings");
|
Languages languages = Languages.get(this);
|
||||||
prefLocale.setEntries(languages.getAllNames());
|
prefLocale.setEntries(languages.getAllNames());
|
||||||
prefLocale.setEntryValues(languages.getSupportedLocales());
|
prefLocale.setEntryValues(languages.getSupportedLocales());
|
||||||
prefLocale.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
|
prefLocale.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
|
||||||
|
@ -71,7 +71,7 @@ public class SettingsPreferences
|
||||||
String lang = settings.getString("pref_default_locale",
|
String lang = settings.getString("pref_default_locale",
|
||||||
Locale.getDefault().getLanguage());
|
Locale.getDefault().getLanguage());
|
||||||
OrbotApp app = (OrbotApp) getApplication();
|
OrbotApp app = (OrbotApp) getApplication();
|
||||||
app.setNewLocale(language);
|
Languages.setLanguage(app, language, true);
|
||||||
lang = settings.getString("pref_default_locale",
|
lang = settings.getString("pref_default_locale",
|
||||||
Locale.getDefault().getLanguage());
|
Locale.getDefault().getLanguage());
|
||||||
OrbotApp.forceChangeLanguage(SettingsPreferences.this);
|
OrbotApp.forceChangeLanguage(SettingsPreferences.this);
|
||||||
|
|
Loading…
Reference in New Issue