概述
在程序设计领域,把在无需改写源代码即可让开发出来的应用程序能够支持多种语言和数据格式的技术称为国际化。
与国际化对应的是本地化,指让一个具备国际化支持的应用程序支持某个特定的地区。(本地化是一个动词)
Struts2国际化是建立在Java国际化基础上的:
-为不同国家/语言提供对应的消息资源文件。
-struts2框架会根据请求中包含的Locale加载对应的资源文件。
-通过程序代码取得该资源文件中指定Key对应的消息。
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
<constant name="struts.custom.i18n.resources" value="baseName"/>
IV.临时指定文件资源:<s:i18n.../>标签的name属性指定临时化的国际化资源文件
国际化资源文件加载的顺序?
离Action近的将优先加载
2)如何在页面上和Action类中访问国际化资源文件的value值
I.在Action类中,若Action实现了TextProvider接口,则可以调用其getText()方法获取value值
>通过继承 ActionSupport的方式
II.页面上可以使用s:text标签,对于表单标签可以使用表单标签的key属性
>如果有占位符,则可以使用s:text标签的s:param子标签来填充占位符
>可以利用标签和OGNL表达式直接访问值栈中的属性值(对象栈和Map栈)
time=Time:{0}
<s:text name="time">
<s:param value="date"></s:param>
</s:text>
time2=Time:${date}
<s:text name="time2"></s:text>
3)实现通过超链接切换语言
关键之处在于struts2框架是如何确定Locale对象的!
可以通过阅读i18n拦截器知道具体Local对象的过程
利用超链接实现动态加载国际化资源文件
1)struts2使用i18n拦截器处理国际化,并且将其注册在默认的拦截器中
2)i18n拦截器在执行Action方法前,自动查找请求中一个名为request_locale的参数。如果该参数存在,拦截器就将其作为参数,转换成Locale对象,并将其设为用户默认的Locale(代表国家/语言环境)。并把其设置为session的WW_TRANS_I18N_LOCALE属性。
3)若request没有名为request_locale的参数,则i18n拦截器会从Session中获取WW_TRANS_I18N_LOCALE的属性值,若该值不为空,则将该属性设置为浏览器默认Locale。
4)若session中的WW_TRANS_I18N_LOCALE的属性值为空,则从ActionContext中获取Loca对象。
具体实现:
只需在超链接后面附上请求参数,值是语言国家代码。
<a href="testI18n.action?request_locale=zh_CN">中文</a>
<a href="testI18n.action?request_locale=en_US">English</a>
注意:超链接必须是一个struts2的请求,即使i18n拦截器工作才行。
范例:
struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!-- 配置全局的国际化资源文件 -->
<constant name="struts.custom.i18n.resources" value="i18n"></constant>
<package name="default" namespace="/" extends="struts-default">
<action name="testI18n" class="com.wul.struts2.i18n.app.TestI18nAction">
<result>/i18n.jsp</result>
</action>
</package>
</struts>
i18n.properties
username=UserName
password=PassWord
submit=Submit
time=Time:{0}
i18n_zh_CN.properties
username=\u7528\u6237\u540D
password=\u5BC6\u7801
submit=\u63D0\u4EA4
time=\u65F6\u95F4:{0}
i18n_en_US.properties
username=UserName
password=PassWord
submit=Submit
time=Time:{0}
TestI18nAction.java
package com.wul.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.带占位符的
String time = getText("time", Arrays.asList(date));
System.out.println(time);
return SUCCESS;
}
}
TestI18nAction_en_US.properties
username=^^UserName
password=^^PassWord
submit=^^Submit
time=^^Time:{0}
TestI18nAction_zh_CN.properties
username=^\u4E2D\u6587\u7528\u6237\u540D
password=^\u4E2D\u6587\u5BC6\u7801
submit=^\u4E2D\u6587\u63D0\u4EA4
time=^\u4E2D\u6587\u65F6\u95F4:{0}
TestI18nAction.properties
username=^^UserName
password=^^PassWord
submit=^^Submit
time=^^Time:{0}
time2=Time:${date}
index.jsp
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!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>
<a href="testI18n">i18n.jsp</a>
</body>
</html>
i18n.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>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<s:debug></s:debug>
<br>
<a href="index.jsp">首页</a>
<br>
<a href="testI18n.action?request_locale=zh_CN">中文</a>
<a href="testI18n.action?request_locale=en_US">English</a>
<br><br>
<s:text name="time">
<s:param value="date"></s:param>
</s:text>
<br>
<s:text name="time2"></s:text>
<br><br>
<s:form action="">
<!--label的方式是把label写死在标签里 -->
<s:textfield name="username" label="UserName"/>
<!-- 若label标签使用%{getText('username')}的方式就可以从国际化资源文件 中获取value值了,
因为此时在对象栈中有DefaultTextProvider的一个实例,该对象提供了访问国际化资源文件的getText()方法,
同时还需要通知struts2框架label中放入的不再是一个普通的字符串,而是一个OGNL表达式,所以使用%{}把getText()
包装起来,以强制进行OGNL解析 -->
<s:textfield name="username" label="%{getText('username')}"/>
<!--key的方式是直接上资源文件中获取value值 -->
<s:textfield name="username" key="username"/>
<s:textfield name="password" key="password"/>
<s:submit key="submit"></s:submit>
</s:form>
<br><br>
<!--主题若是若是simple,key不会起作用,需要自己写s:text -->
<s:form action="" theme="simple">
<!-- 页面上可以直接使用<s:text name=""/>标签来访问国际化资源文件里的value值 -->
<s:text name="username"/>:<s:textfield name="username" key="username"/>
<s:text name="password"/>:<s:textfield name="password" key="password"/>
<s:submit key="submit" value="%{getText('submit')}"></s:submit>
</s:form>
</body>
</html>