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);
}
}
}