zoukankan      html  css  js  c++  java
  • Struts(二十二):国际化

    • 如何配置国际化资源文件?

    1、Action范围资源文件:在Action类文件所在的路径建立名为ActionName_language_country.properties的文件;

    2、包范围资源文件:在包的根路径下建立文件名为package_language_country.properties的属性文件,一旦建立,处于该包下的所有Action都可以访问该资源文件。

    注意:包范围资源文件的baseName就是package,不是Action所在的包名。

    3、全局资源文件:

      3.1、命名方式:basename_language_country.properties

      3.2、struts.xml 中添加配置:<constant name="struts.custom.i18n.resources" value="baseName" />

    4、国际化资源文件加载的顺序:离当前Action较近的资源文件被优先加载。

    新建项目struts_05:

    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="i18nTest" class="com.dx.struts2.i18ntest.I18nAction">
                <result>/i18n.jsp</result>
            </action>
        </package>
    </struts>
    View Code

    web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
        <display-name>Struts 02</display-name>
        <filter>
            <filter-name>struts2</filter-name>
            <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>struts2</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        <welcome-file-list>
            <welcome-file>index.jsp</welcome-file>
        </welcome-file-list>
    </web-app>
    View Code

    com.dx.struts2.i18ntest.I18nAction.java

    package com.dx.struts2.i18ntest;
    
    import com.opensymphony.xwork2.ActionSupport;
    
    public class I18nAction extends ActionSupport {
        private static final long serialVersionUID = 1L;
    
        @Override
        public String execute() throws Exception {
            return SUCCESS;
        }
    }
    View Code

    index.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>
        
    <a href="i18nTest">test</a>
        
    </body>
    </html>
    View Code

    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>
        <s:form action="">
            <s:textfield name="username" label="UserName"></s:textfield>
            <s:textfield name="username" label="%{getText('username')}"></s:textfield>
            <s:textfield name="username" key="username"></s:textfield>
            <s:textfield name="password" key="password"></s:textfield>
            <s:submit key="submit"></s:submit>
        </s:form>
    </body>
    </html>
    View Code

    src下创建i18n.properties

    username=UserName
    password=Password
    submit=Submit

    、i18n_zh_CN.properties

    username=u7528u6237u540D
    password=u5BC6u7801
    submit=u63D0u4EA4

    、i18n_en_US.properties

    username=UserName
    password=Password
    submit=Submit

    访问index.jsp,点击“test”连接跳转到i18n.jsp页面,并修改浏览器的“语言”,看看界面是否有变化。 

    在com.dx.struts2.i18ntest下创建i18n.properties

    username=^UserName
    password=^Password
    submit=^Submit

    、i18n_zh_CN.properties

    username=^u7528u6237u540D
    password=^u5BC6u7801
    submit=^u63D0u4EA4

    、i18n_en_US.properties

    username=^UserName
    password=^Password
    submit=^Submit

    访问index.jsp,点击“test”连接跳转到i18n.jsp页面,并修改浏览器的“语言”,看看界面是否有变化。 

    • 在页面上和Action类中如何访问国际化资源文件的value值

    1、在Action类中:若Action实现了TextProvider接口,则可以通过调用getText()方法来获取资源文件文件中的value值;

    package com.dx.struts2.i18ntest;
    
    import com.opensymphony.xwork2.ActionSupport;
    
    public class I18nAction extends ActionSupport {
        private static final long serialVersionUID = 1L;
    
        @Override
        public String execute() throws Exception {
            String username = this.getText("username");
            String password = this.getText("password");
            System.out.println(username);
            System.out.println(password);
            
            return SUCCESS;
        }
    }

    备注:为什么继承ActionSupport类,因为ActionSupport实现了TextProvider接口。

    2、在 jsp 页面上:可以通过s:text标签来访问资源文件中的value值;对于表单(非theme="simple")标签可以使用表单标签的key属性值:

      2.1、若有占位符,则可以使用s:text标签中嵌套一个子标签s:param来填充占位符;

      2.2、可以利用标签和OGNL表达式直接访问值栈中的属性值(对象栈、Map栈)

     修改i18n.jsp的form主题theme=“simple”,发现之前的页面中的标签中的国际化信息都没有被显示,解决方案:

    <s:form action="" theme="simple">
            <s:textfield name="username" label="UserName"></s:textfield>
            <s:text name="username" />
            <s:textfield name="username" label="%{getText('username')}"></s:textfield>
            <s:text name="username" />
            <s:textfield name="username" key="username"></s:textfield>
            <s:text name="password" />
            <s:textfield name="password" key="password"></s:textfield>
            <s:submit key="submit" value="%{getText('submit')}"></s:submit>
    </s:form>

    针对占位符解决方案一:

    properties文件中:

    time=Time:{0}

    jsp:

        <s:text name="time">
            <s:param value="date"></s:param>
        </s:text>

    针对占位符解决方案一:

    properties文件中:

    time2=Time:${date}

    jsp:

        <s:text name="time2"></s:text>

    I18nAction.java

    package com.dx.struts2.i18ntest;
    
    import java.util.Arrays;
    import java.util.Date;
    
    import com.opensymphony.xwork2.ActionSupport;
    
    public class I18nAction 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 {
            this.date = new Date();
    
            String username = this.getText("username");
            String password = this.getText("password");
            String dateTime = this.getText("time", Arrays.asList(this.date));
            System.out.println(username);
            System.out.println(password);
            System.out.println(dateTime);
    
            return SUCCESS;
        }
    }

     

    • 通过超链接动态加载国际化资源文件

    实际上通过struts2的超级链接,被i18n拦截器拦截掉,过滤请求中是否包含参数,如果包含参数就设置国际化,并把设置信息保存在session中;

    如果请求参数中不包含国际化设置,则查看session中是否已经包含,如果包含,则从session中获取国际化设置;

    如果请求参数中不包含国际化设置,且session中也不包含,则从浏览器中获取国际化设置。

    流程图:

    查看i18n拦截器(com.opensymphony.xwork2.interceptor.I18nInterceptor.java)

    /*
     * Copyright 2002-2006,2009 The Apache Software Foundation.
     * 
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     * 
     *      http://www.apache.org/licenses/LICENSE-2.0
     * 
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package com.opensymphony.xwork2.interceptor;
    
    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.util.LocalizedTextUtil;
    import com.opensymphony.xwork2.util.logging.Logger;
    import com.opensymphony.xwork2.util.logging.LoggerFactory;
    
    import java.util.Arrays;
    import java.util.Locale;
    import java.util.Map;
    
    /**
     * <!-- START SNIPPET: description -->
     * <p/>
     * An interceptor that handles setting the locale specified in a session as the locale for the current action request.
     * In addition, this interceptor will look for a specific HTTP request parameter and set the locale to whatever value is
     * provided. This means that this interceptor can be used to allow for your application to dynamically change the locale
     * for the user's session or, alternatively, only for the current request (since XWork 2.1.3).
     * This is very useful for applications that require multi-lingual support and want the user to
     * be able to set his or her language preference at any point. The locale parameter is removed during the execution of
     * this interceptor, ensuring that properties aren't set on an action (such as request_locale) that have no typical
     * corresponding setter in your action.
     * <p/>
     * <p/>For example, using the default parameter name, a request to <b>foo.action?request_locale=en_US</b>, then the
     * locale for US English is saved in the user's session and will be used for all future requests.
     * <p/>
     if there is no locale set (for example with the first visit), the interceptor uses the browser locale.
     * <p/>
     * <!-- END SNIPPET: description -->
     * <p/>
     * <p/> <u>Interceptor parameters:</u>
     * <p/>
     * <!-- START SNIPPET: parameters -->
     * <p/>
     * <ul>
     * <p/>
     * <li>parameterName (optional) - the name of the HTTP request parameter that dictates the locale to switch to and save
     * in the session. By default this is <b>request_locale</b></li>
     * <p/>
     * <li>requestOnlyParameterName (optional) - the name of the HTTP request parameter that dictates the locale to switch to
     * for the current request only, without saving it in the session. By default this is <b>request_only_locale</b></li>
     * <p/>
     * <li>attributeName (optional) - the name of the session key to store the selected locale. By default this is
     * <b>WW_TRANS_I18N_LOCALE</b></li>
     * <p/>
     * </ul>
     * <p/>
     * <!-- END SNIPPET: parameters -->
     * <p/>
     * <p/> <u>Extending the interceptor:</u>
     * <p/>
     * <p/>
     * <p/>
     * <!-- START SNIPPET: extending -->
     * <p/>
     * There are no known extensions points for this interceptor.
     * <p/>
     * <!-- END SNIPPET: extending -->
     * <p/>
     * <p/> <u>Example code:</u>
     * <p/>
     * <pre>
     * <!-- START SNIPPET: example -->
     * &lt;action name="someAction" class="com.examples.SomeAction"&gt;
     *     &lt;interceptor-ref name="i18n"/&gt;
     *     &lt;interceptor-ref name="basicStack"/&gt;
     *     &lt;result name="success"&gt;good_result.ftl&lt;/result&gt;
     * &lt;/action&gt;
     * <!-- END SNIPPET: example -->
     * </pre>
     *
     * @author Aleksei Gopachenko
     */
    public class I18nInterceptor extends AbstractInterceptor {
        private static final long serialVersionUID = 2496830135246700300L;
    
        protected static final Logger LOG = LoggerFactory.getLogger(I18nInterceptor.class);
    
        public static final String DEFAULT_SESSION_ATTRIBUTE = "WW_TRANS_I18N_LOCALE";
        public static final String DEFAULT_PARAMETER = "request_locale";
        public static final String DEFAULT_REQUESTONLY_PARAMETER = "request_only_locale";
    
        protected String parameterName = DEFAULT_PARAMETER;
        protected String requestOnlyParameterName = DEFAULT_REQUESTONLY_PARAMETER;
        protected String attributeName = DEFAULT_SESSION_ATTRIBUTE;
    
        // Request-Only = None
        protected enum Storage { SESSION, NONE }
    
        public I18nInterceptor() {
            if (LOG.isDebugEnabled()) {
                LOG.debug("new I18nInterceptor()");
            }
        }
    
        public void setParameterName(String parameterName) {
            this.parameterName = parameterName;
        }
    
        public void setRequestOnlyParameterName(String requestOnlyParameterName) {
            this.requestOnlyParameterName = requestOnlyParameterName;
        }
    
        public void setAttributeName(String attributeName) {
            this.attributeName = attributeName;
        }
    
        @Override
        public String intercept(ActionInvocation invocation) throws Exception {
            if (LOG.isDebugEnabled()) {
                LOG.debug("intercept '#0/#1' {",
                    invocation.getProxy().getNamespace(), invocation.getProxy().getActionName());
            }
    
            LocaleFinder localeFinder = new LocaleFinder(invocation);
            Locale locale = getLocaleFromParam(localeFinder.getRequestedLocale());
            locale = storeLocale(invocation, locale, localeFinder.getStorage());
            saveLocale(invocation, locale);
    
            if (LOG.isDebugEnabled()) {
                LOG.debug("before Locale=#0", invocation.getStack().findValue("locale"));
            }
    
            final String result = invocation.invoke();
    
            if (LOG.isDebugEnabled()) {
                LOG.debug("after Locale=#0", invocation.getStack().findValue("locale"));
                LOG.debug("intercept } ");
            }
    
            return result;
        }
    
        /**
         * Store the locale to the chosen storage, like f. e. the session
         *
         * @param invocation the action invocation
         * @param locale the locale to store
         * @param storage the place to store this locale (like Storage.SESSSION.toString())
         */
        protected Locale storeLocale(ActionInvocation invocation, Locale locale, String storage) {
            //save it in session
            Map<String, Object> session = invocation.getInvocationContext().getSession();
    
            if (session != null) {
                synchronized (session) {
                    if (locale == null) {
                        storage = Storage.NONE.toString();
                        locale = readStoredLocale(invocation, session);
                    }
    
                    if (Storage.SESSION.toString().equals(storage)) {
                        session.put(attributeName, locale);
                    }
                }
            }
            return locale;
        }
    
        protected class LocaleFinder {
            protected String storage = Storage.SESSION.toString();
            protected Object requestedLocale = null;
    
            protected ActionInvocation actionInvocation = null;
    
            protected LocaleFinder(ActionInvocation invocation) {
                actionInvocation = invocation;
                find();
            }
    
            protected void find() {
                //get requested locale
                Map<String, Object> params = actionInvocation.getInvocationContext().getParameters();
    
                storage = Storage.SESSION.toString();
    
                requestedLocale = findLocaleParameter(params, parameterName);
                if (requestedLocale != null) {
                    return;
                }
    
                requestedLocale = findLocaleParameter(params, requestOnlyParameterName);
                if (requestedLocale != null) {
                    storage = Storage.NONE.toString();
                }
            }
    
            public String getStorage() {
                return storage;
            }
    
            public Object getRequestedLocale() {
                return requestedLocale;
            }
        }
    
        /**
         * Creates a Locale object from the request param, which might
         * be already a Local or a String
         *
         * @param requestedLocale the parameter from the request
         * @return the Locale
         */
        protected Locale getLocaleFromParam(Object requestedLocale) {
            Locale locale = null;
            if (requestedLocale != null) {
                locale = (requestedLocale instanceof Locale) ?
                        (Locale) requestedLocale :
                        LocalizedTextUtil.localeFromString(requestedLocale.toString(), null);
                if (locale != null && LOG.isDebugEnabled()) {
                    LOG.debug("applied request locale=#0", locale);
                }
            }
    
            if (locale != null && !Arrays.asList(Locale.getAvailableLocales()).contains(locale)) {
                locale = Locale.getDefault();
            }
            return locale;
        }
    
        /**
         * Reads the locale from the session, and if not found from the
         * current invocation (=browser)
         *
         * @param invocation the current invocation
         * @param session the current session
         * @return the read locale
         */
        protected Locale readStoredLocale(ActionInvocation invocation, Map<String, Object> session) {
            Locale locale = this.readStoredLocalFromSession(invocation, session);
    
            if (locale != null) {
                return locale;
            }
    
            return this.readStoredLocalFromCurrentInvocation(invocation);
        }
    
        protected Locale readStoredLocalFromSession(ActionInvocation invocation, Map<String, Object> session) {
             // check session for saved locale
            Object sessionLocale = session.get(attributeName);
            if (sessionLocale != null && sessionLocale instanceof Locale) {
                Locale locale = (Locale) sessionLocale;
                if (LOG.isDebugEnabled()) {
                    LOG.debug("applied session locale=#0", locale);
                }
                return locale;
            }
            return null;
        }
    
        protected Locale readStoredLocalFromCurrentInvocation(ActionInvocation invocation) {
            // no overriding locale definition found, stay with current invocation (=browser) locale
            Locale locale = invocation.getInvocationContext().getLocale();
            if (locale != null && LOG.isDebugEnabled()) {
                LOG.debug("applied invocation context locale=#0", locale);
            }
            return locale;
        }
    
        protected Object findLocaleParameter(Map<String, Object> params, String parameterName) {
            Object requestedLocale = params.remove(parameterName);
            if (requestedLocale != null && requestedLocale.getClass().isArray()
                    && ((Object[]) requestedLocale).length > 0) {
                requestedLocale = ((Object[]) requestedLocale)[0];
    
                if (LOG.isDebugEnabled()) {
                    LOG.debug("requested_locale=#0", requestedLocale);
                }
            }
            return requestedLocale;
        }
    
        /**
         * Save the given locale to the ActionInvocation.
         *
         * @param invocation The ActionInvocation.
         * @param locale     The locale to save.
         */
        protected void saveLocale(ActionInvocation invocation, Locale locale) {
            invocation.getInvocationContext().setLocale(locale);
        }
    
    }
    View Code

      

  • 相关阅读:
    java基础部分的一些有意思的东西。
    antdvue按需加载插件babelpluginimport报错
    阿超的烦恼 javaScript篇
    .NET E F(Entity Framework)框架 DataBase First 和 Code First 简单用法。
    JQuery获得input ID相同但是type不同的方法
    gridview的删除,修改,数据绑定处理
    jgGrid数据格式
    Cannot read configuration file due to insufficient permissions
    Invoke action which type of result is JsonResult on controller from view using Ajax or geJSon
    Entity model数据库连接
  • 原文地址:https://www.cnblogs.com/yy3b2007com/p/6670315.html
Copyright © 2011-2022 走看看