前言
什么是国际化呢?国际惯例,来时来一段官方介绍:
国际化(internationalization)是设计和制造容易适应不同区域要求的产品的一种方式。它要求从产品中抽离所有地域语言,国家/地区和文化相关的元素。换言之,应用程序的功能和代码设计考虑在不同地区运行的需要,其代码简化了不同本地版本的生产。开发这样的程序的过程,就称为国际化。
在我们实际开发中,一个web应用可能要在多个地区使用,面对不同地区的不同语言,为了适应不同的用户,我们可以尝试在前端页面实现多语言的支持,那么同样对于后端返回的一些提示信息,异常信息等,我们后端也可以根据不同的语言环境来进行国际化处理,返回相应的信息。
开发工具
IDEA、Maven、SpringBoot2.0.5、Jdk1.8、google浏览器
SpringBoot中的国际化
原理:
想要使应用支持国际化,首先需要知道用户的语言环境,即用户想要看到的语言,我们设想在用户每次请求时告诉服务器自己的语言环境,服务器收到请求后,根据不同的语言环境返回不同的信息来实现国际化。在spring应用中,用户的语言环境是通过区域解析器
来识别的,而区域解析器有分为好几种(后面详细说
),在我们不做配置修改时,spring使用AcceptHeaderLocaleResolver
作为默认的区域解析器,它是根据HTTP请求 Header中的Accept-language
的值来解析,当然区域解析器我们也可以自定义配置。
springboot默认就支持国际化。我们只需要只需要作相应的配置即可。
1.首先你需要一个springboot项目。IDEA中分分钟创建好一个项目。
2.在resources
下定义国际化配置文件,注意名称必须以messages
开始。(在springboot中,当我们不修改配置时默认去解析名称以message开始的properties文件
)
-
messages.properties (
默认环境,无法确定语言环境时,解析该文件中的相应信息
) -
messages_zh_CN.properties(
中文语言环境时,解析该文件中的相应信息
) -
messages_en_US.properties(
英文语言环境时,解析该文件中的相应信息
)
在三个配置文件中分别以Key = Value
形式存储如下三条信息,如下:
1 | welcome = 这是一个支持国际化的项目。 |
1 | welcome = 这是一个支持国际化的项目。 |
1 | welcome = This is a project supporting internationalization. |
3.创建thymeleaf页面
加入thymeleaf依赖
1 | <dependency> |
在resources/templates
目录下创建hello.html
页面:
尝试在不同的语言环境下,通过#{welcome}
获取信息
1 |
|
4.创建访问页面的controller
注意这里controller的注解时@Controller
1 | import org.springframework.stereotype.Controller; |
测试国际化效果
这里使用google浏览器进行测试,测试之前需要安装插件Language Switcher
Language Switcher : 可以改变当前请求的语言环境(根据自己的选择)
启动我们的springboot项目,google浏览器访问 http://127.0.0.1:8080/hi ,可以看到如下页面:
通过Language Switcher切换语言环境为English - United States
,重新访问 http://127.0.0.1:8080/hi ,可以看到如下页面:
ok,大功告成,到此一个简单的国际化项目就完成了。
扩展国际化
通过上面的小栗子,我们可以看到一个简单的国际化使用,但是在开发中中还需要我们进行一定的配置,来满足我们不同情况下的使用。
在返回结果中获取国际化信息
很多时候,后端接收到一个请求后,需要返回一个提示信息,而此时我们可以使这个返回信息支持国际化
这里就用到了org.springframework.context.MessageSource
接口,MessageSource提供了三个方法
@Nullable//参数字段可为空
String getMessage(String var1, @Nullable Object[] var2, @Nullable String var3, Locale var4);
String getMessage(String var1, @Nullable Object[] var2, Locale var3) throws NoSuchMessageException;
String getMessage(MessageSourceResolvable var1, Locale var2) throws NoSuchMessageException;
-
String getMessage(String var1, @Nullable Object[] var2, @Nullable String var3, Locale var4):用来从MessageSource获取消息的基本方法。如果在指定的locale中没有找到消息,则使用默认的消息。var2中的参数将使用标准类库中的MessageFormat来作消息中替换值。
-
String getMessage(String code, Object[] args, Locale loc):本质上和上一个方法相同,其区别在:没有指定默认值,如果没找到消息,会抛出一个NoSuchMessageException异常。
-
String getMessage(MessageSourceResolvable resolvable, Locale locale):上面方法中所使用的属性都封装到一个MessageSourceResolvable实现中,而本方法可以指定MessageSourceResolvable实现。
下面我们实践一下:
1.创建一个以json返回格式的controller,注入MessageSource,注意controller的注解为@RestController
在这里首先我们需要获取到当前请求的Locale,有两种方法:
1 | Locale locale = LocaleContextHolder.getLocale(); |
两种方式根据情况选择使用,下面是controller代码
1 | package com.example.i18n.controller; |
2.启动项目访问 http://127.0.0.1:8080/ha ,可以看到相应语言环境的返回信息
通过Language Switcher切换语言环境为English - United States
,重新访问http://127.0.0.1:8080/ha,可以看到如下页面:
支持占位符国际化信息返回
我们经常会遇到这样一个场景,登录账号需要验证码,填写完手机号获取验证码后会收到一条类似于尊敬的用户13099999999您好,您的验证码是6666
,这种信息,其实就是一个模板,通过改变参数,重复使用。我们通过国际化资源文件中的占位符,配合MessageSource提供的api也可以实现。
资源文件中加入如下属性:
messages.properties,messages_zh_CN.properties
1 | hello=你好:{0} , 你的验证码为 :{1} |
messages_en_US.properties
1 | hello=Hello: {0}, your verification code is: {1} |
我们在JsonController
中,创建一个测试接口
1 | @RequestMapping("/haha") |
启动项目直接,访问 http://127.0.0.1:8080/haha 可以看到相应语言环境的返回信息
通过Language Switcher切换语言环境为English - United States
,重新访问 http://127.0.0.1:8080/haha ,可以看到如下页面:
支持国际化的枚举类
既然返回信息可以实现国际化,那我们的枚举类同样也可以实现国际化咯
创建一个枚举类EnumSuccessOrError.java
1 |
|
如上,刚刚创建的枚举类是不支持国际化的,我们呢需要改造他,当调用getStatusMsg
方法时根据语言环境返回相应的国际化字符串。可以从如下两个点着手:
- getStatusMsg方法改造
- 资源文件中添加不同语言环境对应的返回值
先在三个资源文件中加入不同环境的返回值:
messages.properties,messages_zh_CN.properties
1 | SUCCESS = 操作成功 |
messages_en_US.properties
1 | SUCCESS=success |
改造后的枚举如下:
1 | public enum EnumSuccessOrError { |
此时我们在JsonController
中,再创建一个测试接口
1 | "/enumDemo") ( |
启动项目直接,访问 http://127.0.0.1:8080/enumDemo 可以看到相应语言环境的返回信息
通过Language Switcher切换语言环境为English - United States
,重新访问 http://127.0.0.1:8080/enumDemo ,可以看到如下页面:
参考和感谢
https://blog.csdn.net/linxingliang/article/details/52350238
https://blog.csdn.net/flowingflying/article/details/76358970