package org.solovyev.android.calculator.language; import android.app.Application; import android.content.Context; import android.content.SharedPreferences; import android.content.res.Configuration; import android.content.res.Resources; import android.text.TextUtils; import android.util.DisplayMetrics; import android.util.Log; import org.solovyev.android.Check; import org.solovyev.android.calculator.Preferences; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.*; public final class Languages implements SharedPreferences.OnSharedPreferenceChangeListener { @Nonnull public static final String SYSTEM_LANGUAGE_CODE = "00"; @Nonnull public static final Language SYSTEM_LANGUAGE = new Language(SYSTEM_LANGUAGE_CODE, Locale.getDefault()); @Nullable private static Locale[] locales; @Nonnull private final List<Language> list = new ArrayList<>(); @Nonnull private final Application application; @Nonnull private final SharedPreferences preferences; public Languages(@Nonnull Application application, @Nonnull SharedPreferences preferences) { this.application = application; this.preferences = preferences; } @Nullable private static Language makeLanguage(@Nonnull String localeId) { final Locale locale = findLocaleById(localeId); if (locale == null) { return null; } return new Language(localeId, locale); } @Nullable private static Locale findLocaleById(@Nonnull String id) { for (Locale locale : getLocales()) { if (TextUtils.equals(locale.toString(), id)) { return locale; } } final String language; final int underscore = id.indexOf("_"); if (underscore >= 0) { language = id.substring(0, underscore); } else { language = id; } for (Locale locale : getLocales()) { if (TextUtils.equals(locale.getLanguage(), language)) { return locale; } } Log.d("Languages", "No locale found for " + id); return null; } @Nonnull public static Locale[] getLocales() { if (locales == null) { locales = Locale.getAvailableLocales(); } return locales; } /** * This method should be called only when default values have been set to application's preferences */ public void init() { preferences.registerOnSharedPreferenceChangeListener(this); } @Nonnull public List<Language> getList() { Check.isMainThread(); if (list.isEmpty()) { loadList(); } return list; } private void loadList() { Check.isMainThread(); Check.isEmpty(list); tryAddLanguage("ar"); tryAddLanguage("cs"); tryAddLanguage("en"); tryAddLanguage("es_ES"); tryAddLanguage("de"); tryAddLanguage("fi"); tryAddLanguage("fr"); tryAddLanguage("it"); tryAddLanguage("it"); tryAddLanguage("pl"); tryAddLanguage("pt_BR"); tryAddLanguage("pt_PT"); tryAddLanguage("ru"); tryAddLanguage("tr"); tryAddLanguage("vi"); tryAddLanguage("uk"); tryAddLanguage("ja"); tryAddLanguage("zh_CN"); tryAddLanguage("zh_TW"); Collections.sort(list, new Comparator<Language>() { @Override public int compare(Language lhs, Language rhs) { return lhs.name.compareTo(rhs.name); } }); list.add(0, SYSTEM_LANGUAGE); } private void tryAddLanguage(@Nonnull String locale) { final Language language = makeLanguage(locale); if (language != null) { list.add(language); } } @Nonnull public Language getCurrent() { return get(Preferences.Gui.language.getPreference(preferences)); } @Nonnull public Language get(@Nonnull String code) { if (TextUtils.equals(SYSTEM_LANGUAGE.code, code)) { // quick check to avoid list loading return SYSTEM_LANGUAGE; } Language language = findLanguageByCode(code); if (language != null) { return language; } return SYSTEM_LANGUAGE; } @Nullable private Language findLanguageByCode(@Nonnull String code) { for (Language language : getList()) { if (TextUtils.equals(language.code, code)) { return language; } } return null; } @Override public void onSharedPreferenceChanged(@Nonnull SharedPreferences p, String key) { if (Preferences.Gui.language.isSameKey(key)) { updateContextLocale(application, false); } } public void updateContextLocale(@Nonnull Context context, boolean initial) { final Language language = getCurrent(); // we don't need to set system language while starting up the app if (initial && language.isSystem()) { return; } if (!Locale.getDefault().equals(language.locale)) { Locale.setDefault(language.locale); } final Resources r = context.getResources(); final DisplayMetrics dm = r.getDisplayMetrics(); final Configuration c = r.getConfiguration(); if (c.locale == null || !c.locale.equals(language.locale)) { c.locale = language.locale; r.updateConfiguration(c, dm); } } }