Spring MessageSource回退到显式语言环境

时间:2018-03-29 16:51:58

标签: java spring spring-boot

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.9.RELEASE</version>
</parent>

在某些弹簧启动应用程序中,使用了i18n。这是配置:

@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;
}

要求从标题Accept-language获取区域设置,如果符合以下情况,则返回“en”:

  • 标题丢失,
  • 标题有错误的值,
  • 区域设置缺少配置。

通过提供LocaleResolver解决了两个第一点(请参阅配置)。但是,我不知道如何实现第3点:翻译配置的可重新加载列表被封装在ReloadableResourceBundleMessageSource中,我看不出如何使它在某些缺席配置上回退到“en”语言环境。 / p>

setFallbackToSystemLocale选项,但系统区域设置!=“en”区域设置。此外,MessageSource仅使用系统区域设置来解析翻译配置中的令牌,而不是用于本地化消息本身,这会导致与本地化数字不一致。

我可能会尝试在setSupportedLocales上使用LocaleResolver来限制支持的语言环境列表,但在我的情况下它不适合,因为翻译配置列表应该在运行时更改。

有没有办法让ReloadableResourceBundleMessageSource回退到显式区域设置?

2 个答案:

答案 0 :(得分:2)

通过在MessageSource周围编写包装来解决这个问题。它并不完全是所要求的:如果请求的令牌不存在,则将使用后备区域设置(这与“配置不存在”接近但不相同)。此外,它吞下异常并将其用于流量控制,这是不好的。

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);
        }
    }
}

答案 1 :(得分:1)

从Spring 5.2.2开始,这是可能的,请参阅This spring-framework commit