struts2国际化

 

1. 国际化的目标

1). 如何配置国际化资源文件

I. Action 范围资源文件: 在Action类文件所在的路径建立名为 ActionName_language_country.properties 的文件
II. 包范围资源文件: 在包的根路径下建立文件名为 package_language_country.properties 的属性文件,
一旦建立,处于该包下的所有 Action 都可以访问该资源文件。注意:包范围资源文件的 baseName 就是package,不是Action所在的包名。
III. 全局资源文件
> 命名方式: basename_language_country.properties

配置全局资源文件需要在struts.xml或者struts.properties中设置资源包的基名
> struts.xml <constant name="struts.custom.i18n.resources" value="baseName"/>

>struts.properties  struts.custom.i18n.resources=baseName

IV. 国际化资源文件加载的顺序如何呢 ?原则: 离当前 Action 较近的将被优先加载.

具体规则:

 

假设我们在某个 ChildAction 中调用了getText("username"):

(1) 加载和 ChildAction 的类文件在同一个包下的系列资源文件 ChildAction.properties
(2) 加载 ChildAction 实现的接口 IChild,且和 IChildn 在同一个包下 IChild.properties 系列资源文件。
(3) 加载 ChildAction 父类 Parent,且和 Parent 在同一个包下的 baseName 为 Parent.properties 系列资源文件。
(4) 若 ChildAction 实现 ModelDriven 接口,则对于getModel()方法返回的model 对象,重新执行第(1)步操作。
(5) 查找当前包下 package.properties 系列资源文件。
(6) 沿着当前包上溯,直到最顶层包来查找 package.properties 的系列资源文件。
(7) 查找 struts.custom.i18n.resources 常量指定 baseName 的系列资源文件。
(8) 直接输出该key的字符串值。

 资源文件内容的配置方式:

将对本地环境敏感的资源数据(例如:错误提示信息,菜单文字等)从网页中分离出来,放在 .properties 属性资源文件中。

对于应用程序中的数值,货币和日期/时间等本地敏感数据,可以通过占位符的方式设置它们的格式类型和格式模式。

如:资源文件的内容

username=\u7528\u6237\u540D
password=\u5BC6\u7801
submit=\u63D0\u4EA4

time=\u65F6\u95F4:{0}
time2=\u65F6\u95F4:${date}

注意:

一个应用程序可以有多个资源包,一个资源包中的每个资源文件都拥有共同的基名。除了基名,每个资源文件的名称中还有标识其本地信息的附加部分。例如:一个资源包的基名是:“myproperties”, 则该资源包中与中文环境相对应的资源文件为: “myproperites_zh_CN.properties”

一般情况下,每个资源包都有一个默认的资源文件,默认的资源文件不带标识本地信息的附加部分。若应用程序在资源包中找不到某个本地环境匹配的资源文件,最后将选择该资源包中的默认资源文件。

 即一般情况下配置国际化资源文件都是至少三个:1,i18n.properties  2,i18n_zh_CN.properties 3,i18n_en_US.properties

 

2). 如何在页面上 和 Action 类中访问国际化资源文件的 value 值

I. 在 Action 类中. 若 Action 实现了 TextProvider 接口, 则可以调用其 getText() 方法获取 value 值
> 通过继承 ActionSupport 的方式。

package com.atguigu.struts2.i18n.app;

import java.util.Arrays;
import java.util.Date;

import com.opensymphony.xwork2.ActionSupport;

public class TestI18nAction extends ActionSupport {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    
    private Date date = null;
    
    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    @Override
    public String execute() throws Exception {
        
        date = new Date();
        
        //1. 在 Action 中访问国际化资源文件的 value 值
        String username = getText("username");
        System.out.println(username);
        
        //2. 带占位符的(参数1:资源文件的key,参数2:该key对应的value中的占位符对应的集合,用来给占位符赋值,
返回值:已经赋值之后的value值,这里赋给资源文件的时间是默认对应国际化格式) String time = getText("time", Arrays.asList(date)); System.out.println(time); return SUCCESS; } }

 

i18n_zh_CN.properties资源文件内容:
username=\u7528\u6237\u540D password=\u5BC6\u7801 submit=\u63D0\u4EA4 time=\u65F6\u95F4:{0} time2=\u65F6\u95F4:${date} //通过值栈的方式直接获取时间,无需再使用getText("time", Arrays.asList(date));

 

II. 页面上可以使用 s:text 标签; 对于表单标签可以使用表单标签的 key 属性值
> 若有占位符, 则可以使用 s:text 标签的 s:param 子标签来填充占位符
> 可以利用标签和 OGNL 表达式直接访问值栈中的属性值(对象栈 和 Map 栈)
1,有占位符的:
time=Time:{0}

<s:text name="time">
<s:param value="date"></s:param>
</s:text>

------------------------------------

time2=Time:${date}

<s:text name="time2"></s:text>

2,普通的

<%@page import="java.util.Date"%>
<%@ 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>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    
    <s:debug></s:debug>
    
    
    <a href="testI18n.action?request_locale=en_US">English</a>
    <a href="testI18n.action?request_locale=zh_CN">中文</a>
    <br><br>
    
    <a href="index.jsp">Index Page</a>
    
    <br><br>

    <s:text name="time">
        <s:param value="date"></s:param>
    </s:text>
    
    <br><br>

    <s:text name="time2"></s:text>
    <br><br>
    
    
    <s:form action="" theme="simple">
        
        <!-- 
            若 label 标签使用 %{getText('username')} 的方式就也可以从国际化资源文件中获取 value 值了 
            因为此时在对象栈中有 DefaultTextProvider 的一个实例, 该对象中提供了访问国际化资源文件的 getText() 方法
            同时还需要通知 struts2 框架 label 中放入的不再是一个普通的字符串, 而是一个 OGNL 表达式. 所以使用 %{} 把 getText()
            包装起来, 以强制进行 OGNL 解析. 
        -->
        <!--  
            页面上可以直接使用 <s:text name="" /> 标签来访问国际化资源文件里的 value 值. 
        -->
        <s:text name="username"/>:<s:textfield name="username" label="%{getText('username')}"></s:textfield>
        
        <!-- key 的方式是直接上资源文件中获取 value 值 -->
        <s:text name="username"/>:<s:textfield name="username" key="username"></s:textfield>
        <s:text name="password"/>:<s:password name="password" key="password"></s:password>
        
        <s:submit key="submit" value="%{getText('submit')}"></s:submit>
            
    </s:form>
    
</body>
</html>

3). 实现通过超链接切换语言.

I. 关键之处在于知道 Struts2 框架是如何确定 Local 对象的 !
II. 可以通过阅读 I18N 拦截器知道.
III. 具体确定 Locale 对象的过程:

  > Struts2 使用 i18n 拦截器 处理国际化,并且将其注册在默认的拦截器栈中
  > i18n拦截器在执行Action方法前,自动查找请求中一个名为 request_locale 的参数。
  如果该参数存在,拦截器就将其作为参数,转换成Locale对象,并将其设为用户默认的Locale(代表国家/语言环境)。
  并把其设置为 session 的 WW_TRANS_I18N_LOCALE 属性
  > 若 request 没有名为request_locale 的参数,则 i18n 拦截器会从 Session 中获取 WW_TRANS_I18N_LOCALE 的属性值,
  若该值不为空,则将该属性值设置为浏览者的默认Locale
  > 若 session 中的 WW_TRANS_I18N_LOCALE 的属性值为空,则从 ActionContext 中获取 Locale 对象。

流程图如下:

 


IV. 具体实现: 只需要在超连接的后面附着 request_locale 的请求参数, 值是 语言国家 代码.
<a href="testI18n.action?request_locale=en_US">English</a>
<a href="testI18n.action?request_locale=zh_CN">中文</a>

> 注意: 超链接必须是一个 Struts2 的请求, 即使 i18n 拦截器工作!

 

posted @ 2018-03-14 09:05  蓝天的永恒  阅读(137)  评论(0编辑  收藏  举报