Merge "Adding a locale picker with two-step selection: language, then region."
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" />