Подтвердить что ты не робот

Выбор языка для упрощенного китайского языка

Как я могу получить упрощенное китайское описание (简体)? Из доступной локали Locale.SIMPLIFIED_CHINESE ни один метод не возвращает это описание:

  • getDisplayLanguage() возвращает правильное имя языка, но без варианта.
  • getDisplayName() возвращает правильное имя языка и страну, но также и без варианта.
  • getDisplayVariant() возвращает пустую строку.

Я также попытался создать новый Locale, используя разные конструкторы, также безрезультатно.

new Locale("zh", "CN");
new Locale("zh", "CN", "Hans");

Я проверил исходный код Android для LocalePicker, и я пришел к выводу, что он загружен из ресурсы (special_locale_codes и special_locale_names).

Любые решения, помимо необходимости жестко кодировать/включать эту строку в мои ресурсы?

4b9b3361

Ответ 1

Позвольте мне объяснить мой процесс, как я это решал. Во-первых, я нашел этот блок кода в LocalePicker.java

private static String getDisplayName(Locale l, String[] specialLocaleCodes, String[] specialLocaleNames) {
    String code = l.toString();

    for (int i = 0; i < specialLocaleCodes.length; i++) {
        if (specialLocaleCodes[i].equals(code)) {
            return specialLocaleNames[i];
        }
    }
    return l.getDisplayName(l);
}

который принимает в Locale, как вы уже знаете. Затем он пытается найти код локали в массиве строк specialLocaleCodes. specialLocaleNames, который вы ищете, получены из arrays.xml, как вы сказали:

<string-array translatable="false" name="special_locale_codes">
    <item>ar_EG</item>
    <item>zh_CN</item>
    <item>zh_TW</item>
</string-array>

и соответствующие языки

<string-array translatable="false" name="special_locale_names">
    <item>العربية</item>
    <item>中文 (简体)</item>
    <item>中文 (繁體)</item>
</string-array>

Обратите внимание, что код с упрощенным китайским языком - zh_CN, а последние два символа - заглавные.

Однако

Locale locale = new Locale("zh_CN");
System.out.println("Locale: " + locale);

печатает

Локаль: zh_cn

Обратите внимание на нижний регистр. Таким образом, нет способа specialLocaleCodes[i].equals(code) вернуть true. Итак, я ткнул Locale.java и, короче говоря, мы можем обойти этот случай, изменяя беспорядок, делая это (и вы ДОЛЖНЫ сохранить 3-й параметр как пустая строка для этого):

Locale locale = new Locale("zh", "CN", "");
System.out.println("Locale: " + locale);

Печать

Локаль: zh_CN

С этим вы сможете это сделать:

Locale locale = new Locale("zh", "CN", "");
System.out.println("Name:" + locale.getDisplayName(locale));

После дальнейшего осмотра Китката, используя это (спасибо Эндрю!)

int specialLocaleNamesId = Resources.getSystem().getIdentifier("special_locale_names", "array", "android");
String[] specialLocaleNames = Resources.getSystem().getStringArray(specialLocaleNamesId);

можно было распечатать

العربية, 中文 (简体), 中文 (繁體)

как ожидалось. Однако что-то в Kitkat все еще препятствует отображению правильной строки. Разочарование.


Однако в Lollipop 5.0+ и Java 1.7 это работает с использованием forLanguageTag() в Locale.

Locale locale = Locale.forLanguageTag("zh-Hans");
System.out.println("getDisplayName:" + locale.getDisplayName(locale));
System.out.println("getDisplayLanguage:" + locale.getDisplayLanguage(locale));

который печатает

getDisplayName: 中文 (简体 中文)
getDisplayLanguage: 中文

Ответ 2

Возможно, вы можете получить доступ к внутреннему ресурсу android: com.android.internal.R.array.special_locale_names так же, как это сделано в LocalePicker:

final Resources resources = context.getResources();
final String[] specialLocaleNames = resources.getStringArray(com.android.internal.R.array.special_locale_names);

Но, вероятно, безопаснее использовать свой собственный ресурс здесь (избегая использование внутренних компонентов)