Пакеты ресурсов Java содержат локализуемый текст. Один тип пакета - это PropertyResourceBundle
. Этот пакет представляет собой текстовый файл, содержащий простые пары ключ-значение, например:
HELLO=I'm just a string, nothing special here. CAVEAT=But my encoding is LATIN-1!
Хотя файлы свойств Java эффективны и широко используются, они ужасно неудобны в одном значительном смысле: они должны быть закодированы как ISO-8859–1
.
Это означает, что вы не можете представить большинство символов Юникода без специальных методов экранирования, если вы используете JDK 8 или более ранние версии.
Возня с кодировками ASCII
В JDK 8 и ранее вы должны использовать escape-символы ASCII, отличные от Latin-1, если вы хотите использовать PropertyResourceBundle
. В Java Development Kit (JDK) есть инструмент под названием native2ascii
для облегчения преобразования. Это дополнительное экранирование делает переведенные пакеты ресурсов практически невозможными для визуального чтения. Например, слово «книга» по-японски - «本» (хон). Используя механизм загрузки пакета свойств по умолчанию, вам нужно будет экранировать файл свойств ASCII. Формат ASCII-escape - \uXXXX
, где XXXX
представляет шестнадцатеричное значение единицы кода UTF-16:
BOOK=\u672C
На мой взгляд, это просто недопустимо. Мы предпочитаем видеть правильный персонаж в его естественной визуальной форме:
BOOK=本
Создание элемента управления ResourceBundle с поддержкой UTF-8
К счастью, вам не нужно жертвовать удобством использования и удобочитаемостью. Мы можем создать наш собственный класс ResourceBundle.Control
, чтобы переопределить стратегию загрузки по умолчанию, используемую методом ResourceBundle.getBundle
. Перегрузив метод newBundle
, мы можем легко указать загрузчику пакета использовать UTF-8 для кодировки кодировки файла свойств.
Создайте PropertyResourceBundle
, используя UTF-8 InputStreamReader
вместо InputStream
, который ограничен Latin-1:
InputStream stream = classLoader.getResourceAsStream(resourceName); Reader reader = new InputStreamReader(stream, “UTF-8”); ResourceBundle bundle = new PropertyResourceBundle(reader);
Полный исходный код UTF8ResourceBundleControl
находится в моем проекте Github Enhanced Resources. Ознакомьтесь с полной информацией о том, как реализовать подкласс ResourceBundle.Control
.
Использование элемента управления UTF 8 ResourceBundle
Использовать новый UTF8ResourceBundleControl
так же просто, как передать его методу ResourceBundle.getBundle
. В этом тесте я создаю пакет японского языка и получаю строку в кодировке UTF-8:
ResourceBundle.Control utf8Control = new Utf8ResourceBundleControl(); ResourceBundle bundle = ResourceBundle.getBundle(“com.joconner.i18n.res.Utf8Resources”, Locale.JAPANESE, utf8Control); String hello = bundle.getString(“HELLO”); assertEquals(“こんにちは!”, hello);
С нетерпением жду JDK 9
В JDK 9 добавлена поддержка файлов свойств UTF-8. Вы можете прочитать больше об этом долгожданном дополнении в этой заметке OpenJDK JEP. Вы сможете пользоваться ресурсами UTF-8 без лишних усилий. А пока, однако, если вы собираетесь продолжать использовать JDK 8 еще какое-то время, пожалуйста, попробуйте мою реализацию.
Загрузите исходный код для UTF8ResourceBundleControl
и других из моего репозитория Расширенные ресурсы на Github. Получайте удовольствие от поддержки UTF-8 в PropertyResourceBundle
файлах без кодировки ASCII.