Velocity本地化应用举例
最近在项目上要对以前使用的vm(velocity模版文件)进行本地化处理,于是便开始在这方面开始下功夫。在查阅了各种资料,并做了各种尝试后,得出一些心得。现总结如下。
1.简介
Velocity 是一种通用的、开放源代码的模板解决方案,可以在报告生成 / 数据转换应用程序中独立使用,也可以在 MVC 模型框架中作为视图组件。Velocity 把数据合并到文本主体中不同的点上。文本可以是文字、电子邮件或 HTML。由于采用这种方式,Velocity 模板引擎有点儿像 Microsoft Word 的“邮件合并”特性。邮件合并允许您方便地把动态数据(例如姓名、地址和电话号码)合并到信件中。
学习velocity最好的方式,当然还是官方的user guide了, 地址为:http://velocity.apache.org/engine/releases/velocity-1.6.4/user-guide.html
当然还有很多其他的实用教程。大家可以自己google,网上有好多的。本文主要侧重其本地化方面的支持,基础部分就不再介绍了。
2.准备工作:一个学习用项目
项目结构如下:
3.开始: L10N
Velocity作为一种实用度非常高的模版引擎,其在I18N(国际化)和L10N(本地化)上的支持自然是非常到位。这里主要针对两种比较典型的应用方式做出说明:
3.1 vm模版的本地化。
其实vm模版的本地化最重要的一点就在于两个api上:Velocity.getTemplate(String name, String encoding) 和 mergeTemplate(String templateName, String encoding, Context context, Writer writer)。前者是用的最多的一个api,velocity使用它来获得对应编码的模版;后者主要用于合并模版。
所以,我们在做L10N时,可以针对不同的locale加载不同的encoding和对应encoding的模版,以此来应对L10N的需求。例子中使用了vmTemplateTest.vm和vmTemplateTestutf.vm这两个模版来针对ISO-8859-1(en_US)和UTF-8(zh_CN)这两种encoding下的模版实现的。在实际项目中,我们可以把encoding作为一个外部的property放入不同locale下的资源文件中,然后在使用getTemplate api时将其从用户对应locale下的资源文件中取出并传入,从而得到对应encoding的模版。
3.2 合并数据的本地化。
??? 有时我们想实现合并数据的本地化。例如针对模版文本 "Hello World! $country!", 我们希望美国用户看到 "Hello World! China!", 而中国用户看到"你好,世界!中国!"。这就需要将合并数据实现本地化。这个问题有两种解决方式。
3.2.1 直接使用resourcebundle来解决
??? 这种方式和velocity其实没有太大关系,主要是使用java自身的本地化方案来解决。只要我们针对要合并的数据文本进行本地化工作即可,然后在生成模版时将完成本地化的数据合并进模版就可以了。例子中resourceBundleTest.vm和resourceBundleTestutf8.vm即为这种方案的一种应用。这种方式比较适合资源数据与代码耦合比较高的场合。如一些需要本地化的数据是以对象方式进行提供的,那就比较适合这种方式。
3.2.2 使用Velocity GenericTool来解决
??? 这种方式使用到了Velocity提供的一组工具集中的一个工具:ResourceTool。这个工具包含在Velocity的Generic Tool工具集中。大家可以在这里看到它们的使用简介:http://velocity.apache.org/tools/releases/2.0/summary.html 。这里就不再做详述了。具体的使用方式大家可以参考我提供的代码。简而言之,使用该工具,允许我们直接在vm模版文件中使用vtl来引用资源文件的属性。例子中resourceToolTest.vm和resourceToolTestutf8.vm使用的就是这种方式。这种方式更为简便,因为我们可以直接将资源数据写入vm模版中,而不必再通过java代码来把资源数据合并进模版中,所以我个人认为在实现html模版的L10N时,这种方式要更好一些。
另外,我在使用ResourceTool时碰到一些问题。按照官方文档所说,ResourceTool默认的key值(即在vm模版中使用的默认variable)是text(在模版中为$text)。我在使用时,如果提供如下toolbox配置:
<tools> <toolbox scope="request"> <tool name="code"><tools> <toolbox scope="request"> <tool key="res" class="org.apache.velocity.tools.generic.ResourceTool" bundles="study.velocity.resources.resource" locale="en_US"/> </toolbox></tools>
并使用$res代替$text来编写模版,velocity工作正常。这个问题我实在veloctiy tools 2.0版本中发现的,不知是否是一个bug。
呵呵, 就说这么多了。 附件中是示例项目代码。(我未在代码中提供apache commons的lib包,请读者自行下载配置)