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

文章目录

    为了练手 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 细节不详

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式