Adding a locale picker with two-step selection: language, then region.
This is intended to replace the UI part of the LocalePicker, at
least for the main "Settings" application (under "Language & Input")
and for the "Setup Wizard".
The UI part in the old LocalePicker can be removed once all the
components that use it are migrated to the new one.
Bug: 25800339
Change-Id: I2f264cdb7b7fc586124dd58fad2c68060d5b7aa8
diff --git a/core/java/com/android/internal/app/LocalePickerWithRegion.java b/core/java/com/android/internal/app/LocalePickerWithRegion.java
new file mode 100644
index 0000000..3b8f865
--- /dev/null
+++ b/core/java/com/android/internal/app/LocalePickerWithRegion.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app;
+
+import com.android.internal.R;
+
+import android.app.ListFragment;
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.util.ArrayMap;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+class LocaleAdapter extends ArrayAdapter<LocalePicker.LocaleInfo> {
+ final private Map<String, LocalePicker.LocaleInfo> mLevelOne = new ArrayMap<>();
+ final private Map<String, HashSet<LocalePicker.LocaleInfo>> mLevelTwo = new ArrayMap<>();
+ final private LayoutInflater mInflater;
+
+ final static class LocaleAwareComparator implements Comparator<LocalePicker.LocaleInfo> {
+ private final Collator mCollator;
+
+ public LocaleAwareComparator(Locale sortLocale) {
+ mCollator = Collator.getInstance(sortLocale);
+ }
+
+ @Override
+ public int compare(LocalePicker.LocaleInfo lhs, LocalePicker.LocaleInfo rhs) {
+ return mCollator.compare(lhs.getLabel(), rhs.getLabel());
+ }
+ }
+
+ static List<Locale> getCuratedLocaleList(Context context) {
+ final Resources resources = context.getResources();
+ final String[] supportedLocaleCodes = resources.getStringArray(R.array.supported_locales);
+
+ final ArrayList<Locale> result = new ArrayList<>(supportedLocaleCodes.length);
+ for (String localeId : supportedLocaleCodes) {
+ Locale locale = Locale.forLanguageTag(localeId);
+ if (!locale.getCountry().isEmpty()) {
+ result.add(Locale.forLanguageTag(localeId));
+ }
+ }
+ return result;
+ }
+
+ public LocaleAdapter(Context context) {
+ this(context, getCuratedLocaleList(context));
+ }
+
+ static Locale getBaseLocale(Locale locale) {
+ return new Locale.Builder()
+ .setLocale(locale)
+ .setRegion("")
+ .build();
+ }
+
+ // There is no good API available for this, not even in ICU.
+ // We can revisit this if we get some ICU support later
+ //
+ // There are currently several tickets requesting this feature:
+ // * ICU needs to provide an easy way to titlecase only one first letter
+ // http://bugs.icu-project.org/trac/ticket/11729
+ // * Add "initial case"
+ // http://bugs.icu-project.org/trac/ticket/8394
+ // * Add code for initialCase, toTitlecase don't modify after Lt,
+ // avoid 49Ers, low-level language-specific casing
+ // http://bugs.icu-project.org/trac/ticket/10410
+ // * BreakIterator.getFirstInstance: Often you need to titlecase just the first
+ // word, and leave the rest of the string alone. (closed as duplicate)
+ // http://bugs.icu-project.org/trac/ticket/8946
+ //
+ // A (clunky) option with the current ICU API is:
+ // BreakIterator breakIterator = BreakIterator.getSentenceInstance(locale);
+ // String result = UCharacter.toTitleCase(locale,
+ // source, breakIterator, UCharacter.TITLECASE_NO_LOWERCASE);
+ // That also means creating BreakIteratos for each locale. Expensive...
+ private static String toTitleCase(String s, Locale locale) {
+ if (s.length() == 0) {
+ return s;
+ }
+ final int firstCodePointLen = s.offsetByCodePoints(0, 1);
+ return s.substring(0, firstCodePointLen).toUpperCase(locale)
+ + s.substring(firstCodePointLen);
+ }
+
+ public LocaleAdapter(Context context, List<Locale> locales) {
+ super(context, R.layout.locale_picker_item, R.id.locale);
+ mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ for (Locale locale : locales) {
+ Locale baseLocale = getBaseLocale(locale);
+ String language = baseLocale.toLanguageTag();
+ if (!mLevelOne.containsKey(language)) {
+ String label = toTitleCase(baseLocale.getDisplayName(baseLocale), baseLocale);
+ mLevelOne.put(language, new LocalePicker.LocaleInfo(label, baseLocale));
+ }
+
+ final HashSet<LocalePicker.LocaleInfo> subLocales;
+ if (mLevelTwo.containsKey(language)) {
+ subLocales = mLevelTwo.get(language);
+ } else {
+ subLocales = new HashSet<>();
+ mLevelTwo.put(language, subLocales);
+ }
+ String label = locale.getDisplayCountry(locale);
+ subLocales.add(new LocalePicker.LocaleInfo(label, locale));
+ }
+
+ setAdapterLevel(null);
+ }
+
+ public void setAdapterLevel(String parentLocale) {
+ this.clear();
+
+ if (parentLocale == null) {
+ this.addAll(mLevelOne.values());
+ } else {
+ this.addAll(mLevelTwo.get(parentLocale));
+ }
+
+ Locale sortLocale = (parentLocale == null)
+ ? Locale.getDefault()
+ : Locale.forLanguageTag(parentLocale);
+ LocaleAwareComparator comparator = new LocaleAwareComparator(sortLocale);
+ this.sort(comparator);
+
+ this.notifyDataSetChanged();
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View view;
+ TextView text;
+ if (convertView == null) {
+ view = mInflater.inflate(R.layout.locale_picker_item, parent, false);
+ text = (TextView) view.findViewById(R.id.locale);
+ view.setTag(text);
+ } else {
+ view = convertView;
+ text = (TextView) view.getTag();
+ }
+ LocalePicker.LocaleInfo item = getItem(position);
+ text.setText(item.getLabel());
+ text.setTextLocale(item.getLocale());
+ return view;
+ }
+}
+
+public class LocalePickerWithRegion extends ListFragment {
+ private static final int LIST_MODE_LANGUAGE = 0;
+ private static final int LIST_MODE_COUNTRY = 1;
+
+ private LocaleAdapter mAdapter;
+ private int mDisplayMode = LIST_MODE_LANGUAGE;
+
+ public static interface LocaleSelectionListener {
+ // You can add any argument if you really need it...
+ public void onLocaleSelected(Locale locale);
+ }
+
+ private LocaleSelectionListener mListener = null;
+
+ @Override
+ public void onActivityCreated(final Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ mAdapter = new LocaleAdapter(getContext());
+ mAdapter.setAdapterLevel(null);
+ setListAdapter(mAdapter);
+ }
+
+ public void setLocaleSelectionListener(LocaleSelectionListener listener) {
+ mListener = listener;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ getListView().requestFocus();
+ }
+
+ /**
+ * Each listener needs to call {@link LocalePicker.updateLocale(Locale)} to actually
+ * change the locale.
+ * <p/>
+ * We don't call {@link LocalePicker.updateLocale(Locale)} automatically, as it halts
+ * the system for a moment and some callers won't want it.
+ */
+ @Override
+ public void onListItemClick(ListView l, View v, int position, long id) {
+ final Locale locale = ((LocalePicker.LocaleInfo) getListAdapter().getItem(position)).locale;
+ // TODO: handle the back buttons to return to the language list
+ if (mDisplayMode == LIST_MODE_LANGUAGE) {
+ mDisplayMode = LIST_MODE_COUNTRY;
+ mAdapter.setAdapterLevel(locale.toLanguageTag());
+ return;
+ }
+ if (mListener != null) {
+ mListener.onLocaleSelected(locale);
+ }
+ }
+}
diff --git a/core/res/res/values/locale_config.xml b/core/res/res/values/locale_config.xml
new file mode 100644
index 0000000..dae7a2e
--- /dev/null
+++ b/core/res/res/values/locale_config.xml
@@ -0,0 +1,507 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/colors.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <string-array translatable="false" name="supported_locales">
+ <item>af-NA</item> <!-- Afrikaans (Namibia) -->
+ <item>af-ZA</item> <!-- Afrikaans (South Africa) -->
+ <item>agq-CM</item> <!-- Aghem (Cameroon) -->
+ <item>ak-GH</item> <!-- Akan (Ghana) -->
+ <item>am-ET</item> <!-- Amharic (Ethiopia) -->
+ <item>ar-AE</item> <!-- Arabic (United Arab Emirates) -->
+ <item>ar-BH</item> <!-- Arabic (Bahrain) -->
+ <item>ar-DJ</item> <!-- Arabic (Djibouti) -->
+ <item>ar-DZ</item> <!-- Arabic (Algeria) -->
+ <item>ar-EG</item> <!-- Arabic (Egypt) -->
+ <item>ar-EH</item> <!-- Arabic (Western Sahara) -->
+ <item>ar-ER</item> <!-- Arabic (Eritrea) -->
+ <item>ar-IL</item> <!-- Arabic (Israel) -->
+ <item>ar-IQ</item> <!-- Arabic (Iraq) -->
+ <item>ar-JO</item> <!-- Arabic (Jordan) -->
+ <item>ar-KM</item> <!-- Arabic (Comoros) -->
+ <item>ar-KW</item> <!-- Arabic (Kuwait) -->
+ <item>ar-LB</item> <!-- Arabic (Lebanon) -->
+ <item>ar-LY</item> <!-- Arabic (Libya) -->
+ <item>ar-MA</item> <!-- Arabic (Morocco) -->
+ <item>ar-MR</item> <!-- Arabic (Mauritania) -->
+ <item>ar-OM</item> <!-- Arabic (Oman) -->
+ <item>ar-PS</item> <!-- Arabic (Palestine) -->
+ <item>ar-QA</item> <!-- Arabic (Qatar) -->
+ <item>ar-SA</item> <!-- Arabic (Saudi Arabia) -->
+ <item>ar-SD</item> <!-- Arabic (Sudan) -->
+ <item>ar-SO</item> <!-- Arabic (Somalia) -->
+ <item>ar-SS</item> <!-- Arabic (South Sudan) -->
+ <item>ar-SY</item> <!-- Arabic (Syria) -->
+ <item>ar-TD</item> <!-- Arabic (Chad) -->
+ <item>ar-TN</item> <!-- Arabic (Tunisia) -->
+ <item>ar-YE</item> <!-- Arabic (Yemen) -->
+ <item>as-IN</item> <!-- Assamese (India) -->
+ <item>asa-TZ</item> <!-- Asu (Tanzania) -->
+ <item>az-Cyrl-AZ</item> <!-- Azerbaijani (Cyrillic,Azerbaijan) -->
+ <item>az-Latn-AZ</item> <!-- Azerbaijani (Latin,Azerbaijan) -->
+ <item>bas-CM</item> <!-- Basaa (Cameroon) -->
+ <item>be-BY</item> <!-- Belarusian (Belarus) -->
+ <item>bem-ZM</item> <!-- Bemba (Zambia) -->
+ <item>bez-TZ</item> <!-- Bena (Tanzania) -->
+ <item>bg-BG</item> <!-- Bulgarian (Bulgaria) -->
+ <item>bm-ML</item> <!-- Bambara (Mali) -->
+ <item>bn-BD</item> <!-- Bengali (Bangladesh) -->
+ <item>bn-IN</item> <!-- Bengali (India) -->
+ <item>bo-CN</item> <!-- Tibetan (China) -->
+ <item>bo-IN</item> <!-- Tibetan (India) -->
+ <item>br-FR</item> <!-- Breton (France) -->
+ <item>brx-IN</item> <!-- Bodo (India) -->
+ <item>bs-Cyrl-BA</item> <!-- Bosnian (Cyrillic,Bosnia & Herzegovina) -->
+ <item>bs-Latn-BA</item> <!-- Bosnian (Latin,Bosnia & Herzegovina) -->
+ <item>ca-AD</item> <!-- Catalan (Andorra) -->
+ <item>ca-ES</item> <!-- Catalan (Spain) -->
+ <item>ca-FR</item> <!-- Catalan (France) -->
+ <item>ca-IT</item> <!-- Catalan (Italy) -->
+ <item>ce-RU</item> <!-- Chechen (Russia) -->
+ <item>cgg-UG</item> <!-- Chiga (Uganda) -->
+ <item>chr-US</item> <!-- Cherokee (United States) -->
+ <item>cs-CZ</item> <!-- Czech (Czech Republic) -->
+ <item>cy-GB</item> <!-- Welsh (United Kingdom) -->
+ <item>da-DK</item> <!-- Danish (Denmark) -->
+ <item>da-GL</item> <!-- Danish (Greenland) -->
+ <item>dav-KE</item> <!-- Taita (Kenya) -->
+ <item>de-AT</item> <!-- German (Austria) -->
+ <item>de-BE</item> <!-- German (Belgium) -->
+ <item>de-CH</item> <!-- German (Switzerland) -->
+ <item>de-DE</item> <!-- German (Germany) -->
+ <item>de-LI</item> <!-- German (Liechtenstein) -->
+ <item>de-LU</item> <!-- German (Luxembourg) -->
+ <item>dje-NE</item> <!-- Zarma (Niger) -->
+ <item>dsb-DE</item> <!-- Lower Sorbian (Germany) -->
+ <item>dua-CM</item> <!-- Duala (Cameroon) -->
+ <item>dyo-SN</item> <!-- Jola-Fonyi (Senegal) -->
+ <item>dz-BT</item> <!-- Dzongkha (Bhutan) -->
+ <item>ebu-KE</item> <!-- Embu (Kenya) -->
+ <item>ee-GH</item> <!-- Ewe (Ghana) -->
+ <item>ee-TG</item> <!-- Ewe (Togo) -->
+ <item>el-CY</item> <!-- Greek (Cyprus) -->
+ <item>el-GR</item> <!-- Greek (Greece) -->
+ <item>en-AG</item> <!-- English (Antigua & Barbuda) -->
+ <item>en-AI</item> <!-- English (Anguilla) -->
+ <item>en-AS</item> <!-- English (American Samoa) -->
+ <item>en-AT</item> <!-- English (Austria) -->
+ <item>en-AU</item> <!-- English (Australia) -->
+ <item>en-BB</item> <!-- English (Barbados) -->
+ <item>en-BE</item> <!-- English (Belgium) -->
+ <item>en-BI</item> <!-- English (Burundi) -->
+ <item>en-BM</item> <!-- English (Bermuda) -->
+ <item>en-BS</item> <!-- English (Bahamas) -->
+ <item>en-BW</item> <!-- English (Botswana) -->
+ <item>en-BZ</item> <!-- English (Belize) -->
+ <item>en-CA</item> <!-- English (Canada) -->
+ <item>en-CC</item> <!-- English (Cocos (Keeling) Islands) -->
+ <item>en-CH</item> <!-- English (Switzerland) -->
+ <item>en-CK</item> <!-- English (Cook Islands) -->
+ <item>en-CM</item> <!-- English (Cameroon) -->
+ <item>en-CX</item> <!-- English (Christmas Island) -->
+ <item>en-CY</item> <!-- English (Cyprus) -->
+ <item>en-DE</item> <!-- English (Germany) -->
+ <item>en-DG</item> <!-- English (Diego Garcia) -->
+ <item>en-DK</item> <!-- English (Denmark) -->
+ <item>en-DM</item> <!-- English (Dominica) -->
+ <item>en-ER</item> <!-- English (Eritrea) -->
+ <item>en-FI</item> <!-- English (Finland) -->
+ <item>en-FJ</item> <!-- English (Fiji) -->
+ <item>en-FK</item> <!-- English (Falkland Islands (Islas Malvinas)) -->
+ <item>en-FM</item> <!-- English (Micronesia) -->
+ <item>en-GB</item> <!-- English (United Kingdom) -->
+ <item>en-GD</item> <!-- English (Grenada) -->
+ <item>en-GG</item> <!-- English (Guernsey) -->
+ <item>en-GH</item> <!-- English (Ghana) -->
+ <item>en-GI</item> <!-- English (Gibraltar) -->
+ <item>en-GM</item> <!-- English (Gambia) -->
+ <item>en-GU</item> <!-- English (Guam) -->
+ <item>en-GY</item> <!-- English (Guyana) -->
+ <item>en-HK</item> <!-- English (Hong Kong) -->
+ <item>en-IE</item> <!-- English (Ireland) -->
+ <item>en-IL</item> <!-- English (Israel) -->
+ <item>en-IM</item> <!-- English (Isle of Man) -->
+ <item>en-IN</item> <!-- English (India) -->
+ <item>en-IO</item> <!-- English (British Indian Ocean Territory) -->
+ <item>en-JE</item> <!-- English (Jersey) -->
+ <item>en-JM</item> <!-- English (Jamaica) -->
+ <item>en-KE</item> <!-- English (Kenya) -->
+ <item>en-KI</item> <!-- English (Kiribati) -->
+ <item>en-KN</item> <!-- English (St. Kitts & Nevis) -->
+ <item>en-KY</item> <!-- English (Cayman Islands) -->
+ <item>en-LC</item> <!-- English (St. Lucia) -->
+ <item>en-LR</item> <!-- English (Liberia) -->
+ <item>en-LS</item> <!-- English (Lesotho) -->
+ <item>en-MG</item> <!-- English (Madagascar) -->
+ <item>en-MH</item> <!-- English (Marshall Islands) -->
+ <item>en-MO</item> <!-- English (Macau) -->
+ <item>en-MP</item> <!-- English (Northern Mariana Islands) -->
+ <item>en-MS</item> <!-- English (Montserrat) -->
+ <item>en-MT</item> <!-- English (Malta) -->
+ <item>en-MU</item> <!-- English (Mauritius) -->
+ <item>en-MW</item> <!-- English (Malawi) -->
+ <item>en-MY</item> <!-- English (Malaysia) -->
+ <item>en-NA</item> <!-- English (Namibia) -->
+ <item>en-NF</item> <!-- English (Norfolk Island) -->
+ <item>en-NG</item> <!-- English (Nigeria) -->
+ <item>en-NL</item> <!-- English (Netherlands) -->
+ <item>en-NR</item> <!-- English (Nauru) -->
+ <item>en-NU</item> <!-- English (Niue) -->
+ <item>en-NZ</item> <!-- English (New Zealand) -->
+ <item>en-PG</item> <!-- English (Papua New Guinea) -->
+ <item>en-PH</item> <!-- English (Philippines) -->
+ <item>en-PK</item> <!-- English (Pakistan) -->
+ <item>en-PN</item> <!-- English (Pitcairn Islands) -->
+ <item>en-PR</item> <!-- English (Puerto Rico) -->
+ <item>en-PW</item> <!-- English (Palau) -->
+ <item>en-RW</item> <!-- English (Rwanda) -->
+ <item>en-SB</item> <!-- English (Solomon Islands) -->
+ <item>en-SC</item> <!-- English (Seychelles) -->
+ <item>en-SD</item> <!-- English (Sudan) -->
+ <item>en-SE</item> <!-- English (Sweden) -->
+ <item>en-SG</item> <!-- English (Singapore) -->
+ <item>en-SH</item> <!-- English (St. Helena) -->
+ <item>en-SI</item> <!-- English (Slovenia) -->
+ <item>en-SL</item> <!-- English (Sierra Leone) -->
+ <item>en-SS</item> <!-- English (South Sudan) -->
+ <item>en-SX</item> <!-- English (Sint Maarten) -->
+ <item>en-SZ</item> <!-- English (Swaziland) -->
+ <item>en-TC</item> <!-- English (Turks & Caicos Islands) -->
+ <item>en-TK</item> <!-- English (Tokelau) -->
+ <item>en-TO</item> <!-- English (Tonga) -->
+ <item>en-TT</item> <!-- English (Trinidad & Tobago) -->
+ <item>en-TV</item> <!-- English (Tuvalu) -->
+ <item>en-TZ</item> <!-- English (Tanzania) -->
+ <item>en-UG</item> <!-- English (Uganda) -->
+ <item>en-UM</item> <!-- English (U.S. Outlying Islands) -->
+ <item>en-US</item> <!-- English (United States) -->
+ <item>en-VC</item> <!-- English (St. Vincent & Grenadines) -->
+ <item>en-VG</item> <!-- English (British Virgin Islands) -->
+ <item>en-VI</item> <!-- English (U.S. Virgin Islands) -->
+ <item>en-VU</item> <!-- English (Vanuatu) -->
+ <item>en-WS</item> <!-- English (Samoa) -->
+ <item>en-ZA</item> <!-- English (South Africa) -->
+ <item>en-ZM</item> <!-- English (Zambia) -->
+ <item>en-ZW</item> <!-- English (Zimbabwe) -->
+ <item>es-AR</item> <!-- Spanish (Argentina) -->
+ <item>es-BO</item> <!-- Spanish (Bolivia) -->
+ <item>es-CL</item> <!-- Spanish (Chile) -->
+ <item>es-CO</item> <!-- Spanish (Colombia) -->
+ <item>es-CR</item> <!-- Spanish (Costa Rica) -->
+ <item>es-CU</item> <!-- Spanish (Cuba) -->
+ <item>es-DO</item> <!-- Spanish (Dominican Republic) -->
+ <item>es-EA</item> <!-- Spanish (Ceuta & Melilla) -->
+ <item>es-EC</item> <!-- Spanish (Ecuador) -->
+ <item>es-ES</item> <!-- Spanish (Spain) -->
+ <item>es-GQ</item> <!-- Spanish (Equatorial Guinea) -->
+ <item>es-GT</item> <!-- Spanish (Guatemala) -->
+ <item>es-HN</item> <!-- Spanish (Honduras) -->
+ <item>es-IC</item> <!-- Spanish (Canary Islands) -->
+ <item>es-MX</item> <!-- Spanish (Mexico) -->
+ <item>es-NI</item> <!-- Spanish (Nicaragua) -->
+ <item>es-PA</item> <!-- Spanish (Panama) -->
+ <item>es-PE</item> <!-- Spanish (Peru) -->
+ <item>es-PH</item> <!-- Spanish (Philippines) -->
+ <item>es-PR</item> <!-- Spanish (Puerto Rico) -->
+ <item>es-PY</item> <!-- Spanish (Paraguay) -->
+ <item>es-SV</item> <!-- Spanish (El Salvador) -->
+ <item>es-US</item> <!-- Spanish (United States) -->
+ <item>es-UY</item> <!-- Spanish (Uruguay) -->
+ <item>es-VE</item> <!-- Spanish (Venezuela) -->
+ <item>et-EE</item> <!-- Estonian (Estonia) -->
+ <item>eu-ES</item> <!-- Basque (Spain) -->
+ <item>ewo-CM</item> <!-- Ewondo (Cameroon) -->
+ <item>fa-AF</item> <!-- Persian (Afghanistan) -->
+ <item>fa-IR</item> <!-- Persian (Iran) -->
+ <item>ff-CM</item> <!-- Fulah (Cameroon) -->
+ <item>ff-GN</item> <!-- Fulah (Guinea) -->
+ <item>ff-MR</item> <!-- Fulah (Mauritania) -->
+ <item>ff-SN</item> <!-- Fulah (Senegal) -->
+ <item>fi-FI</item> <!-- Finnish (Finland) -->
+ <item>fil-PH</item> <!-- Filipino (Philippines) -->
+ <item>fo-DK</item> <!-- Faroese (Denmark) -->
+ <item>fo-FO</item> <!-- Faroese (Faroe Islands) -->
+ <item>fr-BE</item> <!-- French (Belgium) -->
+ <item>fr-BF</item> <!-- French (Burkina Faso) -->
+ <item>fr-BI</item> <!-- French (Burundi) -->
+ <item>fr-BJ</item> <!-- French (Benin) -->
+ <item>fr-BL</item> <!-- French (St. Barthélemy) -->
+ <item>fr-CA</item> <!-- French (Canada) -->
+ <item>fr-CD</item> <!-- French (Congo (DRC)) -->
+ <item>fr-CF</item> <!-- French (Central African Republic) -->
+ <item>fr-CG</item> <!-- French (Congo (Republic)) -->
+ <item>fr-CH</item> <!-- French (Switzerland) -->
+ <item>fr-CI</item> <!-- French (Côte d’Ivoire) -->
+ <item>fr-CM</item> <!-- French (Cameroon) -->
+ <item>fr-DJ</item> <!-- French (Djibouti) -->
+ <item>fr-DZ</item> <!-- French (Algeria) -->
+ <item>fr-FR</item> <!-- French (France) -->
+ <item>fr-GA</item> <!-- French (Gabon) -->
+ <item>fr-GF</item> <!-- French (French Guiana) -->
+ <item>fr-GN</item> <!-- French (Guinea) -->
+ <item>fr-GP</item> <!-- French (Guadeloupe) -->
+ <item>fr-GQ</item> <!-- French (Equatorial Guinea) -->
+ <item>fr-HT</item> <!-- French (Haiti) -->
+ <item>fr-KM</item> <!-- French (Comoros) -->
+ <item>fr-LU</item> <!-- French (Luxembourg) -->
+ <item>fr-MA</item> <!-- French (Morocco) -->
+ <item>fr-MC</item> <!-- French (Monaco) -->
+ <item>fr-MF</item> <!-- French (St. Martin) -->
+ <item>fr-MG</item> <!-- French (Madagascar) -->
+ <item>fr-ML</item> <!-- French (Mali) -->
+ <item>fr-MQ</item> <!-- French (Martinique) -->
+ <item>fr-MR</item> <!-- French (Mauritania) -->
+ <item>fr-MU</item> <!-- French (Mauritius) -->
+ <item>fr-NC</item> <!-- French (New Caledonia) -->
+ <item>fr-NE</item> <!-- French (Niger) -->
+ <item>fr-PF</item> <!-- French (French Polynesia) -->
+ <item>fr-PM</item> <!-- French (St. Pierre & Miquelon) -->
+ <item>fr-RE</item> <!-- French (Réunion) -->
+ <item>fr-RW</item> <!-- French (Rwanda) -->
+ <item>fr-SC</item> <!-- French (Seychelles) -->
+ <item>fr-SN</item> <!-- French (Senegal) -->
+ <item>fr-SY</item> <!-- French (Syria) -->
+ <item>fr-TD</item> <!-- French (Chad) -->
+ <item>fr-TG</item> <!-- French (Togo) -->
+ <item>fr-TN</item> <!-- French (Tunisia) -->
+ <item>fr-VU</item> <!-- French (Vanuatu) -->
+ <item>fr-WF</item> <!-- French (Wallis & Futuna) -->
+ <item>fr-YT</item> <!-- French (Mayotte) -->
+ <item>fur-IT</item> <!-- Friulian (Italy) -->
+ <item>fy-NL</item> <!-- Western Frisian (Netherlands) -->
+ <item>ga-IE</item> <!-- Irish (Ireland) -->
+ <item>gd-GB</item> <!-- Scottish Gaelic (United Kingdom) -->
+ <item>gl-ES</item> <!-- Galician (Spain) -->
+ <item>gsw-CH</item> <!-- Swiss German (Switzerland) -->
+ <item>gsw-FR</item> <!-- Swiss German (France) -->
+ <item>gsw-LI</item> <!-- Swiss German (Liechtenstein) -->
+ <item>gu-IN</item> <!-- Gujarati (India) -->
+ <item>guz-KE</item> <!-- Gusii (Kenya) -->
+ <item>gv-IM</item> <!-- Manx (Isle of Man) -->
+ <item>ha-GH</item> <!-- Hausa (Ghana) -->
+ <item>ha-NE</item> <!-- Hausa (Niger) -->
+ <item>ha-NG</item> <!-- Hausa (Nigeria) -->
+ <item>haw-US</item> <!-- Hawaiian (United States) -->
+ <item>iw-IL</item> <!-- Hebrew (Israel) -->
+ <item>hi-IN</item> <!-- Hindi (India) -->
+ <item>hr-BA</item> <!-- Croatian (Bosnia & Herzegovina) -->
+ <item>hr-HR</item> <!-- Croatian (Croatia) -->
+ <item>hsb-DE</item> <!-- Upper Sorbian (Germany) -->
+ <item>hu-HU</item> <!-- Hungarian (Hungary) -->
+ <item>hy-AM</item> <!-- Armenian (Armenia) -->
+ <item>in-ID</item> <!-- Indonesian (Indonesia) -->
+ <item>ig-NG</item> <!-- Igbo (Nigeria) -->
+ <item>ii-CN</item> <!-- Sichuan Yi (China) -->
+ <item>is-IS</item> <!-- Icelandic (Iceland) -->
+ <item>it-CH</item> <!-- Italian (Switzerland) -->
+ <item>it-IT</item> <!-- Italian (Italy) -->
+ <item>it-SM</item> <!-- Italian (San Marino) -->
+ <item>ja-JP</item> <!-- Japanese (Japan) -->
+ <item>jgo-CM</item> <!-- Ngomba (Cameroon) -->
+ <item>jmc-TZ</item> <!-- Machame (Tanzania) -->
+ <item>ka-GE</item> <!-- Georgian (Georgia) -->
+ <item>kab-DZ</item> <!-- Kabyle (Algeria) -->
+ <item>kam-KE</item> <!-- Kamba (Kenya) -->
+ <item>kde-TZ</item> <!-- Makonde (Tanzania) -->
+ <item>kea-CV</item> <!-- Kabuverdianu (Cape Verde) -->
+ <item>khq-ML</item> <!-- Koyra Chiini (Mali) -->
+ <item>ki-KE</item> <!-- Kikuyu (Kenya) -->
+ <item>kk-KZ</item> <!-- Kazakh (Kazakhstan) -->
+ <item>kkj-CM</item> <!-- Kako (Cameroon) -->
+ <item>kl-GL</item> <!-- Kalaallisut (Greenland) -->
+ <item>kln-KE</item> <!-- Kalenjin (Kenya) -->
+ <item>km-KH</item> <!-- Khmer (Cambodia) -->
+ <item>kn-IN</item> <!-- Kannada (India) -->
+ <item>ko-KP</item> <!-- Korean (North Korea) -->
+ <item>ko-KR</item> <!-- Korean (South Korea) -->
+ <item>kok-IN</item> <!-- Konkani (India) -->
+ <item>ks-IN</item> <!-- Kashmiri (India) -->
+ <item>ksb-TZ</item> <!-- Shambala (Tanzania) -->
+ <item>ksf-CM</item> <!-- Bafia (Cameroon) -->
+ <item>ksh-DE</item> <!-- Colognian (Germany) -->
+ <item>kw-GB</item> <!-- Cornish (United Kingdom) -->
+ <item>ky-KG</item> <!-- Kyrgyz (Kyrgyzstan) -->
+ <item>lag-TZ</item> <!-- Langi (Tanzania) -->
+ <item>lb-LU</item> <!-- Luxembourgish (Luxembourg) -->
+ <item>lg-UG</item> <!-- Ganda (Uganda) -->
+ <item>lkt-US</item> <!-- Lakota (United States) -->
+ <item>ln-AO</item> <!-- Lingala (Angola) -->
+ <item>ln-CD</item> <!-- Lingala (Congo (DRC)) -->
+ <item>ln-CF</item> <!-- Lingala (Central African Republic) -->
+ <item>ln-CG</item> <!-- Lingala (Congo (Republic)) -->
+ <item>lo-LA</item> <!-- Lao (Laos) -->
+ <item>lrc-IQ</item> <!-- Northern Luri (Iraq) -->
+ <item>lrc-IR</item> <!-- Northern Luri (Iran) -->
+ <item>lt-LT</item> <!-- Lithuanian (Lithuania) -->
+ <item>lu-CD</item> <!-- Luba-Katanga (Congo (DRC)) -->
+ <item>luo-KE</item> <!-- Luo (Kenya) -->
+ <item>luy-KE</item> <!-- Luyia (Kenya) -->
+ <item>lv-LV</item> <!-- Latvian (Latvia) -->
+ <item>mas-KE</item> <!-- Masai (Kenya) -->
+ <item>mas-TZ</item> <!-- Masai (Tanzania) -->
+ <item>mer-KE</item> <!-- Meru (Kenya) -->
+ <item>mfe-MU</item> <!-- Morisyen (Mauritius) -->
+ <item>mg-MG</item> <!-- Malagasy (Madagascar) -->
+ <item>mgh-MZ</item> <!-- Makhuwa-Meetto (Mozambique) -->
+ <item>mgo-CM</item> <!-- Metaʼ (Cameroon) -->
+ <item>mk-MK</item> <!-- Macedonian (Macedonia (FYROM)) -->
+ <item>ml-IN</item> <!-- Malayalam (India) -->
+ <item>mn-MN</item> <!-- Mongolian (Mongolia) -->
+ <item>mr-IN</item> <!-- Marathi (India) -->
+ <item>ms-BN</item> <!-- Malay (Brunei) -->
+ <item>ms-MY</item> <!-- Malay (Malaysia) -->
+ <item>ms-SG</item> <!-- Malay (Singapore) -->
+ <item>mt-MT</item> <!-- Maltese (Malta) -->
+ <item>mua-CM</item> <!-- Mundang (Cameroon) -->
+ <item>my-MM</item> <!-- Burmese (Myanmar (Burma)) -->
+ <item>mzn-IR</item> <!-- Mazanderani (Iran) -->
+ <item>naq-NA</item> <!-- Nama (Namibia) -->
+ <item>nb-NO</item> <!-- Norwegian Bokmål (Norway) -->
+ <item>nb-SJ</item> <!-- Norwegian Bokmål (Svalbard & Jan Mayen) -->
+ <item>nd-ZW</item> <!-- North Ndebele (Zimbabwe) -->
+ <item>ne-IN</item> <!-- Nepali (India) -->
+ <item>ne-NP</item> <!-- Nepali (Nepal) -->
+ <item>nl-AW</item> <!-- Dutch (Aruba) -->
+ <item>nl-BE</item> <!-- Dutch (Belgium) -->
+ <item>nl-BQ</item> <!-- Dutch (Caribbean Netherlands) -->
+ <item>nl-CW</item> <!-- Dutch (Curaçao) -->
+ <item>nl-NL</item> <!-- Dutch (Netherlands) -->
+ <item>nl-SR</item> <!-- Dutch (Suriname) -->
+ <item>nl-SX</item> <!-- Dutch (Sint Maarten) -->
+ <item>nmg-CM</item> <!-- Kwasio (Cameroon) -->
+ <item>nn-NO</item> <!-- Norwegian Nynorsk (Norway) -->
+ <item>nnh-CM</item> <!-- Ngiemboon (Cameroon) -->
+ <item>nus-SS</item> <!-- Nuer (South Sudan) -->
+ <item>nyn-UG</item> <!-- Nyankole (Uganda) -->
+ <item>om-ET</item> <!-- Oromo (Ethiopia) -->
+ <item>om-KE</item> <!-- Oromo (Kenya) -->
+ <item>or-IN</item> <!-- Oriya (India) -->
+ <item>os-GE</item> <!-- Ossetic (Georgia) -->
+ <item>os-RU</item> <!-- Ossetic (Russia) -->
+ <item>pa-Arab-PK</item> <!-- Punjabi (Arabic,Pakistan) -->
+ <item>pa-Guru-IN</item> <!-- Punjabi (Gurmukhi,India) -->
+ <item>pl-PL</item> <!-- Polish (Poland) -->
+ <item>ps-AF</item> <!-- Pashto (Afghanistan) -->
+ <item>pt-AO</item> <!-- Portuguese (Angola) -->
+ <item>pt-BR</item> <!-- Portuguese (Brazil) -->
+ <item>pt-CV</item> <!-- Portuguese (Cape Verde) -->
+ <item>pt-GW</item> <!-- Portuguese (Guinea-Bissau) -->
+ <item>pt-MO</item> <!-- Portuguese (Macau) -->
+ <item>pt-MZ</item> <!-- Portuguese (Mozambique) -->
+ <item>pt-PT</item> <!-- Portuguese (Portugal) -->
+ <item>pt-ST</item> <!-- Portuguese (São Tomé & Príncipe) -->
+ <item>pt-TL</item> <!-- Portuguese (Timor-Leste) -->
+ <item>qu-BO</item> <!-- Quechua (Bolivia) -->
+ <item>qu-EC</item> <!-- Quechua (Ecuador) -->
+ <item>qu-PE</item> <!-- Quechua (Peru) -->
+ <item>rm-CH</item> <!-- Romansh (Switzerland) -->
+ <item>rn-BI</item> <!-- Rundi (Burundi) -->
+ <item>ro-MD</item> <!-- Romanian (Moldova) -->
+ <item>ro-RO</item> <!-- Romanian (Romania) -->
+ <item>rof-TZ</item> <!-- Rombo (Tanzania) -->
+ <item>ru-BY</item> <!-- Russian (Belarus) -->
+ <item>ru-KG</item> <!-- Russian (Kyrgyzstan) -->
+ <item>ru-KZ</item> <!-- Russian (Kazakhstan) -->
+ <item>ru-MD</item> <!-- Russian (Moldova) -->
+ <item>ru-RU</item> <!-- Russian (Russia) -->
+ <item>ru-UA</item> <!-- Russian (Ukraine) -->
+ <item>rw-RW</item> <!-- Kinyarwanda (Rwanda) -->
+ <item>rwk-TZ</item> <!-- Rwa (Tanzania) -->
+ <item>sah-RU</item> <!-- Sakha (Russia) -->
+ <item>saq-KE</item> <!-- Samburu (Kenya) -->
+ <item>sbp-TZ</item> <!-- Sangu (Tanzania) -->
+ <item>se-FI</item> <!-- Northern Sami (Finland) -->
+ <item>se-NO</item> <!-- Northern Sami (Norway) -->
+ <item>se-SE</item> <!-- Northern Sami (Sweden) -->
+ <item>seh-MZ</item> <!-- Sena (Mozambique) -->
+ <item>ses-ML</item> <!-- Koyraboro Senni (Mali) -->
+ <item>sg-CF</item> <!-- Sango (Central African Republic) -->
+ <item>shi-Latn-MA</item> <!-- Tachelhit (Latin,Morocco) -->
+ <item>shi-Tfng-MA</item> <!-- Tachelhit (Tifinagh,Morocco) -->
+ <item>si-LK</item> <!-- Sinhala (Sri Lanka) -->
+ <item>sk-SK</item> <!-- Slovak (Slovakia) -->
+ <item>sl-SI</item> <!-- Slovenian (Slovenia) -->
+ <item>smn-FI</item> <!-- Inari Sami (Finland) -->
+ <item>sn-ZW</item> <!-- Shona (Zimbabwe) -->
+ <item>so-DJ</item> <!-- Somali (Djibouti) -->
+ <item>so-ET</item> <!-- Somali (Ethiopia) -->
+ <item>so-KE</item> <!-- Somali (Kenya) -->
+ <item>so-SO</item> <!-- Somali (Somalia) -->
+ <item>sq-AL</item> <!-- Albanian (Albania) -->
+ <item>sq-MK</item> <!-- Albanian (Macedonia (FYROM)) -->
+ <item>sq-XK</item> <!-- Albanian (Kosovo) -->
+ <item>sr-Cyrl-BA</item> <!-- Serbian (Cyrillic,Bosnia & Herzegovina) -->
+ <item>sr-Cyrl-ME</item> <!-- Serbian (Cyrillic,Montenegro) -->
+ <item>sr-Cyrl-RS</item> <!-- Serbian (Cyrillic,Serbia) -->
+ <item>sr-Cyrl-XK</item> <!-- Serbian (Cyrillic,Kosovo) -->
+ <item>sr-Latn-BA</item> <!-- Serbian (Latin,Bosnia & Herzegovina) -->
+ <item>sr-Latn-ME</item> <!-- Serbian (Latin,Montenegro) -->
+ <item>sr-Latn-RS</item> <!-- Serbian (Latin,Serbia) -->
+ <item>sr-Latn-XK</item> <!-- Serbian (Latin,Kosovo) -->
+ <item>sv-AX</item> <!-- Swedish (Åland Islands) -->
+ <item>sv-FI</item> <!-- Swedish (Finland) -->
+ <item>sv-SE</item> <!-- Swedish (Sweden) -->
+ <item>sw-CD</item> <!-- Swahili (Congo (DRC)) -->
+ <item>sw-KE</item> <!-- Swahili (Kenya) -->
+ <item>sw-TZ</item> <!-- Swahili (Tanzania) -->
+ <item>sw-UG</item> <!-- Swahili (Uganda) -->
+ <item>ta-IN</item> <!-- Tamil (India) -->
+ <item>ta-LK</item> <!-- Tamil (Sri Lanka) -->
+ <item>ta-MY</item> <!-- Tamil (Malaysia) -->
+ <item>ta-SG</item> <!-- Tamil (Singapore) -->
+ <item>te-IN</item> <!-- Telugu (India) -->
+ <item>teo-KE</item> <!-- Teso (Kenya) -->
+ <item>teo-UG</item> <!-- Teso (Uganda) -->
+ <item>th-TH</item> <!-- Thai (Thailand) -->
+ <item>ti-ER</item> <!-- Tigrinya (Eritrea) -->
+ <item>ti-ET</item> <!-- Tigrinya (Ethiopia) -->
+ <item>to-TO</item> <!-- Tongan (Tonga) -->
+ <item>tr-CY</item> <!-- Turkish (Cyprus) -->
+ <item>tr-TR</item> <!-- Turkish (Turkey) -->
+ <item>twq-NE</item> <!-- Tasawaq (Niger) -->
+ <item>tzm-MA</item> <!-- Central Atlas Tamazight (Morocco) -->
+ <item>ug-CN</item> <!-- Uyghur (China) -->
+ <item>uk-UA</item> <!-- Ukrainian (Ukraine) -->
+ <item>ur-IN</item> <!-- Urdu (India) -->
+ <item>ur-PK</item> <!-- Urdu (Pakistan) -->
+ <item>uz-Arab-AF</item> <!-- Uzbek (Arabic,Afghanistan) -->
+ <item>uz-Cyrl-UZ</item> <!-- Uzbek (Cyrillic,Uzbekistan) -->
+ <item>uz-Latn-UZ</item> <!-- Uzbek (Latin,Uzbekistan) -->
+ <item>vai-Latn-LR</item> <!-- Vai (Latin,Liberia) -->
+ <item>vai-Vaii-LR</item> <!-- Vai (Vai,Liberia) -->
+ <item>vi-VN</item> <!-- Vietnamese (Vietnam) -->
+ <item>vun-TZ</item> <!-- Vunjo (Tanzania) -->
+ <item>wae-CH</item> <!-- Walser (Switzerland) -->
+ <item>xog-UG</item> <!-- Soga (Uganda) -->
+ <item>yav-CM</item> <!-- Yangben (Cameroon) -->
+ <item>yo-BJ</item> <!-- Yoruba (Benin) -->
+ <item>yo-NG</item> <!-- Yoruba (Nigeria) -->
+ <item>zgh-MA</item> <!-- Standard Moroccan Tamazight (Morocco) -->
+ <item>zh-Hans-CN</item> <!-- Chinese (Simplified Han,China) -->
+ <item>zh-Hans-HK</item> <!-- Chinese (Simplified Han,Hong Kong) -->
+ <item>zh-Hans-MO</item> <!-- Chinese (Simplified Han,Macau) -->
+ <item>zh-Hans-SG</item> <!-- Chinese (Simplified Han,Singapore) -->
+ <item>zh-Hant-HK</item> <!-- Chinese (Traditional Han,Hong Kong) -->
+ <item>zh-Hant-MO</item> <!-- Chinese (Traditional Han,Macau) -->
+ <item>zh-Hant-TW</item> <!-- Chinese (Traditional Han,Taiwan) -->
+ <item>zu-ZA</item> <!-- Zulu (South Africa) -->
+ </string-array>
+
+</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 16c610e..3ee1ca9 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1124,6 +1124,7 @@
<java-symbol type="array" name="sim_colors" />
<java-symbol type="array" name="special_locale_codes" />
<java-symbol type="array" name="special_locale_names" />
+ <java-symbol type="array" name="supported_locales" />
<java-symbol type="array" name="config_cdma_dun_supported_types" />
<java-symbol type="array" name="config_disabledUntilUsedPreinstalledImes" />
<java-symbol type="array" name="config_disabledUntilUsedPreinstalledCarrierApps" />