spring boot + thymeleaf 3 国际化

** 原创文章,请勿转载 **

在给spring boot 1.5.6 + thymeleaf 3进行国际化时,踩了一个坑(其实不止一个)。 现象:

看到了吧, 就是取值的key, 后面被加了_en_US 或 _zh_CN, 以及前后的问号。

先看下代码,首先两个资源文件:

messages_en_US.properties

page.content=this is a test string.

message_zh_CN.properties, 在eclipse里找开的,内容是: 这是一个测试字符串

page.content=\u8FD9\u662F\u4E00\u4E2A\u6D4B\u5B57\u7B26\u4E32\u3002

i18n.html:

<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <h1>spring boot, thymeleaf 3 国际化</h1>
       <hr>
    <a href="/i18n?lang=en_US">English</a> | <a href="/i18n?lang=zh_CN">中文</a>

    <br>
    <br>
    <br>
    <br>
    from thymeleaf engine:      <span th:text="#{page.content}"></span>
    <br>
    <br>
    from controller model:      <span th:text="${content}"></span>
</body>
</html>

其中, #{page.content} 来源于thymeleaf 3,  ${content} 则由controller的Model返回,代码是hardcode, 返回的都是中文

controller:

@Controller
public class I18nController {
    @Autowired
    private MessageSource messageSource;

    @GetMapping("/i18n")
    public String i18n(Model model) {
        String message = messageSource.getMessage("page.content", null, Locale.SIMPLIFIED_CHINESE);
        System.out.println("message=" + message);
        model.addAttribute("content", message);
        return "/i18n";
    }
}

从现象看, ${content}这个是没有问题的, 也就是controller里messageSource.getMessage() 是正常的,再也就是说,资源文件是成功加载的,可见,问题出在thymeleaf 3.

再看下thymeleaf 3的配置:

@Configuration
public class ThymeleafConfig implements ApplicationContextAware {
    private static final String UTF8 = "UTF-8";
    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    private SpringResourceTemplateResolver htmlTemplateResolver() {
        SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
        templateResolver.setApplicationContext(this.applicationContext);
        templateResolver.setPrefix("classpath:/templates/");
        templateResolver.setSuffix(".html");
        templateResolver.setTemplateMode(TemplateMode.HTML);
        templateResolver.setCacheable(false);
        templateResolver.setCharacterEncoding("UTF-8");
        return templateResolver;
    }

    @Autowired
    private MessageSource messageSource;

    // 如果显示 ??x_zh_CN??, 缺少spring-context-support
    private SpringTemplateEngine templateEngine(SpringResourceTemplateResolver templateResolver) {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver);
        templateEngine.setEnableSpringELCompiler(false); 

        return templateEngine;
    }

    @Bean
    public ViewResolver htmlViewResolver(SpringTemplateEngine templateEngine) {
        ThymeleafViewResolver resolver = new ThymeleafViewResolver();
        resolver.setApplicationContext(applicationContext);
        resolver.setTemplateEngine(templateEngine(htmlTemplateResolver()));
        resolver.setCharacterEncoding("UTF-8");
        return resolver;
    }

}

** 临时补一句,国际化要spring-context-support包的支持。

web的配置:

@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {

    @Bean
    public LocaleResolver localeResolver() {
        SessionLocaleResolver slr = new SessionLocaleResolver();
        // 默认语言
        slr.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
        return slr;
    }

    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor() {
        LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
        // 参数名
        lci.setParamName("lang");
        return lci;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(localeChangeInterceptor());
    }

// 这个MessageSource可有可无,spring boot默认是有一个的。 // 如果没有自定义messageSource, 要有一个messages.properties文件。// 如果有这个定义, 就不需要messages.properites
//    @Bean
//    public ResourceBundleMessageSource messageSource() {
//        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
//        messageSource.setBasename("messages");
//        return messageSource;
//    }
}

查找原因, 在thymeleaf.org上看到这样一段:(在线文档3.1: Using th:text and externalizing text)

thymeleaf叫外部文本,无论是在外部的文件里,或者是在数据库,当然国际化使用的是外部文件。

从这段信息看, thymeleaf使用IMessageResolver接口来加载外部文本的,而且有一个标准的实现:

org.thymeleaf.messageresolver.StandardMessageResolver,所以加载.properties文件应该是和这些信息相关。

但 thymeleaf-spring4 里是怎么用的呢,看下代码吧:

org.thymeleaf.spring4.messageresolver.SpringMessageResolver:

    private final StandardMessageResolver standardMessageResolver;
    private MessageSource messageSource;

    public SpringMessageResolver() {
        super();
        this.standardMessageResolver = new StandardMessageResolver();
    }

它就是使用 org.thymeleaf.messageresolver.StandardMessageResolver, 这样看来,我只要在模板引擎的设置里加上这个IMessageResolver的实现即可,新的代码是这样:

private SpringTemplateEngine templateEngine(SpringResourceTemplateResolver templateResolver) {
        SpringTemplateEngine  templateEngine  = new SpringTemplateEngine();
        SpringMessageResolver messageResolver = new SpringMessageResolver();  //
        messageResolver.setMessageSource(messageSource);                      // 加入这三行,即为解决方案
        templateEngine.setMessageResolver(messageResolver);                   //
        templateEngine.setTemplateResolver(templateResolver);
        templateEngine.setEnableSpringELCompiler(false);
        return templateEngine;
}

最终呈现:

时间: 2024-08-05 23:01:23

spring boot + thymeleaf 3 国际化的相关文章

spring boot Thymeleaf模板引擎 最简单输出例子

spring boot  Thymeleaf模板引擎  最简单输出例子 控制器代码如下: @GetMapping(value = "/test")public String test(Model model){ List<Boy> boy = new ArrayList<Boy>(); boy.add(new Boy("xx",11)); boy.add(new Boy("yy",22)); boy.add(new Boy

Spring Boot Thymeleaf 模板引擎的使用

Spring Boot 中可以支持很多模板引擎,Thymeleaf 是 Spring Boot 官方推荐使用的模板引擎,虽然在社区 Thymeleaf 的性能被许多人所吐糟,但这仍然不影响大量的开发人员使用他. Thymeleaf 是后台开发的最佳实践 当前 Spring Boot 2.0 及以后版本已经支持 Thymeleaf 3.0. 本章讲解如何在 Spring Boot 中使用 Themealf. 源码下载 欢迎关注我的微信公众号 程序鱼 ,我们一起编程聊天看世界. 1 创建一个 Spr

Spring Boot 2.X 国际化

国际化文件的编写 messages.properties init project 7月前 messages_en_US.properties init project 7月前 messages_zh_CN.properties 页面非连接配置国际化只需要:  spring.messages.basename=i18n.login 1: 1.5X版本配置的方式 今天发现已久不行了 链接配置 编写类 实现LocaleResover public class LocaleSetting implem

spring boot +thymeleaf+ mybatis

pom <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0

Spring boot Thymeleaf 配置

第一步:pom.xml加入依赖 <!-- HTML templates--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> 如果出现错误 如下.. Exception encountered during context

spring boot(十五)spring boot+thymeleaf+jpa增删改查示例

快速上手 配置文件 pom包配置 pom包里面添加jpa和thymeleaf的相关包引用 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.

spring boot + thymeleaf 报错 org.thymeleaf.exceptions.TemplateInputException

org.thymeleaf.exceptions.TemplateInputException: Error resolving template "admin/verifyPassword", template might not exist or might not be accessible by any of the configured Template Resolvers at org.thymeleaf.TemplateRepository.getTemplate(Tem

spring boot thymeleaf常用方式

js中使用for循环 <script type="text/javascript" th:inline="javascript"> /* <![CDATA[ */ for(var i=1;i<3;i++){ alert(i); } /* ]]> */ </script> js中取出数据 <script th:inline="javascript"></script> var gid

Spring Boot系列(4)——实现国际化

〇.什么是国际化 国际化(internationalization,简称i18n),对不同的语言环境提供一个不同的资源文件,可以笼统地理解为语言切换. 本文以中英文切换为例. 一.添加国际化配置文件 1.在类路径下新建国际化配置文件,当IDEA检测到我们需要做国际化处理时,会自动切换到国际化视图: 2.注意:国际化配置文件得用.properties文件,文件名格式为 [基名]_[语言代码]_[国家代码].properties.配置文件的中文可能会出现乱码,注意设置IDEA的编码. 在File->