Implement language switcher (#344)

* Implement language switcher

* Use unique string resource to enumerate translated locale
This commit is contained in:
0140454 2018-08-01 20:18:54 +08:00 committed by m2049r
parent 403dbdf14f
commit 03efedf35c
20 changed files with 227 additions and 15 deletions

View File

@ -52,6 +52,7 @@ import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.service.WalletService; import com.m2049r.xmrwallet.service.WalletService;
import com.m2049r.xmrwallet.util.Helper; import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.KeyStoreHelper; import com.m2049r.xmrwallet.util.KeyStoreHelper;
import com.m2049r.xmrwallet.util.LocaleHelper;
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor; import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
import com.m2049r.xmrwallet.widget.Toolbar; import com.m2049r.xmrwallet.widget.Toolbar;
@ -62,7 +63,12 @@ import java.io.IOException;
import java.net.Socket; import java.net.Socket;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.Locale;
import timber.log.Timber; import timber.log.Timber;
@ -959,6 +965,48 @@ public class LoginActivity extends SecureActivity
} }
} }
public void onChangeLocale() {
final ArrayList<Locale> translatedLocales = LocaleHelper.getAvailableLocales(LoginActivity.this);
String[] localeDisplayName = new String[1 + translatedLocales.size()];
Collections.sort(translatedLocales, new Comparator<Locale>() {
@Override
public int compare(Locale locale1, Locale locale2) {
String localeString1 = LocaleHelper.getLocaleString(LoginActivity.this, locale1, LocaleHelper.COMPARED_RESOURCE_ID);
String localeString2 = LocaleHelper.getLocaleString(LoginActivity.this, locale2, LocaleHelper.COMPARED_RESOURCE_ID);
return localeString1.compareTo(localeString2);
}
});
localeDisplayName[0] = getString(R.string.language_system_default);
for (int i = 1; i < localeDisplayName.length; i++) {
Locale locale = translatedLocales.get(i - 1);
localeDisplayName[i] = LocaleHelper.getLocaleString(LoginActivity.this, locale, LocaleHelper.COMPARED_RESOURCE_ID);
}
int currentLocaleIndex = 0;
String currentLocaleName = LocaleHelper.getLocale(LoginActivity.this);
if (!currentLocaleName.isEmpty()) {
Locale currentLocale = Locale.forLanguageTag(currentLocaleName);
String currentLocalizedString = LocaleHelper.getLocaleString(LoginActivity.this, currentLocale, LocaleHelper.COMPARED_RESOURCE_ID);
currentLocaleIndex = Arrays.asList(localeDisplayName).indexOf(currentLocalizedString);
}
AlertDialog.Builder builder = new AlertDialog.Builder(LoginActivity.this);
builder.setTitle(getString(R.string.menu_language));
builder.setSingleChoiceItems(localeDisplayName, currentLocaleIndex, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
dialog.dismiss();
LocaleHelper.setLocale(LoginActivity.this,
(i == 0) ? "" : translatedLocales.get(i - 1).toLanguageTag());
startActivity(getIntent().addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK));
}
});
builder.show();
}
@Override @Override
public void onBackPressed() { public void onBackPressed() {
Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_container); Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
@ -1007,6 +1055,9 @@ public class LoginActivity extends SecureActivity
case R.id.action_privacy_policy: case R.id.action_privacy_policy:
PrivacyFragment.display(getSupportFragmentManager()); PrivacyFragment.display(getSupportFragmentManager());
return true; return true;
case R.id.action_language:
onChangeLocale();
return true;
case R.id.action_stagenet: case R.id.action_stagenet:
try { try {
LoginFragment loginFragment = (LoginFragment) LoginFragment loginFragment = (LoginFragment)

View File

@ -16,13 +16,12 @@
package com.m2049r.xmrwallet; package com.m2049r.xmrwallet;
import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import com.m2049r.xmrwallet.util.Helper; import com.m2049r.xmrwallet.util.LocaleHelper;
import java.io.File;
import static android.view.WindowManager.LayoutParams; import static android.view.WindowManager.LayoutParams;
@ -36,4 +35,9 @@ public abstract class SecureActivity extends AppCompatActivity {
getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE); getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
} }
} }
@Override
protected void attachBaseContext(Context context) {
super.attachBaseContext(LocaleHelper.setLocale(context, LocaleHelper.getLocale(context)));
}
} }

View File

@ -18,8 +18,10 @@ package com.m2049r.xmrwallet;
import android.app.Application; import android.app.Application;
import android.content.Context;
import android.content.res.Configuration;
import com.m2049r.xmrwallet.util.Helper; import com.m2049r.xmrwallet.util.LocaleHelper;
import timber.log.Timber; import timber.log.Timber;
@ -27,9 +29,21 @@ public class XmrWalletApplication extends Application {
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
Timber.plant(new Timber.DebugTree()); Timber.plant(new Timber.DebugTree());
} }
} }
@Override
protected void attachBaseContext(Context context) {
super.attachBaseContext(LocaleHelper.setLocale(context, LocaleHelper.getLocale(context)));
}
@Override
public void onConfigurationChanged(Configuration configuration) {
super.onConfigurationChanged(configuration);
LocaleHelper.updateSystemDefaultLocale(configuration.locale);
LocaleHelper.setLocale(XmrWalletApplication.this, LocaleHelper.getLocale(XmrWalletApplication.this));
}
} }

View File

@ -19,6 +19,7 @@ package com.m2049r.xmrwallet.service;
import android.app.Notification; import android.app.Notification;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.Service; import android.app.Service;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Binder; import android.os.Binder;
import android.os.Bundle; import android.os.Bundle;
@ -36,6 +37,7 @@ import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletListener; import com.m2049r.xmrwallet.model.WalletListener;
import com.m2049r.xmrwallet.model.WalletManager; import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.util.Helper; import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.LocaleHelper;
import timber.log.Timber; import timber.log.Timber;
@ -418,6 +420,11 @@ public class WalletService extends Service {
} }
} }
@Override
protected void attachBaseContext(Context context) {
super.attachBaseContext(LocaleHelper.setLocale(context, LocaleHelper.getLocale(context)));
}
public class WalletServiceBinder extends Binder { public class WalletServiceBinder extends Binder {
public WalletService getService() { public WalletService getService() {
return WalletService.this; return WalletService.this;

View File

@ -0,0 +1,74 @@
package com.m2049r.xmrwallet.util;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Configuration;
import android.preference.PreferenceManager;
import com.m2049r.xmrwallet.R;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Locale;
public class LocaleHelper {
public static final int COMPARED_RESOURCE_ID = R.string.language;
private static final String PREFERRED_LOCALE_KEY = "preferred_locale";
private static Locale SYSTEM_DEFAULT_LOCALE = Locale.getDefault();
public static ArrayList<Locale> getAvailableLocales(Context context) {
ArrayList<Locale> locales = new ArrayList<>();
HashSet<String> localizedStrings = new HashSet<>();
for (String localeName : context.getAssets().getLocales()) {
Locale locale = Locale.forLanguageTag(localeName);
String localizedString = getLocaleString(context, locale, COMPARED_RESOURCE_ID);
if (localizedStrings.add(localizedString)) {
locales.add(locale);
}
}
return locales;
}
public static String getLocale(Context context) {
return getPreferredLocale(context);
}
public static Context setLocale(Context context, String locale) {
setPreferredLocale(context, locale);
Locale newLocale = (locale.isEmpty()) ? SYSTEM_DEFAULT_LOCALE : Locale.forLanguageTag(locale);
Configuration configuration = context.getResources().getConfiguration();
Locale.setDefault(newLocale);
configuration.setLocale(newLocale);
configuration.setLayoutDirection(newLocale);
return context.createConfigurationContext(configuration);
}
public static void updateSystemDefaultLocale(Locale locale) {
SYSTEM_DEFAULT_LOCALE = locale;
}
public static String getLocaleString(Context context, Locale locale, int resId) {
Configuration configuration = context.getResources().getConfiguration();
configuration.setLocale(locale);
return context.createConfigurationContext(configuration).getString(resId);
}
private static String getPreferredLocale(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context)
.getString(PREFERRED_LOCALE_KEY, "");
}
@SuppressLint("ApplySharedPref")
private static void setPreferredLocale(Context context, String locale) {
PreferenceManager.getDefaultSharedPreferences(context).edit()
.putString(PREFERRED_LOCALE_KEY, locale).commit();
}
}

View File

@ -10,21 +10,27 @@
app:showAsAction="never" /> app:showAsAction="never" />
<item <item
android:id="@+id/action_license_info" android:id="@+id/action_language"
android:orderInCategory="200" android:orderInCategory="200"
android:title="@string/menu_language"
app:showAsAction="never" />
<item
android:id="@+id/action_license_info"
android:orderInCategory="300"
android:title="@string/menu_about" android:title="@string/menu_about"
app:showAsAction="never" /> app:showAsAction="never" />
<item <item
android:id="@+id/action_privacy_policy" android:id="@+id/action_privacy_policy"
android:orderInCategory="300" android:orderInCategory="400"
android:title="@string/menu_privacy" android:title="@string/menu_privacy"
app:showAsAction="never" /> app:showAsAction="never" />
<item <item
android:id="@+id/action_help_list" android:id="@+id/action_help_list"
android:icon="@drawable/ic_help_white_24dp" android:icon="@drawable/ic_help_white_24dp"
android:orderInCategory="400" android:orderInCategory="500"
android:title="@string/menu_help" android:title="@string/menu_help"
app:showAsAction="ifRoom" /> app:showAsAction="ifRoom" />

View File

@ -318,4 +318,8 @@
<string name="send_sweepall">Versende ALLE(!) verfügbaren Gelder aus diesem Konto</string> <string name="send_sweepall">Versende ALLE(!) verfügbaren Gelder aus diesem Konto</string>
<string name="tx_subaddress">Subadresse #%1$d</string> <string name="tx_subaddress">Subadresse #%1$d</string>
<string name="generate_address_label_sub">Öffentliche Subadresse #%1$d</string> <string name="generate_address_label_sub">Öffentliche Subadresse #%1$d</string>
<string name="language">Deutsch</string>
<string name="menu_language">Language</string>
<string name="language_system_default">Use System Language</string>
</resources> </resources>

View File

@ -317,4 +317,8 @@
<string name="send_sweepall">Send all confirmed funds in this account!</string> <string name="send_sweepall">Send all confirmed funds in this account!</string>
<string name="tx_subaddress">Subaddress #%1$d</string> <string name="tx_subaddress">Subaddress #%1$d</string>
<string name="generate_address_label_sub">Public Subaddress #%1$d</string> <string name="generate_address_label_sub">Public Subaddress #%1$d</string>
<string name="language">Ελληνικά</string>
<string name="menu_language">Language</string>
<string name="language_system_default">Use System Language</string>
</resources> </resources>

View File

@ -303,4 +303,8 @@
<string name="send_sweepall">Send all confirmed funds in this account!</string> <string name="send_sweepall">Send all confirmed funds in this account!</string>
<string name="tx_subaddress">Subaddress #%1$d</string> <string name="tx_subaddress">Subaddress #%1$d</string>
<string name="generate_address_label_sub">Public Subaddress #%1$d</string> <string name="generate_address_label_sub">Public Subaddress #%1$d</string>
<string name="language">Español</string>
<string name="menu_language">Language</string>
<string name="language_system_default">Use System Language</string>
</resources> </resources>

View File

@ -321,4 +321,8 @@
<string name="send_sweepall">Send all confirmed funds in this account!</string> <string name="send_sweepall">Send all confirmed funds in this account!</string>
<string name="tx_subaddress">Subaddress #%1$d</string> <string name="tx_subaddress">Subaddress #%1$d</string>
<string name="generate_address_label_sub">Public Subaddress #%1$d</string> <string name="generate_address_label_sub">Public Subaddress #%1$d</string>
<string name="language">Français</string>
<string name="menu_language">Language</string>
<string name="language_system_default">Use System Language</string>
</resources> </resources>

View File

@ -319,4 +319,8 @@
<string name="send_sweepall">Teljes megerősített egyenleg küldése!</string> <string name="send_sweepall">Teljes megerősített egyenleg küldése!</string>
<string name="tx_subaddress">Alcím #%1$d</string> <string name="tx_subaddress">Alcím #%1$d</string>
<string name="generate_address_label_sub">Nyilvános alcím #%1$d</string> <string name="generate_address_label_sub">Nyilvános alcím #%1$d</string>
<string name="language">Magyar</string>
<string name="menu_language">Language</string>
<string name="language_system_default">Use System Language</string>
</resources> </resources>

View File

@ -319,4 +319,8 @@
<string name="send_sweepall">Manda tutti i fondi confermati in questo account!</string> <string name="send_sweepall">Manda tutti i fondi confermati in questo account!</string>
<string name="tx_subaddress">Subaddress #%1$d</string> <string name="tx_subaddress">Subaddress #%1$d</string>
<string name="generate_address_label_sub">Subaddress pubblico #%1$d</string> <string name="generate_address_label_sub">Subaddress pubblico #%1$d</string>
<string name="language">Italiano</string>
<string name="menu_language">Language</string>
<string name="language_system_default">Use System Language</string>
</resources> </resources>

View File

@ -317,4 +317,8 @@
<string name="send_sweepall">Send all confirmed funds in this account!</string> <string name="send_sweepall">Send all confirmed funds in this account!</string>
<string name="tx_subaddress">Subaddress #%1$d</string> <string name="tx_subaddress">Subaddress #%1$d</string>
<string name="generate_address_label_sub">Public Subaddress #%1$d</string> <string name="generate_address_label_sub">Public Subaddress #%1$d</string>
<string name="language">Norsk bokmål</string>
<string name="menu_language">Language</string>
<string name="language_system_default">Use System Language</string>
</resources> </resources>

View File

@ -321,4 +321,8 @@
<string name="send_sweepall">Send all confirmed funds in this account!</string> <string name="send_sweepall">Send all confirmed funds in this account!</string>
<string name="tx_subaddress">Subaddress #%1$d</string> <string name="tx_subaddress">Subaddress #%1$d</string>
<string name="generate_address_label_sub">Public Subaddress #%1$d</string> <string name="generate_address_label_sub">Public Subaddress #%1$d</string>
<string name="language">Português</string>
<string name="menu_language">Language</string>
<string name="language_system_default">Use System Language</string>
</resources> </resources>

View File

@ -317,4 +317,8 @@
<string name="send_sweepall">Send all confirmed funds in this account!</string> <string name="send_sweepall">Send all confirmed funds in this account!</string>
<string name="tx_subaddress">Subaddress #%1$d</string> <string name="tx_subaddress">Subaddress #%1$d</string>
<string name="generate_address_label_sub">Public Subaddress #%1$d</string> <string name="generate_address_label_sub">Public Subaddress #%1$d</string>
<string name="language">Română</string>
<string name="menu_language">Language</string>
<string name="language_system_default">Use System Language</string>
</resources> </resources>

View File

@ -320,4 +320,8 @@
<string name="send_sweepall">Отправить все средства на этот счет!</string> <string name="send_sweepall">Отправить все средства на этот счет!</string>
<string name="tx_subaddress">Субадрес #%1$d</string> <string name="tx_subaddress">Субадрес #%1$d</string>
<string name="generate_address_label_sub">Публичный субадрес #%1$d</string> <string name="generate_address_label_sub">Публичный субадрес #%1$d</string>
<string name="language">Русский</string>
<string name="menu_language">Language</string>
<string name="language_system_default">Use System Language</string>
</resources> </resources>

View File

@ -302,4 +302,8 @@
<string name="send_sweepall">Send all confirmed funds in this account!</string> <string name="send_sweepall">Send all confirmed funds in this account!</string>
<string name="tx_subaddress">Subaddress #%1$d</string> <string name="tx_subaddress">Subaddress #%1$d</string>
<string name="generate_address_label_sub">Public Subaddress #%1$d</string> <string name="generate_address_label_sub">Public Subaddress #%1$d</string>
<string name="language">Svenska</string>
<string name="menu_language">Language</string>
<string name="language_system_default">Use System Language</string>
</resources> </resources>

View File

@ -315,4 +315,8 @@
<string name="send_sweepall">发送这个户口的所有已确认款项!</string> <string name="send_sweepall">发送这个户口的所有已确认款项!</string>
<string name="tx_subaddress">附属地址 #%1$d</string> <string name="tx_subaddress">附属地址 #%1$d</string>
<string name="generate_address_label_sub">附属公开地址 #%1$d</string> <string name="generate_address_label_sub">附属公开地址 #%1$d</string>
<string name="language">中文(中国)</string>
<string name="menu_language">语言</string>
<string name="language_system_default">使用系统语言</string>
</resources> </resources>

View File

@ -308,12 +308,16 @@
<string name="fab_restore_key">從私鑰回復錢包</string> <string name="fab_restore_key">從私鑰回復錢包</string>
<string name="fab_restore_seed">從25字種子碼回復錢包</string> <string name="fab_restore_seed">從25字種子碼回復錢包</string>
<string name="accounts_drawer_new">新戶</string> <string name="accounts_drawer_new">增帳</string>
<string name="accounts_drawer_title"></string> <string name="accounts_drawer_title"></string>
<string name="accounts_new">已新增戶 #%1$d</string> <string name="accounts_new">已新增戶 #%1$d</string>
<string name="tx_account"> #</string> <string name="tx_account">戶 #</string>
<string name="send_sweepall">發送這個戶口的所有已確認款項!</string> <string name="send_sweepall">發送這個帳戶的所有已確認款項!</string>
<string name="tx_subaddress">附屬地址 #%1$d</string> <string name="tx_subaddress">子地址 #%1$d</string>
<string name="generate_address_label_sub">附屬公開地址 #%1$d</string> <string name="generate_address_label_sub">公開子地址 #%1$d</string>
<string name="language">中文(台灣)</string>
<string name="menu_language">語言</string>
<string name="language_system_default">使用系統語言</string>
</resources> </resources>

View File

@ -365,4 +365,8 @@
<string name="send_sweepall">Send all confirmed funds in this account!</string> <string name="send_sweepall">Send all confirmed funds in this account!</string>
<string name="tx_subaddress">Subaddress #%1$d</string> <string name="tx_subaddress">Subaddress #%1$d</string>
<string name="generate_address_label_sub">Public Subaddress #%1$d</string> <string name="generate_address_label_sub">Public Subaddress #%1$d</string>
<string name="language">English</string>
<string name="menu_language">Language</string>
<string name="language_system_default">Use System Language</string>
</resources> </resources>