package org.wikipedia.language; import android.content.Context; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import org.apache.commons.lang3.StringUtils; import org.wikipedia.settings.Prefs; import org.wikipedia.util.StringUtil; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; import static org.apache.commons.lang3.StringUtils.defaultString; /** Language lookup and state management for the application language and most recently used article * and application languages. */ public class AppLanguageState { public static final String SYSTEM_LANGUAGE_CODE = null; @NonNull private final AppLanguageLookUpTable appLanguageLookUpTable; // The language code used by the app when the article language is unspecified. It's possible for // this code to be unsupported if the languages supported changes. Null is a special value that // indicates the system language should used. @Nullable private String appLanguageCode; // Language codes that have been explicitly chosen by the user in most recently used order. This // list includes both app and article languages. @NonNull private final List<String> mruLanguageCodes; public AppLanguageState(@NonNull Context context) { appLanguageLookUpTable = new AppLanguageLookUpTable(context); appLanguageCode = Prefs.getAppLanguageCode(); mruLanguageCodes = unmarshalMruLanguageCodes(); } @Nullable public String getAppLanguageCode() { return appLanguageCode; } @NonNull public String getAppOrSystemLanguageCode() { return isSystemLanguageEnabled() ? getSystemLanguageCode() : appLanguageCode; } public void setAppLanguageCode(@Nullable String code) { appLanguageCode = code; Prefs.setAppLanguageCode(code); } public boolean isSystemLanguageEnabled() { return isSystemLanguageCode(getAppLanguageCode()); } public boolean isSystemLanguageCode(@Nullable String code) { return StringUtils.equals(code, SYSTEM_LANGUAGE_CODE); } @NonNull public String getSystemLanguageCode() { String code = LanguageUtil.languageCodeToWikiLanguageCode(Locale.getDefault().getLanguage()); return appLanguageLookUpTable.isSupportedCode(code) ? code : AppLanguageLookUpTable.FALLBACK_LANGUAGE_CODE; } /** Note: returned codes may include languages offered by articles but not the app. */ @NonNull public List<String> getMruLanguageCodes() { return mruLanguageCodes; } public void setMruLanguageCode(@Nullable String code) { List<String> codes = getMruLanguageCodes(); codes.remove(code); codes.add(0, code); Prefs.setMruLanguageCodeCsv(StringUtil.listToCsv(codes)); } /** @return All app supported languages in MRU order. */ public List<String> getAppMruLanguageCodes() { List<String> codes = new ArrayList<>(appLanguageLookUpTable.getCodes()); int insertIndex = 0; for (String code : getMruLanguageCodes()) { if (codes.contains(code)) { codes.remove(code); codes.add(insertIndex, code); ++insertIndex; } } return codes; } /** @return English name if app language is supported. */ @Nullable public String getAppLanguageCanonicalName(@Nullable String code) { return appLanguageLookUpTable.getCanonicalName(code); } @Nullable public String getAppOrSystemLanguageLocalizedName() { return getAppLanguageLocalizedName(getAppOrSystemLanguageCode()); } /** @return Native name if app language is supported. */ @Nullable public String getAppLanguageLocalizedName(@Nullable String code) { return appLanguageLookUpTable.getLocalizedName(code); } @NonNull private List<String> unmarshalMruLanguageCodes() { // Null value is used to indicate that system language should be used. String systemLanguageCodeString = String.valueOf(SYSTEM_LANGUAGE_CODE); String csv = defaultString(Prefs.getMruLanguageCodeCsv(), systemLanguageCodeString); List<String> list = new ArrayList<>(StringUtil.csvToList(csv)); Collections.replaceAll(list, systemLanguageCodeString, SYSTEM_LANGUAGE_CODE); return list; } }