Spring Boot 项目信息国际化

目录

信息国际化概述

准备国际化文件

Spring Boot 国际化自动配置原理

前端页面获取国际化值

指定语言切换


信息国际化概述

1、国际化主要用于应用跨国时使用,比如在中国时应用为中文,在韩国时,应用显示为韩文,在日本时,应用又显示为日文等,应用跟着系统语言环境自动切换。又或者是用户点击什么语言就可以自动切换什么语言。

准备国际化文件

1、编写国际化配置文件,抽取页面需要显示的国际化消息

2、在类路径下新建一个目录“i18n”(目录名字随意),然后在“i18n”目录下新建 “index.properties”、“index_en_US.properties”、“index_zh_CN.properties” 三个属性文件(名称强制可以与页面名称一致)。

xxx.properties存放默认的语言
xxx_en_US.properties存放英文,en表示语言(英文)缩写,US表示国家(美国)缩写,请按规范格式写即可
xxx_zh_CN.properties存放中文,zh表示语言(中文)缩写,CN表示国家(中国)缩写,请按规范格式写即可

3、当然还可以写更多的语言文件,当它们的命名符合规范时,IDEA 会自动将它们绑定到一起,这样在后面输入值的时候会很方便.

4、为了防止 *. properties 资源文件中文乱码,IDEA设置:
打开:Settings->Editor->File Encodings,"Default encoding for properties files" 设置为 UTF-8,勾选后面的 "Transparent native-to-asci conversion"

https://gitee.com/wangmx1993/thymeleafapp/blob/master/src/main/resources/i18n 

Spring Boot 国际化自动配置原理

1、Spring Boot 现在自动配置好了管理国际化资源文件的组件 MessageSourceAutoConfiguration,底层仍然使用的是 ResourceBundleMessageSource。

2、页面使用 fmt:message 获取国际化内容,本文使用 Thymeleaf 模板引擎,所以会用 Thymeleaf 进行取值。

package org.springframework.boot.autoconfigure.context;
@Configuration
@ConditionalOnMissingBean(value = MessageSource.class, search = SearchStrategy.CURRENT)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Conditional(ResourceBundleCondition.class)
@EnableConfigurationProperties
public class MessageSourceAutoConfiguration {
	private static final Resource[] NO_RESOURCES = {};
	@Bean
	@ConfigurationProperties(prefix = "spring.messages")
	public MessageSourceProperties messageSourceProperties() {
		return new MessageSourceProperties();
	}
	@Bean
	public MessageSource messageSource() {
		MessageSourceProperties properties = messageSourceProperties();
		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;
	}
......

3、如上所示在它的 MessageSourceProperties 可以看到可以配置的属性,同理可以直接在官网进行查看,可以在全局配置文件中覆盖其默认配置,官方文档查看:Spring Boot Reference Guide.

# 国际化(MessageSourceProperties)
spring.messages.always-use-message-format=false # 是否始终应用MessageFormat规则,甚至解析没有参数的消息
spring.messages.basename=messages # 以逗号分隔的基名列表(基本上是一个完全限定的类路径位置),每个基名都遵循ResourceBundle约定,并放松了对基于斜杠的位置的支持。
spring.messages.cache-duration= #加载的资源包文件缓存持续时间。未设置时,捆绑包将永久缓存。如果未指定持续时间后缀,将使用秒。
spring.messages.encoding=UTF-8 # 消息包编码
spring.messages.fallback-to-system-locale=true # 如果找不到特定区域设置的文件,是否返回到系统区域设置。
spring.messages.use-code-as-default-message=false # 是否将消息代码用作默认消息,而不是引发“NoSuchMessageException”。仅在开发期间推荐。

4、如上所示,spring.messages.basename=messages,就是配置国际化资源文件的基本名路径,默认是“message”,意思是如果没有在全局配置文件中覆盖此配置项的话,它默认会扫描类路径下的“messages.properties”、"messages_en_US.properties"、"messages_zh_CN.properties"等格式的文件作为国际化文件。

5、因为应用会有多个页面,以及其它形式的国际化设置,就会有多套资源文件,这时在 application.yml 文件中覆盖配置,spring.messages.basename 的值用逗号分隔即可

spring:
  #国际化消息配置,多个时用逗号隔开.
  messages:
    basename: i18n.login,i18n.index

src/main/resources/application.yml · 汪少棠/thymeleafapp - Gitee.com 

前端页面获取国际化值

1、因为本文使用的是 Thymeleaf 模板引擎,所以页面上直接使用 Thymeleaf 的方式获取国际化文件的值即可,对于 Thymeleaf 不熟悉的,可以参考《Thymeleaf 简介及入门》

2、th:text="#{xxx}":获取国际化文件中 xxx 的属性值,然后替换标签原来的文本默认值。
3、th:placeholder="#{xxx}":获取国际化文件中 xxx 的属性值,然后替换标签 placeholder 属性原来的默认值,同理可以替换任意属性的默认值。
4、[[#{login_remember}]]:对于 <input xxx />这种自封闭标签得用 Thymeleaf的行内表达式取值。

示例1:<title th:text="#{login_title}">银河系大数据平台</title>
示例2:<div class="message">[[#{login_title}]]</div>

src/main/resources/templates/login.html · 汪少棠/thymeleafapp - Gitee.com 

5、下面进行测试,根据浏览器语言设置的信息切换了国际化。

指定语言切换

1、上面是应用根据跟随浏览器语音自动进行语音切换,现在需要改成用户“点击中文”则切换中文,“点击英文”则切换英文。

2、原理是需要使用到 “国际化Locale(区域信息对象)”与 “ LocaleResolver(获取区域信息对象)”两个API

3、应用国际化默认之所以能随着浏览器的语言变化而变化,是因为浏览器Http请求时,会在请求头中携带语言信息,这是后台国际化变换的依据。

4、第一部分中的 “自动语言切换” 之所以能用,是因为在 WebMvcAutoConfiguration 配置类中自动配置好了一个 区域信息解析器组件,如下所示逻辑是如果用户没有自己提供 区域信息解析器 “LocaleResolver”,那么它默认会使用一个叫 “AcceptHeaderLocaleResolver” 进行解析。

5、所以我们只需要自己提供一个  “LocaleResolver” 组件覆盖默认的即可

package org.springframework.boot.autoconfigure.web.servlet;
.....
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,
		ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
......
		@Bean
		@ConditionalOnMissingBean
		@ConditionalOnProperty(prefix = "spring.mvc", name = "locale")
		public LocaleResolver localeResolver() {
			if (this.mvcProperties
					.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) {
				return new FixedLocaleResolver(this.mvcProperties.getLocale());
			}
			AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
			localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
			return localeResolver;
		}
.......
}

页面修改

1、修改一下首页的“中文”、“英文”按钮,使用 Thymeleaf 的 @{xxx} 取值是会默认带上应用上下文。

2、@{/} 的效果类似 http://localhost:8080/tiger/,其中 titer 是应用名称。

3、@{/(l=zh_CN)} 相当于 @{/?zh_CN},只是 Thymeleaf 不再使用 "?" 的方式为get请求路径带参数,而是使用"()"的方式。

    <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_button}">Sign in</button>
    <p class="mt-5 mb-3 text-muted">© 2017-2018</p>
    <a class="btn btn-sm" th:href="@{/(l=zh_CN)}">中文</a>
    <a class="btn btn-sm" th:href="@{/(l=en_US)}">English</a>
</form>
</body>
</html>

页面上点击“中文”后,会跳转:http://localhost:8080/tiger/?l=zh_CN
页面上点击“英文”后,会跳转:http://localhost:8080/tiger/?l=en_US 

自定义区域信息解析器

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;
/**
 * Created by Administrator on 2018/7/28 0028.
 * 自定义区域信息解析器
 */
public class MyLocaleResolve implements LocaleResolver {
    /**
     * 解析http请求中地址中的标识,然后设置对应的区域信息值
     *
     * @param httpServletRequest
     * @return
     */
    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        /**
         * 如果请求地址中含有l参数,如 http://localhost:8080/tiger/?l=en_US,则设置新的区域对象
         * 否则使用默认的区域对象,默认的区域对象不会使国际化再随着浏览器语言的变化而变化的
         */
        Locale locale = Locale.getDefault();
        String l = request.getParameter("l");
        if (!StringUtils.isEmpty(l) && l.split("_").length >= 2) {
            String[] ls = l.split("_");
            locale = new Locale(ls[0], ls[1]);
        }
        return locale;
    }
    /**
     * 设置区域信息,一般不做处理
     *
     * @param httpServletRequest
     * @param httpServletResponse
     * @param locale
     */
    @Override
    public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {

    }
}
import com.lct.component.MyLocaleResolve;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
/**
 * Created by Administrator on 2018/7/28 0028.
 * 自定义配置类
 */
@Configuration
public class MyMvcConfig {
    /**
     * 将我们自己的 LocaleResolver 组件交于 Spring 容器管理
     * 从而覆盖 Spring Boot默认的区域信息解析器
     *
     * @return
     */
    @Bean
    public LocaleResolver localeResolver() {
        return new MyLocaleResolve();
    }
}

运行测试

1、和预期的完全一致,因为请求路径中携带了"L"参数,所以不管浏览器 语言 选择的是什么,都不会影响。

2、当请求地址中不带 “L” 参数时,此时后台使用的是默认的 Locale,此时即使浏览器切换了语言,同样国际化也不会生效的。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蚩尤后裔-汪茂雄

芝兰生于深林,不以无人而不芳。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值