javaspringspring-mvcthymeleafspring-thymeleaf

springBoot + Thymeleaf: set Locale


I have this configutation that is working fine:

@Configuration
@EnableWebSecurity
@EnableMethodSecurity(securedEnabled = true, jsr250Enabled = true)
public class MvcConfig implements WebMvcConfigurer {

    private final MessageSource messageSource;

    public MvcConfig(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    @Bean
    public LocaleResolver localeResolver() {
        SessionLocaleResolver slr = new SessionLocaleResolver();
        slr.setDefaultLocale(Locale.ENGLISH);
        return slr;
    }

    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor() {
        LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
        lci.setParamName("lang");
        return lci;
    }

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

    @Override
    @Bean
    public LocalValidatorFactoryBean getValidator() {
        LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
        bean.setValidationMessageSource(messageSource);
        return bean;
    }
}

but when I try to set the locale like this:

 @PostMapping("/blogs")
    public String handleSubmit(@RequestParam("langCode") String langCode) {
        // Handle the selected option here
        if (FR_LANG.equalsIgnoreCase(langCode)) {
            LocaleContextHolder.setLocale(Locale.FRENCH);
        } else if (ES_LANG.equalsIgnoreCase(langCode)) {
            LocaleContextHolder.setLocale(new Locale.Builder().setLanguage("es").build());
        } else if (PT_LANG.equalsIgnoreCase(langCode)) {
            LocaleContextHolder.setLocale(new Locale.Builder().setLanguage("pt").build());
        } else {
            LocaleContextHolder.setLocale(Locale.ENGLISH);
        }

        // Redirect to a different page or return the same page
        return "redirect:/blogs";
    }

the locale is not set


Solution

  • The LocaleContextHolder will give you the current locale set, but not resolve a new one to use. Try the following:

    @PostMapping("/blogs")
    public String handleSubmit(@RequestParam("langCode") String langCode,
                               HttpServletRequest request,
                               HttpServletResponse response) {
    
        if (langCode!= null && !langCode.isBlank()) {
            LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
            if (localeResolver == null)
                throw new IllegalStateException("No LocaleResolver found");
    
            try {
                localeResolver.setLocale(request, response, StringUtils.parseLocale(langCode));
            } catch (IllegalArgumentException e) {
                logger.debug("Ignoring invalid locale value [{}]: {}", langCode, e.getMessage());
            }
        }
    
        return "redirect:/blogs";
    }
    

    StringUtils#parseLocale see documentation here will parse langCode according to language and region, thus possible values would be en_US, es_ES, de_DE, ... you get the idea ;) If you set a locale which your application doesn't support it will always fallback to the default, so need to worry about that.