使用Velocity/FreeMarker模板的电子邮件国际化 [英] Email Internationalization using Velocity/FreeMarker Templates

查看:326
本文介绍了使用Velocity/FreeMarker模板的电子邮件国际化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用诸如Velocity或FreeMarker的模板引擎来构建电子邮件正文,以实现i18n?

How can I achieve i18n using a templating engine such as Velocity or FreeMarker for constructing email body?

通常,人们倾向于创建如下模板:

Typically people tend to create templates like:

<h3>${message.hi} ${user.userName}, ${message.welcome}</h3>
<div>
   ${message.link}<a href="mailto:${user.emailAddress}">${user.emailAddress}</a>.
</div>

并创建具有以下属性的资源包:

And have a resource bundle created with properties like:

message.hi=Hi
message.welcome=Welcome to Spring!
message.link=Click here to send email.

这产生了一个基本问题:如果我的.vm文件变大且包含多行文本,那么在单独的资源束(.properties)文件中转换和管理它们中的每一个都会变得很麻烦.

This creates one basic problem: If my .vm files becomes large with many lines of text, it becomes tedious to translate and manage each of them in separate resource bundle (.properties) files.

我想做的是,为每种语言创建一个单独的.vm文件,例如mytemplate_en_gb.vm, mytemplate_fr_fr.vm, mytemplate_de_de.vm,然后以某种方式告诉Velocity/Spring根据输入的语言环境选择正确的文件.

What I am trying to do is, have a separate .vm file created for each language, something like mytemplate_en_gb.vm, mytemplate_fr_fr.vm, mytemplate_de_de.vmand then somehow tell Velocity/Spring to pick up the right one based on the input Locale.

春天有可能吗?还是应该寻找更简单,更明显的替代方法?

Is this possible in Spring? Or should I be looking at perhaps more simple and obvious alternative approaches?

注意:我已经看过春季教程关于如何使用模板引擎创建电子邮件正文.但这似乎无法回答我在i18n上的问题.

Note: I have already seen the Spring tutorial on how to create email bodies using templating engines. But it doesn't seem to answer my question on i18n.

推荐答案

原来使用一个模板和多种语言.属性文件胜过拥有多个模板.

It turns out using one template and multiple language.properties files wins over having multiple templates.

这产生了一个基本问题:如果我的.vm文件变大, 多行文字,翻译和管理每行文字都变得很乏味 它们放在单独的资源包(.properties)文件中.

This creates one basic problem: If my .vm files becomes large with many lines of text, it becomes tedious to translate and manage each of them in separate resource bundle (.properties) files.

如果您的电子邮件结构在多个.vm文件上重复,则维护起来会更加困难.同样,人们将不得不重新发明资源束的后备机制.资源束尝试找到给定语言环境的最接近匹配项.例如,如果语言环境为en_GB,它将尝试按顺序查找以下文件,如果没有可用文件,则回退到最后一个文件.

It is even harder to maintain if your email structure is duplicated over multiple .vm files. Also, one will have to re-invent the fall-back mechanism of resource bundles. Resource bundles try to find the nearest match given a locale. For example, if the locale is en_GB, it tries to find the below files in order, falling back to the last one if none of them is available.

  • language_zh_CN.properties
  • language_zh.properties
  • language.properties

在这里,我将详细介绍如何简化在Velocity模板中读取资源包的操作.

I will post (in detail) what I had to do to simplify reading resource bundles in Velocity templates here.

春季配置

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basename" value="content/language" />
</bean>

<bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">    
    <property name="resourceLoaderPath" value="/WEB-INF/template/" />
    <property name="velocityProperties">
        <map>
            <entry key="velocimacro.library" value="/path/to/macro.vm" />
        </map>
    </property>
</bean>

<bean id="templateHelper" class="com.foo.template.TemplateHelper">
    <property name="velocityEngine" ref="velocityEngine" />
    <property name="messageSource" ref="messageSource" />
</bean>

TemplateHelper类

public class TemplateHelper {
    private static final XLogger logger = XLoggerFactory.getXLogger(TemplateHelper.class);
    private MessageSource messageSource;
    private VelocityEngine velocityEngine;

    public String merge(String templateLocation, Map<String, Object> data, Locale locale) {
        logger.entry(templateLocation, data, locale);

        if (data == null) {
            data = new HashMap<String, Object>();
        }

        if (!data.containsKey("messages")) {
            data.put("messages", this.messageSource);
        }

        if (!data.containsKey("locale")) {
            data.put("locale", locale);
        }

        String text =
            VelocityEngineUtils.mergeTemplateIntoString(this.velocityEngine,
                templateLocation, data);

        logger.exit(text);

        return text;
    }
}

速度模板

#parse("init.vm")
#msg("email.hello") ${user} / $user,
#msgArgs("email.message", [${emailId}]).
<h1>#msg("email.heading")</h1>

我必须创建一个简短的宏msg以便从消息束中读取.看起来像这样:

I had to create a short-hand macro, msg in order to read from message bundles. It looks like this:

#**
 * msg
 *
 * Shorthand macro to retrieve locale sensitive message from language.properties
 *#
#macro(msg $key)
$messages.getMessage($key,null,$locale)
#end

#macro(msgArgs $key, $args)
$messages.getMessage($key,$args.toArray(),$locale)
#end

资源包

email.hello=Hello
email.heading=This is a localised message
email.message=your email id : {0} got updated in our system.

用法

Map<String, Object> data = new HashMap<String, Object>();
data.put("user", "Adarsh");
data.put("emailId", "adarsh@email.com");

String body = templateHelper.merge("send-email.vm", data, locale);

这篇关于使用Velocity/FreeMarker模板的电子邮件国际化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆