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

Commit c033ce97 authored by Victor Chang's avatar Victor Chang
Browse files

Update LocaleUtils.filterByLanguage due to addLikelySubtags change

ULocale.addLikelySubtags is allowed to canonicalize subtags according to
step 1 in the spec http://www.unicode.org/reports/tr35/#Likely_Subtags
- "Replace any deprecated subtags with their canonical values using the
  <alias> data in supplemental metadata. Use the first value in the
  replacement list, if it exists."
- In this case, ULocale.addLikelySubtag("sr-Latn-CS") returns
  "sr-Latn-RS". Thus, the algorithm of LocaleUtils.calculateMatchingSubScore
  needs to be updated to do what it tries to do.

In addition, update DateIntervalFormatTest due to
  ICU 74 de locale data change

Bug: 327164201
Test: atest FrameworksCoreTests:android.text.format
Test: atest FrameworksServicesTests:com.android.server.inputmethod
Test: atest CtsInputMethodTestCases
Change-Id: I5902000994c8af8bdb7e26c99ae33b85cd5ccca4
parent 9138e506
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -149,7 +149,7 @@ public class DateIntervalFormatTest {
                FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
        assertEquals("19.–22.01.2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY,
                FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
        assertEquals("19.01.22.04.2009",
        assertEquals("19.01.\u2009–\u200922.04.2009",
                formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * MONTH,
                        FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
        assertEquals("19.01.2009\u2009\u2013\u200909.02.2012",
@@ -220,10 +220,10 @@ public class DateIntervalFormatTest {
                formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY, 0));
        assertEquals("19.–22. Jan. 2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY,
                FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
        assertEquals("Mo., 19.Do., 22. Jan. 2009",
        assertEquals("Mo., 19.\u2009–\u2009Do., 22. Jan. 2009",
                formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY,
                        FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
        assertEquals("Montag, 19.Donnerstag, 22. Januar 2009",
        assertEquals("Montag, 19.\u2009–\u2009Donnerstag, 22. Januar 2009",
                formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY));

        assertEquals("19. Januar\u2009\u2013\u200922. April 2009",
+21 −7
Original line number Diff line number Diff line
@@ -46,30 +46,45 @@ final class LocaleUtils {
     * @param desired The locale preferred by user.
     * @return A score based on the locale matching for the default subtype enabling.
     */
    @IntRange(from = 1, to = 3)
    @IntRange(from = 1, to = 4)
    private static byte calculateMatchingSubScore(@NonNull final ULocale supported,
            @NonNull final ULocale desired) {
        // Assuming supported/desired is fully expanded.
        if (supported.equals(desired)) {
            return 3;  // Exact match.
            return 4;  // Exact match.
        }

        // addLikelySubtags is a maximization process as per
        // https://www.unicode.org/reports/tr35/#Likely_Subtags
        ULocale maxDesired = ULocale.addLikelySubtags(desired);

        // Skip language matching since it was already done in calculateMatchingScore.

        final String supportedScript = supported.getScript();
        if (supportedScript.isEmpty() || !supportedScript.equals(desired.getScript())) {
        if (supportedScript.isEmpty() || !supportedScript.equals(maxDesired.getScript())) {
            // TODO: Need subscript matching. For example, Hanb should match with Bopo.
            return 1;
        }

        final String supportedCountry = supported.getCountry();
        if (supportedCountry.isEmpty() || !supportedCountry.equals(desired.getCountry())) {
        if (supportedCountry.isEmpty() || !supportedCountry.equals(maxDesired.getCountry())) {
            return 2;
        }

        // Ignore others e.g. variants, extensions.

        // Since addLikelySubtags can canonicalize subtags, e.g. the deprecated country codes
        // an locale with an identical script and country before addLikelySubtags is in favour,
        // and a score of 4 is returned.
        String desiredScript = desired.getScript();
        String desiredCountry = desired.getCountry();
        if ((desiredScript.isEmpty() || desiredScript.equals(maxDesired.getScript()))
                && (desiredCountry.isEmpty() || desiredCountry.equals(maxDesired.getCountry()))) {
            return 4;
        } else {
            return 3;
        }
    }

    private static final class ScoreEntry implements Comparable<ScoreEntry> {
        public int mIndex = -1;
@@ -180,8 +195,7 @@ final class LocaleUtils {
                            ULocale.forLocale(preferredLocale));
                }
                score[j] = calculateMatchingSubScore(
                        preferredULocaleCache[j],
                        ULocale.addLikelySubtags(ULocale.forLocale(locale)));
                        preferredULocaleCache[j], ULocale.forLocale(locale));
                if (canSkip && score[j] != 0) {
                    canSkip = false;
                }
+23 −0
Original line number Diff line number Diff line
@@ -357,6 +357,29 @@ public class LocaleUtilsTest {
            assertEquals(1, dest.size());
            assertEquals(availableLocales.get(0), dest.get(0));  // "sr-Latn-RS"
        }
        // Locale with deprecated subtag, e.g. CS for Serbia and Montenegro, should not win
        // even if the other available locale doesn't have explicit script / country.
        // On Android, users don't normally use deprecated subtags unless the application requests.
        {
            final LocaleList preferredLocales = LocaleList.forLanguageTags("sr-RS");
            final ArrayList<Locale> availableLocales = new ArrayList<>();
            availableLocales.add(Locale.forLanguageTag("sr-Cyrl-CS"));
            availableLocales.add(Locale.forLanguageTag("sr-RS"));
            final ArrayList<Locale> dest = new ArrayList<>();
            LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
            assertEquals(1, dest.size());
            assertEquals(availableLocales.get(1), dest.get(0));  // "sr-RS"
        }
        {
            final LocaleList preferredLocales = LocaleList.forLanguageTags("sr-RS");
            final ArrayList<Locale> availableLocales = new ArrayList<>();
            availableLocales.add(Locale.forLanguageTag("sr-Cyrl-CS"));
            availableLocales.add(Locale.forLanguageTag("sr"));
            final ArrayList<Locale> dest = new ArrayList<>();
            LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
            assertEquals(1, dest.size());
            assertEquals(availableLocales.get(1), dest.get(0));  // "sr"
        }
    }

    @Test