Reputation: 1217
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
In some spring boot application, i18n is used. Here is the config:
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename(translationsPath);
messageSource.setDefaultEncoding("UTF-8");
messageSource.setFallbackToSystemLocale(false);
messageSource.setCacheSeconds(5);
return messageSource;
}
@Bean
public LocaleResolver localeResolver() {
AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
localeResolver.setDefaultLocale(Locale.ENGLISH);
return localeResolver;
}
There is a requirement to obtain a locale from header Accept-language
, falling back to "en" if:
Two first points are resolved by provided LocaleResolver
(see config). However, I don't know how to implement point 3: the reloadable list of translation configs is encapsulated in ReloadableResourceBundleMessageSource
, and I see no way how to make it fall back to "en" locale on some absent config.
There is setFallbackToSystemLocale
option, but system locale != "en" locale. Moreover, MessageSource
uses system locale only to resolve the token from translation config, not for localizing the message itself, which causes discrepancies with localizing the numbers.
I might try to limit the list of supported locales by using setSupportedLocales
on LocaleResolver
, but it is not suitable solution in my case, since the list of translation configs is supposed to change in runtime.
Is there a way to make ReloadableResourceBundleMessageSource
fallback to explicit locale?
Upvotes: 3
Views: 4990
Reputation: 8570
There is an useful config spring.messages.use-code-as-default-message. When it's true case the code message cannot be found: <spring:message code="not_found_label"/> the tag will render the code as default message.
Whether to fall back to the system Locale if no files for a specific Locale have been found. if this is turned off, the only fallback will be the default file (e.g. "messages.properties" for basename "messages").
Here is the official complete core properties that can be used with spring application
Here the official docs about <spring:message code="code" text="fallback text"/> It's also possible define a fallback text on text param.
in properties - application.properties
spring.messages.use-code-as-default-message=true
in YML format - application.yml
spring:
messages:
use-code-as-default-message: true
Or a configuration bean:
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setUseCodeAsDefaultMessage(true);
return messageSource;
}
Upvotes: 1
Reputation: 1440
Starting with Spring 5.2.2, this will be possible, see This spring-framework commit
Upvotes: 2
Reputation: 1217
Solved that in a bit dirty way by writing a wrapper around MessageSource
. It is not exactly what was requested: the fallback locale will be used if the token for requested one is absent (which is close but not the same as "config was absent"). Also, it swallows exceptions and uses them for flow control, which is not good.
final class FallbackMessageSource implements MessageSource {
private final MessageSource delegate;
private final Locale fallbackLocale;
public FallbackMessageSource(MessageSource delegate, Locale fallbackLocale) {
this.delegate = delegate;
this.fallbackLocale = fallbackLocale;
}
@Override
public String getMessage(String code, Object[] args, String defaultMessage, Locale locale) {
try {
return delegate.getMessage(code, args, defaultMessage, locale);
} catch(NoSuchMessageException ex) {
return delegate.getMessage(code, args, defaultMessage, fallbackLocale);
}
}
@Override
public String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException {
try {
return delegate.getMessage(code, args, locale);
} catch(NoSuchMessageException ex) {
return delegate.getMessage(code, args, fallbackLocale);
}
}
@Override
public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException {
try {
return delegate.getMessage(resolvable, locale);
} catch(NoSuchMessageException ex) {
return delegate.getMessage(resolvable, fallbackLocale);
}
}
}
Upvotes: 4