SpringBoot-thymeleaf 基于数据库国际化

251 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第20天,点击查看活动详情

Spring配置

配置拦截器及语言环境解析

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Bean
    public LocaleResolver localeResolver() {
        //设置cookie模式处理国际化
        CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver();
        cookieLocaleResolver.setDefaultLocale(Locale.CHINESE);
        return cookieLocaleResolver;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //指定国际化标识
        LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
        localeChangeInterceptor.setParamName("lang");
        registry.addInterceptor(localeChangeInterceptor);
    }
}
  • LocaleResolver:指定存储本地化标识的处理类,这里使用的是cookie,还可以使用SessionLocaleResolver,AcceptHeaderLocaleResolver这个是依据请求头中language指定即浏览器语言,不支持修改。
  • LocaleChangeInterceptor:指定语言设置参数名称默认为locale

配置国际化数据源

@Component("messageSource")
public class DBMessageSource extends AbstractMessageSource {
    // 自定义service
    @Autowired
    private LanguageRepository languageRepository;
    // 2.国际化处理方法依据key在数据库中查找对应国际化内容
    @Override
    protected MessageFormat resolveCode(String key, Locale locale) {
        LanguageEntity message = languageRepository.findByKeyAndLocale(key,locale.getLanguage());
        if (message == null) {
            message = languageRepository.findByKeyAndLocale(key,Locale.getDefault().getLanguage());
        }
        return new MessageFormat(message.getContent(), locale);
    }

    //3.新增方法,用于后端传参国际化
    public final String getMessage(String code, @Nullable Object[] args) throws NoSuchMessageException {
        Locale locale = LocaleContextHolder.getLocale();
        String msg = getMessageInternal(code, args, locale);
        if (msg != null) {
            return msg;
        }
        String fallback = getDefaultMessage(code);
        if (fallback != null) {
            return fallback;
        }
        throw new NoSuchMessageException(code, locale);
    }
}
  • messageSource为spring上下文中,国际化资源处理bean固定名称,需覆盖默认配置。
  • AbstractMessageSource:抽象资国际化资源处理类,下面子类中就有我们常用的配置文件支持ResourceBundleMessageSource,ReloadableResourceBundleMessageSource
  • LocaleContextHolder:使用ThreadLocal存储上下文中国际化标识,还存储了时区信息
  • args:这里的参数也是支持国际化的,最终会使用MessageFormat.format来格式化

thymeleaf 页面使用

<h2 th:text="#{home.welcome('xxx')}"></h2>
<p th:text="#{home.info}"></p>
<p th:text="#{home.changelanguage}"></p>
<ul>
    <li><a href="?lang=en" th:text="#{home.lang.en}"></a></li>
    <li><a href="?lang=de" th:text="#{home.lang.de}"></a></li>
    <li><a href="?lang=zh" th:text="#{home.lang.zh}"></a></li>
</ul>

参数传递为#{key(参数……)}

遗留问题:

  1. Thymeleaf中[[]]为转义符导致在js代码中使用国际化并不方便,需将国际化内容定义与js业务代码分开。
  2. 如何整合现在流行的前端国际化库使用动态国际化资源,如i18next。

参考资料

zhangjiaheng.cn/blog/201903…

github.com/PhraseApp-B…