package de.robv.android.xposed.mods.appsettings.settings; import java.text.Collator; import java.util.Arrays; import java.util.List; import java.util.Locale; import android.content.res.Resources; /** * Manages a list of valid locales for the system */ public class LocaleList { /* * From AOSP code - listing available languages to present to the user */ private static class LocaleInfo implements Comparable<LocaleInfo> { static final Collator sCollator = Collator.getInstance(); String label; Locale locale; public LocaleInfo(String label, Locale locale) { this.label = label; this.locale = locale; } @Override public String toString() { return this.label; } @Override public int compareTo(LocaleInfo another) { return sCollator.compare(this.label, another.label); } } private String[] localeCodes; private String[] localeDescriptions; public LocaleList(String defaultLabel) { final String[] locales = Resources.getSystem().getAssets().getLocales(); Arrays.sort(locales); final int origSize = locales.length; final LocaleInfo[] preprocess = new LocaleInfo[origSize]; int finalSize = 0; for (int i = 0; i < origSize; i++) { final String s = locales[i]; final int len = s.length(); if (len == 5) { String language = s.substring(0, 2); String country = s.substring(3, 5); final Locale l = new Locale(language, country); if (finalSize == 0) { preprocess[finalSize++] = new LocaleInfo(toTitleCase(l.getDisplayLanguage(l)), l); } else { // check previous entry: // same lang and a country -> upgrade to full name and // insert ours with full name // diff lang -> insert ours with lang-only name if (preprocess[finalSize - 1].locale.getLanguage().equals(language)) { preprocess[finalSize - 1].label = toTitleCase(getDisplayName(preprocess[finalSize - 1].locale)); preprocess[finalSize++] = new LocaleInfo(toTitleCase(getDisplayName(l)), l); } else { String displayName; if (s.equals("zz_ZZ")) { displayName = "Pseudo..."; } else { displayName = toTitleCase(l.getDisplayLanguage(l)); } preprocess[finalSize++] = new LocaleInfo(displayName, l); } } } } final LocaleInfo[] localeInfos = new LocaleInfo[finalSize]; for (int i = 0; i < finalSize; i++) { localeInfos[i] = preprocess[i]; } Arrays.sort(localeInfos); localeCodes = new String[localeInfos.length + 1]; localeDescriptions = new String[localeInfos.length + 1]; localeCodes[0] = ""; localeDescriptions[0] = defaultLabel; for (int i = 1; i < finalSize + 1; i++) { localeCodes[i] = getLocaleCode(localeInfos[i - 1].locale); localeDescriptions[i] = localeInfos[i - 1].label; } } private static String toTitleCase(String s) { if (s.length() == 0) { return s; } return Character.toUpperCase(s.charAt(0)) + s.substring(1); } private static String getDisplayName(Locale loc) { return loc.getDisplayName(loc); } private static String getLocaleCode(Locale loc) { String result = loc.getLanguage(); if (loc.getCountry().length() > 0) result += "_" + loc.getCountry(); if (loc.getVariant().length() > 0) result += "_" + loc.getVariant(); return result; } /** * Retrieve the locale code at a specific position in the list. */ public String getLocale(int pos) { return localeCodes[pos]; } /** * Retrieve the position where the specified locale code is, or 0 if it was * not found. */ public int getLocalePos(String locale) { for (int i = 1; i < localeCodes.length; i++) { if (localeCodes[i].equals(locale)) return i; } return 0; } /** * Retrieve an ordered list of the locale descriptions */ public List<String> getDescriptionList() { return Arrays.asList(localeDescriptions); } }