国际化:
国际化是指,使程序在不做任何修改的情况下,就可以使用在不同的语言环境中。国际化在一般性项目中是不常用的。在编程中简称 i18n。
国际化是通过读取资源文件的形式实现的。资源文件的定义与注册,主要分为全局范围的、包范围的、Action范围的,下面分别介绍:
(1)全局范围的:
全局资源文件是指,整个应用中所有文件均可访问的资源文件,其命名要遵循的格式:baseName-language_country.properties
其中baseName是资源文件的基本名,可以自定义。但language和country必须是Java支持的语言和国家的简称。例如:myBaseName_en_US.properties
(2)包范围的:
可以针对不同模块、不同的action来组织国际化文件。
再要使用该资源文件的java包下,放置以下格式的资源文件:package_language_country.properties。其中,package为固定写法。例如:package_en_US.properties
(3)Action范围的:
可以单独为某个action指定资源文件,只需在Action类所在的包中放置以下格式的资源文件:ActionClassName_language_country.properties。其中ActionClassName是action类的简单名称。例如:LoginAction_en_US.properties
综述:对于前端的某个值来说,如果未指定读取哪一个范围的资源文件,则加载资源文件的顺序是Action范围-->包范围-->全局范围
下图是资源文件的放置示意图:
国际化的代码:
(1)资源文件的配置(分别是myBaseName_en_US.properties和myBaseName_zh_CN.properties):
解释:其中的占位符 {0} 是为了实现,为资源文件的动态参数赋值
(2)Action类的代码:
package com.tongji.actions; import com.opensymphony.xwork2.ActionSupport; public class LoginAction extends ActionSupport{ private static final long serialVersionUID = -7398591714651064707L; private String username; private int age; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String execute() { String msg = this.getText("action.out.msg"); System.out.println(msg); String[] args = {username}; //什么意思??? String msg2 = this.getText("action.out.msg2",args); System.out.println(msg2); return "success"; } }
解释:ActionSupport中的getText方法,是在Action内加载资源文件,第二种实现方式加入了动态参数。
(3)前端页面代码:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ taglib uri="/struts-tags" prefix="s"%> <html> <head> <title>index page</title> </head> <body> <a href="test/language.action?request_locale=zh_CN">中文</a> <a href="test/language.action?request_locale=en_US">English</a> <br> <br> <s:i18n name="com/tongji/actions/LoginAction"> <s:text name="index.form.title" /><br> <!-- 读取Action范围资源文件 --> </s:i18n> <s:i18n name="com/tongji/package"> <!-- 读取包范围资源文件 --> <s:form action="test/login.action" method="POST"> <s:textfield name="username" key="index.form.uname"/> <s:textfield name="age" key="index.form.uage"/> <s:submit key="index.form.submit"/> </s:form> </s:i18n> </body> </html>
解释:对于前端的某个值来说,如果未指定读取哪一个范围的资源文件,则加载资源文件的顺序是Action范围-->包范围-->全局范围;但是,这里指定了读取指定范围的资源文件。
(4)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="myBaseName"/> <package name="demo" namespace="/test" extends="struts-default"> <action name="language"> <result>/index.jsp</result> </action> <action name="login" class="com.tongji.actions.LoginAction"> <result>/welcome.jsp</result> </action> </package> </struts>
解释:第一次加载页面,页面就加载了全局资源文件(如果未指定读取包范围或Action范围的资源文件),这个资源文件的类型(zh_CN,还是en_US,还是其他)由浏览器默认指定的。
只有在执行Action时才会自动加载包范围的或Action范围的资源文件。因此,如果想在Action未执行前,改变加载的资源文件类型,可以这样做:
前端:<a href="test/language.action?request_locale=zh_CN">中文</a>
<a href="test/language.action?request_locale=en_US">English</a>
struts.xml配置:<action name="language">
<result>/index.jsp</result>
</action>
目的:是为了让i18n拦截器起作用,改变其中的request_locale值,从而改变加载的资源文件类型。一旦,request_locale值改变,接下来的Action加载的包范围的或Action范围的资源文件都会遵从这个类型。