Springboot与国际化(i18n)
一、什么是国际化?国际化就是在不修改内部代码的情况下,根据不同语言及地区显示相应的语言界面。i18n的由来→internationalization,数一下,首字母i和末位字母之间有18个字母。类似的命名还有很多,例如k8s。Springboot已经对i18n国际化做了自动配置,自动配置类。org.springframework.boot.autoconfigure.context.Message
一、什么是国际化?
-
国际化就是在不修改内部代码的情况下,根据不同语言及地区显示相应的语言界面。
-
i18n的由来→internationalization,数一下,首字母i和末位字母之间有18个字母。类似的命名还有很多,例如k8s。
-
Springboot已经对i18n国际化做了自动配置,自动配置类。
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration
如果想自定义国际化,通过@Autowired
配置使用MessageSource
进行自定义。
二、前端联合后端实现国际化。
一图解释什么是国际化:
原理:由前端页面某个元素(中文/English)返回给后端一个标识,后端根据标识获取地域信息,Springboot框架内置的MessageSource会获取该标识(图中只有两种标识,因此只有两种语种)来进行语种转换。当然转换的前提是要提前通过messages.properties文件来配置相应语言。
-
前端代码如下:(l='zh_CN’和l='en_US’就是标识)
-
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="description" content=""> <meta name="author" content=""> <title>Signin Template for Bootstrap</title> <!-- Bootstrap core CSS --> <link href="asserts/css/bootstrap.min.css" th:href="@{/webjars/bootstrap/4.2.1/css/bootstrap.css}" rel="stylesheet"> <!-- Custom styles for this template --> <link href="asserts/css/signin.css" rel="stylesheet"> </head> <body class="text-center"> <form class="form-signin" action="dashboard.html"> <img class="mb-4" src="asserts/img/bootstrap-solid.svg" alt="" width="72" height="72"> <h1 class="h3 mb-3 font-weight-normal" th:text="#{login.btn}">Please sign in</h1> <label class="sr-only">Username</label> <input type="text" class="form-control" th:placeholder="#{login.username}" placeholder="Username" required="" autofocus=""> <label class="sr-only">Password</label> <input type="password" class="form-control" th:placeholder="#{login.password}" placeholder="Password" required=""> <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" th:text="#{login.sign}" type="submit">Sign in</button> <p class="mt-5 mb-3 text-muted">© 2017-2018</p> <a class="btn btn-sm" th:href="@{/login.html(l='zh_CN')}">中文</a> <a class="btn btn-sm" th:href="@{/login.html(l='en_US')}">English</a> </form> </body> </html>
-
后端代码:
-
package com.example.bootstudy.component; 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; /** * ---------------------------------------------------------------- * @description: 自定义Local地域的解析 * @author: Create by Liu Wen at 2020-07-08 17:34 * ---------------------------------------------------------------- **/ public class MyLocaleResolver implements LocaleResolver { @Override public Locale resolveLocale(HttpServletRequest httpServletRequest) { String l = httpServletRequest.getParameter("l"); Locale locale = Locale.getDefault(); if(!StringUtils.isEmpty(l)){ String[] atts = l.split("_"); locale = new Locale(atts[0],atts[1]); } return locale; } @Override public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) { } }
package com.example.bootstudy.config; import com.example.bootstudy.component.MyLocaleResolver; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * ---------------------------------------------------------------- * @description: 将自定义的MyLocaleResolver配置到Springboot框架中 * @author: Create by Liu Wen at 2020-07-08 17:34 * ---------------------------------------------------------------- **/ @Configuration public class MymvcConfig implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("login"); registry.addViewController("/login.html").setViewName("login"); } @Bean public LocaleResolver localeResolver(){ return new MyLocaleResolver(); } }
-
login.properties文件配置
-
#login_en_US.properties文件 login.btn=\u8BF7\u767B\u5F55 login.password=\u5BC6\u7801 login.remember=\u8BB0\u4F4F\u6211 login.sign=\u767B\u5F55 login.username=\u7528\u6237\u540D #login_zh_CN.properties文件 login.btn=Please sign in login.password=Password login.remember=Remember me login.sign=Sign in login.username=Username
-
application.yml配置
-
spring: messages: basename: i18n/login
代码结构如图:
三、服务端国际化(Springboot内置国际化)
服务端的国际化一般用于信息提示。不集成前端。
可以直接使用默认的Springboot内置国际化,也可以自定义。代码如下:
-
messages.properties文件配置
-
#messages_zh_CN.properties文件 MSGFM00100001=\u8282\u70B9(id:{0})\u4E0D\u5B58\u5728. MSGFM00100002=\u8282\u70B9(id:{0})\u4E0D\u662F\u6D41\u7A0B\uFF0C\u6240\u4EE5\u5E76\u6CA1\u6709\u6D41\u7A0B\u56FE. MSGFM00100003=\u9879\u76EE(id:{0})\u5DF2\u7ECF\u5B58\u5728\u8BE5\u8282\u70B9. MSGFM00100004=\u9879\u76EE(id:{0})\u7684\u6839\u8282\u70B9\u4E0D\u5B58\u5728. MSGFM00100005=\u8282\u70B9(id:{0})\u7684\u7236\u8282\u70B9\u4E0D\u5B58\u5728. #messages_en_US.properties文件 MSGFM00100001=The node(id:{0}) does not exist. MSGFM00100002=The node(id:{0}) is not a "FLOW" node, so it can not have a graph. MSGFM00100003=The project(id:{0}) has already got a root node. MSGFM00100004=The root node of project(id:{0}) does not exist. MSGFM00100005=The parent node(id:{0}) does not exist.
-
自定义MessageSource工具:
-
package com.sample.utils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.stereotype.Component; import java.util.Locale; /** * MessageSource工具 * 依賴{@link MessageSource} * * @author Catscan * @date 2019-06-07 */ @Component public class MessageSourceUtil { @Autowired private MessageSource messageSource; public String getMessage(String code) { return getMessage(code, null); } public String getMessage(String code, Object[] args) { return getMessage(code, args, ""); } public String getMessage(String code, Object[] args, String defaultMsg) { // 這裡可以使用一些比較trick的方法動態設定語言 // 可以做全站全局、單個request,當然,方法需要根據不同情況修改 Locale locale = LocaleContextHolder.getLocale(); return messageSource.getMessage(code, args, defaultMsg, locale); } }
-
测试内置的国际化与自定义的国际化
-
package com.sample.controller; import com.sample.utils.MessageSourceUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.Locale; import java.util.Map; /** * 測試用的Controller * * @author Catscan * @date 2019-06-07 */ @RestController @RequestMapping("/") public class MessageController { @Autowired private MessageSourceUtil messageSourceUtil; @Autowired private MessageSource messageSource; /** * 測試使用{@link MessageSource} * * @return {@link ResponseEntity} */ @RequestMapping("/message") public ResponseEntity pingResource(){ Map<String ,String> result = new HashMap<>(3); result.put("default",messageSource.getMessage("hello", null, "", null)); result.put("en_US",messageSource.getMessage("hello", null, "", Locale.US)); result.put("zh_CN",messageSource.getMessage("hello", null, "", Locale.SIMPLIFIED_CHINESE)); return ResponseEntity.ok(result); } /** * 測試使用{@link MessageSourceUtil} * * @return {@link ResponseEntity} */ @RequestMapping("/util") public ResponseEntity pingUtil(){ return ResponseEntity.ok(messageSourceUtil.getMessage("hello")); } }
多语言环境是定义在
java.util.Locale
类中的,如:... static public final Locale SIMPLIFIED_CHINESE = createConstant("zh", "CN"); static public final Locale CHINA = SIMPLIFIED_CHINESE; static public final Locale UK = createConstant("en", "GB"); static public final Locale US = createConstant("en", "US"); static public final Locale CANADA = createConstant("en", "CA"); ...
分析:在
MessageSource.getMessage(...)
所有方法中,都有Locale
参数,指定区域信息。
当调用时,要如果指定位置为:Locale.CHINA
,这时ResourceBundelMessageSource
会从messages_zh_CN.properties中寻找对应的键值。
当给出Locale
参数值为null
,空的区域信息;或者对应的properties文件中没有找到对应的键值对,那么ResourceBundelMessageSource
默认会从messages.properties中
寻找键,当都找不到的时候,会返回空字符串。
更多推荐
所有评论(0)