#java #internationalization #locale
#java #интернационализация #язык
Вопрос:
С локалями UNIX разбивка которых означает то, что относительно хорошо документировано.
LC_COLLATE
(сопоставление строк)LC_CTYPE
(преобразование символов)LC_MESSAGES
(сообщения, отображаемые в пользовательском интерфейсе)LC_MONETARY
(форматирование денежных значений)LC_NUMERIC
(форматирование неденежных числовых значений)LC_TIME
(форматирование значений даты и времени)LANG
(запасной вариант, если какой-либо из вышеперечисленных параметров не установлен)
Java имеет другую классификацию, которая не совсем соответствует реальному миру (как обычно):
Locale.getDefault()
Locale.getDefault(Locale.Category.DISPLAY)
Locale.getDefault(Locale.Category.FORMAT)
Если вы читаете документацию по ним, Locale.getDefault(Locale.Category.DISPLAY)
кажется, соответствует LC_MESSAGES
while Locale.getDefault(Locale.Category.FORMAT)
, похоже, соответствует некоторой комбинации LC_MONETARY
LC_NUMERIC
LC_TIME
.
Однако есть проблемы.
Если вы читаете исходный код JDK, вы начинаете находить много тревожных вещей. Например, ResourceBundle.getBundle(String)
— который полностью касается строковых сообщений — использует Locale.getDefault()
, а не Locale.getDefault(Locale.Category.DISPLAY)
.
Итак, я думаю, что я хочу знать:
Какой из этих методов предполагается использовать для какой цели?
Связано, но я сделал небольшую тестовую программу, чтобы увидеть, какие локали Java соответствуют каким локалям UNIX, и получил еще более удивительные результаты.
import java.util.Locale;
public class Test {
public static void main(String[] args) {
System.out.println(" Unqualified: " Locale.getDefault());
System.out.println(" Display: " Locale.getDefault(Locale.Category.DISPLAY));
System.out.println(" Format: " Locale.getDefault(Locale.Category.FORMAT));
}
}
Локали в соответствии с моей оболочкой:
$ locale
LANG="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_CTYPE="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_ALL="en_US.UTF-8"
Вывод программы:
$ java Test
Unqualified: en_AU
Display: en_AU
Format: en_AU
Получается, что Java даже не получает его из локали UNIX. Должно быть, он использует какой-то другой черный ход, чтобы получить настройки без их использования.
Ответ №1:
Трудно понять, о чем вы здесь спрашиваете. Вместо этого вы делаете заявление, которое показывает, что вам не нужен Java-программист. Все в порядке, на самом деле это не имеет значения.
Несколько вещей, которые нужно уточнить:
- Класс Locale находится в JDK начиная с Java 1.1
- Такие вещи, как локаль.Конструктор, локаль.Категория и многие другие здесь из Java 7 (JDK 1.7)
- Классы и методы, зависящие от локали, такие как DateFormat, NumberFormat, Collator, ResourceBundle, String.toLowerCase(Locale), String.toUpperCase(Locale) и многие, многие другие находятся здесь довольно долго (задолго до JDK 1.7)
- До Java 7 / JDK 1.7 существовал только один способ получения текущей локали ОС — вызов
Locale.getDefault()
(то есть без параметров)
Другими словами, до Java 7 модель локали Java была такой же простой, как одно системное свойство, состоящее из языка, страны и необязательного варианта локали. Это изменилось с Java 7 (end был расширен с Java 8 …), И теперь у вас есть два системных свойства: одно для форматирования, а другое для отображения сообщений пользовательского интерфейса.
Проблема в том, что на Java написано значительное количество устаревшего кода, и это может не сломаться при обновлении платформы. И именно поэтому у вас все еще нет параметров Locale.getDefault()
. Более того (вы можете проверить это самостоятельно), Locale.getDefault()
в основном взаимозаменяема с Locale.getDefault(Locale.Category.DISPLAY)
.
Теперь я сказал о форматировании и сообщениях пользовательского интерфейса. По сути, форматирование — это не только форматирование, но и такие вещи, как преобразование регистра символов ( LC_CTYPE
), сопоставление ( LC_COLLATE
). Вроде ничего, кроме сообщений пользовательского интерфейса. Вроде того, потому что кодировка символов по умолчанию (которая, кстати, зависит от операционной системы) не является частью Locale
. Вместо этого вам нужно вызвать Charset.defaultCharset() .
И резервные правила (встроенные в Java, а не считываемые из ОС) могут быть разработаны с помощью ResourceBundle.Класс управления. И, как мы знаем, это скорее связано с категорией пользовательского интерфейса…
Причина, по которой модель локали Java отличается от POSIX (не UNIX, она более универсальна), заключается в том простом факте, что существует довольно много платформ. И эти платформы не обязательно используют POSIX … я имею в виду не только операционные системы, но и такие вещи, как web… Java стремится быть универсальной и универсальной. В результате языковая модель Java оказывается запутанной, и это неудача.
Я должен добавить, что в настоящее время дело не только в языке и стране, но и в таких вещах, как предпочитаемый сценарий, календарная система, система нумерации, конкретные настройки сортировки и, возможно, многое другое. Иногда это даже работает.
Комментарии:
1.Говоря об этих старых API,
NumberFormat
,DateFormat
,MessageFormat
и family были обновлены для использованияgetDefault(Locale.Category.FORMAT)
, тогда какResourceBundle
не были обновлены для использованияgetDefault(Locale.Category.DISPLAY)
. Поэтому, если я установлюuser.language.display
системное свойство, оно не будет использоваться для того, для чего оно должно использоваться, если я также не пройду через свое приложение и все сторонние библиотеки для обновления любых вызововMessageFormat
, чтобы явно передать правильную локаль (это практично в нашем приложении, но библиотеки недействительно …)