4

After making some tests, it looks ReloadableResourceBundleMessageSource does not support wildcards.

Let's suppose bundle files are located in resources and have the following names: messages.properties, messages_fr.properties, etc.

This base name works:

setBasename("classpath:/messages");

This one doesn't

setBasename("classpath*:/messages*");

So, what can I do to load every property files matching a given pattern?

Remark: I need to use this implementation of ReloadableResourceBundleMessageSource as I would like to expose every properties of a given locale at REST level...to be usable by Angular translate on client side as explained here.

Some ideas? Many thanks.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
  • Why? The correct `messages.properties` is loaded based on the locale of the current user. So what you are trying is already done automatically... – M. Deinum Jan 11 '16 at 18:53
  • Wildcard need to be used as my application is modular and multiple messages.properties are defined in these modules. For the moment, only one is taken into account. It looks it's the last one to be loaded. The current implementation suppose we have all properties defined in the same file. – François Rosière Jan 12 '16 at 08:25
  • That is how a `ResourceBundle` works. – M. Deinum Jan 12 '16 at 08:38
  • So, just to be clear, no way to have properties splitted in multiple files using this implementation of message source? – François Rosière Jan 12 '16 at 08:57

1 Answers1

3

As explained on this post, the refreshProperties method of ReloadableResourceBundleMessageSource could be overriden to allow loading of multiple resources from classpath and corresponding to the given pattern

Let's take a concrete example using most of the Spring boot defaults:

public class BaseReloadableResourceBundleMessageSource extends ReloadableResourceBundleMessageSource
    implements InitializingBean {

private static final String PROPERTIES_SUFFIX = ".properties";

private final PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

private final Charset encoding = Charset.forName("UTF-8");

@Autowired
private Environment environment;

/**
 * Returns the resource bundle corresponding to the given locale.
 */
public Properties getResourceBundle(Locale locale) {
    clearCacheIncludingAncestors();
    return getMergedProperties(locale).getProperties();
}

@Override
public void afterPropertiesSet() {
    setBasename("classpath*:/" + environment.getProperty("spring.messages.basename", "messages"));
    setDefaultEncoding(environment.getProperty("spring.messages.encoding", encoding.name()));
    setCacheSeconds(environment.getProperty("spring.messages.cache-seconds", int.class, -1));
    setFallbackToSystemLocale(environment.getProperty("spring.messages.fallback-to-system-locale",
            boolean.class, true));
}

@Override
protected PropertiesHolder refreshProperties(String filename, PropertiesHolder propHolder) {
    final Properties properties = new Properties();
    long lastModified = -1;
    try {
        for (Resource resource : resolver.getResources(filename + PROPERTIES_SUFFIX)) {
            final PropertiesHolder holder = super.refreshProperties(cleanPath(resource), propHolder);
            properties.putAll(holder.getProperties());
            if (lastModified < resource.lastModified())
                lastModified = resource.lastModified();
        }
    } catch (IOException ignored) {
        // nothing to do
    }
    return new PropertiesHolder(properties, lastModified);
}

private String cleanPath(Resource resource) throws IOException {
    return resource.getURI().toString().replace(PROPERTIES_SUFFIX, "");
}

}

Community
  • 1
  • 1