使用Velocity/FreeMarker模板进行国际化电子邮件

如何使用Velocity或FreeMarker等模板引擎来构建邮件正文?

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

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

并使用以下属性创建资源包:

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

这会产生一个基本问题:如果我的.vm文件变得很大,文本行很多,那么在单独的资源包(.properties)文件中翻译和管理它们就变得很繁琐。

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

这在春天有可能吗?或者我应该考虑更简单明了的替代方法?

注意:我已经看过Spring tutorial如何使用模板引擎创建电子邮件主体。但它似乎没有回答我关于i18n的问题。

事实证明,使用一个模板和多个language.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,它会尝试按顺序查找下面的文件,如果它们都不可用,则回退到最后一个文件。

> language_en_GB.properties
> language_en.properties
> language.properties

我将发布(详细)我必须做什么来简化在Velocity模板中阅读资源包。

访问Velocity模板中的资源包

弹簧配置

<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以便从消息包中读取。它看起来像这样:

#**
 * 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);
相关文章
相关标签/搜索