OperaMasks中的扩展国际化支持首先应该明确的是,OperaMasks是完全兼容JSF规范的,因此上面一节介绍的方法在OperaMasks中仍然可用。但OperaMasks在IoVC的支持下,允许将国际化资源引用从页面中移到LiteBean中,并因此扩展出多种支持多语言的方式。在本节的后续描述中,将统一使用以下页面为例,可以看出,现在页面完全不需要关心国际化的问题: <f:view xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
xmlns:w="http://www.apusic.com/jsf/widget" xmlns:layout="http://www.apusic.com/jsf/layout"
renderKitId="AJAX" xmlns:h="http://java.sun.com/jsf/html">
<w:page title="Calculator">
<w:form id="calc">
<layout:panelGrid columns="3">
<h:outputLabel for="first"/>
<w:textField id="first"/>
<h:message for="first"/>
<h:outputLabel for="second"/>
<w:textField id="second"/>
<h:message for="second"/>
<h:outputLabel for="result"/>
<h:outputText id="result"/>
</layout:panelGrid>
<br/>
<layout:panelGrid columns="4">
<w:button id="add"/>
<w:button id="subtract"/>
<w:button id="multiply"/>
<w:button id="divide"/>
</layout:panelGrid>
</w:form>
</w:page>
</f:view>最直接的改变形式是,在LiteBean中引入资源,然后使用与页面类似的统一EL表达式。加入了国际化支持的LiteBean看上去是这个样子的:
由于现在所有对资源文件的引用集中到了LiteBean中,我们可以更为自然地加入一些更详细和更灵活的提示。假设我们现在有这样一种需求:当用户点击某一个操作时,result并不仅仅简单的显示一个结果, 我们还希望能够显示用户的操作是什么,譬如,当用户执行 1 + 2 操作时,中文环境下显示:"数据1加数据2等于3",英文环境下显示:"Number 1 add number 2 equals 3"。换言之,我们现在要对多语言字符串进行参数化处理。在OperaMasks中是如何实现的呢? 首先修改资源文件加入资源串: #demo.LocalStrings_en_US.properties
...
resultLabel=Number {0} {1} Number {2} equals {3}#demo.LocalStrings_zh_CN.properties
...
resultLabel=数值{0}{1}数值{2}等于{3}然后对页面代码作如下修改: <h:outputLabel for="result"/> <h:outputText id="result"/> 改为: <h:outputText id="resultLabel"/> 对LiteBean代码做如下修改: @ManagedBean(scope=ManagedBeanScope.SESSION)
public class CalcBean implements Serializable {
/**
* 注入资源文件
*/
@LocalString
private Map<String,String> messages;
@Bind
@Label("#{this.messages['first.label']}")
private double first = 22.0;
@Bind
@Label("#{this.messages['second.label']}")
private double second = 7.0;
/**
* 用来保存计算结果
*/
// @Bind
// @Label("#{this.messages['result.label']}")
在服务器上运行页面,在中文环境下页面展现如下: ![]() 可以看出,在标准JSF如果要实现同样功能,需要在页面和LiteBean中同时关注多语言特性,了解各键值含义。通过使用IoVC,我们把页面解放出来,而只需要在LiteBean中统一进行多语言支持。 @LocalString标注用来向LiteBean中引入资源。从上面例子我们可以看出它的其中一种常用使用形式:
也可以通过指定@LocalString标注的basename属性,引入任意位于/WEB-INF/classes目录下的资源文件。例如 @LocalString(basename="demo.CalcBean") 将引入/WEB-INF/classes/demo/目录中前缀为CalcBean的资源文件。 除了java.util.Map类型属性外,@LocalString标注还可以作用在以下类型的对象属性上:
@LocalString标注具有@Accessible特性,被其标注的属性将自动在统一EL表达式中具有公共可见性(只对统一EL表达式有效)。例如,上面在CalcBean中定义的private属性messages,由于标注为@LocalString,也允许在页面中使用统一EL表达式#{CalcBean.messages}进行访问。如果希望取消这种附加的公共可见性,可以使用@Accessible(false)进行标注。 上面介绍的方法,无论是在页面中使用<w:loadBundle>标签,或是在LiteBean中使用@LocalString标注,其本质都是由应用程序主动从资源文件中抽取资源串。OperaMasks还支持一种更为简捷的形式:由资源文件主动向LiteBean中注入多语言信息。 在此方式下,在页面和LiteBean中都无须关注多语言特性。因此除了页面仍可沿用本节开始时所描述的最简形式外,LiteBean也可以还原为没有国际化支持最简形式: @ManagedBean(scope=ManagedBeanScope.SESSION)
public class CalcBean implements Serializable {
@Bind
private double first = 22.0;
@Bind
private double second = 7.0;
/**
* 用来保存计算结果
*/
@Bind
private double result = 0;
@Action
public void add() {
result = first + second;
}
@Action
public void subtract() {
result = first - second;
}
@Action
public void multiply() {
result = first * second;
}
@Action
public void divide() {
result = first / second;
}
}现在,为了在应用中加入多语言支持,我们在CalcBean所在的包目录中加入以下LocalStrings资源文件: LocalStrings_en_US.properties #demo.LocalStrings_en_US.properties CalcBean.first.label=First CalcBean.second.label=Second CalcBean.result.label=Result CalcBean.add.label= + CalcBean.subtract.label= - CalcBean.multiply.label= * CalcBean.divide.label = / LocalStrings_zh_CN.properties #demo.LocalStrings_zh_CN.properties CalcBean.first.label=数值一 CalcBean.second.label=数值二 CalcBean.result.label=结果 CalcBean.add.label= 加 CalcBean.subtract.label= 减 CalcBean.multiply.label= 乘 CalcBean.divide.label = 除 在服务器上运行,可以看到页面展示中已加入多语言支持。 可以看出,在这种形式中,由于页面和代码中没有任何与资源文件关联的信息,对多语言的支持完全是通过以下约定规则加入的:
使用这种形式,我们还可以很方便地在资源文件中对页面组件属性进行初始化,从而达到更友好的国际化展现效果。例如,假如“add”这个Button,在中文环境下显示“加”,在英文环境下显示“Plus”,由于语言的差异,导致在不同语言下,button的宽度发生变化。我们希望,在中文环境下,此按钮的宽度为30,而在英文环境下,此按钮的宽度为60。为了实现这个需求,只需要在资源文件中分别加入: LocalStrings_zh_CN.properties #demo.LocalStrings_zh_CN.properties CalcBean.add.minWidth=30 CalcBean.subtract.minWidth=30 CalcBean.multiply.minWidth=30 CalcBean.divide.minWidth=30 LocalStrings_en_US.properties #demo.LocalStrings_en_US.properties CalcBean.add.minWidth=60 CalcBean.subtract.minWidth=60 CalcBean.multiply.minWidth=60 CalcBean.divide.minWidth=60 在服务器上运行页面,可看到在中英文环境下button将以不同宽度展现。 |
|||||||||
| [上一页] [下一页] | |||||||||
JSF常规国际化支持
package demo;
...
@ManagedBean(scope = ManagedBeanScope.REQUEST)
public class CalcBean {
/**
* 注入资源文件
*/
@LocalString
private Map<String,String> messages;
@Bind
@Label("#{this.messages['first.label']}")
private double first = 22.0;
@Bind
@Label("#{this.messages['second.label']}")
private double second = 7.0;
@Bind
@Label("#{this.messages['result.label']}")
private String resultLabel;
/**
* 用来保存计算结果
*/
@Bind
@Label("#{this.messages['result.label']}")
private double result = 0;
@Action
@Label("#{this.messages['add.label']}")
public void add() {
result = first + second;
}
@Action
@Label("#{this.messages['subtract.label']}")
public void subtract() {
result = first - second;
}
@Action
@Label("#{this.messages['multiply.label']}")
public void multiply() {
result = first * second;
}
@Action
@Label("#{this.messages['divide.label']}")
public void divide() {
result = first / second;
}
}
operatorKey = "add.label";
}
@Action
@Label("#{this.messages['subtract.label']}")
public void subtract() {
result = first - second;
operatorKey = "subtract.label";
}
@Action
@Label("#{this.messages['multiply.label']}")
public void multiply() {
result = first * second;
operatorKey = "multiply.label";
}
@Action
@Label("#{this.messages['divide.label']}")
public void divide() {
result = first / second;
operatorKey = "divide.label";
}
}
