Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fb9236cb authored by Roozbeh Pournader's avatar Roozbeh Pournader
Browse files

For locale negotiation, assume English is always supported

In practice, a lot of apps provide English resources as their default
resources, so assume that English is always supported.

With this change, users can safely set secondary locales after
English in their preferred locale lists. Such settings would help
the apps (and parts of the system that are aware of multiple locales)
consider the user's familiarity with the secondary locale or the
user's preference for glyphs forms in the secondary locale.  This
change makes sure that no app unintentionally switches to such
secondary locales.

Note that this doesn't break from the tradition of previous releases.
Traditionally, if the user had set the system locale to English, they
would get the default resources when the app didn't explicitly
provide English resources. This will continue to be the case where
the user's locale list has English in it before another supported
language. (English will be the first locale in most cases.)

Bug: 26192817
Change-Id: I2c1a003760299157786c1b3f9fb116ce18db3b8c
parent ab6fb6fc
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1978,7 +1978,7 @@ public class Resources {
                    || (configChanges & Configuration.NATIVE_CONFIG_LOCALE) != 0) {
                if (locales.size() == 1) {
                    // This is an optimization to avoid the JNI call(s) when the result of
                    // getFirstMatch() does not depend on the supported locales.
                    // getFirstMatchWithEnglishSupported() does not depend on the supported locales.
                    mResolvedLocale = locales.getPrimary();
                } else {
                    String[] supportedLocales = mAssets.getNonSystemLocales();
@@ -1989,7 +1989,7 @@ public class Resources {
                        // their own.
                        supportedLocales = mAssets.getLocales();
                    }
                    mResolvedLocale = locales.getFirstMatch(supportedLocales);
                    mResolvedLocale = locales.getFirstMatchWithEnglishSupported(supportedLocales);
                }
            }
            mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc,
+33 −10
Original line number Diff line number Diff line
@@ -246,14 +246,9 @@ public final class LocaleList implements Parcelable {
        return supportedScr.equals(desiredScr) ? 1 : 0;
    }

    /**
     * Returns the first match in the locale list given an unordered array of supported locales
     * in BCP47 format.
     *
     * If the locale list is empty, null would be returned.
     */
    @Nullable
    public Locale getFirstMatch(String[] supportedLocales) {
    private static final Locale EN_LATN = Locale.forLanguageTag("en-Latn");

    private Locale computeFirstMatch(String[] supportedLocales, boolean assumeEnglishIsSupported) {
        if (mList.length == 1) {  // just one locale, perhaps the most common scenario
            return mList[0];
        }
@@ -261,8 +256,16 @@ public final class LocaleList implements Parcelable {
            return null;
        }
        int bestIndex = Integer.MAX_VALUE;
        for (String tag : supportedLocales) {
            final Locale supportedLocale = Locale.forLanguageTag(tag);
        final int numSupportedLocales =
                supportedLocales.length + (assumeEnglishIsSupported ? 1 : 0);
        for (int i = 0; i < numSupportedLocales; i++) {
            final Locale supportedLocale;
            if (assumeEnglishIsSupported) {
                // Try English first, so we can return early if it's in the LocaleList
                supportedLocale = (i == 0) ? EN_LATN : Locale.forLanguageTag(supportedLocales[i-1]);
            } else {
                supportedLocale = Locale.forLanguageTag(supportedLocales[i]);
            }
            // We expect the average length of locale lists used for locale resolution to be
            // smaller than three, so it's OK to do this as an O(mn) algorithm.
            for (int idx = 0; idx < mList.length; idx++) {
@@ -283,6 +286,26 @@ public final class LocaleList implements Parcelable {
        }
    }

    /**
     * Returns the first match in the locale list given an unordered array of supported locales
     * in BCP47 format.
     *
     * If the locale list is empty, null would be returned.
     */
    @Nullable
    public Locale getFirstMatch(String[] supportedLocales) {
        return computeFirstMatch(supportedLocales, false /* assume English is not supported */);
    }

    /**
     * Same as getFirstMatch(), but with English assumed to be supported, even if it's not.
     * {@hide}
     */
    @Nullable
    public Locale getFirstMatchWithEnglishSupported(String[] supportedLocales) {
        return computeFirstMatch(supportedLocales, true /* assume English is supported */);
    }

    /**
     * Returns true if the array of locale tags only contains empty locales and pseudolocales.
     * Assumes that there is no repetition in the input.
+1 −1
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@ LOCAL_SRC_FILES := \
	$(call all-java-files-under, EnabledTestApp/src)

LOCAL_DX_FLAGS := --core-library
LOCAL_AAPT_FLAGS = -0 dat -0 gld
LOCAL_AAPT_FLAGS = -0 dat -0 gld -c fa
LOCAL_STATIC_JAVA_LIBRARIES := \
    core-tests-support \
    android-common \
+4 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="dummy_string">رشتهٔ الکی</string>
</resources>
+3 −0
Original line number Diff line number Diff line
@@ -139,4 +139,7 @@
    <!-- RestrictionsManagerTest -->
    <string name="restrictionManager_title">Title</string>
    <string name="restrictionManager_desc">Description</string>

    <!-- ResourcesLocaleResolutionTest -->
    <string name="dummy_string">dummy string</string>
</resources>
Loading