Android上的toUpperCase对于双参数和默认的希腊语和土耳其语语言环境是不正确的

amh*_*est 7 java turkish android internationalization

当使用带有默认语言环境的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"))
Run Code Online (Sandbox Code Playgroud)

两者都生成正确的结果.仔细观察,在T和P之后有刻度线.

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

但是,我得到了默认语言环境和双参数Locale构造函数的不同结果.

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

Locale.getDefault() ==  el_GR
Run Code Online (Sandbox Code Playgroud)

哪个用于通用的toUpperCase()

public String toUpperCase() {
    return CaseMapper.toUpperCase(Locale.getDefault(), this, value, offset, count);
}
Run Code Online (Sandbox Code Playgroud)

当我调用它时,它返回不正确的结果.

title.toUpperCase()
Run Code Online (Sandbox Code Playgroud)

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

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

如果我将两个参数构造函数用于新的语言环境,我会得到相同的结果:

title.toUpperCase(new Locale("el","GR"))
Run Code Online (Sandbox Code Playgroud)

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

将这些行添加到应用程序启动可以解决问题,但却相当苛刻.

String language = Locale.getDefault().getLanguage();
String country = Locale.getDefault().getCountry();
Locale.setDefault(new Locale(language + "-" + country));
Run Code Online (Sandbox Code Playgroud)

我宁愿简单地遵循默认语言环境.

Mat*_*ini 4

正如您在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);
    }

    ...
}
Run Code Online (Sandbox Code Playgroud)

为什么根据使用的类型会得到不同的结果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()));
Run Code Online (Sandbox Code Playgroud)

这些是获得的结果:

[el_GR] Language: 'el_gr' ~ Country: ''
[el, GR] Language: 'el' ~ Country: 'GR'
[default] Language: 'el' ~ Country: 'GR'
Run Code Online (Sandbox Code Playgroud)

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

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