大数据、Java EE 学习资料请关注 B 站:https://space.bilibili.com/204792350

SpringBoot 处理国际化相关,搭配 Thymeleaf 模板引擎

简介

通俗的讲,将一个页面里面的内容抽取出来,分类的创建一个个资源包, 这些资源包分别对应着不同国家的语言,在需要的时候,会根据条件来切换目标的资源包。

在 SpringBoot 中,搭配 Thymeleaf 模板引擎,可以识别浏览器语言,自动切换资源包。

使用

单纯的 SpringMVC 需要完成以下几步:

  • 编写国际化配置文件
  • 使用 ResourceBundleMessageSource 管理国际化资源文件
  • 在页面使用 fmt:message 取出国际化内容

SpringBoot 国际化

现在在 SpringBoot 中,不需要另外的手动配置,内置了自动配置。

在 SpringBoot 中,简化了步骤:

  • 编写国际化资源包
  • 使用国际化内容

国际化资源包

国际化资源包文件必须是:.properties 后缀,同时在 IDEA 中,也有相应的可视化支持。

  • 在项目的 resources 目录创建一个:i18n 目录,存放资源包
  • 创建 Resource Bundle 文件
    • 这种文件,IDEA 支持可视化编辑
      Snipaste_2020-05-23_13-08-50

使用国际化内容

搭配 Thymeleaf 模板引擎,可以使用特定的语法从资源包中获取对应内容。

<form class="form-signin" action="dashboard.html">
    <h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}"></h1>
    <label class="sr-only" th:text="#{login.user}"></label>
    <input type="text" class="form-control" th:placeholder="#{login.user}" required="" autofocus="">
    <label class="sr-only" th:text="#{login.password}"></label>
    <input type="password" class="form-control" th:placeholder="#{login.password}" required="">
    <div class="checkbox mb-3">
        <label>
            <input type="checkbox" value="remember-me"> [[#{login.remember}]]
        </label>
    </div>
    <button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.sign}"></button>
</form>

#{...}:Thymeleaf 模板引擎国际化语法,花括号里面是资源包里面的键。

就这样简单的使用,根据浏览器的语言,来自动切换,当然若是没有匹配的资源包,则使用默认的,也就是不在任何后缀的资源包。

自动配置类

SpringBoot 自动配置文件类:org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration

@Bean
public MessageSource messageSource(MessageSourceProperties properties) {
    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    if (StringUtils.hasText(properties.getBasename())) {
        messageSource.setBasenames(StringUtils.commaDelimitedListToStringArray(
            StringUtils.trimAllWhitespace(properties.getBasename()))
        );
    }
    if (properties.getEncoding() != null) {
        messageSource.setDefaultEncoding(properties.getEncoding().name());
    }
    messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale());
    Duration cacheDuration = properties.getCacheDuration();
    if (cacheDuration != null) {
        messageSource.setCacheMillis(cacheDuration.toMillis());
    }
    messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat());
    messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage());
    return messageSource;
}

其中,特别需要注意的一点是:

messageSource.setBasenames(StringUtils.commaDelimitedListToStringArray(
            StringUtils.trimAllWhitespace(properties.getBasename()))
);

这行代码表示,设置一个基础名,也就是资源包去除其他后缀名,剩下的相同的部分,如:

Snipaste_2020-05-23_13-08-50

前面的 messages 就是基础名,可以通过在配置文件中设置,例如资源包在:resoureces/i18n

spring.messages.basename=i18n/basename

必须要带上目录名称,否则找不到对应的资源包。

自定义国际化

下面我们自定义区域解析器,这里是根据你的定制规则实现的,我的定制规则是将国际化信息放在了请求中。

切换国际化的两个按钮

<a class="btn btn-sm" th:href="@{/index.html(l='zh_CN')}">中文</a>
<a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>

自定义解析器:

package com.huasio.learning.demo.component;

import org.springframework.util.StringUtils;
import org.springframework.web.servlet.LocaleResolver;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;

/**
 * @author yu
 */
public class UserLocaleResolver implements LocaleResolver {

    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        System.out.println(123);
        // 1. 获取到区域信息
        String l = request.getParameter("l");
        // 2. 获取系统默认的区域信息或者请求头区域信息
        Locale locale = Locale.getDefault();
        // 3. 创建一个自定义区域对象
        if (!StringUtils.isEmpty(l)) {
            String[] split = l.split("_");
            locale = new Locale(split[0], split[1]);
        }

        return locale;
    }

    @Override
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
        throw new UnsupportedOperationException(
                "Cannot change HTTP accept header - use a different locale resolution strategy");
    }
}

注册组件:

@Bean(name = "localeResolver")
public LocaleResolver localeResolver() {
    return new UserLocaleResolver();
}

可以使用 @Bean 其中 name 的属性,来设置 bean id。

注意:方法名一定是 localeResolver,否则是无法匹配到的。

配置

配置项描述
spring.messages.basename设置资源包的基础文件名称,该名称是资源包前缀。
以逗号分隔的 basenames 列表(本质上是一个完全限定的类路径位置)。
每个都遵循ResourceBundle 约定,并且放宽了对基于斜杠的位置的支持。
如果它不包含包限定符(例如“org.mypackage”),它将从类路径根解析。
spring.messages.encoding资源包编码。
spring.messages.always-use-message-format是否始终应用MessageFormat规则,甚至在不带参数的情况下解析消息。
spring.messages.cache-duration加载的资源包文件缓存持续时间。当未设置时,包将被永久缓存。如果没有指定持续时间后缀,将使用秒。
spring.messages.fallback-to-system-locale如果没有找到特定语言环境的文件,是否退回到系统语言环境。如果这是关闭的,唯一的备份将是默认文件。”messages.properties“ 用于 basename “messages”)。
spring.messages.use-code-as-default-message是否使用消息代码作为默认消息,而不是抛出“NoSuchMessageException”。只建议在开发期间使用。
# Java   SpringBoot   Thymeleaf  

评论

公众号:mumuser

企鹅群:932154986

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×