diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 00eb3a43..09ed951b 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -1,43 +1,7 @@ - - - Default - English - العربية - فارسی - 中文(简体) - Deutsche - Español - Français - Italian - Nederlands - Magyar - Português - Português Brasileiro - русский язык - - - - xx - en - ar - fa - zh - de - es - fr - it - nl - hu - pt - pt_BR - ru - - - - + Obfs4 (Recommended) Obfs3 diff --git a/res/values/strings.xml b/res/values/strings.xml index 0f98f5ef..e5b4cd35 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -236,7 +236,7 @@ Bridges enabled! - Set Locale + Language Choose the locale and language for Orbot Choose Language Leave default or switch the current language diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml index 3778dd6f..d910fee2 100644 --- a/res/xml/preferences.xml +++ b/res/xml/preferences.xml @@ -25,8 +25,6 @@ android:title="@string/pref_use_expanded_notifications_title"/> diff --git a/src/info/guardianproject/util/Languages.java b/src/info/guardianproject/util/Languages.java new file mode 100644 index 00000000..b776f758 --- /dev/null +++ b/src/info/guardianproject/util/Languages.java @@ -0,0 +1,157 @@ + +package info.guardianproject.util; + +import android.app.Activity; +import android.content.res.AssetManager; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.text.TextUtils; +import android.util.DisplayMetrics; + +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +public class Languages { + private static final String TAG = "Languages"; + private static Languages singleton; + private static Map tmpMap = new TreeMap(); + private static Map nameMap; + public static final String USE_SYSTEM_DEFAULT = ""; + public static final Locale TIBETAN = new Locale("bo"); + static final Locale localesToTest[] = { + Locale.ENGLISH, Locale.FRENCH, Locale.GERMAN, + Locale.ITALIAN, Locale.JAPANESE, Locale.KOREAN, + Locale.TRADITIONAL_CHINESE, Locale.SIMPLIFIED_CHINESE, + TIBETAN, new Locale("af"), new Locale("am"), + new Locale("ar"), new Locale("az"), new Locale("bg"), + new Locale("bn"), new Locale("ca"), new Locale("cs"), + new Locale("da"), new Locale("el"), new Locale("es"), + new Locale("et"), new Locale("eu"), new Locale("fa"), + new Locale("fi"), new Locale("gl"), new Locale("hi"), + new Locale("hr"), new Locale("hu"), new Locale("hy"), + new Locale("in"), new Locale("hy"), new Locale("in"), + new Locale("is"), new Locale("it"), new Locale("iw"), + new Locale("ka"), new Locale("kk"), new Locale("km"), + new Locale("kn"), new Locale("ky"), new Locale("lo"), + new Locale("lt"), new Locale("lv"), new Locale("mk"), + new Locale("ml"), new Locale("mn"), new Locale("mr"), + new Locale("ms"), new Locale("my"), new Locale("nb"), + new Locale("ne"), new Locale("nl"), new Locale("pl"), + new Locale("pt"), new Locale("rm"), new Locale("ro"), + new Locale("ru"), new Locale("si"), new Locale("sk"), + new Locale("sl"), new Locale("sn"), new Locale("sr"), + new Locale("sv"), new Locale("sw"), new Locale("ta"), + new Locale("te"), new Locale("th"), new Locale("tl"), + new Locale("tr"), new Locale("uk"), new Locale("ur"), + new Locale("uz"), new Locale("vi"), new Locale("zu"), + }; + + private Languages(Activity activity, int resId, String defaultString) { + AssetManager assets = activity.getAssets(); + Configuration config = activity.getResources().getConfiguration(); + DisplayMetrics metrics = new DisplayMetrics(); + activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); + Resources resources; + Set localeSet = new LinkedHashSet(); + for (Locale locale : localesToTest) { + config.locale = locale; + resources = new Resources(assets, metrics, config); + if (!TextUtils.equals(defaultString, resources.getString(resId)) + || locale.equals(Locale.ENGLISH)) + localeSet.add(locale); + } + for (Locale locale : localeSet) { + if (locale.equals(TIBETAN)) { + // include English name for devices that don't support Tibetan + // font + tmpMap.put(TIBETAN.getLanguage(), "Tibetan བོད་སྐད།"); // Tibetan + } else if (locale.equals(Locale.SIMPLIFIED_CHINESE)) { + tmpMap.put(Locale.SIMPLIFIED_CHINESE.toString(), "中文 (中国)"); // Chinese + // (China) + } else if (locale.equals(Locale.TRADITIONAL_CHINESE)) { + tmpMap.put(Locale.TRADITIONAL_CHINESE.toString(), "中文 (台灣)"); // Chinese + // (Taiwan) + } else { + 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. */ + // localeSet.add(null); + // tmpMap.put(USE_SYSTEM_DEFAULT, + // activity.getString(R.string.use_system_default)); + nameMap = Collections.unmodifiableMap(tmpMap); + } + + /** + * Get the instance of {@link Languages} to work with, providing the + * {@link Activity} that is will be working as part of. This uses the + * provided string resource {@code resId} find the supported translations: + * if an included translation has a translated string that matches that + * {@code resId}, i.e. {@code R.string.menu_settings}, then that language + * will be included as a supported language. + * + * @param activity the {@link Activity} this is working as part of + * @param resId the string resource ID to test, e.g. + * {@code R.string.menu_settings} + * @param defaultString the string resource in the default language, e.g. + * {@code "Settings"} + * @return + */ + public static Languages get(Activity activity, int resId, String defaultString) { + if (singleton == null) + singleton = new Languages(activity, resId, defaultString); + return singleton; + } + + /** + * Return the name of the language based on the locale. + * + * @param locale + * @return + */ + public String getName(String locale) { + String ret = nameMap.get(locale); + // if no match, try to return a more general name (i.e. English for + // en_IN) + if (ret == null && locale.contains("_")) + ret = nameMap.get(locale.split("_")[0]); + return ret; + } + + /** + * Return an array of the names of all the supported languages, sorted to + * match what is returned by {@link Languages#getSupportedLocales()}. + * + * @return + */ + public String[] getAllNames() { + return nameMap.values().toArray(new String[nameMap.size()]); + } + + public int getPosition(Locale locale) { + String localeName = locale.getLanguage(); + int i = 0; + for (String key : nameMap.keySet()) + if (TextUtils.equals(key, localeName)) + return i; + else + i++; + return -1; + } + + /** + * Get sorted list of supported locales. + * + * @return + */ + public String[] getSupportedLocales() { + Set keys = nameMap.keySet(); + return keys.toArray(new String[keys.size()]); + } +} diff --git a/src/org/torproject/android/OrbotApp.java b/src/org/torproject/android/OrbotApp.java index 4e6d9ec6..744d5383 100644 --- a/src/org/torproject/android/OrbotApp.java +++ b/src/org/torproject/android/OrbotApp.java @@ -4,11 +4,14 @@ import java.util.Locale; import org.torproject.android.service.TorServiceUtils; +import android.app.Activity; import android.app.Application; import android.content.SharedPreferences; import android.content.res.Configuration; import android.preference.PreferenceManager; +import info.guardianproject.util.Languages; + public class OrbotApp extends Application implements OrbotConstants { @@ -65,4 +68,8 @@ public class OrbotApp extends Application implements OrbotConstants getResources().updateConfiguration(myConfig, getResources().getDisplayMetrics()); } } + + public static Languages getLanguages(Activity activity) { + return Languages.get(activity, R.string.menu_settings, "Settings"); + } } diff --git a/src/org/torproject/android/settings/SettingsPreferences.java b/src/org/torproject/android/settings/SettingsPreferences.java index 5b215140..f20898be 100644 --- a/src/org/torproject/android/settings/SettingsPreferences.java +++ b/src/org/torproject/android/settings/SettingsPreferences.java @@ -3,13 +3,6 @@ package org.torproject.android.settings; -import java.util.Locale; - -import org.sufficientlysecure.rootcommands.RootCommands; -import org.sufficientlysecure.rootcommands.Shell; -import org.torproject.android.R; -import org.torproject.android.service.TorServiceUtils; - import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; @@ -23,9 +16,19 @@ import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceActivity; import android.widget.Toast; +import info.guardianproject.util.Languages; + +import org.sufficientlysecure.rootcommands.RootCommands; +import org.sufficientlysecure.rootcommands.Shell; +import org.torproject.android.R; +import org.torproject.android.service.TorServiceUtils; + +import java.util.Locale; + public class SettingsPreferences extends PreferenceActivity implements OnPreferenceClickListener { + private static final String TAG = "SettingsPreferences"; private CheckBoxPreference prefCBTransProxy = null; private CheckBoxPreference prefcBTransProxyAll = null; @@ -50,6 +53,9 @@ public class SettingsPreferences prefLocale = (ListPreference) findPreference("pref_default_locale"); prefLocale.setOnPreferenceClickListener(this); + Languages languages = Languages.get(this, R.string.menu_settings, "Settings"); + prefLocale.setEntries(languages.getAllNames()); + prefLocale.setEntryValues(languages.getSupportedLocales()); prefCBTransProxy = (CheckBoxPreference) findPreference("pref_transparent"); prefcBTransProxyAll = (CheckBoxPreference) findPreference("pref_transparent_all"); @@ -128,25 +134,24 @@ public class SettingsPreferences } else if (preference == prefLocale) { - SharedPreferences settings = TorServiceUtils.getSharedPrefs(getApplicationContext()); + SharedPreferences settings = TorServiceUtils.getSharedPrefs(getApplicationContext()); - Configuration config = getResources().getConfiguration(); + Configuration config = getResources().getConfiguration(); - String lang = settings.getString("pref_default_locale", ""); - - Locale locale; - - if (lang.equals("xx")) - { - locale = Locale.getDefault(); - - } - else - locale = new Locale(lang); - - Locale.setDefault(locale); - config.locale = locale; - getResources().updateConfiguration(config, getResources().getDisplayMetrics()); + String lang = settings.getString("pref_default_locale", "en"); + + Locale locale; + + if (lang.equals("xx")) + { + locale = Locale.getDefault(); + } + else + locale = new Locale(lang); + + Locale.setDefault(locale); + config.locale = locale; + getResources().updateConfiguration(config, getResources().getDisplayMetrics()); } else diff --git a/src/org/torproject/android/ui/wizard/ChooseLocaleWizardActivity.java b/src/org/torproject/android/ui/wizard/ChooseLocaleWizardActivity.java index 79faa83d..a804f45c 100644 --- a/src/org/torproject/android/ui/wizard/ChooseLocaleWizardActivity.java +++ b/src/org/torproject/android/ui/wizard/ChooseLocaleWizardActivity.java @@ -1,11 +1,5 @@ package org.torproject.android.ui.wizard; -import java.util.Locale; - -import org.torproject.android.R; -import org.torproject.android.OrbotConstants; -import org.torproject.android.service.TorServiceUtils; - import android.app.Activity; import android.content.Intent; import android.content.SharedPreferences; @@ -21,32 +15,39 @@ import android.widget.Button; import android.widget.ListView; import android.widget.Toast; +import info.guardianproject.util.Languages; + +import org.torproject.android.OrbotApp; +import org.torproject.android.OrbotConstants; +import org.torproject.android.R; +import org.torproject.android.service.TorServiceUtils; + +import java.util.Locale; + public class ChooseLocaleWizardActivity extends Activity implements OrbotConstants { - private int flag = 0; private ListView listLocales; + private String[] localeValues; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_wizard_locale); - - + listLocales = (ListView)findViewById(R.id.wizard_locale_list); Button next = ((Button)findViewById(R.id.btnWizard2)); // next.setEnabled(false); - String[] strLangs = getResources().getStringArray(R.array.languages); - strLangs[0] = Locale.getDefault().getDisplayName(); - ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, android.R.id.text1, strLangs); + Languages languages = OrbotApp.getLanguages(this); + localeValues = languages.getSupportedLocales(); + ArrayAdapter adapter = new ArrayAdapter(this, + android.R.layout.simple_list_item_1, android.R.id.text1, + languages.getAllNames()); listLocales.setAdapter(adapter); - + listLocales.setSelection(0); - - listLocales.setOnItemClickListener(new OnItemClickListener() { - @Override public void onItemClick(AdapterView arg0, View arg1, @@ -55,7 +56,6 @@ public class ChooseLocaleWizardActivity extends Activity implements OrbotConstan setLocalePref(arg2); finish(); startActivity(new Intent(ChooseLocaleWizardActivity.this, PromoAppsActivity.class)); - } }); @@ -68,21 +68,15 @@ public class ChooseLocaleWizardActivity extends Activity implements OrbotConstan } }); - - - } private void setLocalePref(int selId) { - SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); Configuration config = getResources().getConfiguration(); - - String[] localeVals = getResources().getStringArray(R.array.languages_values); - String lang = localeVals[selId]; + String lang = localeValues[selId]; Editor pEdit = prefs.edit(); pEdit.putString(PREF_DEFAULT_LOCALE, lang);