`
apusiczhang
  • 浏览: 16922 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

OperaMasks 2.0特性之二:国际化

阅读更多

假设我们现在希望让 Calculator 这个示例支持中英文,让我们先回顾一下常规JSF的实现手段:

首先,我们需要准备两个资源文件,分别是:

#demo.LocalStrings_en_US.properties
first.label=First:
second.label=Second:
result.label=Result:
add.label= +
subtract.label= -
multiply.label= *
divide.label = /

  

#demo.LocalStrings_zh_CN.properties
first.label=数值一:
second.label=数值二:
result.label=结果:
add.label= +
subtract.label= -
multiply.label= *
divide.label = /

 

当然,我们需要通过 Ant 将上述的LocalStrings_zh_CN.properties进行 native2ascii 的转换,这是基础知识,不是本文介绍的重点。

为了使用上述资源文件,我们的页面要改成这样:

<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">
  <f:loadBundle basename="demo.LocalStrings" var="msgs"/>
  <w:page title="Calculator">
    <w:form id="calc">
      <layout:panelGrid columns="3">
        <h:outputLabel for="first" value="#{msgs['first.label']}"/>
        <w:textField id="first"/>
        <h:message for="first" value="#{msgs['second.label']}"/>
        <h:outputLabel for="second"/>
        <w:textField id="second"/>
        <h:message for="second"/>
        <h:outputLabel for="result" value="#{msgs['result.label']}"/>
        <h:outputText id="result"/>
      </layout:panelGrid>
      <br/>
      <layout:panelGrid columns="4">
        <w:button id="add" value="#{msgs['add.label']}"/>
        <w:button id="subtract" value="#{msgs['subtract.label']}"/>
        <w:button id="multiply" value="#{msgs['multiply.label']}"/>
        <w:button id="divide" value="#{msgs['divide.label']}"/>
      </layout:panelGrid>
    </w:form>
  </w:page>
</f:view>

 

经过对页面进行上述修订,在中文环境下,页面运行效果如下图所示:

 

 

而在英文环境中,运行效果是这样的:

 

 

看上去好像也完成了我们的需求,但回过头来看看我们的页面,已经被我们改的面目全非。倘若这个页面是由美工设计的,请问,她知道什么叫做资源文件吗?她知道什么是 "#{msgs['add.label']}" 吗?

让我们忘掉这种丑陋的做法吧,看看 AOM 会带来怎样的魔力!

首先,让我们把页面恢复成原先那整洁的基于IoVC原理的页面:

<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>

我们继续保留 LocalStrings_en_US.properties 以及 LocalStrings_zh_CN.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 = /
#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 = /

换言之,我们只是在资源串中的key上,加了一个限定词:CalcBean,然后,让我们运行这个页面。

你会发觉:哇,页面已经是多语言的了,这就是你想要的!

但回顾你做的工作,你会发觉,这是多么的简单,多么的享受!

我们现在希望对这个示例扩展一下:当鼠标移到第一个<w:textFiled>时,希望能够显示提示“请输入第一个参数”;当鼠标移到add button时,希望能够显示提示“将这些数值相加”。那么,我们只需要扩展一下这两个资源文件:

#demo.LocalStrings.properties
CalcBean.first.description=Please input the first number
CalcBean.add.description=Add these numbers
#demo.LocalStrings_zh_CN.properties
CalcBean.first.description=请输入第一个数值
CalcBean.add.description=将数值相加

然后,我们重新运行此页面,你会发觉,你预期的效果已经达到了!

 

 

我们还可以做的更好!

假设我们有这样一种场景:“add”这个Button,在中文环境下显示“加”,在英文环境下显示“Plus”,由于语言的差异, 导致在不同语言下,button的宽度发生变化。我们希望,在中文环境下,此按钮的宽度为 30,而在英文环境下,此按钮的宽度为 60。那么,我们该怎么办?

解决这个问题的思路,无非要把宽度作为一个多语言资源拿出来放到properties文件中,但我们要怎么做呢?难道在页面中写入: <w:button id="add" minWidth="#{msgs['add.minWidth]}"/>?这样一来,岂非很丑陋?在 AOM 2.0中,我们只需要更改一下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

注意,上述资源文件中设置最小宽度为60,比中文环境下的设置大了一倍,那么,在英文环境下,效果如下:

 

是不是非常之简单?让我们再来看一看更高级的用法。

假设我们现在有这样一种需求:当用户点击某一个操作时,result并不仅仅简单的显示一个结果, 我们还希望能够显示用户的操作是什么,譬如,当用户执行 1 + 2 操作时,中文环境下显示:"数据 1 加 数据 2 等于 3",英文环境下显示:"Number 1 add number 2 equals 3"。换言之,我们现在要对多语言字符串进行参数化处理。在 AOM 2.0 中是怎样做的呢?

首先,我们需要把页面改一下:

<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" />
        <layout:cell colspan="3" rowspan="1">
           <h:outputText id="resultLabel" />
        </layout:cell>
      </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>

请注意,我们将<h:outputText>进行了修订,它占据了三列,id改为resultLabel。

然后,我们需要修订 CalcBean,修订如下:

@ManagedBean(scope = ManagedBeanScope.REQUEST)
public class CalcBean {

  @Bind
  private double first = 22.0;

  @Bind
  private double second = 7.0;

  @Bind
  private String resultLabel;

  /**
  * 注入资源文件
  */
  @LocalString
  private Map<String,String> messages;

  /**
   * 用来保存计算结果
   */
  private double result = 0;

  /**
   * 用来保存用户的操作符
   */
  private String operator = "";

  @Action
  public void add() {
    result = first + second;
   operator = "+";
  }

  @Action
  public void subtract() {
    result = first - second;
    operator = "-";
  }

  @Action
  public void multiply() {
    result = first * second;
    operator = "*";
  }

  @Action
  public void divide() {
    result = first / second;
    operator = "/";
  }
 
  @BeforeRender
  private void beforeRender(boolean isPostBack) {
    resultLabel = MessageFormat.format(messages.get("resultLabel"), first, operator, second, result);
  }
}

请注意,在CalcBean中,我们声明了两个临时变量 result 和 operator 来保存用户的计算结果及操作符,另外,声明了一个 @BeforeRender 的方法,意思就是告诉AOM,在你决定渲染前,请调用此方法。 我们在这个方法中,设置 resultLabel的具体值。那么,资源文件是怎样获取得呢?非常简单,只需要在前面声明一个private @LocalString Map<String,String> messages 即可。

再来看一下我们的资源文件:

#demo.LocalStrings_en_US.properties
CalcBean.resultLabel=Number {0} {1} number {2} equals {3}
#demo.LocalStrings_zh_CN.properties
CalcBean.resultLabel=数值 {0} {1} 数值 {2} 等于 {3}

我们在获取上述资源以后,只需要对其进行一下 format,将参数传递进去,即可获得我们期望的结果:

 

等等,这里好像有一个疑问:你只是帮我把资源文件的获取简化了,但在对资源字符串的解析上,AOM好像并没有带来任何改进, 我还是需要调用 MessageFormat.format 方法,在这方面上,AOM能否带来一些便利呢?要知道,我可是非常懒惰的。

OK,我只能说:AOM 的 ELite 对资源文件的处理是非常简单的,简单到令人之发指,但同时,这也超出了本章所要阐述的范围,且留待下一章节分解吧。

 

分享到:
评论
1 楼 QuakeWang 2008-04-15  
有3个问题:
1. 在你前面的博客文章中提到过OperaMasks提倡的是"约定优于配置",那么为什么这里又开始需要繁琐的配置呢?定义在资源文件里面的多个CalcBean前缀看起来都是重复的,我觉得可以按照这篇文章里面提到的做法简化:http://www.iteye.com/post/512472,统一在BeforeRender之前按照默认的约定去读取同名资源文件。当然,这种想法其实在很久以前就在一些开源框架(tapestry, ofbiz)中出现过,也不是我的独特创新想法。

2. 一个对象在不同情景下可能有不同的国际化内容,比如说有一个UserBean,在登陆界面它的name属性对应的label是"登录名",而在用户搜索界面它的label是"用户名",那么在这里UserBean的beforeRender里面代码应该如何处理呢,还是说需要创建一个新的LoginUserBean和SearchUserBean?我查看了你们文档和例子,并没有发现针对这种常见情况的实践方法。

3. 这个例子里面提到的用资源文件控制按钮宽度我觉得不妥,现在主流的浏览器CSS和HTML标准支持已经很不错,上面提到的问题完全可以用CSS来解决,没有必要还采用7,8年前这种旧做法,把它放在你们的例子中会被误认为是一个推荐的实践方法而造成不必要的麻烦。

相关推荐

    operamasks-ui-2.0.zip

    《深入理解OperaMasks UI 2.0:前端框架与应用实践》 OperaMasks UI 2.0是一款由金蝶公司推出的高效、易用的前端界面库,它旨在为开发者提供一套完整的用户界面解决方案,以提升Web应用程序的用户体验和开发效率。...

    operamasks-ui-2.0-doc

    "Operamasks UI 2.0 Doc"是一个针对 Operamasks 用户界面的开发文档,它提供了详尽的指导和信息,帮助开发者理解和构建基于Operamasks的Web应用程序。这个离线版文档对于开发者来说尤其珍贵,因为在线寻找这类资源...

    operamasks2.0M2

    operamasks的作用手册

    operamasks-ui-2.0

    operamasks-ui-2.0 这个帮助文档很难才找到的,感谢CSDN,其中的说明真的是很详细了,维护旧代码用到的这个框架,相比easyui和bootstrap这个框架简单一些,不过用起来还是不错的,除了文档太少,不过有这个就基本...

    operamasks-ui-2.0-demo--.zip

    "Operamasks UI 2.0 Demo" 是一个专门针对Opera浏览器的扩展或应用界面设计的开发套件,主要用于创建和定制用户界面。这个压缩包文件 "operamasks-ui-2.0-demo--.zip" 包含了用于演示和实践如何使用Opera Masks UI ...

    operamasks-ui-2.0-demo.zip

    "Operamasks UI 2.0 Demo"是一个与JavaScript相关的压缩包,包含了对Opera Masks用户界面新版本的演示。这个项目可能是一个Web应用程序框架或库,专为开发人员设计,以便在Opera浏览器或其他支持JavaScript的环境中...

    OperaMasks快速进阶

    IoVC是OperaMasks2.0引入的概念,旨在解决传统MVC模式中控制逻辑与展现逻辑难以完全解耦的问题。在IoVC模型中,控制逻辑不再由展现层触发,而是由后台业务逻辑控制,这样开发者可以通过绑定ID来实现展现层与业务逻辑...

    operamasks-ui 帮助文档

    只是我在网上找的 operamasks-ui api 文档 , 希望对你们有帮助

    jQuery2.0应用开发SSH框架整合jQuery2.0实战OA办公自动化

    其中重点详细的介绍了jQuery2.0的新特征以及operamasks前端UI框架。从系统数据库分析到系统角色权限,从功能到业务流程。介绍整个OA办公系统的开发过程及开发中碰到的基础问题进行深入讲解。对代码重构及代码优化...

    operamasks-ui-master.zip

    OperaMasks UI 2.0 可能采用模块化设计,支持按需引入,减少了页面加载的负担。它还可能兼容各种浏览器,包括对IE的兼容性处理,以满足不同用户环境的需求。此外,它通常会遵循一定的前端开发规范,如ES6语法、...

    operaMasks_studio应用手册

    #### 二、operaMasks_studio的主要功能与特点 1. **集成开发环境(IDE)支持**:operaMasks_studio作为一款专门针对JSF的开发工具,它能够很好地与主流的IDE(如Eclipse、IntelliJ IDEA等)集成,为用户提供一个...

    operamasks-sdk_3.2

    **Operamasks SDK 3.2:金蝶中间件的创新解决方案** Operamasks SDK 3.2 是金蝶中间件公司推出的一款重要的软件开发工具包,专为开发者设计,旨在简化与金蝶产品集成的过程,提高开发效率,并增强应用程序的功能。...

    operamasks安装包

    在使用过程中,用户可以根据自己的需求调整operamasks-options.jar中的设置,或者利用operamasks-api.jar提供的接口与其他软件或扩展进行交互,以实现更个性化的浏览体验。总的来说,OperaMasks通过这些组件提供了一...

    operamasks官方jsf教程

    5. **05-Properties-Files.ppt** - 这部分可能讨论了如何使用资源包(properties files)来处理多语言支持和国际化,这是任何Web应用都需要考虑的关键问题。 6. **06-Event-Handling.ppt** - JSF事件处理机制让...

    operamasks-ui-2.1-demo

    "Operamasks UI 2.1 Demo"是一个专注于前端用户界面的项目,主要基于流行的开源浏览器扩展框架——OperaMasks。这个项目的目的是提供一个演示版本,让用户和开发者能够体验和理解OperaMasks UI 2.1版本的功能和设计...

    operamasks-faces_1.0

    "Operamasks-faces_1.0" 是一个与Opera浏览器相关的扩展或资源包,它主要专注于面部识别或个性化功能。这个压缩包可能是为Opera浏览器设计的一系列面具或表情符号,让用户在浏览网页时能够使用各种有趣的脸部形象...

Global site tag (gtag.js) - Google Analytics