Search code examples
javaspringjakarta-eespring-mvcspring-roo

Spring MVC ResourceBundleMessageSource XML configuration


I would like to mimic the Grails way of resolving i18n messages.

In WEB-INF/i18n/ I have the following directories:

admin/messages_EN.properties

admin/messages_FR.properties

website/messages_EN.properties

website/messages_FR.properties

please ignore the language endings ( EN and FR ) in this example

in my xml configuration I currently have:

<!-- Register the welcome.properties -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
  <property name="defaultEncoding" value="utf-8" />
  <property name="basename" value="/WEB-INF/i18n/" />
</bean>

What I am looking for here, is a way to tell Spring to look for .properties files under i18n but without explicitly telling it what each subdirectory is. That is without a list of basenames that points to /WEB-INF/i18n/admin/ and /WEB-INF/i18n/website/

I want the WEB-INF/i18n/ directory to be dynamic, and that bundles ( directories ) can be created without having to remodify the xml configuration file.

I am not trying to solve this particular example with admin and website sub directories

Is this possible?

Thanks!


Solution

  • Here is the solution:

    package com.mypackage.core.src;
    
    import java.io.File;
    import java.util.ArrayList;
    
    import javax.servlet.ServletContext;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.support.ReloadableResourceBundleMessageSource;
    
    public class UnderDirectoryReloadableResourceBundleMessageSource extends ReloadableResourceBundleMessageSource {
    
        @Autowired
        ServletContext servletContext;
    
        public void setWorkingDirectory(String directoryPath) {
            File rootDir = new File( servletContext.getRealPath(directoryPath) );
            ArrayList<String> baseNames = new ArrayList<String>();
            iterateScanDirectoryAndAddBaseNames(baseNames, rootDir);
            setBasenames(baseNames.toArray(new String[baseNames.size()]));
        }
    
        private void iterateScanDirectoryAndAddBaseNames(ArrayList<String> baseNames, File directory) {
            File[] files = directory.listFiles();
    
            for (File file : files) {
                if (file.isDirectory()) {
                    iterateScanDirectoryAndAddBaseNames(baseNames, file);
                } else {
                    if (file.getName().endsWith(".properties")) {
                        String filePath = file.getAbsolutePath().replaceAll("\\\\", "/").replaceAll(".properties$", "");
                        filePath = filePath.substring(filePath.indexOf("/WEB-INF/"), filePath.length());
                        baseNames.add(filePath);
                        System.out.println("Added file to baseNames: " + filePath);
                    }
                }
            }
        }
    
    }
    

    XML config:

    <bean id="messageSource" class="com.mypackage.core.src.UnderDirectoryReloadableResourceBundleMessageSource">
      <property name="defaultEncoding" value="utf-8" />
      <property name="workingDirectory" value="/WEB-INF/webspring/i18n" />
      <property name="cacheSeconds" value="3" />
      <property name="fallbackToSystemLocale" value="false" />
    </bean>
    

    Enjoy!