/*####################################################### * * Maintained 2017-2023 by Gregor Santner * * License: Apache 2.0 * https://github.com/gsantner/opoc/#licensing * https://www.apache.org/licenses/LICENSE-2.0 * #########################################################*/ /* * Requires: The BuildConfig field "APPLICATION_LANGUAGES" which is a array of all available languages opoc/ContextUtils * BuildConfig field can be defined by using the method below buildConfigField "String[]", "APPLICATION_LANGUAGES", "${getUsedAndroidLanguages()}" @SuppressWarnings(["UnnecessaryQualifiedReference", "SpellCheckingInspection", "GroovyUnusedDeclaration"]) // Returns used android languages as a buildConfig array: {'de', 'it', ..}" static String getUsedAndroidLanguages() { Set langs = new HashSet<>() new File('.').eachFileRecurse(groovy.io.FileType.DIRECTORIES) { final foldername = it.name if (foldername.startsWith('values-') && !it.canonicalPath.contains("build" + File.separator + "intermediates")) { new File(it.toString()).eachFileRecurse(groovy.io.FileType.FILES) { if (it.name.toLowerCase().endsWith(".xml") && it.getCanonicalFile().getText('UTF-8').contains(" */ package net.gsantner.opoc.preference.nonsupport; import android.annotation.TargetApi; import android.content.Context; import android.os.Build; import android.preference.ListPreference; import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.AttributeSet; import net.gsantner.opoc.util.ContextUtils; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; /** * A {@link android.preference.ListPreference} that displays a list of languages to select from */ @SuppressWarnings({"unused", "SpellCheckingInspection", "WeakerAccess"}) public class LanguagePreference extends ListPreference { private static final String SYSTEM_LANGUAGE_CODE = ""; // The language of res/values/ -> (usually English) public String _systemLanguageName = "System"; public String _defaultLanguageCode = "en"; public LanguagePreference(Context context) { super(context); loadLangs(context, null); } public LanguagePreference(Context context, AttributeSet attrs) { super(context, attrs); loadLangs(context, attrs); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public LanguagePreference(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); loadLangs(context, attrs); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public LanguagePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); loadLangs(context, attrs); } @Override public boolean callChangeListener(Object newValue) { if (newValue instanceof String) { // Does not apply to existing UI, use recreate() new ContextUtils(getContext()).setAppLanguage((String) newValue); } return super.callChangeListener(newValue); } private void loadLangs(Context context) { loadLangs(context, null); } private void loadLangs(Context context, @Nullable AttributeSet attrs) { setDefaultValue(SYSTEM_LANGUAGE_CODE); // Fetch readable details ContextUtils contextUtils = new ContextUtils(context); List languages = new ArrayList<>(); Object bcof = contextUtils.getBuildConfigValue("DETECTED_ANDROID_LOCALES"); if (bcof instanceof String[]) { for (String langId : (String[]) bcof) { Locale locale = contextUtils.getLocaleByAndroidCode(langId); languages.add(summarizeLocale(locale, langId) + ";" + langId); } } // Sort languages naturally Collections.sort(languages); // Show in UI String[] entries = new String[languages.size() + 2]; String[] entryval = new String[languages.size() + 2]; for (int i = 0; i < languages.size(); i++) { entries[i + 2] = languages.get(i).split(";")[0]; entryval[i + 2] = languages.get(i).split(";")[1]; } entryval[0] = SYSTEM_LANGUAGE_CODE; entries[0] = _systemLanguageName + " ยป " + summarizeLocale(context.getResources().getConfiguration().locale, ""); entryval[1] = _defaultLanguageCode; entries[1] = summarizeLocale(contextUtils.getLocaleByAndroidCode(_defaultLanguageCode), _defaultLanguageCode); setEntries(entries); setEntryValues(entryval); } // Concat english and localized language name // Append country if country specific (e.g. Portuguese Brazil) private String summarizeLocale(final Locale locale, final String localeAndroidCode) { String country = locale.getDisplayCountry(locale); String language = locale.getDisplayLanguage(locale); String ret = locale.getDisplayLanguage(Locale.ENGLISH) + " (" + language.substring(0, 1).toUpperCase(Locale.getDefault()) + language.substring(1) + ((!country.isEmpty() && !country.toLowerCase(Locale.getDefault()).equals(language.toLowerCase(Locale.getDefault()))) ? (", " + country) : "") + ")"; if (localeAndroidCode.equals("zh-rCN")) { ret = ret.substring(0, ret.indexOf(" ") + 1) + "Simplified" + ret.substring(ret.indexOf(" ")); } else if (localeAndroidCode.equals("zh-rTW")) { ret = ret.substring(0, ret.indexOf(" ") + 1) + "Traditional" + ret.substring(ret.indexOf(" ")); } return ret; } // Add current language to summary @Override public CharSequence getSummary() { Locale locale = new ContextUtils(getContext()).getLocaleByAndroidCode(getValue()); String prefix = TextUtils.isEmpty(super.getSummary()) ? "" : super.getSummary() + "\n\n"; return prefix + summarizeLocale(locale, getValue()); } public String getSystemLanguageName() { return _systemLanguageName; } public void setSystemLanguageName(String systemLanguageName) { _systemLanguageName = systemLanguageName; loadLangs(getContext()); } public String getDefaultLanguageCode() { return _defaultLanguageCode; } public void setDefaultLanguageCode(String defaultLanguageCode) { _defaultLanguageCode = defaultLanguageCode; loadLangs(getContext()); } }