Ответ 1
Поставщики локальных услуг
Java использует расширяемый механизм для предоставления данных (таких как строки, форматировщики и т.д.), которые локализованы.
Классы могут реализовать
LocaleServiceProvider
как factoryлокальные данные. Множество классов вjava.util
иjava.text
полагайтесь на этих поставщиков для правильной работы с разнымиLocale
делегируя им создание объектов.
Примеры поставщиков локальных услуг можно найти в пакете java.util.spi
, который обычно используется для отображения текста или цифр таким образом, чтобы зависит от Locale. Он включает CurrencyNameProvider
, который используется Currency
при вызове Currency#getDisplayName
.
Поиск реализации
В классах, желающих использовать определенный LocaleServiceProvider
(например, CurrencyNamePovider
), используйте LocaleServiceProviderPool
, чтобы найти экземпляры поставщика, поддерживающего определенный язык.
LocaleServiceProviderPool
сначала пытается использовать стандартную реализацию, включенную в JRE. Если он не найден, он полагается на простой механизм интерфейса поставщика услуг (SPI) в Java и использует ServiceLoader
1 чтобы попытаться найти реализации, предоставляемые сторонними библиотеками.
Это то, что написано в учебнике о Locale:
Эти методы сначала проверяют, поддерживает ли среда выполнения Java запрошенную локаль; если это так, они используют эту поддержку. В противном случае методы вызывают методы getAvailableLocales() установленных поставщиков для соответствующего интерфейса, чтобы найти поставщика, который поддерживает запрошенный язык.
Стандартные реализации поставщиков, поставляемых с JRE, можно найти в пакете sun.util.locale.provider
. Он сложный, но он по сути получает данные из jar localedata.jar
. В Oracle JDK он находится в java_home/jre/lib/ext/localedata.jar
. Если вы перечислите файлы, находящиеся в этой банке, и проверьте файлы в sun.util.resources.es
и в sun.util.resources.ru
, вы увидите, что для испанского языка существует больше имен валют, чем для русского.
Вот файлы для OpenJDK: Russian vs Испанский.
Что делать, если он вообще не определен
Локали организованы в иерархии. Например, конкретный регион страны может иметь локаль, которая отражает некоторые локальные различия с местностью страны. Если данные не найдены для Locale, LocaleServiceProviderPool
попытается использовать родительский язык Locale.
Корень дерева локалей в основном представляет собой "резервную" вымышленную локаль, которая предоставляет значения по умолчанию для всех локализованных данных.
Что, вероятно, происходит, когда вы запрашиваете отображаемое имя USD на русском языке.
расширяемость
Любая программа может предоставить дополнительную информацию о локали. Им нужно определить поставщика услуг 1 создав файл метаданных и реализуя CurrencyNameProvider
. Вы можете заполнить отсутствующие локализованные данные в своей собственной банке.
Заключение
Или Java не получил, чтобы перевести его?
Это в значительной степени.
Или я делаю что-то неправильно?
Нет, вы можете либо полагаться на значения по умолчанию, либо сами предоставлять локализованные данные.
1ServiceLoader
найдет их, попросив загрузчика классов загрузить ресурс META-INF/services/java.text.spi.DateFormatProvider
. Если такой файл найден, он должен иметь в нем конкретное имя класса реализации. Затем он пытается создать экземпляр его через загрузчик классов.