Struts2 - интернационализация

Вопросу интернационализации приложений уделено немало внимания на наших страницах, где приводятся понятия интернационализации и локализации, дается объяснение региональным стандартам, описываются форматы представления даты, времени, чисел для различных стран и языков. Но самое главное, что мы будем использовать в Struts2, так это описание Пакетов ресурсов.

При использовании Struts2 для интернационализации приложения нам необходимо только знание структуры пакетов ресурсов и их размещение в директории. Под пакетом ресурсов будем подразумевать все файлы для разных языков, т.е. три файла i18n.properties, i18n_ru.properties, i18n_en.properties будут составлять один пакет ресурсов.

Пакет ресурсов может быть общий для всего приложения. Общий пакет ресурсов имеет наименование package.properties; для русского и английского языков соответственно package_ru.properties, package_en.properties. Дополнительно можно создать пакеты ресурсов для действий (страниц); в этом случае название пакета ресурсов должно совпадать с наименованием Action-класса. Пакеты ресурсов располагаются в директории classes.

Преобразование ресурсного файла в Unicode

Вопросу преобразования ресурсных файлов в Unicode посвящено немало статей. Поэтому мы данному вопросу не будем уделять столь значительного внимания. Отметим только, что для преобразования можно использовать native2ascii, который поставляется с JDK. Данная утилита преобразует файл с символами национальной кодировки (не-Латинские и не-Unicode символы) в точно такой же файл с Unicode-символами.

Для преобразования можно воспользоваться следующей командой

native2ascii  -encoding  UTF-8   i18n_ru.properties  i18n_ru.propertiesX

После выполнения данной команды все параметры преобразованы в Unicode и браузер может их прочитать!
При локализации WEB-приложения необходимо помнить, что имеется клиентская и серверная части приложения. В качестве клиента выступает WEB-браузер, который отправляет серверу запрос. Браузер может работать в различных кодировках. Самое главное, чтобы наш сервер разобрался с кодировкой браузера и подключил соответствующий файл ресурсов.

Выбор языка локализации в браузере

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

Интерцептор i18n фреймворка Struts2 предоставляет простой способ решения проблемы интернационализации. Данный перехватчик проверяет, содержит ли запрос ( request ) параметр, который имеет наименование request_locale. Если параметр request_locale присутствует, то его значение сохраняется в объекте ActionContext фреймворка, переопределяя объект Locale, созданный для данной сессии по умолчанию. Все, что теперь требуется от разработчика, так это обеспечить пользователя формой, в которой он сможет выбрать желаемый язык представления.

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

Фрагменты кода страницы JSP для выбора языка локализации
<s:url id="lang_en" action="ChangeLanguage"> <s:param name="request_locale">en</s:param> </s:url> <s:a href="%{lang_en}">English</s:a> <s:url id="lang_ru" action="ChangeLanguage"> <s:param name="request_locale">ru</s:param> </s:url> <s:a href="%{lang_ru}"><s:text name="lang_ru"/>

Данный фрагмент кода очень поучительный. Здесь представлены две ссылки, по нажатию которых вызывается действие ChangeLanguage. В качестве значения параметра request_locale данного действия в запросе передается либо en, либо ru.

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

В представленном фрагменте кода интерес представляет также локализация самих ссылок. Если для английского языка ссылка имеет постоянное обозначение English, то обозначение русского языка меняется в зависимости от языка локализации и содержимого ресурсного файла. Struts2 получает локализованное обозначение ссылки русского языка в следующем коде : <s:text name="lang_ru"/>

Ресурсные файлы

Структура ресурсных файлов (i18n.properties, i18n_en.properties, i18n_ru.properties) для двух параметров представлена в следующем листинге :

[ i18n.properties ]
  
greeting=Hi 
lang_ru=Russion 
  
[ i18n_en.properties ]
  
greeting=Hi 
lang_ru=Russion 
  
[ i18n_ru.properties ] 
  
greeting=\u041F\u0440\u0438\u0432\u0435\u0442 
lang_ru=\u0420\u0443\u0441\u0441\u043A\u0438\u0439 

В ресурсном файле i18n_ru.properties значения параметров greeting (Привет) и lang_ru (Русский) представлены в кодировке Unicode.

ActionSupport обеспечивает интернационализацию

После выбора языка локализации в браузере необходимо рассмотреть данный вопрос и с точки зрения Action-класса.

Класс ActionSupport обеспечивает решение задачи интернационализации сообщений. Для этого необходимо использовать метод getLocale интерфейса com.opensymphony.xwork2.LocaleProvider, который ActionSupport наследует.

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

Листинг Action-класса HelloUser.java
package examples.localization; import java.util.Locale; import java.util.ResourceBundle; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ActionContext; public class HelloUser extends ActionSupport { private String username = null; private String customGreeting = null; private ResourceBundle bundle = null; private static String GREETING = "Привет"; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public String execute () { String username = getUsername (); bundle = ResourceBundle.getBundle ("examples/localization/i18n", getLocale ()); GREETING = bundle.getString ("greeting"); if ((username != null) && (username.trim().length()>0)) setCustomGreeting (GREETING + ", " + username); else setCustomGreeting (GREETING); return "SUCCESS"; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public String getUsername () { return username; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public void setUsername (String username) { this.username = username; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public String getCustomGreeting () { return customGreeting; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public void setCustomGreeting (String customGreeting) { this.customGreeting = customGreeting; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public Locale getLocale() { return ActionContext.getContext().getLocale(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ }

В данном Action-классе в методе execute приводятся строки кода, в которых выполняется обращение к региональному стандарту Locale и пакету ресурсов ResourceBundle, извлечение из ресурсного пакета значения параметра greeting для соответствующего языка локализации. Если userName определен, то формируется строка представления, включающая локализованное приветствие (Hi или Привет) и имя пользователя, в противном случае только локализованное приветствие.