1,JAVA程序的国际化主要是通过如下3个类完成:
1,java.util.ResourceBundle:用于加载一个资源包
2,java.util.Locale:对应一个特定的国家/区域,语言环境
3,java.text.MessageFormat:用于将消息格式化
为了实现程序的格式化,必须提供资源文件,资源文件的内容以key-value对来提供信息。资源文件的命名有如下3种形式:
1,baseName_language_country.properties
2,baseName_language.properties
3,baseName.properties
baseName用户可以自定义,但是language和country必须是JAVA所支持的语言和国家/区域。
2,以下代码获取所有JAVA支持的语言和国家/区域:
import java.util.Locale;
public class LocaleList {
public static void main(String[] args) {
}
}
比较常用的有以下几种:日文=ja;日本=JP;英文=en;美国=US;中文=zh;中国=CN;中文=zh;台湾地区=TW;
对于包含非西欧字符的资源文件,JAVA提供了native2ascii工具来进行转换(将各个语言的原始编码转成JAVA支持的unicode编码),用法如下,在命令行下进入资源文件所在的目录,执行以下命令:
native2ascii 源资源文件名 目的资源文件名
3,我们在JAVA源文件中调用资源文件中的信息方式如下:
public static void main(String[] args) {
}
4,带占位符的消息
有时候我们需要要输出的消息中带动态生成的内容,这个时候就需要用动态生成的消息取代资源文件中的部分内容。
1,资源文件内容如下:msg=Hello,{0}!Today is{1}.
0和1就是我们将要取代的地方。
2,JAVA类代码如下:
public static void main(String[] args)
{
}
红色部分为资源文件存放的包。我的电脑使用的是中文操作系统,因此输入的内容如下:你好,annlee!今天是08-7-31下午5:09。
5,使用类.class文件来代替资源文件存放信息
在JAVA中还可以使用类.class文件来存放信息,虽然这种方式根本上不会有人使用。类的源文件如下:
import java.util.ListResourceBundle;
import java.util.Locale;
//给zh_CN定义的资源包
public class MyResource_zh_CN extendsListResourceBundle
{
//定义资源
private final Object myData[][]=
{
};
//实现抽象方法getContents()
public Object[][] getContents()
{
}
}
类资源文件的命名规范同资源文件是一致的。JAVA客户端调用方式如下:
public static void main(String[] args)
{
}
2,Struts2中的国际化
1,Struts2中通过在struts.properties配置文件或者struts.xml配置文件中的struts.custom.i18n.resources元素来指定配置文件的baseName名称。如下例:
struts.custom.i18n.resources=resource.messageResource
指定资源文件为resource目录下的messageResource.properties。
2,在页面获取资源文件中的内容的方式为:
<s:textname="login.jsp.title">//获取资源文件中key为login.jsp.title的value值,并显示在页面上
<s:textfield name="username"key="login.jsp.username"></s:textfield>//key为login.jsp.username信息
3,在Action获取资源文件中的内容,可以继承ActionSupport类,再用此类的getText()方法获取资源文件中的信息,例:getText("login.jsp.user.validate");就可以获取login.jsp.user.validate信息。
4,输出带占位符的国际化信息
如果要在JSP页面输出带占位符的国际化信息,可以通过<param>标签来指定占位符的内容,如下例:
如果要在Action代码里填充国际化消息里的占位符,可以通过调用getText()方法时填充值,如下例:
getText("failTip" , newString[]{username,password})//username和password为action中的属性,此时
3,Struts2中加载资源文件的方式
对于一个大型的应用而言,可能资源文件非常庞大,因此有必要将它分成多个较小的文件,Struts2可以指定包范围资源文件,类范围资源文件,以及临时指定资源文件。
1,包范围资源文件
Struts2指定包范围资源文件的方法是:在包的根目录下建立多个名为package_<language>_<country>.properties文件,这个文件的命名同普通资源文件的命名方式一样。建立了此文件之后,该包下的所有Action都可以访问资源文件。例:我们在lee这个包下建立多个资源文件,文件名分别为:package.properties,package_en_US.properties,package_zh_CN.properties;那么在此包中所有的Action都可以获取资源文件,获取的方式同普通的一样,如下:getText("succTip")。如果存在包资源文件,则包资源文件中的内容将优先于普通的资源文件。
2,Action范围资源文件
Struts2还允许为Action单独指定一份国际化资源文件。它的方式为:在Action类文件所在的路径下建立多个文件名为<ActionName>_<language>_<country>.properties文件。例:在LoginAction的同目录下建立多个资源文件:LoginAction.properties,LoginAction_en_US.properties,LoginAction_zh_CN.properties;那么这个资源文件仅对此Action开放。获取资源文件中内容的方式不变。如果存在Action范围资源文件,则此文件中的内容将优先于所有的资源文件。
3,临时指定资源文件
Struts的页面有一个标签<s:i18n>,可以通过它来指定资源文件的位置。这个标签一般可做为其它标签的父标签,这样其它标签所读取的内容就是<s:i18n>标签所指定的资源文件中的内容。用法如下:
<%@ page language="java" contentType="text/html;charset=GBK"%>
<%@taglib prefix="s"uri="/struts-tags"%>
<html>
<head>
<title>
<s:i18nname="tmp">
<s:textname="loginPage"/>
</s:i18n>
</title>
</head>
<body>
<s:i18nname="tmp">
<s:form action="Login">
<s:textfield name="username"key="user"/>
<s:textfield name="password"key="pass"/>
<s:submit key="login"/>
</s:form>
</s:i18n>
</body>
</html>
通常若查找不到所需要的资源文件中的内容,都是直接输出KEY的字符串值。
4,让用户自行选择语言
在很多应用中,我们需要提供允许用户自行选择语言的功能。Struts2中可以通过ActionContext.getContext().setLocale(Localelocale)设置用户的默认语言。Struts2还提供了一个名为i18n的拦截器(已经包含在默认拦截器栈中),i18n拦截器首先在请求中查找名为request_locale,如果存在,就将其转换成Locale对象,并设置成用户默认的Locale,此外i18n还会将其保存在Session的WW_TRANS_I18N_LOCALE属性中,如果存在此属性,则指定为用户浏览器的默认Locale。
我们在应用中,可以将我们系统所支持的语言放在一个下拉列表中,用户选择下拉列表中的某项时,将其值作为request_locale参数提交给Struts2就可以了。实现代码如下:
1,searchlanguage.jsp页面代码:此页面就是用户选择语言的页面,它也以嵌在任何页面下
<%@ page language="java"contentType="text/html; charset=GBK"%>
<%@taglib prefix="s"uri="/struts-tags"%>
<script type="text/javascript">
function langSelecter_onChanged()
{
document.getElementByIdx("langForm").submit();
}
</script>
<!--将session里的WW_TRANS_I18N_LOCALE属性的值取出来,赋值给此页面的属性SESSION_LOCALE-->
<s:set name="SESSION_LOCALE"value="#session['WW_TRANS_I18N_LOCALE']"/>
<!-- 在此页面注册一个lee.Locales类型的Bean-->
<s:bean id="locales"name="lee.Locales">
<!-- 给lee.Locales的参数current注入值SESSION_LOCALE-->
<s:param name="current" value="#SESSION_LOCALE ==null ? locale : #SESSION_LOCALE"/>
</s:bean>
<!--提交给当前目录名.action处理,这样做是为了在任何都可以嵌入此selectlanguage.jsp页面,如果用户不需要此功能,这里也可以指定action-->
<form action="<s:url/>"id="langForm"
<!-- 从资源文件中读出key为languag的信息 -->
<!--读出刚才注册的locales类实例的locales属性 -->
<s:select label="Language" list="#locales.locales"listKey="value" listValue="key"
</form>
2,Locales类的代码如下:此类仅作数据装载,不做其它用途。
package lee;
import java.util.*;
public class Locales
{
//current属性,由于此属性只做赋值操作,不做取值操作,因此没有get方法
private Locale current;
public void setCurrent(Locale cur)
{
}
//locales属性,由于此属性只做取值操作,不做赋值操作,因此没有set方法
{
}
3,资源文件messageResource.properties中的内容如下:
languag=选择语言
usen=美式英语
zhcn=简体中文
4,struts.xml配置文件中的配置如下:
这个action的配置意思就是返回你请求的那个JSP页面,因为所有的操作,在你选择语言的时候就已经完成了,所以无需其它的处理。
5,其它页面的调用方式:
其它JSP页面要调用此页面,只需要include就行了。如下例
<%@ page language="java" contentType="text/html;charset=GBK"%>
<%@taglib prefix="s"uri="/struts-tags"%>
<html>
<head>
<title><s:textname="loginPage"/></title>
</head>
<body>
<s:includevalue="selectlanguage.jsp"/>
<s:form action="Login">
<s:textfield name="username"key="user"/>
<s:textfield name="password"key="pass"/>
<s:submit key="login"/>
</s:form>
</body>
</html>