Search code examples
javaspringthymeleaf

Why does Thymeleaf International only works with ResourceBundleMessageSource


So in helping answer This question Thymeleaf + Spring (not Boot) - how to show messages from messageSource

I found that if you use the ReloadableResourceBundleMessageSource it wouldn't working. Thymeleaf would display ??app.name_pt_BR?? instead of the expected result.

@Bean(name = "messageSource")
public MessageSource messageSource() {

    ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
    messageSource.setBasename("/i18n/messages");
    messageSource.setFallbackToSystemLocale(false);
    messageSource.setCacheSeconds(0);
    messageSource.setDefaultEncoding("UTF-8");

    return messageSource;
}

when I switch to the below it worked as expected.

@Bean(name = "messageSource")
public MessageSource messageSource() {

    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    messageSource.setBasename("/i18n/messages");
    messageSource.setFallbackToSystemLocale(false);
    messageSource.setCacheSeconds(0);
    messageSource.setDefaultEncoding("UTF-8");

    return messageSource;
}

Why is the ReloadableResourceBundleMessageSource not able to be use?

adding code for this question: GitHub


Solution

  • Found the answer!

    Per the javadocs for ReloadableResouceBundleMessageSource

    Spring-specific MessageSource implementation that accesses resource bundles using specified basenames, participating in the Spring ApplicationContext's resource loading. In contrast to the JDK-based ResourceBundleMessageSource, this class uses Properties instances as its custom data structure for messages, loading them via a PropertiesPersister strategy from Spring Resource handles. This strategy is not only capable of reloading files based on timestamp changes, but also of loading properties files with a specific character encoding. It will detect XML property files as well.

    Note that the basenames set as "basenames" property are treated in a slightly different fashion than the "basenames" property of ResourceBundleMessageSource. It follows the basic ResourceBundle rule of not specifying file extension or language codes, but can refer to any Spring resource location (instead of being restricted to classpath resources). With a "classpath:" prefix, resources can still be loaded from the classpath, but "cacheSeconds" values other than "-1" (caching forever) might not work reliably in this case.

    For a typical web application, message files could be placed into WEB-INF: e.g. a "WEB-INF/messages" basename would fine a "WEB-INF/messages.properties", "WEB-INF/messages_en.properties" etc arrangement as well as "WEB-INF/messages.xml", "WEB-INF/messages_en.xml" etc. Note that message definitions in a previous resource bundle will override ones in a later bundle, due to sequential lookup.

    This MessageSource can easily be used outside of an ApplicationContext: It will use a DefaultResourceLoader as default, simply getting overridden with the ApplicationContext's resource loader if running in a context. It does not have any other specific dependencies.

    so the fix is to provide the path.

    from

    @Bean
    public MessageSource messageSource()
    {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename("messages");
        messageSource.setFallbackToSystemLocale(false);
        messageSource.setCacheSeconds(0);
        messageSource.setDefaultEncoding("UTF-8");
        return messageSource;
    }
    

    to includeing the path on setBasename()

    @Bean
    public MessageSource messageSource()
    {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename("classpath:messages");
        messageSource.setFallbackToSystemLocale(false);
        messageSource.setCacheSeconds(0);
        messageSource.setDefaultEncoding("UTF-8");
        return messageSource;
    }