Search code examples
javaspring-bootthymeleafspring-thymeleaf

Set Thymeleaf language using session attribute


I am failing to solve a seemingly easy problem.

  • Whenever a session is opened (session.user_lang is null), English is used as the default language (messages.properties). A (registered) user can change the language in which case the language is saved to the session attribute (session.user_lang) and to the database.
  • Thymeleaf should check session.user_lang and translate based on that value.

I couldn't get it to work for a long time. I have tried defining

@Component
public class LocaleInterceptor implements HandlerInterceptor {

    private LocaleResolver localeResolver;

    @Autowired
    public void setLocaleResolver(LocaleResolver localeResolver) {
        this.localeResolver = localeResolver;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();
        String language = (String) session.getAttribute("user_lang");
        if (language != null) {
            Locale locale = new Locale(language);
            localeResolver.setLocale(request, response, locale);
        }
        return true;
    }
}

and

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    private LocaleInterceptor localeInterceptor;

    @Autowired
    public void setLocaleInterceptor(LocaleInterceptor localeInterceptor) {
        this.localeInterceptor = localeInterceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(localeInterceptor);
    }
}

Solution

  • Spring provides several implementations of the LocaleResolver one of them is the SessionLocaleResolver. The SessionLocaleResolver uses, as the name implies, the HttpSession to store the Locale to be used. Just what you want. So instead of writing your own, you can simply use the SessionLocaleResolver.

    @Bean
    public LocaleResolver localeResolver() {
      SessionLocaleResolver localResolver = new SessionLocaleResolver();
      localeResolver.setLocaleAttributeName("user_locale"); // Not strictly needed
      localeResolver.setDefaultLocale(Locale.ENGLISH);
      return localResolver;
    };
    

    The SessionLocaleResolver also allows the Locale to be changed by the user (if desired). You can achieve this by configuring the LocaleChangeInterceptor which will, when requested, store the new Locale in the HttpSession (it actually delegates this to the LocaleResolver that is configured).

    All in all there is no need to write custom code all is supported out-of-the-box.