1. 国际化的目标
1). 如何配置国际化资源文件
I. Action 范围资源文件: 在Action类文件所在的路径建立名为 ActionName_language_country.properties 的文件
II. 包范围资源文件: 在包的根路径下建立文件名为 package_language_country.properties 的属性文件,
一旦建立,处于该包下的所有 Action 都可以访问该资源文件。注意:包范围资源文件的 baseName 就是package,不是Action所在的包名。
III. 全局资源文件
> 命名方式: basename_language_country.properties
> struts.xml <constant name="struts.custom.i18n.resources" value="baseName"/>
IV. 国际化资源文件加载的顺序如何呢 ? 离当前 Action 较近的将被优先加载.
假设我们在某个 ChildAction 中调用了getText("username"):
(1) 加载和 ChildAction 的类文件在同一个包下的系列资源文件 ChildAction.properties
(2) 加载 ChildAction 实现的接口 IChild,且和 IChildn 在同一个包下 IChild.properties 系列资源文件。
(3) 加载 ChildAction 父类 Parent,且和 Parent 在同一个包下的 baseName 为 Parent.properties 系列资源文件。
(4) 若 ChildAction 实现 ModelDriven 接口,则对于getModel()方法返回的model 对象,重新执行第(1)步操作。
(5) 查找当前包下 package.properties 系列资源文件。
(6) 沿着当前包上溯,直到最顶层包来查找 package.properties 的系列资源文件。
(7) 查找 struts.custom.i18n.resources 常量指定 baseName 的系列资源文件。
(8) 直接输出该key的字符串值。
2). 如何在页面上 和 Action 类中访问国际化资源文件的 value 值
I. 在 Action 类中. 若 Action 实现了 TextProvider 接口, 则可以调用其 getText() 方法获取 value 值
> 通过继承 ActionSupport 的方式。
II. 页面上可以使用 s:text 标签; 对于表单标签可以使用表单标签的 key 属性值
> 若有占位符, 则可以使用 s:text 标签的 s:param 子标签来填充占位符
> 可以利用标签和 OGNL 表达式直接访问值栈中的属性值(对象栈 和 Map 栈)
time=Time:{0}
<s:text name="time">
<s:param value="date"></s:param>
</s:text>
------------------------------------
time2=Time:${date}
<s:text name="time2"></s:text>
3). 实现通过超链接切换语言.
I. 关键之处在于知道 Struts2 框架是如何确定 Local 对象的 !
II. 可以通过阅读 I18N 拦截器知道.
III. 具体确定 Locale 对象的过程:
> Struts2 使用 i18n 拦截器 处理国际化,并且将其注册在默认的拦截器栈中
> i18n拦截器在执行Action方法前,自动查找请求中一个名为 request_locale 的参数。
如果该参数存在,拦截器就将其作为参数,转换成Locale对象,并将其设为用户默认的Locale(代表国家/语言环境)。
并把其设置为 session 的 WW_TRANS_I18N_LOCALE 属性
> 若 request 没有名为request_locale 的参数,则 i18n 拦截器会从 Session 中获取 WW_TRANS_I18N_LOCALE 的属性值,
若该值不为空,则将该属性值设置为浏览者的默认Locale
> 若 session 中的 WW_TRANS_I18N_LOCALE 的属性值为空,则从 ActionContext 中获取 Locale 对象。
IV. 具体实现: 只需要在超连接的后面附着 request_locale 的请求参数, 值是 语言国家 代码.
<a href="testI18n.action?request_locale=en_US">English</a>
<a href="testI18n.action?request_locale=zh_CN">中文</a>
> 注意: 超链接必须是一个 Struts2 的请求, 即使 i18n 拦截器工作!
> 注意: 超链接必须是一个 Struts2 的请求, 即使 i18n 拦截器工作!
使用label标签时要用%{getText{'username'}}方式也可以从国际化资源文件中获取value值 因为此时在对象栈中有
DefaultTypeProvider的一个实例 该对象中提供访问资源化文件的方法 同时还要通知label中放入的不再是普通的字符串
而是一个OGNL表达式 可以使用%{}包装起来
如果form的主题为simple的时候 所有设置都不起作用
这时使用s:text 标签 和强制ognl解析
有占位符的国际化资源文件的输出方式:
新建acton I18nAction
还可以使用time=Time:${date} 来直接获取值栈中的属性值
实现通过超链接切换语言:
关键之处在于struts2框架是如何确定Local对象的 i18n拦截器 I18nInterceptor
publicStringintercept(ActionInvocationinvocation)throwsException{
if(LOG.isDebugEnabled()){
LOG.debug("intercept
'#0/#1' {",
invocation.getProxy().getNamespace(),invocation.getProxy().getActionName());
}
//get requested locale
Map<String,Object>params=invocation.getInvocationContext().getParameters();
//保持session的falg默认为true
booleanstoreInSession=true;
//parameteName 为request_locale
//requsetedLocale为转换过的浏览器参数
ObjectrequestedLocale=findLocaleParameter(params,parameterName);
<!--
---findLocaleParameter
privateObjectfindLocaleParameter(Map<String,Object>params,StringparameterName){
//将从浏览器带过来的request_locale参数保存到requestedLoclae中
ObjectrequestedLocale=params.remove(parameterName);
//如果requestedLocale不为空 类型是数组 并取长度是1
if(requestedLocale!=null&&requestedLocale.getClass().isArray()
&&((Object[])requestedLocale).length==1){
//将数组中的参数取出赋给requestedLocale
requestedLocale=((Object[])requestedLocale)[0];
if(LOG.isDebugEnabled()){
LOG.debug("requested_locale=#0",requestedLocale);
}
}
returnrequestedLocale;
}
--> //如果请求擦拭你为空就从requestOnlyParmeteName中去找
if(requestedLocale==null){
//requestOnlyParameterName默认为request_only_locale
requestedLocale=findLocaleParameter(params,requestOnlyParameterName);
//如果上面的保存到request中的不为空 则将保存到session的flag设置为false
if(requestedLocale!=null){
storeInSession=false;
}
}
//将找到的requestLocale参数赋值给local
Localelocale=getLocaleFromParam(requestedLocale);
<!--
---getLocaleFromParam
protectedLocalegetLocaleFromParam(ObjectrequestedLocale){
Localelocale=null;
//如果传进来的参数不为空
if(requestedLocale!=null){
//如果参数的类型为Locale 就强转为Locale 如果不是就执行下面的代码 将将参数转换为Locale类型并赋值
locale=(requestedLocaleinstanceofLocale)?
(Locale)requestedLocale:
LocalizedTextUtil.localeFromString(requestedLocale.toString(),null);
if(locale!=null&&LOG.isDebugEnabled()){
LOG.debug("applied
request locale=#0",locale);
}
}
returnlocale;
}
-->
//获取sessionMap
Map<String,Object>session=invocation.getInvocationContext().getSession();
//如果session不为空 并取locale不为空 就把参数保存到session中
if(session!=null){
synchronized(session){
if(locale==null){
storeInSession=false;
locale=readStoredLocale(invocation,session);
}
if(storeInSession){
session.put(attributeName,locale);
}
}
}
saveLocale(invocation,locale);
<!--
//将获取到的locale值放入context 中 在值栈的栈顶可见
protectedvoidsaveLocale(ActionInvocationinvocation,Localelocale){
invocation.getInvocationContext().setLocale(locale);
}
-->
if(LOG.isDebugEnabled()){
LOG.debug("before
Locale=#0",invocation.getStack().findValue("locale"));
}
finalStringresult=invocation.invoke();
if(LOG.isDebugEnabled()){
LOG.debug("after
Locale=#0",invocation.getStack().findValue("locale"));
LOG.debug("intercept
} ");
}
returnresult;
}
//默认请况下走的是左边这条线 如果通过url改变locle的值则走右边 设置之后 如果没有设置的url访问就会从session取对应的locale参数去使用
本文介绍了Struts2框架中的国际化配置方法,包括不同级别的资源文件配置方式、资源文件加载顺序及如何在Action和页面中访问这些资源。此外,还详细讲解了如何通过超链接实现语言切换。
303

被折叠的 条评论
为什么被折叠?



