[英]Email Internationalization using Velocity/FreeMarker Templates
如何使用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.vm
然后以某種方式告訴Velocity / Spring根據輸入Locale選擇正確的文件。
這在春天有可能嗎? 或者我應該考慮更簡單明了的替代方法?
注意:我已經看過關於如何使用模板引擎創建電子郵件主體的Spring教程 。 但它似乎沒有回答我關於i18n的問題。
事實證明,使用一個模板和多個language.properties文件勝過多個模板。
這會產生一個基本問題:如果我的.vm文件變得很大,文本行很多,那么在單獨的資源包(.properties)文件中翻譯和管理它們就變得很繁瑣。
如果您的電子郵件結構在多個.vm
文件上重復,則更難維護。 此外,人們將不得不重新發明資源包的回退機制。 資源包嘗試在給定區域設置的情況下找到最接近的匹配。 例如,如果區域設置是en_GB
,它會嘗試按順序查找下面的文件,如果它們都不可用,則回退到最后一個文件。
我將發布(詳細)我必須做什么來簡化在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);
這是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<String, Object> model = new HashMap<String, Object>();
// 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")}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.