Spring Boot i18n 中英双语的多语言实现方案

更新日期: 2021-01-07 阅读次数: 7895 字数: 687 分类: spring

为了练手 Spring Boot 写了个 Emoji 查询的小网站

https://www.paobujie.com/emoji

第一版实现了英文的,后来想干脆再加上中文翻译,于是就查了一下如何使用 Spring Boot 来实现 i18n,即国际化。不得不说 Spring 相关的文档真是差劲,基本没有说明白的,都是你抄我,我抄你。涉及到实现细节,没有一个讲的完整的。踩了不少坑,虽然功能实现了,但是还是有不少疑惑。

引入阶段

在英文版完成之后,再处理 i18n 的兼容逻辑。

路由规划 (废弃)

英文

  • 首页 /emoji/en
  • tag /emoji/tag/en/some-tag
  • detail /emoji/

更简洁的网址方案

使用查询参数,例如

https://www.paobujie.com/emoji/?lang=en

https://www.paobujie.com/emoji/?lang=zh

这种形式。默认不加语言就是英文,或者浏览器的语言。

LocaleResolver 配置在哪个文件

看起来应该在 config 目录下,因为默认有个 SecurityConfig 的文件。

package com.sunzhongwei.calf.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;

import java.util.Locale;

/**
 * 配置国际化语言
 **/
@Configuration
public class LocaleConfig {

    /**
     * 默认解析器 其中locale表示默认语言
     */
    @Bean
    public LocaleResolver localeResolver() {
        SessionLocaleResolver localeResolver = new SessionLocaleResolver();
        localeResolver.setDefaultLocale(Locale.US);
        return localeResolver;
    }
}

拦截器,用于拦截链接中的语言参数 lang

package com.sunzhongwei.calf.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;

/**
 * Web相关配置
 **/
@Configuration
public class WebConfig implements WebMvcConfigurer {

    /**
     * 默认拦截器 其中lang表示切换语言的参数名
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        LocaleChangeInterceptor localeInterceptor = new LocaleChangeInterceptor();
        localeInterceptor.setParamName("lang");
        registry.addInterceptor(localeInterceptor);
    }
}

拦截器与解析器是如何联系的

没看明白。

翻译文件放到哪个目录下

按照 Spring Boot 的默认规则,那么直接放在 src/main/resources 目录下,以标准文件名命名即可:

  • messages.properties
  • messages_en_US.properties
  • messages_zh_CN.properties
  • messages_zh_TW.properties

但这样,会造成 resources 目录下文件过乱,所以我想放到 src/main/resources/lang 目录下,则需要在 application.properties 中配置:

spring.messages.basename=lang/messages
spring.messages.encoding=UTF-8

翻译文件的文件名格式

文件名格式:

messages_语言_国家或地区.properties 

是否可以省略掉国家或地区呢?例如,我想所有英文国家使用一份英文翻译,不区分地区差异?

只写成 messages_en.properties 是否支持?

支持。

中文的简写是什么

zh。但是具体到简体,繁体,就是 zh_CN, zh_TW 了。

所有语言的 locale 简写,参考 jdk8 的官方文档:

https://www.oracle.com/java/technologies/javase/jdk8-jre8-suported-locales.html

spring messages.properties messages_en.properties same?

暂时没有找到好的方法,只能保持这两个文件一致。

http://localhost:9090/emoji?lang=fr 为啥显示的是中文

如何设置英文为默认语言?

TODO.

thymeleaf 模板中判断当前语言

http://localhost:9090/emoji?lang=zh_CN

<div th:text="${#locale}"></div>
<div th:text="${#locale.language}"></div>

显示为

zh_CN
zh

参考

  • https://lokalise.com/blog/spring-boot-internationalization/ 写的最详细
  • https://www.baeldung.com/spring-boot-internationalization 细节不详
  • https://my.oschina.net/u/2364451/blog/4339313 细节不详

tags: i18n

关于作者 🌱

我是来自山东烟台的一名开发者,有敢兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式