Локализация информации - пакеты ресурсов

  • Поиск ресурсов
  • Файлы свойств properties
  • Классы, реализующие пакеты ресурсов
  • Методы пакета iava.util.ResourceBundle
  • При локализации приложений необходимо переводить огромное количество сообщений, надписей на кнопках и т.п. Для упрощения задачи рекомендуется собрать все локализуемые строки в отдельном месте, которое называется ресурсом (resource). В этом случае достаточно отредактировать файлы ресурсов, не трогая исходный код программы.

    В Java для определения строковых ресурсов используются файлы свойств, а для ресурсов других типов создаются классы ресурсов.

    Технология использования ресурсов в Java отличается от технологии использования ресурсов в операционных системах Windows и Macintosh. В выполняемой программе системы Windows такие ресурсы, как меню, диалоговые окна, пиктограммы и сообщения, хранятся отдельно от программы. Поэтому специальный редактор ресурсов позволяет просматривать и модифицировать их без изменения программного кода.

    В Java технологии применяется концепция использования ресурсов, позволяющая размещать файлы данных, аудиофайлы и изображения в JAR-архивах. Метод getResource () класса Class находит файл, открывает его и возвращает URL, указывающий на ресурс. При размещении файлов в JAR-архивах задачу поиска файлов решает загрузчик классов. Следует заметить, что этот механизм не обеспечивает поддержку региональных стандартов.

    Поиск ресурсов

    Для локализации приложений создаются так называемые пакеты ресурсов (resource bundle). Каждый пакет представляет собой файл свойств или класс, который описывает элементы, специфические для конкретного регионального стандарта (например, сообщения, надписи и т.д.). В каждый пакет помещаются ресурсы для всех региональных стандартов, поддержка которых предполагается в программе.

    Для именования пакетов ресурсов используются специальные соглашения. Например, ресурсы, специфические для Германии, помещаются в файл с именем имяПакета_de_DE, а ресурсы, общие для стран, в которых используется немецкий язык, размещаются в классе имяПакета_de. Общие правила таковы : ресурсы для конкретной страны именуются по принципу:

    имяПакета_язык_СТРАНА

    Имя файла ресурсов для конкретного языка формируется так :

    имяПакета_язык

    Ресурсы, применяемые по умолчанию, помещаются в файл, имя которого не содержит суффикса.
    Для загрузки пакета ресурсов используется метод getBundle().

    ResourceBundle bundle = ResourceBundle.getBundle("ProgramResources", currentLocale)

    Метод getBundle () пытается загрузить информацию из пакета ресурсов, которая соответствует языку, расположению и варианту текущего регионального стандарта.Если попытка загрузки окончилась неудачей, последовательно отбрасывается вариант, страна и язык. Затем осуществляется поиск ресурса, соответствующего текущему региональному стандарту, и происходит обращение к пакету ресурсов по умолчанию. Если и эта попытка завершается неудачей, генерируется исключение MissingResourceException. Таким образом, метод getBundle () пытается загрузить первый доступный ресурс из перечисленных пакетов:

    имяПакета_трс_язык_трс_СТРАНА_трс_вариант
    имяПакета_трс_язык_трс_СТРАНА
    имяПакета_трс_язык
     
    имяПакета_рсу_язык_рсу_СТРАНА_рсу_вариант
    имяПакета_рсу_язык_рсу_СТРАНА
    имяПакета_рсу_язык
     
    имяПакета

    Здесь используются сокращения :

  • трс - текущий региональный стандарт;
  • рсу - региональный стандарт по умолчанию.
  • Даже, если метод getBundle () находит пакет, например имяПакета_de_DE, он продолжает искать пакеты имяПакета_de, имяПакета. Если такие пакеты существуют, то они становятся родительскими по отношению к пакету имяПакета_de_DE в иерархии ресурсов. Родительские классы нужны в тех случаях, когда необходимый ресурс не найден в пакете имяПакета_de_DE, и выполняется поиск ресурса в пакетах имяПакета_de, имяПакета. Другими словами, поиск ресурса проверяется последовательно во всех пакетах до первого вхождения.

    Очевидно, что это очень полезный механизм, однако для его реализации вручную программисту пришлось бы выполнить большой объем рутинной работы. Средства поддержки пакетов ресурсов Java автоматически находят ресурсы, наилучшим образом соответствующие конкретному региональному стандарту. Для включения в существующую программу новых локальных настроек необходимо всего лишь дополнить соответствующие пакеты ресурсов.

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

    Файлы свойств

    Для интернационализации строк необходимо все строки поместить в файл свойств, например MyPackage.properties. Файл свойств - это обычный текстовый файл, каждая строка которого содержит ключ и значение. Пример содержимого такого файла приведен ниже :

    colorName=black
    PageSize=210x297
    buttonName=Insert

    Имя файла выбирается по принципу, описанному в предыдущем разделе.

    MyPackage.properties
    MyPackage_en.properties
    MyPackage_de_DE.properties

    Для загрузки пакета ресурсов из файла свойств применяется приведенное ниже выражение :

    ResourceBundle bundle = ResourceBundle.getBundle("MyPackage", locale);

    Поиск конкретной строки выполняется следующим образом :

    String label = bundle.getString ("PageSize");

    Файлы свойств могут содержать только ASCII-символы. Для размещения в них сомволов в кодировке Unicode следует использовать формат \uxxxx. Например, строка colorName=Зеленый для кириллицы будет иметь вид

    colorName=\u0417\u0435\u043B\u0435\u043D\u044B\u0439

    Для такого преобразования можно использовать утилиту native2ascii.

    Классы, реализующие пакеты ресурсов

    Для поддержки ресурсов, не являющихся строками, необходимо определить классы, являющиеся подклассами класса ResourceBundle. Выбор имен таких классов осуществляется в соответствии с соглашениями об именовании, например:

    MyProgrammResource.java
    MyProgrammResource_en.java
    MyProgrammResource_de_DE.java

    Для загрузки класса используется тот же метод getBundle (), что и для загрузки свойств.

    ResourceBoundle boundle = ResourceBoundle.getBundle ("MyProgrammResource", locale);

    Если два пакета ресурсов, один из которых реализован в виде класса, а другой в виде файла свойств имеют одинаковые имена, то при загрузке предпочтение отдается классу.
    В каждом классе, реализующем пакет ресурсов, поддерживается таблица поиска. Для получения значения используется строка-ключ.

    Color backgroundColor = (Color) bundle.getObject("backgroundColor");
    double [] paperSize = (double [])bundle.getObject("defaultPaperSize");

    Самый простой способ реализации пакета ресурсов - создание подкласса ListResourceBundle. Класс ListResourceBundle позволяет помещать все ресурсы в массив объектов и выполняет поиск. Подкласс класса ListResourceBundle должен иметь следующую структуру:

    public class имяПакета_язык_СТРАНА extends ListResourceBundle
    {
      private static final Objects [] [] contents =
      {
       {ключ1, значение1},
       {ключ2, значение2},
       . . .
      }
      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      public Object [] [] getContents () {return contents; }
    }

    Пример классов, созданных на базе ListResourceBundle, приведен ниже.

    Листинг примера использования ListResourceBundle
     
    public class ProgramResources_de extends ListResourceBundle
    {
      private static final Objects [] [] contents =
      {
       {"backgroundColor", Color.black},
       {defaultPaperSize, new double [] {210, 297}}
      }
      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      public Object [] [] getContents () {return contents; }
    }
     
    public class ProgramResources_en_US extends ListResourceBundle
    {
      private static final Objects [] [] contents =
      {
       {"backgroundColor", Color.blue},
       {defaultPaperSize, new double [] {216, 279}}
      }
      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      public Object [] [] getContents () {return contents; }
    }

    Класс пакета ресурсов можно также создать как подкласс класса ResourceBundle. В этом случае необходимо реализовывать два метода, предназначенные для получения объекта Enumeration,содержащего ключи, и для извлечения значения, соответствующего конкретному ключу.

    Enumeration getKeys ();
    Object handleGetObject (String key)

    Метод getObject () класса ResourceBundle вызывает определяемый разработчиком метод handleGetObject ().

    Методы пакета java.util.ResourceBundle

    Партнеры:

    Rambler's Top100 Рейтинг@Mail.ru