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

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

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

${message.hi} ${user.userName}, ${message.welcome}

${message.link}${user.emailAddress}.

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

 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.vm然后以某种方式告诉Velocity / Spring根据输入Locale选择正确的文件。

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

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

事实certificate,使用一个模板和多个language.properties文件胜过多个模板。

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

如果您的电子邮件结构在多个.vm文件上重复,则更难维护。 此外,人们将不得不重新发明资源包的回退机制。 资源包尝试在给定区域设置的情况下找到最接近的匹配。 例如,如果语言环境是en_GB ,它会尝试按顺序查找下面的文件,如果它们都不可用,则回退到最后一个文件。

  • language_en_GB.properties
  • language_en.properties
  • language.properties

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

访问Velocity模板中的资源包

弹簧配置

                

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 data, Locale locale) { logger.entry(templateLocation, data, locale); if (data == null) { data = new HashMap(); } 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}]). 

#msg("email.heading")

我不得不创建一个简写宏, 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 data = new HashMap(); data.put("user", "Adarsh"); data.put("emailId", "adarsh@email.com"); String body = templateHelper.merge("send-email.vm", data, locale); 

这是Freemarker的解决方案(一个模板,几个资源文件)。

主程序

 // defined in the Spring configuration file MessageSource messageSource; Configuration config = new Configuration(); // ... additional config settings // get the template (notice that there is no Locale involved here) Template template = config.getTemplate(templateName); Map model = new HashMap(); // the method called "msg" will be available inside the Freemarker template // this is where the locale comes into play model.put("msg", new MessageResolverMethod(messageSource, locale)); 

MessageResolverMethod类

 private class MessageResolverMethod implements TemplateMethodModel { private MessageSource messageSource; private Locale locale; public MessageResolverMethod(MessageSource messageSource, Locale locale) { this.messageSource = messageSource; this.locale = locale; } @Override public Object exec(List arguments) throws TemplateModelException { if (arguments.size() != 1) { throw new TemplateModelException("Wrong number of arguments"); } String code = (String) arguments.get(0); if (code == null || code.isEmpty()) { throw new TemplateModelException("Invalid code value '" + code + "'"); } return messageSource.getMessage(code, null, locale); } 

}

Freemarker模板

 ${msg("subject.title")}