Интернационализация i18n

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

Для локализации интерфейса WEB-приложения необходимо создать пакеты ресурсов. Под пакетом ресурсов подразумеваются файлы для разных языков, т.е. три файла i18n.properties, i18n_ru.properties, i18n_en.properties будут составлять один пакет ресурсов. Пакет ресурсов может быть общий для всего приложения. Если ресурсный файл обозначить как global, то общий пакет ресурсов имеет наименование global.properties; для русского и английского языков соответственно global_ru.properties, global_en.properties. Дополнительно можно создать пакеты ресурсов для действий; в этом случае название пакета ресурсов должно совпадать с наименованием action-класса. Пакеты ресурсов располагаются в директории classes.

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

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

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

native2ascii -encoding UTF-8 global.properties global_ru.properties

Среда разработки типа IDE Eclipse, как правило, самостоятельно определяет принадлежность файла к ресурсам по его расширению "properties" и формату данных "key=value", и символы кирилицы значения "value" преобразовывает в Unicode.

Struts2 пример с локализацией интерфейса

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

Рассмотрим пример локализации интерфейса, позволяющий переходить с одного языка на другой без перезагрузки приложения; локализованные текстовые строки разместим в отдельных файлах. На следующем скриншоте представлена структура проекта StrutsLocalization в среде разработки Eclipse.

Проект включает действия LocaleAction.java, UserAction.java, 4 файла ресурсов global.properties, файл конфигурации struts.xml, две JSP-страницы и дескриптор приложения web.xml. Листинг и описание web.xml приведен на странице Пример Struts2, где дополнительно рассматривается вопрос кодировки передаваемых серверу сообщений.

Листинг файла ресурсов global.properties

global.name=Login
global.password=Password
global.submit=Entry
global.heading=Authorization
global.success=Successfully authenticated
global.welcome=Welcome

Листинг файла ресурсов global_ru.properties

global.name=\u041B\u043E\u0433\u0438\u043D
global.password=\u041F\u0430\u0440\u043E\u043B\u044C
...

Файл русскоязычных ресурсов приведен в сокращении. Остальные файлы ресурсов можно скачать вместе с примером.

Листинг класса-действия LocaleAction.java

Данный action-класс обеспечивает выбор Locale.

package example;

import com.opensymphony.xwork2.ActionSupport;

public class LocaleAction extends ActionSupport
{
    @Override
    public String execute() {
        return SUCCESS;
    }
}

Листинг класса-действия UserAction.java

UserAction обрабатывает параметры login и password. В приложении они не используются и не контролируются, поскольку преследуется другая цель - показать локализацию интерфейса.

package example;

import com.opensymphony.xwork2.ActionSupport;

public class UserAction extends ActionSupport
{
	private String login;
	private String password;

	@Override
	public String execute() {
		return SUCCESS;
	}	   
	public String getLogin() {
		return login;
	}
	public void setLogin(String login) {
		this.login = login;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
}

Листинг файла конфигурации struts.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" 
          "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
   <constant name="struts.devMode" value="false" />
   <constant name="struts.custom.i18n.resources" value="global" />

   <package name="default" namespace="/" extends="struts-default" >
      <action name="login" class="example.UserAction"  method="execute">
         <result name="input">/index.jsp</result>
         <result name="success">/success.jsp</result>
      </action>
      
      <action name="locale" class="example.LocaleAction" method="execute">
         <result name="success">/index.jsp</result>
      </action>
   </package>
</struts>

В представленном файле конфигурации определены действия "login" и "locale". Эти действия возвращают только результат "success". По результату действия "login" будет выполнен переход на странице success.jsp. Действие "locale" заставит перезагрузить страницу index.jsp, т.е. будет изменена локализация интерфейса.

Листинг JSP страницы index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
                      "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <title>Мультиязычная авторизация</title>
    </head>
    <body>
        <h1><s:text name="global.heading"/></h1>

        <s:form action="login" method="post" namespace="/">
            <s:textfield name="login" key="global.name" size="20" />
            <s:password name="password" key="global.password" size="20" />
            <s:submit name="submit" key="global.submit" />
        </s:form>

        <s:url var="indexEN" namespace="/" action="locale" >
            <s:param name="request_locale" >en</s:param>
        </s:url>
        <s:url var="indexES" namespace="/" action="locale" >
            <s:param name="request_locale" >es</s:param>
        </s:url>
        <s:url var="indexFR" namespace="/" action="locale" >
            <s:param name="request_locale" >fr</s:param>
        </s:url>
        <s:url var="indexRU" namespace="/" action="locale" >
            <s:param name="request_locale" >ru</s:param>
        </s:url>

        <s:a href="%{indexEN}" >English</s:a>
        <s:a href="%{indexES}" >Spanish</s:a>
        <s:a href="%{indexFR}" >France</s:a>
        <s:a href="%{indexRU}" >Russian</s:a>
    </body>
</html>

Данный фрагмент кода очень поучительный. Здесь представлены четыре ссылки, по нажатию на которые вызывается действие locale. В качестве значения параметра request_locale данного действия в запросе передается en, es, fr или ru. Таким образом, размещая ссылки на JSP-странице, пользователь получает возможность выбора языка локализации WEB приложения. В качестве ссылки можно использовать изображения национальных флагов государств.

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

На следующих скриншотах представлен интерфейс страницы index.jsp для русского и английского языков локализации.

Рускоязычный интерфейс установлен по умолчанию.

После нажатия на ссылку "English" интерфейс страницы будет обновлен.

JSP страница success.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"	pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
                      "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <title><s:text name="global.welcome"/></title>
    </head>
    <body>
        <s:property value="getText('global.success')" />
    </body>
</html>

На следующих скриншотах представлен интерфейс страницы success.jsp для русского и английского языков локализации.

Интернационализация action-класса

Приведенный выше код позволяет оперировать локалью (Locale) на уровне фреймворка. Но иногда приходится заниматься локализацией на уровне действия. Ниже приведен пример локализации поля "greeting" action-класса Welcome.

Листинг Action-класса HelloUser.java

package examples.localization; 
  
import java.util.Locale; 
import java.util.ResourceBundle; 
  
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
  
public class Welcome extends ActionSupport 
{ 
    private String greeting = null; 
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    @Override 
    public String execute () 
    { 
        ResourceBundle bundle = ResourceBundle.getBundle ("examples/localization/i18n", getLocale ()); 
        setGreeting (bundle.getString ("greeting")); 
        return Action.SUCCESS; 
    } 
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    public Locale getLocale() 
    { 
        return ActionContext.getContext().getLocale(); 
    } 
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    public String getGreeting () 
    { 
        return greeting; 
    } 
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    public void setGreeting (String greeting) 
    { 
        this.greeting = greeting; 
    } 
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
} 

В данном action-классе в методе execute приводятся строки кода, в которых выполняется обращение к региональному стандарту Locale и пакету ресурсов ResourceBundle, извлечение из ресурсного пакета значения параметра greeting для соответствующего языка локализации.

Скачать пример

Исходные коды рассмотренного примера можно скачать здесь (5.20 Мб).

  Рейтинг@Mail.ru