Spring Boot和Freemarker国际化无法在电子邮件中起作用

发布于 2025-02-04 03:31:00 字数 5737 浏览 3 评论 0原文

我正在使用Spring Boot(2.5.2)和FreeMarker将电子邮件发送给用户。它在没有添加任何国际化支持的情况下工作正常,但是我今天尝试添加它,但它不起作用。由于某种原因,Spring.ftl抱怨它无法在我的消息中找到属性。

以下是我的配置文件

@Configuration
public class CommonConfiguration implements WebMvcConfigurer {

    @Bean
    public LocaleResolver localeResolver() {
        AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
        localeResolver.setDefaultLocale(Locale.US);
        return localeResolver;
    }

    @Override
    public void addInterceptors(final InterceptorRegistry registry) {
        final LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
        localeChangeInterceptor.setParamName("lang");
        registry.addInterceptor(localeChangeInterceptor);
    }

    @Bean(name = "messageSource")
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource ms = new ReloadableResourceBundleMessageSource();
        ms.setBasenames("classpath:i18n/messages");
        ms.setDefaultEncoding("UTF-8");
        ms.setCacheSeconds(3600);
        return ms;
    }

}

application.yml file(对于春季freemarker设置)

spring:
  profiles:
    active: dev
  autoconfigure:
    exclude: org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
  freemarker:
    settings:
      auto_import: /spring.ftl as spring

我的邮件.ftl文件,此行引起了问题

<@spring.message "email.common.logo.alt.txt"/>

我已经验证了此文本是否存在当我使用 messagesource.getMessage(“ email.common.logo.alt.txt”,null,localecontextholder.getlocale())在我的Java代码中时,我可以访问相应的值。

错误日志

2022-06-03 16:08:48.590 ERROR 67685 --- [         task-2] f.runtime                                : Error executing FreeMarker template

freemarker.core.InvalidReferenceException: The following has evaluated to null or missing:
==> springMacroRequestContext  [in template "spring.ftl" at line 28, column 24]

----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----

----
FTL stack trace ("~" means nesting-related):
    - Failed at: ${springMacroRequestContext.getMessag...  [in template "spring.ftl" in macro "message" at line 28, column 22]
    - Reached through: @spring.message "email.common.logo.al...  [in template "emails/layout/email-header.ftl" at line 3, column 109]
    - Reached through: #include "email-header.ftl"  [in template "emails/layout/email-layout.ftl" in macro "generalEmailLayout" at line 72, column 8]
    - Reached through: @layout.generalEmailLayout headInclud...  [in template "emails/user-management/mail.ftl" at line 2, column 1]
----
    at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:134) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.UnexpectedTypeException.newDescriptionBuilder(UnexpectedTypeException.java:85) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.UnexpectedTypeException.<init>(UnexpectedTypeException.java:48) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.NonHashException.<init>(NonHashException.java:49) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Dot._eval(Dot.java:48) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Expression.eval(Expression.java:101) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.MethodCall._eval(MethodCall.java:55) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Expression.eval(Expression.java:101) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.BuiltInsForOutputFormatRelated$AbstractConverterBI.calculateResult(BuiltInsForOutputFormatRelated.java:50) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.MarkupOutputFormatBoundBuiltIn._eval(MarkupOutputFormatBoundBuiltIn.java:40) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Expression.eval(Expression.java:101) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.DollarVariable.calculateInterpolatedStringOrMarkup(DollarVariable.java:100) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.DollarVariable.accept(DollarVariable.java:63) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Environment.visit(Environment.java:383) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Environment.invokeMacroOrFunctionCommonPart(Environment.java:889) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Environment.invokeMacro(Environment.java:825) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.UnifiedCall.accept(UnifiedCall.java:84) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Environment.visit(Environment.java:347) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Environment.visit(Environment.java:353) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Environment.include(Environment.java:2955) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Include.accept(Include.java:171) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Environment.visit(Environment.java:383) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Environment.invokeMacroOrFunctionCommonPart(Environment.java:889) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Environment.invokeMacro(Environment.java:825) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.UnifiedCall.accept(UnifiedCall.java:84) ~[freemarker-2.3.31.jar:2.3.31]

I'm using Spring Boot (2.5.2) and Freemarker to send the emails to the users. It's working fine without adding any internationalization support but I tried adding it today and it didn't work. For some reason, spring.ftl is complaining that it's not able to find the property in my message.properties file.

Below is my configuration file

@Configuration
public class CommonConfiguration implements WebMvcConfigurer {

    @Bean
    public LocaleResolver localeResolver() {
        AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
        localeResolver.setDefaultLocale(Locale.US);
        return localeResolver;
    }

    @Override
    public void addInterceptors(final InterceptorRegistry registry) {
        final LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
        localeChangeInterceptor.setParamName("lang");
        registry.addInterceptor(localeChangeInterceptor);
    }

    @Bean(name = "messageSource")
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource ms = new ReloadableResourceBundleMessageSource();
        ms.setBasenames("classpath:i18n/messages");
        ms.setDefaultEncoding("UTF-8");
        ms.setCacheSeconds(3600);
        return ms;
    }

}

application.yml file (for spring freemarker setup)

spring:
  profiles:
    active: dev
  autoconfigure:
    exclude: org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
  freemarker:
    settings:
      auto_import: /spring.ftl as spring

In my mail.ftl file, this line is causing the issue

<@spring.message "email.common.logo.alt.txt"/>

I've verified that this text exists and when I use the messageSource.getMessage("email.common.logo.alt.txt", null, LocaleContextHolder.getLocale()) in my java code, I can access the corresponding value.

Error log

2022-06-03 16:08:48.590 ERROR 67685 --- [         task-2] f.runtime                                : Error executing FreeMarker template

freemarker.core.InvalidReferenceException: The following has evaluated to null or missing:
==> springMacroRequestContext  [in template "spring.ftl" at line 28, column 24]

----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----

----
FTL stack trace ("~" means nesting-related):
    - Failed at: ${springMacroRequestContext.getMessag...  [in template "spring.ftl" in macro "message" at line 28, column 22]
    - Reached through: @spring.message "email.common.logo.al...  [in template "emails/layout/email-header.ftl" at line 3, column 109]
    - Reached through: #include "email-header.ftl"  [in template "emails/layout/email-layout.ftl" in macro "generalEmailLayout" at line 72, column 8]
    - Reached through: @layout.generalEmailLayout headInclud...  [in template "emails/user-management/mail.ftl" at line 2, column 1]
----
    at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:134) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.UnexpectedTypeException.newDescriptionBuilder(UnexpectedTypeException.java:85) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.UnexpectedTypeException.<init>(UnexpectedTypeException.java:48) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.NonHashException.<init>(NonHashException.java:49) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Dot._eval(Dot.java:48) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Expression.eval(Expression.java:101) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.MethodCall._eval(MethodCall.java:55) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Expression.eval(Expression.java:101) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.BuiltInsForOutputFormatRelated$AbstractConverterBI.calculateResult(BuiltInsForOutputFormatRelated.java:50) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.MarkupOutputFormatBoundBuiltIn._eval(MarkupOutputFormatBoundBuiltIn.java:40) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Expression.eval(Expression.java:101) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.DollarVariable.calculateInterpolatedStringOrMarkup(DollarVariable.java:100) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.DollarVariable.accept(DollarVariable.java:63) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Environment.visit(Environment.java:383) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Environment.invokeMacroOrFunctionCommonPart(Environment.java:889) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Environment.invokeMacro(Environment.java:825) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.UnifiedCall.accept(UnifiedCall.java:84) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Environment.visit(Environment.java:347) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Environment.visit(Environment.java:353) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Environment.include(Environment.java:2955) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Include.accept(Include.java:171) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Environment.visit(Environment.java:383) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Environment.invokeMacroOrFunctionCommonPart(Environment.java:889) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.Environment.invokeMacro(Environment.java:825) ~[freemarker-2.3.31.jar:2.3.31]
    at freemarker.core.UnifiedCall.accept(UnifiedCall.java:84) ~[freemarker-2.3.31.jar:2.3.31]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文