Spring Boot 多语言配置
建立一个多语言网站不仅有助于提高访问量,同时还能减少维护成本(相对于同时维护2
个不同语言的网站)。
多语言网站也称为国际化(i18n),是对应于本地化(i10n)的叫法。
说明:i18n 来自英文单词(
Internationalization
),因为这个单词太长,所以取其首尾字母,加上中间的18
个字母,组合成i18n
。类似的还有 k8s(kubernetes)等。
Spring Boot 默认就包含有多种语言的国际化工具,包括拦截器、语言处理器(Resolver) 和语言包。
本文详细说明如何使用 Spring Boot 创建一个多语言网站。
用户切换不同语言有2
种方式,通过 query 参数以及通过路径方式。
第一种情况:语言参数在 URL query 上
第二种情况:语言参数在 URL path 上
本文会讲解这两种方式的实现。
1 创建 Spring Boot 工程
打开 Idea 编辑器,选择菜单 File – New – Project…,创建一个 Spring Boot 项目,如下:
组件只选择 Spring Web 和 Thymeleaf 模板引擎。
再点击 Finish 完成创建。
2 创建语言包文件
这里我们创建 2 个语言包:英文语言包和中文语言包,它们将由 messageResource
Bean 加载和管理,更多语言包可自行增加。
需要注意的是,非英文语言包创建后不是 UTF-8 格式的,显示的时候会是乱码,所以需要将 .properties
文件默认的编码格式由 ISO-8859-1
改为 UTF-8
,方法如下图。
创建英文语言包文件 src/main/resources/i18n/message_en.properties
:
title = Internationalization test
username = Username
password = Password
submit = Submit
简体中文语言包文件 src/main/resources/i18n/message_zh_CN.properties
:
title = 国际化测试
username = 用户名
password = 密码
submit = 提交
3 语言信息在 URL 参数上的情况
3.1 运行效果
最终效果如下,通过链接切换语言,相当于修改了请求参数,语言切换后即使刷新页面也同样有效。
3.2 拦截器和 LocaleResolver
创建一个 WebMvcConfig.java
配置类,配置 localeResolver
和 messageResource
两个 bean,以及addInterceptors
语言拦截器。
localeResolver
– 指明如何获取用户所选择的语言信息,CookieLocaleResolver
会从本 Cookie 中读取用户之前使用的的语言。messageResource
– 配置语言包文件所在的位置。addInterceptors
– 在 Controller 执行之前,注册LocaleChangeInterceptor
拦截器。这个拦截器会在展示内容给用户之前提前处理语言内容。
站点配置文件 src/main/java/com/awaimai/i18demo/config/WebMvcConfig.java
:
package com.awaimai.i18demo.config;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Bean(name = "localeResolver")
public LocaleResolver getLocaleResolver() {
CookieLocaleResolver resolver = new CookieLocaleResolver();
resolver.setCookieDomain("myAppLocaleCookie");
resolver.setCookieMaxAge(60 * 60); // 60 minutes
return resolver;
}
@Bean(name = "messageSource")
public MessageSource getMessageResource() {
ReloadableResourceBundleMessageSource messageResource = new ReloadableResourceBundleMessageSource();
messageResource.setBasename("classpath:i18n/message");
messageResource.setDefaultEncoding("UTF-8");
return messageResource;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
LocaleChangeInterceptor localeInterceptor = new LocaleChangeInterceptor();
localeInterceptor.setParamName("lang");
registry.addInterceptor(localeInterceptor).addPathPatterns("/*");
}
}
3.3 控制器和视图
控制器文件 src/main/java/com/awaimai/i18demo/controller/MainController.java
:
package com.awaimai.i18demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class MainController {
@RequestMapping(value = { "login1" })
public String login() {
return "login1";
}
}
Thymeleaf 视图文件 src/main/resources/templates/login1.html
:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title th:utext="#{title}"></title>
</head>
<body>
<div style="text-align: right;padding:5px;margin:5px 0px;background:#ccc;">
<a th:href="@{/login1?lang=en}">English</a>
|
<a th:href="@{/login1?lang=cn}">简体中文</a>
</div>
<form method="post" action="">
<table>
<tr>
<td>
<strong th:utext="#{username}"></strong>
</td>
<td><input name="userName"/></td>
</tr>
<tr>
<td>
<strong th:utext="#{password}"></strong>
</td>
<td><input name="password"/></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" th:value="#{submit}"