各位大侠,现在遇上这样的一个问题,我用struts2国际化,当用户选择了语言后,点击页面上的超级连接,如果页面中的连接通过action进行转,跳转到另外一个页面用户选择的语言还是保存着,如果超级连接是通过<a>这样连接过去的,用户选择的语言就丢失了,直接又回到默认语言了!不知道有什么办法解决。例如用户在index.jsp页面中选择了"英文",现在整个index.jsp都国际化成了英文,现在index.jsp页面有个连接<a href='test.jsp'>测试</a> 当程序跳转到test.jsp页面中原来选择的英文就丢失了,又变成了中文。如果我这个<a href="action地址">测试</a>这样中转的,在跳到test.jsp页面,整个国际化是保存的,还是英文。如果所有这样的普通连接都通过action进行中转,增加了工作量,不知道各位大侠有没有别的办法?谢谢!

解决方案 »

  1.   


    1.定义properties文件
    资源文件查找顺序
    JAVA国际化 
    如果系统同时存在资源文件、类文件,系统将以类文件为主,而不会调用资源文件。 
    对于简体中文的Locale,ResourceBundle搜索资源的顺序是: 
    (1)baseName_zh_CN.class 
    (2)baseName_zh_CN.properties 
    (3)baseName_zh.class 
    (4)baseName_zh.properties 
    (5)baseName.class 
    (6)baseName.properties 
     
    /* Struts2找不到对应语言的配置文件时,会先找系统语言对应的配置文件,再找不到才使用baseName.properties */
    国际化分为三类:全局的,包级别的,类级别的
      全局的: 
       1.在struts.xml中的<constant name="struts.custom.i18n.resources" value="message"></constant>指定baseName 
       国际化文件名为:baseName_语言名_国家名.properties(如:message_zh_CN.properties) 
       2.全局的国际化资源文件放在src下面 
     
      包级别的: 
       1.包级别的国际化资源文件放在该包下面 
       2.命名规则为:package_语言名_国家名.properties(如:package_zh_CN.properties) 
          其中package不变,不是指的是包名,每个包的国际化文件命名都这样 
       
      类级别的: 
       1.与该类放在同一目录中 
       2.命名规则为:类名_语言名_国家名.properties(如:RegisterAction_zh_CN.properties) 
        
      若同一key 在上面三个国际化文件中都为value值则:(优先级)类级别的>包级别的>全局的
    2.在jsp中访问国际化资源文件
      <!-- 输出国际化 --> 
      <!-- name为国际化文件中的key --> 
      <s:text name="hello"> 
                    <!-- 若该国际化文件的value中有{0}则可用下面的标签把参数传进去 --> 
                    <s:param>mengya</s:param> 
                    <s:param><s:property value="firstName"/></s:param> 
      </s:text> 
       
      <s:property value="%{getText('customer.contact')}"/> 
      传参数 
      <s:property value="%{getText('customer.contact','sh')}"/> 
       
      定义变量,加var属性 
      <s:text name="greetings" var="msg"/> 
      <s:property value="#msg"/> 
       
      <!-- 指定特定的国际化文件,name为全局国际化文件的baseName --> 
      <s:i18n name="temp"> 
       <!-- 下面的<s:text>标签与上面的用法一样 --> 
       <s:text name="hello"> 
        <s:param>mengya</s:param> 
       </s:text> 
      </s:i18n> 
       
      表单国际化: 
       1.theme不能为simple如:<s:form action="register">(默认的theme不是simple) 
       2.使用key如:<s:textfield name="username" key="" id="usernameId"></s:textfield> 
       3.或者使用getText方法<s:textfield name="username" label="%{getText('customer.name')}"/>
    3.在Action中访问国际化资源文件,该Action继承了ActionSupport类
      this.getText("username.invalid") 
      若该key对应的value需要参数则: 
      this.getText("username.invalid",new String[]{username}) 
      或 
      List list = new ArrayList(); 
      list.add(username); 
      this.getText("username.invalid",list) 
      如: 
      if (null == username || username.length() < 6 || username.length() > 10) 
      { 
       List list = new ArrayList(); 
       list.add(username); 
       this.addActionError(this.getText("username.invalid",new String[]{username})); 
      } 
      该国际化资源文件中的key和value为: 
      username.invalid = \u7528\u6237\u540d "{0}" \u586b\u5199\u4e0d\u6b63\u786e
    4.在输入验证框架访问国际化资源文件
      <!-- 使用<message key="..."></message> -> 
      <field-validator type="requiredstring"> 
               <param name="trim">true</param> 
               <message key="username.invalid"></message> 
      </field-validator>
    5.动态改变语言
    只有在url传入request_locale=en_US就可以指定为en_US的语言1.如果配置文件是en_US结尾,传入en,en_US都可以找到2.如果配置文件是en结尾,只能传入en,传入en_US会找不到,从而找默认的配置文件(en的范围>en_US,使用英语的国家不止美国一个)
    <a  href="${pageContext.request.contextPath}/i18n/i18nAction?request_locale=en_US">English</a>
    6.使用类来代替properties文件
    //继承ListResourceBundle实现getContents方法 
    public class MyCustomResourceBundle extends ListResourceBundle { 
        public Object[][] getContents() { 
            if (Calendar.getInstance().get(Calendar.HOUR_OF_DAY) < 12) { 
                return contents1; 
            } else { 
                return contents2; 
            } 
        } 
        static final Object[][] contents1 = {  
                { "greetings", "中午好 {0}" }, 
                { "farewell", "再见" } }; 
     
        static final Object[][] contents2 = {  
                { "greetings", "你好 {0}" }, 
                { "farewell", "再见" } }; 

     
    //en对应的字符串 
    public class MyCustomResourceBundle_en extends ListResourceBundle { 
        public Object[][] getContents() { 
            if (Calendar.getInstance().get(Calendar.HOUR_OF_DAY) < 12) { 
                return contents1; 
            } else { 
                return contents2; 
            } 
        } 
        static final Object[][] contents1 = {  
                { "greetings", "Good morning {0}" }, 
                { "farewell", "Good bye" } }; 
     
        static final Object[][] contents2 = {  
                { "greetings", "Hello {0}" }, 
                { "farewell", "Good bye" } }; 

     
    //jsp中使用 
    <s:i18n name="com.resourcebundle.MyCustomResourceBundle"> 
        <s:text name="greetings"> 
            <s:param>Jon</s:param> 
        </s:text>. 
        <s:text name="farewell"/> 
    </s:i18n>
      

  2.   

    动态改变语言
    只有在url传入request_locale=en_US就可以指定为en_US的语言
    用这种方式更烦人啊
      

  3.   

    没别的方法。你要明白你的国际化实际上是通过struts的过滤器实现的,你不跳到action,过滤器也就不起效果。这个时候struts怎么帮你实现国际化呢?并且jsp直接跳转jsp是很不推荐的方式,因为这个时候过滤器都不起作用了。有安全隐患。
      

  4.   

    最近刚做过struts2的国际化,碰到类似的问题,这个真没办法,都是通过action跳转来完成的,基本逗是没一个普通的一面,都用了跳转,如test.jsp,在struts.xml中配了个
    <action name="toTest*">
    <result>test.jsp</result>
    </action>访问的时候逗用toTest.action访问。。蛋疼的配置