Removed locale manager loading languages in advance
Instead they are loaded on demand
This commit is contained in:
parent
58a449d437
commit
9491ba77e0
@ -146,7 +146,7 @@ public class MagiskDB {
|
|||||||
String dateString = null, newString;
|
String dateString = null, newString;
|
||||||
for (ContentValues values : SQL("SELECT * FROM %s ORDER BY time DESC", LOG_TABLE)) {
|
for (ContentValues values : SQL("SELECT * FROM %s ORDER BY time DESC", LOG_TABLE)) {
|
||||||
Date date = new Date(values.getAsLong("time"));
|
Date date = new Date(values.getAsLong("time"));
|
||||||
newString = DateFormat.getDateInstance(DateFormat.MEDIUM, LocaleManager.locale).format(date);
|
newString = DateFormat.getDateInstance(DateFormat.MEDIUM, LocaleManager.getLocale()).format(date);
|
||||||
if (!TextUtils.equals(dateString, newString)) {
|
if (!TextUtils.equals(dateString, newString)) {
|
||||||
dateString = newString;
|
dateString = newString;
|
||||||
list = new ArrayList<>();
|
list = new ArrayList<>();
|
||||||
|
@ -47,10 +47,10 @@ public class SuLogEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getDateString() {
|
public String getDateString() {
|
||||||
return DateFormat.getDateInstance(DateFormat.MEDIUM, LocaleManager.locale).format(date);
|
return DateFormat.getDateInstance(DateFormat.MEDIUM, LocaleManager.getLocale()).format(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTimeString() {
|
public String getTimeString() {
|
||||||
return new SimpleDateFormat("h:mm a", LocaleManager.locale).format(date);
|
return new SimpleDateFormat("h:mm a", LocaleManager.getLocale()).format(date);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import android.text.TextUtils
|
|||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.topjohnwu.magisk.*
|
import com.topjohnwu.magisk.*
|
||||||
import com.topjohnwu.magisk.utils.LocaleManager
|
|
||||||
import com.topjohnwu.magisk.utils.Utils
|
import com.topjohnwu.magisk.utils.Utils
|
||||||
import com.topjohnwu.magisk.view.Notifications
|
import com.topjohnwu.magisk.view.Notifications
|
||||||
import com.topjohnwu.magisk.view.Shortcuts
|
import com.topjohnwu.magisk.view.Shortcuts
|
||||||
@ -45,9 +44,6 @@ open class SplashActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynamic detect all locales
|
|
||||||
LocaleManager.loadAvailableLocales(R.string.app_changelog)
|
|
||||||
|
|
||||||
// Set default configs
|
// Set default configs
|
||||||
Config.initialize()
|
Config.initialize()
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ import android.view.ViewGroup;
|
|||||||
|
|
||||||
import com.topjohnwu.magisk.App;
|
import com.topjohnwu.magisk.App;
|
||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.utils.Event;
|
|
||||||
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.PreferenceCategory;
|
import androidx.preference.PreferenceCategory;
|
||||||
@ -21,7 +20,7 @@ import androidx.preference.PreferenceViewHolder;
|
|||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
public abstract class BasePreferenceFragment extends PreferenceFragmentCompat
|
public abstract class BasePreferenceFragment extends PreferenceFragmentCompat
|
||||||
implements SharedPreferences.OnSharedPreferenceChangeListener, Event.AutoListener {
|
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
public App app = App.self;
|
public App app = App.self;
|
||||||
|
|
||||||
@ -29,22 +28,15 @@ public abstract class BasePreferenceFragment extends PreferenceFragmentCompat
|
|||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
View v = super.onCreateView(inflater, container, savedInstanceState);
|
View v = super.onCreateView(inflater, container, savedInstanceState);
|
||||||
app.getPrefs().registerOnSharedPreferenceChangeListener(this);
|
app.getPrefs().registerOnSharedPreferenceChangeListener(this);
|
||||||
Event.register(this);
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
app.getPrefs().unregisterOnSharedPreferenceChangeListener(this);
|
app.getPrefs().unregisterOnSharedPreferenceChangeListener(this);
|
||||||
Event.unregister(this);
|
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int[] getListeningEvents() {
|
|
||||||
return new int[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
|
protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
|
||||||
return new PreferenceGroupAdapter(preferenceScreen) {
|
return new PreferenceGroupAdapter(preferenceScreen) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.topjohnwu.magisk.ui.settings;
|
package com.topjohnwu.magisk.ui.settings;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -14,7 +15,6 @@ import com.topjohnwu.magisk.Const;
|
|||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.ui.base.BasePreferenceFragment;
|
import com.topjohnwu.magisk.ui.base.BasePreferenceFragment;
|
||||||
import com.topjohnwu.magisk.utils.DownloadApp;
|
import com.topjohnwu.magisk.utils.DownloadApp;
|
||||||
import com.topjohnwu.magisk.utils.Event;
|
|
||||||
import com.topjohnwu.magisk.utils.FingerprintHelper;
|
import com.topjohnwu.magisk.utils.FingerprintHelper;
|
||||||
import com.topjohnwu.magisk.utils.LocaleManager;
|
import com.topjohnwu.magisk.utils.LocaleManager;
|
||||||
import com.topjohnwu.magisk.utils.PatchAPK;
|
import com.topjohnwu.magisk.utils.PatchAPK;
|
||||||
@ -25,7 +25,6 @@ import com.topjohnwu.superuser.Shell;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.preference.ListPreference;
|
import androidx.preference.ListPreference;
|
||||||
@ -33,6 +32,9 @@ import androidx.preference.Preference;
|
|||||||
import androidx.preference.PreferenceCategory;
|
import androidx.preference.PreferenceCategory;
|
||||||
import androidx.preference.PreferenceScreen;
|
import androidx.preference.PreferenceScreen;
|
||||||
import androidx.preference.SwitchPreferenceCompat;
|
import androidx.preference.SwitchPreferenceCompat;
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
import kotlin.Pair;
|
||||||
|
|
||||||
public class SettingsFragment extends BasePreferenceFragment {
|
public class SettingsFragment extends BasePreferenceFragment {
|
||||||
|
|
||||||
@ -115,6 +117,8 @@ public class SettingsFragment extends BasePreferenceFragment {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setLocalePreference((ListPreference) findPreference(Config.Key.LOCALE));
|
||||||
|
|
||||||
/* We only show canary channels if user is already on canary channel
|
/* We only show canary channels if user is already on canary channel
|
||||||
* or the user have already chosen canary channel */
|
* or the user have already chosen canary channel */
|
||||||
if (!Utils.isCanary() &&
|
if (!Utils.isCanary() &&
|
||||||
@ -168,19 +172,36 @@ public class SettingsFragment extends BasePreferenceFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
private void setLocalePreference(ListPreference lp) {
|
private void setLocalePreference(ListPreference lp) {
|
||||||
CharSequence[] entries = new CharSequence[LocaleManager.locales.size() + 1];
|
lp.setSummary("Loading");
|
||||||
CharSequence[] entryValues = new CharSequence[LocaleManager.locales.size() + 1];
|
lp.setEnabled(false);
|
||||||
entries[0] = LocaleManager.getString(LocaleManager.defaultLocale, R.string.system_default);
|
LocaleManager.getAvailableLocales()
|
||||||
entryValues[0] = "";
|
.flattenAsFlowable(locales -> locales)
|
||||||
int i = 1;
|
.map(locale -> new Pair<>(locale.getDisplayName(locale), LocaleManager.toLanguageTag(locale)))
|
||||||
for (Locale locale : LocaleManager.locales) {
|
.toList()
|
||||||
entries[i] = locale.getDisplayName(locale);
|
.map(list -> {
|
||||||
entryValues[i++] = LocaleManager.toLanguageTag(locale);
|
CharSequence[] names = new CharSequence[list.size() + 1];
|
||||||
}
|
CharSequence[] values = new CharSequence[list.size() + 1];
|
||||||
lp.setEntries(entries);
|
|
||||||
lp.setEntryValues(entryValues);
|
names[0] = LocaleManager.getString(LocaleManager.getDefaultLocale(), R.string.system_default);
|
||||||
lp.setSummary(LocaleManager.locale.getDisplayName(LocaleManager.locale));
|
values[0] = "";
|
||||||
|
int i = 1;
|
||||||
|
for (Pair<String, String> item : list) {
|
||||||
|
names[i] = item.getFirst();
|
||||||
|
values[i++] = item.getSecond();
|
||||||
|
}
|
||||||
|
return new Pair<>(names, values);
|
||||||
|
})
|
||||||
|
.subscribeOn(Schedulers.computation())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(it -> {
|
||||||
|
lp.setEnabled(true);
|
||||||
|
lp.setEntries(it.getFirst());
|
||||||
|
lp.setEntryValues(it.getSecond());
|
||||||
|
lp.setSummary(LocaleManager.getLocale().getDisplayName(LocaleManager.getLocale()));
|
||||||
|
}, Throwable::printStackTrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -198,7 +219,8 @@ public class SettingsFragment extends BasePreferenceFragment {
|
|||||||
if (prefs.getBoolean(key, false)) {
|
if (prefs.getBoolean(key, false)) {
|
||||||
try {
|
try {
|
||||||
Const.MAGISK_DISABLE_FILE.createNewFile();
|
Const.MAGISK_DISABLE_FILE.createNewFile();
|
||||||
} catch (IOException ignored) {}
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Const.MAGISK_DISABLE_FILE.delete();
|
Const.MAGISK_DISABLE_FILE.delete();
|
||||||
}
|
}
|
||||||
@ -252,27 +274,27 @@ public class SettingsFragment extends BasePreferenceFragment {
|
|||||||
break;
|
break;
|
||||||
case Config.Key.ROOT_ACCESS:
|
case Config.Key.ROOT_ACCESS:
|
||||||
rootConfig.setSummary(getResources()
|
rootConfig.setSummary(getResources()
|
||||||
.getStringArray(R.array.su_access)[(int)Config.get(key)]);
|
.getStringArray(R.array.su_access)[(int) Config.get(key)]);
|
||||||
break;
|
break;
|
||||||
case Config.Key.SU_AUTO_RESPONSE:
|
case Config.Key.SU_AUTO_RESPONSE:
|
||||||
autoRes.setSummary(getResources()
|
autoRes.setSummary(getResources()
|
||||||
.getStringArray(R.array.auto_response)[(int)Config.get(key)]);
|
.getStringArray(R.array.auto_response)[(int) Config.get(key)]);
|
||||||
break;
|
break;
|
||||||
case Config.Key.SU_NOTIFICATION:
|
case Config.Key.SU_NOTIFICATION:
|
||||||
suNotification.setSummary(getResources()
|
suNotification.setSummary(getResources()
|
||||||
.getStringArray(R.array.su_notification)[(int)Config.get(key)]);
|
.getStringArray(R.array.su_notification)[(int) Config.get(key)]);
|
||||||
break;
|
break;
|
||||||
case Config.Key.SU_REQUEST_TIMEOUT:
|
case Config.Key.SU_REQUEST_TIMEOUT:
|
||||||
requestTimeout.setSummary(
|
requestTimeout.setSummary(
|
||||||
getString(R.string.request_timeout_summary, (int)Config.get(key)));
|
getString(R.string.request_timeout_summary, (int) Config.get(key)));
|
||||||
break;
|
break;
|
||||||
case Config.Key.SU_MULTIUSER_MODE:
|
case Config.Key.SU_MULTIUSER_MODE:
|
||||||
multiuserConfig.setSummary(getResources()
|
multiuserConfig.setSummary(getResources()
|
||||||
.getStringArray(R.array.multiuser_summary)[(int)Config.get(key)]);
|
.getStringArray(R.array.multiuser_summary)[(int) Config.get(key)]);
|
||||||
break;
|
break;
|
||||||
case Config.Key.SU_MNT_NS:
|
case Config.Key.SU_MNT_NS:
|
||||||
nsConfig.setSummary(getResources()
|
nsConfig.setSummary(getResources()
|
||||||
.getStringArray(R.array.namespace_summary)[(int)Config.get(key)]);
|
.getStringArray(R.array.namespace_summary)[(int) Config.get(key)]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -286,16 +308,4 @@ public class SettingsFragment extends BasePreferenceFragment {
|
|||||||
setSummary(Config.Key.SU_MULTIUSER_MODE);
|
setSummary(Config.Key.SU_MULTIUSER_MODE);
|
||||||
setSummary(Config.Key.SU_MNT_NS);
|
setSummary(Config.Key.SU_MNT_NS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@Deprecated
|
|
||||||
public void onEvent(int event) {
|
|
||||||
setLocalePreference((ListPreference) findPreference(Config.Key.LOCALE));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Deprecated
|
|
||||||
public int[] getListeningEvents() {
|
|
||||||
return new int[] {Event.LOCALE_FETCH_DONE};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,148 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.utils;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.ContextWrapper;
|
|
||||||
import android.content.res.Configuration;
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.App;
|
|
||||||
import com.topjohnwu.magisk.Config;
|
|
||||||
import com.topjohnwu.superuser.Shell;
|
|
||||||
import com.topjohnwu.superuser.internal.InternalUtils;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import androidx.annotation.StringRes;
|
|
||||||
|
|
||||||
public class LocaleManager {
|
|
||||||
public static Locale locale = Locale.getDefault();
|
|
||||||
public static final Locale defaultLocale = Locale.getDefault();
|
|
||||||
public static List<Locale> locales;
|
|
||||||
|
|
||||||
public static Locale forLanguageTag(String tag) {
|
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
|
||||||
return Locale.forLanguageTag(tag);
|
|
||||||
} else {
|
|
||||||
String[] tok = tag.split("-");
|
|
||||||
if (tok.length == 0) {
|
|
||||||
return new Locale("");
|
|
||||||
}
|
|
||||||
String language;
|
|
||||||
switch (tok[0]) {
|
|
||||||
case "und":
|
|
||||||
language = ""; // Undefined
|
|
||||||
break;
|
|
||||||
case "fil":
|
|
||||||
language = "tl"; // Filipino
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
language = tok[0];
|
|
||||||
}
|
|
||||||
if (language.length() != 2 && language.length() != 3)
|
|
||||||
return new Locale("");
|
|
||||||
if (tok.length == 1)
|
|
||||||
return new Locale(language);
|
|
||||||
String country = tok[1];
|
|
||||||
if (country.length() != 2 && country.length() != 3)
|
|
||||||
return new Locale(language);
|
|
||||||
return new Locale(language, country);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String toLanguageTag(Locale loc) {
|
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
|
||||||
return loc.toLanguageTag();
|
|
||||||
} else {
|
|
||||||
String language = loc.getLanguage();
|
|
||||||
String country = loc.getCountry();
|
|
||||||
String variant = loc.getVariant();
|
|
||||||
if (language.isEmpty() || !language.matches("\\p{Alpha}{2,8}")) {
|
|
||||||
language = "und"; // Follow the Locale#toLanguageTag() implementation
|
|
||||||
} else if (language.equals("iw")) {
|
|
||||||
language = "he"; // correct deprecated "Hebrew"
|
|
||||||
} else if (language.equals("in")) {
|
|
||||||
language = "id"; // correct deprecated "Indonesian"
|
|
||||||
} else if (language.equals("ji")) {
|
|
||||||
language = "yi"; // correct deprecated "Yiddish"
|
|
||||||
}
|
|
||||||
// ensure valid country code, if not well formed, it's omitted
|
|
||||||
if (!country.matches("\\p{Alpha}{2}|\\p{Digit}{3}")) {
|
|
||||||
country = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// variant subtags that begin with a letter must be at least 5 characters long
|
|
||||||
if (!variant.matches("\\p{Alnum}{5,8}|\\p{Digit}\\p{Alnum}{3}")) {
|
|
||||||
variant = "";
|
|
||||||
}
|
|
||||||
StringBuilder tag = new StringBuilder(language);
|
|
||||||
if (!country.isEmpty())
|
|
||||||
tag.append('-').append(country);
|
|
||||||
if (!variant.isEmpty())
|
|
||||||
tag.append('-').append(variant);
|
|
||||||
return tag.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setLocale(ContextWrapper wrapper) {
|
|
||||||
String localeConfig = Config.get(Config.Key.LOCALE);
|
|
||||||
if (TextUtils.isEmpty(localeConfig)) {
|
|
||||||
locale = defaultLocale;
|
|
||||||
} else {
|
|
||||||
locale = forLanguageTag(localeConfig);
|
|
||||||
}
|
|
||||||
Locale.setDefault(locale);
|
|
||||||
InternalUtils.replaceBaseContext(wrapper, getLocaleContext(locale));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Context getLocaleContext(Context context, Locale locale) {
|
|
||||||
Configuration config = new Configuration(context.getResources().getConfiguration());
|
|
||||||
config.setLocale(locale);
|
|
||||||
return context.createConfigurationContext(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Context getLocaleContext(Locale locale) {
|
|
||||||
return getLocaleContext(App.self.getBaseContext(), locale);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getString(Locale locale, @StringRes int id) {
|
|
||||||
return getLocaleContext(locale).getString(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static void loadAvailableLocales(@StringRes int compareId) {
|
|
||||||
Shell.EXECUTOR.execute(() -> {
|
|
||||||
locales = new ArrayList<>();
|
|
||||||
HashSet<String> set = new HashSet<>();
|
|
||||||
Resources res = App.self.getResources();
|
|
||||||
Locale locale;
|
|
||||||
|
|
||||||
// Add default locale
|
|
||||||
locales.add(Locale.ENGLISH);
|
|
||||||
set.add(getString(Locale.ENGLISH, compareId));
|
|
||||||
|
|
||||||
// Add some special locales
|
|
||||||
locales.add(Locale.TAIWAN);
|
|
||||||
set.add(getString(Locale.TAIWAN, compareId));
|
|
||||||
locale = new Locale("pt", "BR");
|
|
||||||
locales.add(locale);
|
|
||||||
set.add(getString(locale, compareId));
|
|
||||||
|
|
||||||
// Other locales
|
|
||||||
for (String s : res.getAssets().getLocales()) {
|
|
||||||
locale = forLanguageTag(s);
|
|
||||||
if (set.add(getString(locale, compareId))) {
|
|
||||||
locales.add(locale);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Collections.sort(locales, (a, b) -> a.getDisplayName(a).compareTo(b.getDisplayName(b)));
|
|
||||||
Event.trigger(Event.LOCALE_FETCH_DONE);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
135
app/src/main/java/com/topjohnwu/magisk/utils/LocaleManager.kt
Normal file
135
app/src/main/java/com/topjohnwu/magisk/utils/LocaleManager.kt
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
package com.topjohnwu.magisk.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.ContextWrapper
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import android.content.res.Resources
|
||||||
|
import android.os.Build
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import com.topjohnwu.magisk.App
|
||||||
|
import com.topjohnwu.magisk.Config
|
||||||
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.superuser.internal.InternalUtils
|
||||||
|
import io.reactivex.Single
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
object LocaleManager {
|
||||||
|
@JvmStatic
|
||||||
|
var locale = Locale.getDefault()
|
||||||
|
@JvmStatic
|
||||||
|
val defaultLocale = Locale.getDefault()
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
val availableLocales = Single.fromCallable {
|
||||||
|
val compareId = R.string.app_changelog
|
||||||
|
val res: Resources by inject()
|
||||||
|
mutableListOf<Locale>().apply {
|
||||||
|
// Add default locale
|
||||||
|
add(Locale.ENGLISH)
|
||||||
|
|
||||||
|
// Add some special locales
|
||||||
|
add(Locale.TAIWAN)
|
||||||
|
add(Locale("pt", "BR"))
|
||||||
|
|
||||||
|
// Other locales
|
||||||
|
val otherLocales = res.assets.locales
|
||||||
|
.map { forLanguageTag(it) }
|
||||||
|
.distinctBy { getString(it, compareId) }
|
||||||
|
|
||||||
|
listOf("", "").toTypedArray()
|
||||||
|
|
||||||
|
addAll(otherLocales)
|
||||||
|
}.sortedWith(Comparator { a, b ->
|
||||||
|
a.getDisplayName(a).toLowerCase(a)
|
||||||
|
.compareTo(b.getDisplayName(b).toLowerCase(b))
|
||||||
|
})
|
||||||
|
}.cache()
|
||||||
|
|
||||||
|
private fun forLanguageTag(tag: String): Locale {
|
||||||
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
|
return Locale.forLanguageTag(tag)
|
||||||
|
} else {
|
||||||
|
val tok = tag.split("-".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||||
|
if (tok.isEmpty()) {
|
||||||
|
return Locale("")
|
||||||
|
}
|
||||||
|
val language = when (tok[0]) {
|
||||||
|
"und" -> "" // Undefined
|
||||||
|
"fil" -> "tl" // Filipino
|
||||||
|
else -> tok[0]
|
||||||
|
}
|
||||||
|
if (language.length != 2 && language.length != 3)
|
||||||
|
return Locale("")
|
||||||
|
if (tok.size == 1)
|
||||||
|
return Locale(language)
|
||||||
|
val country = tok[1]
|
||||||
|
|
||||||
|
return if (country.length != 2 && country.length != 3) Locale(language)
|
||||||
|
else Locale(language, country)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun toLanguageTag(loc: Locale): String {
|
||||||
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
|
return loc.toLanguageTag()
|
||||||
|
} else {
|
||||||
|
var language = loc.language
|
||||||
|
var country = loc.country
|
||||||
|
var variant = loc.variant
|
||||||
|
when {
|
||||||
|
language.isEmpty() || !language.matches("\\p{Alpha}{2,8}".toRegex()) ->
|
||||||
|
language = "und" // Follow the Locale#toLanguageTag() implementation
|
||||||
|
language == "iw" -> language = "he" // correct deprecated "Hebrew"
|
||||||
|
language == "in" -> language = "id" // correct deprecated "Indonesian"
|
||||||
|
language == "ji" -> language = "yi" // correct deprecated "Yiddish"
|
||||||
|
}
|
||||||
|
// ensure valid country code, if not well formed, it's omitted
|
||||||
|
|
||||||
|
// variant subtags that begin with a letter must be at least 5 characters long
|
||||||
|
// ensure valid country code, if not well formed, it's omitted
|
||||||
|
if (!country.matches("\\p{Alpha}{2}|\\p{Digit}{3}".toRegex())) {
|
||||||
|
country = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// variant subtags that begin with a letter must be at least 5 characters long
|
||||||
|
if (!variant.matches("\\p{Alnum}{5,8}|\\p{Digit}\\p{Alnum}{3}".toRegex())) {
|
||||||
|
variant = ""
|
||||||
|
}
|
||||||
|
val tag = StringBuilder(language)
|
||||||
|
if (country.isNotEmpty())
|
||||||
|
tag.append('-').append(country)
|
||||||
|
if (variant.isNotEmpty())
|
||||||
|
tag.append('-').append(variant)
|
||||||
|
return tag.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun setLocale(wrapper: ContextWrapper) {
|
||||||
|
val localeConfig = Config.get<String>(Config.Key.LOCALE)
|
||||||
|
locale = when {
|
||||||
|
localeConfig.isNullOrEmpty() -> defaultLocale
|
||||||
|
else -> forLanguageTag(localeConfig)
|
||||||
|
}
|
||||||
|
Locale.setDefault(locale)
|
||||||
|
InternalUtils.replaceBaseContext(wrapper, getLocaleContext(locale))
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getLocaleContext(context: Context, locale: Locale): Context {
|
||||||
|
val config = Configuration(context.resources.configuration)
|
||||||
|
config.setLocale(locale)
|
||||||
|
return context.createConfigurationContext(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getLocaleContext(locale: Locale): Context {
|
||||||
|
return getLocaleContext(App.self.baseContext, locale)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getString(locale: Locale, @StringRes id: Int): String {
|
||||||
|
return getLocaleContext(locale).getString(id)
|
||||||
|
}
|
||||||
|
}
|
@ -71,7 +71,7 @@ public class Utils {
|
|||||||
if (info.labelRes > 0) {
|
if (info.labelRes > 0) {
|
||||||
Resources res = pm.getResourcesForApplication(info);
|
Resources res = pm.getResourcesForApplication(info);
|
||||||
Configuration config = new Configuration();
|
Configuration config = new Configuration();
|
||||||
config.setLocale(LocaleManager.locale);
|
config.setLocale(LocaleManager.getLocale());
|
||||||
res.updateConfiguration(config, res.getDisplayMetrics());
|
res.updateConfiguration(config, res.getDisplayMetrics());
|
||||||
return res.getString(info.labelRes);
|
return res.getString(info.labelRes);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user