Spring Boot and Freemarker internationalization is not working in the email

714 views Asked by At

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]
0

There are 0 answers