所谓的i18n问题指的是(软件的)国际化问题,简单来说就是使咱们的软件可让世界使用任何语言的人们都能使用,软件自身会根据语言环境的不一样进行自动配置,若是你是中文环境那界面以中文显示,若是是英文环境就以英文显示。在i18n问题的解决中,国际化资源文件是不可或缺的,程序正是经过对资源文件的读取来决定究竟以何种界面显示。说到这里若是你认为国际化资源文件仅仅可以解决不一样语言版本的显示问题那你就错了,经过对国际化资源文件进行配置咱们一样能够实现消息的动态建立和显示。下面咱们就来经过实例详细讲解struts如何解决i18n问题。html
首先来简单了解国际化资源文件。国际化资源文件是由basename + local+.properties构成的,local指的是语言环境,缺省的local是由操做系统决定的,local由语言和国家代码组成,basename为MessagesBundle,以中文为例,其资源文件名称为:MessagesBundle_zh_CN.properties,缺省的国际化资源文件名称为MessagesBundle.properties。在该文件中,存储方式为key-value形式,全部的key均对应一个value值,程序经过读取该文件中的key值肯定应显示的文本。下面经过实例来说解用struts如何应用资源文件解决i18n问题。java
1. struts的国际化配置。在struts-config.xml文件中加入<message-resourcesparameter="MessageResources"/>。注意parameter的值为国际化资源文件所在的路径,若是国际化资源文件位于src下一个名为resources的文件夹下,则此处parameter的值应为“resources.MessageResources”。node
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd"> <struts-config> <form-beans> <form-bean name="loginForm" type="com.bjpowernode.struts.LoginActionForm"/> </form-beans> <action-mappings> <action path="/login" type="com.bjpowernode.struts.LoginAction" name="loginForm" scope="request" > <forward name="success" path="/login_success.jsp"/> <forward name="error" path="/login.jsp"/> </action> <action path="/changLang" type="com.bjpowernode.struts.ChangeLanguageAction" > <forward name="index" path="/index.jsp"></forward> </action> </action-mappings> <message-resources parameter="resources.MessageResources"/> </struts-config>
2. 提供国际化资源文件。在本例中咱们提供三个国际化资源文件,分别为:中文的国际化资源文件MessageResources_zh_CN.properties,英文的国际化资源文件MessageResources_en_US.properties以及缺省的国际化资源文件:MessageResources.properties。注意在中文的国际化文件中,须要把全部的中文转换成unicode编码格式。apache
3.利用struts默认将locale放到session中的特性,咱们能够完成语言的自动切换。session
package com.bjpowernode.struts; import java.util.Locale; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.Globals; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; public class ChangeLanguageAction extends Action { @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { //取得客户端传过来的参数 String lang = request.getParameter("lang"); //取得session中默认的locale Locale locale = Locale.getDefault(); //若是传过来的参数为“zh”将locale设为中文,若是参数为“en”则将locale设为英文 if("zh".equals(lang)){ locale = new Locale("zh","CN"); }else if("en".equals(lang)){ locale = new Locale("en", "US"); } //将locale设置到session中 //request.getSession().setAttribute(Globals.LOCALE_KEY, locale); this.setLocale(request, locale); return mapping.findForward("index"); } }
4.上文中咱们已经提过国际化资源文件的做用并不单单在于语言环境的转变,他还支持页面的个性化设计以及动态消息的建立。下面咱们提供一个英文的资源文件,并以此文件为例介绍动态消息的建立。
app
4.1 英文国际化资源文件:jsp
errors.header=<UL> errors.prefix=<font color="blue"><LI> errors.suffix=</LI></font> errors.footer=</UL> login.form.field.username=User Name login.form.field.password=Password login.form.button.login=Login login.success={0},Login Success login.user.not.found=User Not Found,UserName\=[{0}] login.password.error=Password Error
4.2 建立动态消息。动态消息的建立分为三个步骤,分别是 建立国际化消息文本,传递国际化消息文本,显示国际化消息文本。在上面的资源文件按中咱们能够看到占位符的存在,占位符的存在就给咱们动态的建立信息提供了可能,下面看咱们是如何经过填充占位符建立动态信息的。 ide
package com.bjpowernode.struts; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionMessage; import org.apache.struts.action.ActionMessages; public class LoginAction extends Action { @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { LoginActionForm laf = (LoginActionForm)form; String username = laf.getUsername(); String password = laf.getPassword(); UserManager userManager = new UserManager(); ActionMessages messages = new ActionMessages(); try{ userManager.login(username, password); //建立国际化消息文本 //ActionMessage message = new ActionMessage("login.success",new Object[]{username}); ActionMessage message = new ActionMessage("login.success",username); messages.add("login_success_1",message); ActionMessage message1 = new ActionMessage("login.success",username); messages.add("login_success_2",message1); //传递国际化消息 this.saveMessages(request, messages); return mapping.findForward("success"); }catch(UserNotFoundException e){ e.printStackTrace(); //建立国际化消息文本 ActionMessage error = new ActionMessage("login.user.not.found",username); messages.add("error_1",error); //传递国际化消息 this.saveErrors(request, messages); }catch(PasswordErrorException e){ e.printStackTrace(); //建立国际化消息文本 ActionMessage error = new ActionMessage("login.password.error"); messages.add("error_2",error); //传递国际化消息 this.saveErrors(request, messages); } return mapping.findForward("error"); } }
请注意上面代码中的这条语句:ActionMessagemessage = new ActionMessage("login.success",username);,该语句的做用就在于填充国际化资源文件中的占位符,经过这种方式咱们能够动态的建立消息。ui
5. 在jsp中采用<bean:message>读取国际化消息文本(本例中以登陆成功后的页面为例)。this
<%@ page language="java" contentType="text/html; charset=GB18030" pageEncoding="GB18030"%> <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %> <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %> <!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=GB18030"> <title>Insert title here</title> </head> <body> <html:messages id="msg" message="true" > <bean:write name="msg"/> </html:messages> </body> </html>
在该jsp中咱们采用的是html:messages标签来读取信息的,在这里须要注意的一点是,这个标签既能够读取message key又能够读取error key,而html:error标签只能够读取error key。根据这一点咱们能够决定在错误处理页面和成功页面具体使用哪一种标签进行读取。另外使用jstl标签一样能够读取国际化资源文件中的消息,再引入jstl格式化标签库后,使用<html:errors>标签能够读取错误信息,使用<fmt:message>标签能够读取消息。