DecimalFormatSymbols има неочаквани специфични за региона стойности за неортодоксални локали

С помощта на DecimalFormatSymbols можете да поискате характеристики, базирани на локал, като десетичен разделител или разделител на хиляди.

Докато го поискате за обичайни езикови тагове (напр. de-AT, en-US), той работи според очакванията. Но ако смесите комбинации език-държава, това се държи странно. По-специално, нека да разгледаме разделителя на хилядите. (за английски е ,, за немски е .)

    System.out.println("en-US: " + DecimalFormatSymbols.getInstance(Locale.US).getGroupingSeparator());
    System.out.println("de-DE: " + DecimalFormatSymbols.getInstance(Locale.GERMANY).getGroupingSeparator());
    System.out.println("de-US: " + DecimalFormatSymbols.getInstance(new Locale.Builder().setLanguage("de").setRegion("US").build()).getGroupingSeparator());
    System.out.println("de: "+DecimalFormatSymbols.getInstance(new Locale.Builder().setLanguage("de").build()).getGroupingSeparator());
    System.out.println("DE: " + DecimalFormatSymbols.getInstance(new Locale.Builder().setRegion("DE").build()).getGroupingSeparator());
    System.out.println("ru-RU: " + DecimalFormatSymbols.getInstance(new Locale.Builder().setLanguage("ru").setRegion("RU").build()).getGroupingSeparator());
    System.out.println("RU: " + DecimalFormatSymbols.getInstance(new Locale.Builder().setRegion("RU").build()).getGroupingSeparator());

Резултатът е:

en-US: ,
de-DE: .
de-US: .
de: .
DE: ,
ru-RU: 0x160
RU: ,

За de-US посочва точка като разделител, който представлява разделителя на немски, но не и за САЩ. Сякаш взема предвид само езиковия таг.

Ако създам локал, който има само информация за държава (липсващ език), изглежда, че винаги се връща английският разделителен формат.

Как мога да се справя правилно с това? Искам формата за най-конкретната информация в локала. За de искам немския. За de-US искам английския формат.


person PAX    schedule 30.03.2021    source източник


Отговори (1)


Информация, свързана с локала, като DecimalFormatSymbols, обикновено се съхраняват в Java Runtime Library в ResourceBundle файлове.

Прочетете javadoc за пълни подробности, но съответната част е:

Пакетите ресурси принадлежат на семейства, чиито членове споделят общо базово име, но чиито имена също имат допълнителни компоненти, които идентифицират техните локали. Например основното име на семейство от пакети с ресурси може да бъде MyResources. Фамилията трябва да има набор от ресурси по подразбиране, който просто има същото име като своето семейство - MyResources - и ще се използва като пакет от последна инстанция, ако не се поддържа конкретен локал. След това семейството може да предостави толкова много специфични за локала членове, колкото е необходимо, например немски, наречен MyResources_de.

Ако има различни ресурси за различни страни, можете да направите специализации: например MyResources_de_CH съдържа обекти за немски език (de) в Швейцария (CH). Ако искате да промените само някои от ресурсите в специализацията, можете да го направите.

Така че търсенето на символ ще използва language-country комбо. Ако не бъде намерено, ще се опита да използва само language. В противен случай той ще използва основния файл, който има стойности по подразбиране.

Стойността по подразбиране за getGroupingSeparator е ,, така че това е стойността, която получавате за неподдържани локали като DE и RU.

person Andreas    schedule 30.03.2021
comment
Благодаря за това пояснение. Благодарение на вашата помощ разбрах, че тези налични настройки се намират в /jdk-installation/jre/lib/ext/localedata.jar. Има Java класове за пакети с ресурси за много локали, които предоставят различна информация, специфична за локала, статично. Ключът NumberElements се изследва по-късно, за да се осигури този разделител за групиране. Всичко, което трябва да направя сега, е да добавя липсващи локали в тези сложни структури от данни на java. - person PAX; 31.03.2021