Đa ngôn ngữ (i18n) trong Struts 2




Internationalization (i18n) là tiến trình triển khai các sản phẩm và dịch vụ để chúng thích nghi với locale và culture cụ thể. Internationalization được viết tắt thành i18n vì từ này bắt đầu với chữ i, kết thúc với chữ n và ở giữa có 18 chữ. Struts 2 hỗ trợ i18n thông qua resource bunble, interceptor và các tab library.

Giới thiệu i18n Interceptor

i18n Interceptor cung cấp hỗ trợ đa ngôn ngữ cho ứng dụng của bạn. Nó được tìm thấy trong defaultStack, do đó bạn không cần xác định nó một cách tường minh. i18n Interceptor có các tham số sau:

  • Ten_tham_so: xác định tên của tham số HTTP request. Theo mặc định, nó được thiết lập là request_locale.

  • Ten_thuoc_tinh: xác định tên của session key để lưu trữ locale. Theo mặc định, nó là WW_TRANS_I18N_LOCALE.

Giới thiệu global.properties file

Để phát triển ứng dụng của bạn trong nhiều ngôn ngữ, bạn cần phải duy trì nhiều property file tương ứng với các language/locale đó và định nghĩa nội dung theo cách là các cặp key/value. Ví dụ, nếu bạn muốn phát triển ứng dụng cho US (mặc định), Tây Ba Nha và Pháp thì bạn phải tạo 3 properties file. Trong chương này chúng tôi chỉ sử dụng global.properties, và tất nhiên bạn cũng có thể sử dụng nhiều property file khác nhau để tách riêng các kiểu thông điệp khác nhau.

  • global.properties: thiết lập mặc định cho US.

  • global_fr.properties: được sử dụng cho Franch locale.

  • global_es.properties: được sử dụng cho Spanish locale.

Truy cập các Message Resource

Có nhiều cách khác nhau để truy cập các Message Resource, bao gồm getText, text tag, thuộc tính key của UI tags, và i18n tag. Sau đây chúng ta giới thiệu ngắn gọn chúng:

Để hiển thị i18n text, sử dụng lời gọi tới getText trong thẻ property, hoặc bất kỳ thẻ khác như UI tags, như sau:

<s:property value="getText('some.key')" />

Thẻ text lấy một thông điệp từ resource bundle mặc định:

<s:text name="some.key" />

Thẻ i18n đẩy một resource bundle lên trên cùng của Value Stack. Các thẻ khác bên trong phạm vi của thẻ i18n có thể hiển thị các thông điệp từ resource bundle đó:

<s:i18n name="some.package.bundle">
     <s:text name="some.key" />
</s:i18n>

Thuộc tính key của hầu hết các UI tags có thể được sử dụng để thu nhận một thông điệp từ một resource bundle.

<s:textfield key="some.key" name="textfieldName"/>

Ví dụ i18n trong Struts 2

Mục tiêu của chúng ta là tạo trang index.jsp có thể hiển thị trong nhiều ngôn ngữ. Bây giờ file này được viết như sau:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
   pageEncoding="ISO-8859-1"%>
<%@ 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>Employee Form ho tro Da ngon ngu</title>
</head>

<body>
   <h1><s:text name="global.heading"/></h1>

   <s:url id="indexEN" namespace="/" action="locale" >
      <s:param name="request_locale" >en</s:param>
   </s:url>
   <s:url id="indexES" namespace="/" action="locale" >
      <s:param name="request_locale" >es</s:param>
   </s:url>
   <s:url id="indexFR" namespace="/" action="locale" >
      <s:param name="request_locale" >fr</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:form action="empinfo" method="post" namespace="/">
      <s:textfield name="name" key="global.name" size="20" />
      <s:textfield name="age" key="global.age" size="20" />
      <s:submit name="submit" key="global.submit" />
   </s:form>

</body>
</html>

Chúng ta sẽ tạo success.jsp mà sẽ được triệu hồi khi action đã định nghĩa là SUCCESS.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<%@ 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>Success</title>
</head>
<body>
   <s:property value="getText('global.success')" />
</body>
</html>

Tiếp theo chúng ta cần tạo hai action như sau. Một action là cho Locale và hiển thị cùng index.jsp file trong các ngôn ngữ khác nhau. Một action khác để đệ trình form cho chính nó. Cả hai action này đều trả về SUCCESS, nhưng chúng ta sẽ nhận các action khác nhau dựa trên các giá trị trả về.

Action đầu tiên cho Locale:

package com.vietjack.struts2;

import com.opensymphony.xwork2.ActionSupport;

public class Locale extends ActionSupport{
   public String execute() 
   {
       return SUCCESS;
   }
}

Action thứ hai để đệ trình form cho chính nó:

package com.vietjack.struts2;

import com.opensymphony.xwork2.ActionSupport;

public class Employee extends ActionSupport{
   private String name;
   private int age;
   
   public String execute() 
   {
       return SUCCESS;
   }
   
   public String getName() {
       return name;
   }
   public void setName(String name) {
       this.name = name;
   }
   public int getAge() {
       return age;
   }
   public void setAge(int age) {
       this.age = age;
   }
}

Bây giờ chúng ta tạo ba global.properties file và đặt trong CLASSPATH:

global.properties

global.name = Name
global.age = Age
global.submit = Submit
global.heading = Select Locale
global.success = Successfully authenticated

global_fr.properties

global.name = Nom d'utilisateur 
global.age = l'âge
global.submit = Soumettre des
global.heading = Sé lectionnez Local
global.success = Authentifi	é  avec succès

global_es.properties

global.name = Nombre de usuario
global.age = Edad
global.submit = Presentar
global.heading = seleccionar la configuracion regional
global.success = Autenticado correctamente

Tiếp theo, chúng ta sẽ tạo struts.xml với hai action trên như sau:

<?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="true" />
   <constant name="struts.custom.i18n.resources" value="global" />

   <package name="helloworld" extends="struts-default" namespace="/">
      <action name="empinfo" 
         class="com.vietjack.struts2.Employee"
         method="execute">
         <result name="input">/index.jsp</result>
         <result name="success">/success.jsp</result>
      </action>
      
      <action name="locale" 
         class="com.vietjack.struts2.Locale"
         method="execute">
         <result name="success">/index.jsp</result>
      </action>
   </package>

</struts>

Và nội dung của web.xml là:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id="WebApp_ID" version="3.0">

   <display-name>Struts 2</display-name>
   <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
   </welcome-file-list>

   <filter>
      <filter-name>struts2</filter-name>
      <filter-class>
         org.apache.struts2.dispatcher.FilterDispatcher
      </filter-class>
   </filter>

   <filter-mapping>
      <filter-name>struts2</filter-name>
      <url-pattern>/*</url-pattern>
   </filter-mapping>
</web-app>

Cuối cùng, bạn chạy thử ứng dụng trên. Theo mặc định nó sẽ hiển thị ngôn ngữ US, bạn có thể lựa chọn bất kỳ ngôn ngữ nào khác với Spanish hoặc France, khi bạn lựa trọn một trong số chúng thì ngôn ngữ tương ứng sẽ được áp dụng cho ứng dụng.