Какая «локаль по умолчанию» какая?

#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-программист. Все в порядке, на самом деле это не имеет значения.

Несколько вещей, которые нужно уточнить:

Другими словами, до 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 , чтобы явно передать правильную локаль (это практично в нашем приложении, но библиотеки недействительно …)