1、资源国际化开发
1.1 什么是资源国际化?
软件的国际化:软件开发时,要使它能同时应对世界不同地区和国家的访问,并针对不同地区和国家的访问,提供相应的、符合来访者阅读习惯的页面或数据。国际化(internationalization)又称为 i18n(读法为i 18 n,据说是因为internationalization(国际化)这个单词从i到n之间有18个英文字母,i18n的名字由此而来)
1.2 国际化的基本规则
国际化信息”也称为“本地化信息”,一般需要两个条件才可以确定一个特定类型的本地化信息,它们分别是“语言类型”
和“国家/地区的类型”
。如中文本地化信息既有中国大陆地区的中文,又有中国台湾、中国香港地区的中文,还有新加坡地区的中文。Java通过java.util.Locale
类表示一个本地化对象,它允许通过语言参数和国家/地区参数创建一个确定的本地化对象。
语言参数
使用ISO标准语言代码表示,这些代码是由ISO-639标准定义的,每一种语言由两个小写字母表示。在许多网站上都可以找到这些代码的完整列表,下面的网址是提供了标准语言代码的信息:http://www.loc.gov/standards/iso639-2/php/English_list.php。
国家/地区参数
也由标准的ISO国家/地区代码表示,这些代码是由ISO-3166标准定义的,每个国家/地区由两个大写字母表示。用户可以从以下网址查看ISO-3166的标准代码: http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html。下面是常用的国家/地区语言参数:

2、资源国际化简单示例
编写国际化资源文件:国际化资源文件就是用一种key-value的形式把要显示的信息的不同语言的翻译版本写到properties资源文件中。 (1)英文的资源文件
login_en_US.properties:
welcomeInfo=Welcome to my personal blog LoveITer
username=USERNAME
password=PASSWORD
loginbtn=LOGIN
placeholder_username=please input username
placeholder_password=please input password
(2)简体中文的资源文件
login_zh_CN.properties
welcomeInfo=欢迎访问我的个人博客LoveITer
username=用户名
password=密码
loginbtn=登录
placeholder_username=请输入用户名
placeholder_password=请输入密码
注意:一般情况下我们用
*._zh_CN.properties
表示中文资源文件,*.properties
表示默认的资源文件。
在springmvc配置文件中简单的配置一下,把我们的资源文件交给SpringMVC管理
<!--配置国际化资源文件-->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="login"/>
</bean>
编写一个用户登录表单
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
</head>
<body>
<h3><fmt:message key="welcomeInfo"/></h3>
<form action="checkLogin" method="post" >
<table>
<tr><th><fmt:message key="username"/></th><td><input type="text" placeholder="<fmt:message key='placeholder_username'/>"/></td></tr>
<tr><th><fmt:message key="password"/></th><td><input type="password" placeholder="<fmt:message key='placeholder_password'/>"/></td></tr>
<tr><th><input type="submit" value="<fmt:message key="loginbtn"/>"/></th></tr>
</table>
</form>
</body>
</html>
上面的代码中用到了JSTL中的fmt标签<fmt:message>
,因此需要导入对应的jar包。
测试结果 我的浏览器默认就是中文,因此显示的就是中文的欢迎信息:

在火狐浏览器中手动更改语言为英文


3、资源文件的编码问题
一般我们采用properties文件来保存资源文件。properties文件是以key-value的形式来保存文件的。login_zh_CN.properties中保存的是经过utf-8编码字后的ASCII字符,Unicode字符中不允许出现中文、日文等其他字符的文字。但是Unicode编码后的文字阅读起来比较困难,在IDEA中,可以在File->Settings->Editor->File Encodings
设置中勾选Transparent native-to-ascii conversion,如下图,设置好后点击Apply
,然后回到刚才编写的中文资源文件发现中文字符全部乱码了,这时可以在编辑器中直接重新输入中文。虽然我们输入的是中文,但是IDEA已经帮我们做了中文转码。

4、在程序中获取国际化信息
在程序中我们可以通过ResourceBundleMessageSource
来获取资源文件的信息:
package com.xust.iot.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Locale;
@Controller
public class UserController {
@Autowired
private MessageSource messageSource;
/**
* SpringMVC会自动把locale信息注入
* @param locale
* @return
*/
@RequestMapping("/toLogin")
public String logIn(Locale locale) {
System.out.println(locale);
String welcomeInfo=messageSource.getMessage("welcomeInfo",null,locale);
String userName=messageSource.getMessage("username",null,locale);
String password=messageSource.getMessage("password",null,locale);
System.out.println(welcomeInfo+"----"+userName+"----"+password);
return "login";
}
}
执行结果: 可以看到在不同对语言环境下使用了不同的资源文件。

5、自定义区域信息解析器
3个步骤:
1、写一个类实现LocaleResolver接口或他的子接口或继承他的实现类,最主要是要实现它的resolveLocale方法 2、在springmvc的配置文件中注册自定义的区域信息解析器 3、启动测试
(1)写一个类实现LocalResolver接口
package com.xust.iot.LocaleResolver;
import net.sf.cglib.core.Local;
import org.springframework.web.servlet.LocaleResolver;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
public class MyLocaleResolver implements LocaleResolver {
/**
* 解析locale信息
* @param request
* @return
*/
@Override
public Locale resolveLocale(HttpServletRequest request) {
Locale locale=null;
//通过请求解析请求参数中的locale来让用户可以根据自己的习惯选择语言
String localeStr=null!=request.getParameter("locale")?request.getParameter("locale"):"";
if(!"".equals(localeStr)){
locale=new Locale(localeStr.split("_")[0],localeStr.split("_")[1]);
}else{
locale=request.getLocale();
}
return locale;
}
@Override
public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
}
}
(2.1)在springmvc的配置文件中注册自定义的区域信息解析器
<!--自定义区域信息解析器-->
<bean id="localeResolver" class="com.xust.iot.LocaleResolver.MyLocaleResolver"/>
注意:解析器的id必须是localeResolver
,如果写错了就没有效果了。至于为啥非要这么写请参考SpringMVC源码中的DispatcherServlet这个类。
(2.2)在页面中加入可以切换语言的链接
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
</head>
<body>
<h3><fmt:message key="welcomeInfo"/></h3>
<form action="checkLogin" method="post" >
<table>
<tr><th><fmt:message key="username"/></th><td><input type="text" placeholder="<fmt:message key='placeholder_username'/>"/></td></tr>
<tr><th><fmt:message key="password"/></th><td><input type="password" placeholder="<fmt:message key='placeholder_password'/>"/></td></tr>
<tr><th><input type="submit" value="<fmt:message key="loginbtn"/>"/></th></tr>
</table>
</form>
<a href="toLogin?locale=zh_CN"><fmt:message key="Chinese"/></a>|
<a href="toLogin?locale=en_US"><fmt:message key="English"/></a>
</body>
</html>
(3)测试

6、SessionLocaleResolver

从SpringMVC的区域信息的继承图中我么看到了几个特别的区域信息解析器: 1. AcceptHeaderLocaleResolver:它是SpringMVC默认装配的区域信息解析器,他会默认从 accept-language请求头信息进行解析处理,通常这个头信息包含客户端操作信息的本地标示。它不支持通过链接的方式改变locale信息。 2. FixedLocaleResolver:从字面意思就可以知道,这也是一个不支持通过链接的方式改变locale信息的一个解析器,它默认会从操作系统拿locale信息。 3. SessionocaleResolver:从session中拿locale信息,允许设置区域信息。 4. CookieLocaleResolver:从Cookie中拿locale信息,允许设置区域信息。
下面我们借助SessionLocaleResolver来实现我们上面自定义区域信息解析器的功能:
package com.xust.iot.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import javax.servlet.http.HttpSession;
import java.util.Locale;
@Controller
public class UserController {
@Autowired
private MessageSource messageSource;
@RequestMapping("/toLogin")
public String logIn(
@RequestParam(value = "locale",defaultValue = "zh_CN") String localeStr,
Model model,
Locale locale,
HttpSession session) {
Locale l=null;
if(null!=localeStr&&!"".equals(localeStr)){
l=new Locale(localeStr.split("_")[0],localeStr.split("_")[1]);
}else{
l=locale;
}
session.setAttribute(SessionLocaleResolver.class.getName() + ".LOCALE",l);
return "login";
}
}
测试结果:

7、使用LocaleChangeInterceptor
通过配置LocaleChangeInterceptor
,我们可以动态改变本地语言。它会检测请求中的参数并且改变地区信息。它调用LoacalResolver.setLocal()进行配置。

既然是拦截器,要使用他就需要在springmvc配置文件中配置它,配置也很简单:
<mvc:interceptors>
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
</mvc:interceptors>
然后在配合SessionLocaleResovler,实现动态的改变本地信息
<!--SessionLocaleResolver-->
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"/>
<!--资源国际化拦截器-->
<mvc:interceptors>
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
</mvc:interceptors>
控制器层的代码瞬间变得极其简单,就一个跳转页面对返回语句
@Controller
public class UserController {
@RequestMapping("/toLogin")
public String logIn() {
return "login";
}
}
测试结果:
