在Struts 2.0中国际化(i18n)您的应用程序(3)

资源文件查

找顺序之所以说Struts 2.0的国际化更灵活是因为它可以能根据不同需要配置和获取资源(properties)文件。在Struts 2.0中有下面几种方法:

  1. 使用全局的资源文件,方法如上例所示。这适用于遍布于整个应用程序的国际化字符串,它们在不同的包(package)中被引用,如一些比较共用的出错提示;
  2. 使用包范围内的资源文件。做法是在包的根目录下新建名的package.properties和package_xx_XX.properties文件。这就适用于在包中不同类访问的资源;
  3. 使用Action范围的资源文件。做法为Action的包下新建文件名(除文件扩展名外)与Action类名同样的资源文件。它只能在该Action中访问。如此一来,我们就可以在不同的Action里使用相同的properties名表示不同的值。例如,在ActonOne中title为“动作一”,而同样用title在ActionTwo表示“动作二”,节省一些命名工夫;
  4. 使用<s:i18n>标志访问特定路径的properties文件。使用方法请参考我早前的文章《常用的Struts 2.0的标志(Tag)介绍》。在您使用这一方法时,请注意<s:i18n>标志的范围。在<s:i18n name="xxxxx">到</s:i18n>之间,所有的国际化字符串都会在名为xxxxx资源文件查找,如果找不到,Struts 2.0就会输出默认值(国际化字符串的名字)。

上面我列举了四种配置和访问资源的方法,它们的范围分别是从大到小,而Struts 2.0在查找国际化字符串所遵循的是特定的顺序,如图3所示:图3 资源文件查找顺序图假设我们在某个ChildAction中调用了getText("user.title"),Struts 2.0的将会执行以下的操作:

  1. 查找ChildAction_xx_XX.properties文件或ChildAction.properties;
  2. 查找ChildAction实现的接口,查找与接口同名的资源文件MyInterface.properties;
  3. 查找ChildAction的父类ParentAction的properties文件,文件名为ParentAction.properties;
  4. 判断当前ChildAction是否实现接口ModelDriven。如果是,调用getModel()获得对象,查找与其同名的资源文件;
  5. 查找当前包下的package.properties文件;
  6. 查找当前包的父包,直到最顶层包;
  7. 在值栈(Value Stack)中,查找名为user的属性,转到user类型同名的资源文件,查找键为title的资源;
  8. 查找在struts.properties配置的默认的资源文件,参考例1;
  9. 输出user.title。

参数化国际化字符串

许多情况下,我们都需要在动行时(runtime)为国际化字符插入一些参数,例如在输入验证提示信息的时候。在Struts 2.0中,我们通过以下两种方法做到这点:

  1. 在资源文件的国际化字符串中使用OGNL,格式为${表达式},例如:
    validation.require = ${getText(fileName)} is required
  2. 使用java.text.MessageFormat中的字符串格式,格式为{ 参数序号(从0开始), 格式类形(number | date | time | choice), 格式样式},例如:
    validation.between = Date must between { 0 ,  date, short} and { 1 ,  date, short}
在显示这些国际化字符时,同样有两种方法设置参数的值:
  1. 使用标志的value0、value1...valueN的属性,如:
    < s:text  name ="validation.required"  value0 ="User Name" />
  2. 使用param子元素,这些param将按先后顺序,代入到国际化字符串的参数中,例如:
    < s:text  name ="validation.required" >
       
    < s:param  value ="User Name" />
    </ s:text >

    让用户方便地选择语言

    开发国际化的应用程序时,有一个功能是必不可少的——让用户快捷地选择或切换语言。在Struts 2.0中,通过ActionContext.getContext().setLocale(Locale arg)可以设置用户的默认语言。不过,由于这是一个比较普遍的应用场景(Scenario),所以Struts 2.0为您提供了一个名i18n的拦截器(Interceptor),并在默认情况下将其注册到拦截器链(Interceptor chain)中。它的原理为在执行Action方法前,i18n拦截器查找请求中的一个名为"request_locale"的参数。如果其存在,拦截器就将其作为参数实例化Locale对象,并将其设为用户默认的区域(Locale),最后,将此Locale对象保存在session的名为“WW_TRANS_I18N_LOCALE”的属性中。

    下面,我将提供一完整示例演示它的使用方法。

    在Struts 2.0中国际化(i18n)您的应用程序(3) - 小鲍 - 小鲍 package  tutorial;
    在Struts 2.0中国际化(i18n)您的应用程序(3) - 小鲍 - 小鲍
    在Struts 2.0中国际化(i18n)您的应用程序(3) - 小鲍 - 小鲍
    import  java.util.Hashtable;
    在Struts 2.0中国际化(i18n)您的应用程序(3) - 小鲍 - 小鲍
    import  java.util.Locale;
    在Struts 2.0中国际化(i18n)您的应用程序(3) - 小鲍 - 小鲍
    import  java.util.Map;
    在Struts 2.0中国际化(i18n)您的应用程序(3) - 小鲍 - 小鲍
    在Struts 2.0中国际化(i18n)您的应用程序(3) - 小鲍 - 小鲍
    public class  Locales  {
    在Struts 2.0中国际化(i18n)您的应用程序(3) - 小鲍 - 小鲍    
    public Map<String, Locale> getLocales() {
    在Struts 2.0中国际化(i18n)您的应用程序(3) - 小鲍 - 小鲍        Map
    <String, Locale> locales =new Hashtable<String, Locale>(2);
    在Struts 2.0中国际化(i18n)您的应用程序(3) - 小鲍 - 小鲍        locales.put(
    "American English", Locale.US);
    在Struts 2.0中国际化(i18n)您的应用程序(3) - 小鲍 - 小鲍        locales.put(
    "Simplified Chinese", Locale.CHINA);
    在Struts 2.0中国际化(i18n)您的应用程序(3) - 小鲍 - 小鲍        
    return locales;
    在Struts 2.0中国际化(i18n)您的应用程序(3) - 小鲍 - 小鲍    }

    在Struts 2.0中国际化(i18n)您的应用程序(3) - 小鲍 - 小鲍}
    tutorial/Locales.java

    <% @taglib prefix = " s "  uri = " /struts-tags " %>
    < script  type ="text/javascript" >
    <!--
        
    function  langSelecter_onChanged() {
            document.langForm.submit();
        }
    // -->
    </ script >
    < s:set  name ="SESSION_LOCALE"  value ="#session['WW_TRANS_I18N_LOCALE']" />
    < s:bean  id ="locales"  name ="tutorial.Locales" />
    < form  action ="<s:url includeParams=" get" encode ="true" /> " name="langForm" 
        style="background-color: powderblue; padding-top: 4px; padding-bottom: 4px;">
        Language: 
    < s:select  label ="Language"  
            list
    ="#locales.locales"  listKey ="value"     listValue ="key"
            value
    ="#SESSION_LOCALE == null ? locale : #SESSION_LOCALE"
            name
    ="request_locale"  id ="langSelecter"  
            onchange
    ="langSelecter_onChanged()"  theme ="simple" />
    </ form >
    LangSelector.jsp

    上述代码的原理为,LangSelector.jsp先实例化一个Locales对象,并把对象的Map类型的属性locales赋予下拉列表(select) 。如此一来,下拉列表就获得可用语言的列表。大家看到LangSelector有<s:form>标志和一段Javascript脚本,它们的作用就是在用户在下拉列表中选择了后,提交包含“reqeust_locale”变量的表单到Action。在打开页面时,为了下拉列表的选中的当前区域,我们需要到session取得当前区域(键为“WW_TRANS_I18N_LOCALE”的属性),而该属性在没有设置语言前是为空的,所以通过值栈中locale属性来取得当前区域(用户浏览器所设置的语言)。

    你可以把LangSelector.jsp作为一个控件使用,方法是在JSP页面中把它包含进来,代码如下所示:
    < s:include  value ="/LangSelector.jsp" />

    在例1中的HellloWorld.jsp中<body>后加入上述代码,并在struts.xml中新建Action,代码如下:
    < action  name ="HelloWorld" >
        
    < result > /HelloWorld.jsp </ result >
    </ action >

    或者,如果你多个JSP需要实现上述功能,你可以使用下面的通用配置,而不是为每一个JSP页面都新建一个Action。
    < action  name ="*" >
        
    < result > /{1}.jsp </ result >
    </ action >

    分布运行程序,在浏览器的地址栏中输入http://localhost:8080/Struts2_i18n/HelloWorld.action,出现图4所示页面:
    图3 HelloWorld.action
    图3 HelloWorld.action

    在下拉列表中,选择“American English”,出现图5所示页面:
    图3 HelloWorld.action
    图4 HelloWorld.action
    在Struts 2.0中国际化(i18n)您的应用程序(3) - 小鲍 - 小鲍可能大家会问为什么一定要通过Action来访问页面呢?
    你可以试一下不用Action而直接用JSP的地址来访问页面,结果会是无论你在下拉列表中选择什么,语言都不会改变。这表示不能正常运行的。其原因为如果直接使用JSP访问页面,Struts 2.0在web.xml的配置的过滤器(Filter)就不会工作,所以拦截器链也不会工作。


    参考网址:http://www.blogjava.net/max/archive/2006/11/01/78536.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值