В Java, почему десятичный разделитель соответствует языку локали, а не стране, и, что более важно, как его переопределить? - PullRequest
8 голосов
/ 17 февраля 2010

Я работаю над международным проектом и заметил, что в Java выбор десятичного разделителя основан на языке Locale, а не на его стране. Например:

DecimalFormat currencyFormatter = (DecimalFormat) NumberFormat.getInstance(new Locale("it","IT"));
System.out.println(currencyFormatter.format(-123456.78));

currencyFormatter = (DecimalFormat) NumberFormat.getInstance(new Locale("en","IT"));
System.out.println(currencyFormatter.format(-123456.78));

производит следующий вывод:

-123.456,78
-123,456.78

Я бы ожидал, что он будет следовать за страной, поскольку, если я нахожусь в стране, независимо от того, говорю ли я по-английски или по-итальянски, числа в этой стране пишутся с десятичным разделителем в виде запятой.

У меня вопрос двоякий:

  1. Кто-нибудь знает, почему это поведение следует за языком?
  2. Что более важно, кто-нибудь может предложить подробности о том, как изменить поведение по умолчанию в Java, чтобы вместо этого следовать языку?

Спасибо.

Ответы [ 8 ]

6 голосов
/ 17 февраля 2010

Весьма вероятно, что в вашей системе нет известного языкового стандарта "en_IT" и Java не знает такого языкового стандарта.

Поэтому вы получите ресурсы для ближайшего соответствующего языкового стандарта, так каксогласно этой заметке в JavaDoc Locale:

Когда вы запрашиваете ресурс для определенной локали, вы получаете лучшее доступное соответствие, не обязательно точно то, что выпопросил о.Для получения дополнительной информации см. ResourceBundle.

Соответствующая документация в ResourceBundle показывает, что одна страна никогда не используется в качестве идентификатора длянайти данный ресурс.Используются только язык, язык + страна и язык + страна + вариант.

4 голосов
/ 17 февраля 2010

1.- Кто-нибудь знает, почему это поведение следует за языком?

Одним из первых аспектов, которые изменяются в приложении в зависимости от его языка, является язык.Подумайте о Швейцарии, в которой официальными языками являются французский и немецкий.Использование страны в этом сценарии не имеет смысла, потому что, помимо валюты, есть и другой аспект (например, отображать сообщения, которые необходимо учитывать)

То же самое относится и к ряду стран (на мой взгляд, Канада - это другая страна)).

В стране есть возможность специализировать этот язык.

Поскольку нет «итальянского английского», en_IT не имеет особого смысла.Таким образом, он принимает «английский», и поэтому возвращаемый экземпляр - это «английский».

2.- Что более важно, кто-нибудь может предложить подробности о том, как изменить поведение по умолчанию в Java, чтобы вместо этого следовать языку?

Ты имеешь в виду, правильно ли страна?

Ответ находится в методе: NumberFormat.getAvailableLocales () , что, в свою очередь, приводит вас к: NumberFormatProvider , который является абстрактным классом, который вы можете расширить для возврата правильногоNumberFormat для "en_IT" (который в значительной степени вернет it_IT)

Как установить этот новый класс выходит за рамки моих знаний, но я думаю, вам придется взломать его где-то в jre каталог.

EDIT

Как я подозреваю, класс должен быть установлен в папке jre/ext и все.

В другом месте есть проект, который сделал что-то похожее на поддержку "gl_ES" (Галисийский)

Вот инструкции о том, как его установить и что это такое:

http://www.javagalician.org/install.html

Итак, в основном, если вы хотите предоставить кучу экземпляров для Италии (или даже лучше, один), вам просто нужно создать один экземпляр NumberFormatProvider и заставить его отвечать на все языки.имеется в наличии.

4 голосов
/ 17 февраля 2010

Но если вы англичанин, живущий в Италии, скорее всего, вы по-прежнему пишете свои цифры по-английски и считаете свои деньги в фунтах у себя в голове - и наоборот; -)

Так что мне такое поведениевыглядит вполне логично.И я боюсь, что не может быть способа получить то, что вы хотите: - (

Обновление на основе комментария Оскара Рейеса: В Java 6 NumberFormatProvider позволяет вам достичь своей цели.

2 голосов
/ 17 февраля 2010

Ваше предположение "Я бы ожидал, что он будет следовать за страной, поскольку, если я нахожусь в стране, независимо от того, говорю ли я по-английски или по-итальянски, числа в этой стране пишутся с десятичным разделителем в виде запятой." 1002 * неверно. В нескольких двуязычных странах существуют правила форматирования чисел для конкретных языков. Среди стран, где правила форматирования в Sun JDK, это относится к Канаде, Индии и Люксембургу.

2 голосов
/ 17 февраля 2010

Изменение всего Java - большой заказ; Насколько я знаю, это невозможно сделать на уровне JVM. Однако вы можете вручную установить числовой формат для ваших конкретных классов / проектов практически в любой локали (или даже в воображаемой системе) с помощью класса DecimalFormatSymbols . См. "Изменение символов форматирования" на странице Учебники Java по настройке формата для получения примеров и дополнительной информации.

Конечно, это не оптимальный подход, если ваша программа может использоваться более чем в трех или четырех разных местах, но она может работать, если вы поддерживаете только несколько.

0 голосов
/ 24 июля 2012

Как уже отмечалось, проблема, скорее всего, в том, что java не может найти ваш точный локальный адрес, поэтому он подошел к тому, что считалось наиболее близким. Если у вас есть объект DecimalFormat, вы можете вручную изменить разделители, если хотите.

DecimalFormat format = ...;
DecimalFormatSymbols symbols = format.getDecimalFormatSymbols();
symbols.setDecimalSeparator(',');
symbols.setGroupingSeparator('.');
format.setDecimalFormatSymbols(symbols);
0 голосов
/ 24 июля 2012

Я бы ожидал, что он будет следовать за страной, поскольку, если я нахожусь в стране, независимо от того, говорю ли я по-английски или по-итальянски, числа в этой стране записываются с десятичным разделителем в виде запятой.

Нет. В некоторых странах со многими официальными языками, такими как Канада (два официальных языка), действуют разные правила форматирования в зависимости от языка:

-1 234,56 (Locale.CANADA_FRENCH)
-1,234.56 (Locale.CANADA (should probably be named CANADA_ENGLISH))
0 голосов
/ 17 февраля 2010

Я думаю, вы можете переопределить поведение NumberFormat для локали, используя LocaleServiceProvider Это потребует Java 6, хотя ...

...