Android 上的 toUpperCase 对于 two-argument 和默认的希腊语和土耳其语区域设置不正确

toUpperCase on Android is incorrect for two-argument and default Greek and Turkish Locales

在默认语言环境下使用 toUpperCase() 或更有趣的是两个参数 Locale 构造函数时,我在使用希腊语和土耳其语时遇到问题。

问题发生在 Galaxy Tab S2 Android 5.0.2(也在 5.1.1 上重现)
该问题可通过设置应用程序和 MoreLocale 2 重现

考虑标题的这个值:Τέλος συνεδρίας

这些调用工作正常。

title.toUpperCase(new Locale("el_GR")) 
title.toUpperCase(new Locale("el-GR"))

两者都产生了正确的结果。如果你仔细看,在 T 和 P 之后有刻度线。

ΤΈΛΟΣ ΣΥΝΕΔΡΙΑΣ

但是,对于默认语言环境和 two-argument 语言环境构造函数,我得到了不同的结果。

这是我平板电脑上的默认语言环境:

Locale.getDefault() ==  el_GR

在泛型 toUpperCase() 中使用

public String toUpperCase() {
    return CaseMapper.toUpperCase(Locale.getDefault(), this, value, offset, count);
}

当我称它时 returns 结果不正确。

title.toUpperCase()

注意 T 和 P 上缺少的刻度线。

ΤΕΛΟΣ ΣΥΝΕΔΡΙΑΣ

如果我对新语言环境使用双参数构造函数,我会得到相同的结果:

title.toUpperCase(new Locale("el","GR"))

ΤΕΛΟΣ ΣΥΝΕΔΡΙΑΣ

将这些行添加到应用程序启动中可以解决问题,但有点老套。

String language = Locale.getDefault().getLanguage();
String country = Locale.getDefault().getCountry();
Locale.setDefault(new Locale(language + "-" + country));

我宁愿简单地遵从默认语言环境。

正如您在 CaseMapper.java 中看到的那样,方法 toUpperCase 对阿塞拜疆语、立陶宛语、土耳其语和希腊语语言环境有特殊的行为:

public static String toUpperCase(Locale locale, String s, int count) {
    String languageCode = locale.getLanguage();
    if (languageCode.equals("tr") || languageCode.equals("az") || languageCode.equals("lt")) {
        return ICU.toUpperCase(s, locale);
    }
    if (languageCode.equals("el")) {
        return EL_UPPER.get().transliterate(s);
    }

    ...
}

为什么根据使用的 Locale 类型会得到不同的结果?

让我们尝试分析创建的 Locale 的不同类型:

locale = new Locale("el_GR");
Log.d(TAG, String.format("[el_GR] Language: '%s' ~ Country: '%s'", locale.getLanguage(), locale.getCountry()));

locale = new Locale("el", "GR");
Log.d(TAG, String.format("[el, GR] Language: '%s' ~ Country: '%s'", locale.getLanguage(), locale.getCountry()));

locale = Locale.getDefault(); //Device with el_GR language
Log.d(TAG, String.format("[default] Language: '%s' ~ Country: '%s'", locale.getLanguage(), locale.getCountry()));

获得的结果如下:

[el_GR] Language: 'el_gr' ~ Country: ''
[el, GR] Language: 'el' ~ Country: 'GR'
[default] Language: 'el' ~ Country: 'GR'

正如您在手动创建的 Locale 中看到的那样,只有一个参数的语言是 el_gr,而对于其他两种情况,语言是 eltoUpperCase 只有当语言代码为 trazltel 时才会有不同的行为,否则它会正常行为。由于这个原因,输出是不同的。

不幸的是,如果你想要刻度线,唯一可行的解​​决方案是使用只有一个参数的 Locale 构造函数。