Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Velocity/FreeMarker模板的电子邮件国际化_Java_Spring_Internationalization_Template Engine - Fatal编程技术网

Java 使用Velocity/FreeMarker模板的电子邮件国际化

Java 使用Velocity/FreeMarker模板的电子邮件国际化,java,spring,internationalization,template-engine,Java,Spring,Internationalization,Template Engine,如何使用模板引擎(如Velocity或FreeMarker)构建电子邮件正文来实现i18n 通常,人们倾向于创建以下模板: <h3>${message.hi} ${user.userName}, ${message.welcome}</h3> <div> ${message.link}<a href="mailto:${user.emailAddress}">${user.emailAddress}</a>. </div&g

如何使用模板引擎(如Velocity或FreeMarker)构建电子邮件正文来实现i18n

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

<h3>${message.hi} ${user.userName}, ${message.welcome}</h3>
<div>
   ${message.link}<a href="mailto:${user.emailAddress}">${user.emailAddress}</a>.
</div>
这就产生了一个基本问题:如果我的
.vm
文件变得很大,有很多行文本,那么在单独的资源包(
.properties
)文件中翻译和管理它们就会变得很乏味

我想做的是,为每种语言创建一个单独的
.vm
文件,比如
mytemplate\u en\u gb.vm、mytemplate\u fr\u fr.vm、mytemplate\u de\u de.vm
,然后告诉Velocity/Spring根据输入的语言环境选择正确的文件

这在春天可能吗?或者我应该看看更简单、更明显的替代方法吗


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

事实证明,使用一个模板和多个语言。属性文件胜过使用多个模板

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

如果您的电子邮件结构在多个
.vm
文件上重复,那么维护起来就更加困难了。此外,还必须重新发明资源束的回退机制。资源束尝试查找给定区域设置的最近匹配项。例如,如果区域设置为
en_GB
,它将尝试按顺序查找以下文件,如果没有可用的文件,则返回到最后一个文件

  • 语言属性
  • 语言属性
  • 语言属性
我将在这里发布(详细)我为简化Velocity模板中资源包的阅读所做的工作

在Velocity模板中访问资源束 弹簧配置


TemplateHelper类

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);
  }
公共类TemplateHelper{
私有静态最终XLogger记录器=XLoggerFactory.getXLogger(TemplateHelper.class);
私有消息源;
私人VelocityEngine VelocityEngine;
公共字符串合并(字符串模板位置、地图数据、区域设置){
logger.entry(模板位置、数据、区域设置);
如果(数据==null){
data=newhashmap();
}
如果(!data.containsKey(“消息”)){
data.put(“messages”,this.messageSource);
}
如果(!data.containsKey(“区域设置”)){
data.put(“locale”,locale);
}
字符串文本=
VelocityEngineUtils.mergeTemplateIntoString(this.velocityEngine,
模板(位置、数据);
logger.exit(文本);
返回文本;
}
}
速度模板

#parse("init.vm")
#msg("email.hello") ${user} / $user,
#msgArgs("email.message", [${emailId}]).
<h1>#msg("email.heading")</h1>
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);
${msg("subject.title")}
资源包

#parse("init.vm")
#msg("email.hello") ${user} / $user,
#msgArgs("email.message", [${emailId}]).
<h1>#msg("email.heading")</h1>
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);
${msg("subject.title")}
用法

#parse("init.vm")
#msg("email.hello") ${user} / $user,
#msgArgs("email.message", [${emailId}]).
<h1>#msg("email.heading")</h1>
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);
${msg("subject.title")}
Map data=newhashmap();
数据。put(“用户”、“Adarsh”);
data.put(“emailId”adarsh@email.com");
String body=templateHelper.merge(“send email.vm”、数据、区域设置);
以下是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));
}

自由标记模板

#parse("init.vm")
#msg("email.hello") ${user} / $user,
#msgArgs("email.message", [${emailId}]).
<h1>#msg("email.heading")</h1>
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);
${msg("subject.title")}

这是一篇非常有用的文章,但是,如果能够将模板值传递给国际化消息(如email.hello=hello{0},#parse(“init.vm”)#msg(“email.hello”$user.name),那就太好了,尽管我看不出原因了。@Ken谢谢。您节省了我的时间。也许有人会遇到同样的问题:如果您必须向getMessage发送多个参数,您可以使用$messages.getMessage($key,$parameters.toArray($arraySample),$locale),其中$arraySample已在数据映射中设置为data.put(“arraySample”,新对象[0]);我不知道这是否是最好的解决方案,但它确实起到了作用,因为默认情况下,Velocity将发送ArrayList而不是ArrayTanks。如果您想在模型级别上应用您的解决方案,在@ControllerAdvice-d类中只需放置:@Autowired private MessageResolverMethod mrm@ModelAttribute(“msg”)公共FormatDateTimeMethodModel formatDateTime(){return mrm;}哇,谢谢!最后,我用这段代码将我的模板缩减为一个。请注意,
TemplateMethodModel
现在已被弃用,建议改用
TemplateMethodModelEx
。此外,我必须通过
toString()
方法将参数转换为字符串,而不是使用显式
(String)
转换。