Spring5 全家桶 | 22 - Spring MVC I18N

283 阅读5分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情

i18n 是 internationalization 首字母i和末尾字母n以及中间18个字母的简称,意于国际化。

国际化(i18n)指让产品(出版物,软件,硬件等)无需做大的改变就能够适应不同的语言和地区的需要。对程序来说,在不修改内部代码的情况下,能根据不同语言及地区显示相应的界面。 在全球化的时代,国际化尤为重要,因为产品的潜在用户可能来自世界的各个角落。通常与i18n相关的还有L10n(“本地化”的简称)。

Spring MVC 通过ResourceBundleMessageSource管理国际化资源文件,使得国际化的配置非常简单。

在index.jsp页面中增加一个超链接,点击超链接跳转至登录页面

<a href="/tologinpage">跳转至登录页面</a>

在pages目录下新建登录页面login.jsp,在body标签中增加登录表单

<h2>Login</h2>

<h3>登录表单</h3>
<form action="">
    用户名:<input type="text" name="username">
    密码:<input type="password" name="password">
    <input type="submit" />
</form>

在controller包中新家I18NController,添加一个toLoginPage方法,该方法返回登录界面

@Controller
public class I18NController {

    @RequestMapping("/tologinpage")
    public String toLoginPage(){
        return "login";
    }
}

一、国际化配置

国际化资源文件

在resource目录下新建两个properties配置文件login_us_EN.properties和login_zh_CN.properties,将需要国际化的项配置到里面

username=USERNAME
password=PASSWORD
username=用户名
password=密码

国际化XML配置

在Spring MVC配置文件中增加国际化资源配置,通过ResourceBundleMessageSource来管理国际化资源文件,其中basename属性是指国际化资源的位置以及文件标识

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basename" value="loginpage/login"></property>
</bean>

页面获取国际化消息

首先在login.jsp页面上导入fmt标签

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

接着修改登录表单,使用fmt标签取出国际化内容

<form action="">
    <fmt:message key="username">:<input type="text" name="username">
    <fmt:message key="password">:<input type="password" name="password">
    <input type="submit" />
</form>

测试国际化

重新启动该应用,点击首页的超链接,跳转至登录页面 image.png

中文显示乱码,这是因为国际化资源中文一定要使用ASCII编码,修改login_zh_CN.properties为

username=\u7528\u6237\u540d
password=\u5bc6\u7801

再次重启应用,点击首页超链接,跳转至登录页面 image.png

修改浏览器语言为英文

image.png

中文英文都可以正常显示,国际化配置生效

二、国际化原理

Spring MVC中国际化区域信息解析器负责解析区域信息,而区域信息根据浏览器携带的信息来获取的。

Spring MVC中配置了默认的区域信息解析器AcceptHeaderLocalResolver,该类实现了LocaleResolver接口。

image.png

LocalResolve接口中定义了两个方法,分别是解析和设置区域信息解析器 image.png

AcceptHeaderLocalResolver实现了LocalResolver接口中的方法 image.png

其中resolveLocale方法就是根据请求头中浏览器的语言来设置的来设置区域信息

image.png 页面渲染时都是通过resolveLocale方法来获取区域信息的

获取区域信息解析器

在toLoginPage方法中增加Locale参数,并在代码中打印

@RequestMapping("/tologinpage")
public String toLoginPage(Locale locale){
    System.out.println("此时请求头中携带的区域信息为:" + locale);
    return "login";
}

重启浏览器,访问登录界面 image.png 可以看出浏览器在不同语言设置下显示出不同的区域信息

获取国际化配置信息

Spring MVC中的国际化配置是由ResourceBundleMessageSource来管理的,该类是MessageResource接口的实现类,通过该类可以获取到国际化配置信息

@Controller
public class I18NController {

    @Autowired
    private MessageSource messageSource;

    @RequestMapping("/tologinpage")
    public String toLoginPage(Locale locale){
        System.out.println("此时请求头中携带的区域信息为:" + locale);
        // key, 占位符, 区域信息
        String usernameInfo = messageSource.getMessage("username", null,locale);
        System.out.println("国际化文件中Key为username在" + locale + "下的配置信息为:" + usernameInfo);
        return "login";
    }
}

重启应用,分别设置浏览器语言为中文和英文时请求登录页面 image.png

可用于在校验时返回国际化信息

三、国际化切换

在登录表单下面增加两个超链接,实现通过点击中文或者English来切换语言

<a class="btn btn-sm" href="#">中文</a> |
<a class="btn btn-sm" href="#">English</a>

默认Spring MVC是通过请求头中的浏览器携带的区域信息来解析的,要想实现通过点击实现切换语言的目的就需要自定义一个区域信息解析器,用来解析超链接中传递的区域信息

<a class="btn btn-sm" href="tologinpage?locale=zh_CN">中文</a> |
<a class="btn btn-sm" href="tologinpage?locale=en_US">English</a>

注册区域信息解析器

DispatcherServlet类中的区域解析器属性名称为localeResolver,所以要想使用自定义的区域信息解析器就需要在Spring MVC配置文件中配置id为localeResolver的Bean

image.png

屏幕录制2022-04-16 上午12.44.35.gif

Spring MVC中的区域信息解析器

image.png

  • AcceptHeaderLocaleResolver:使用请求头的区域信息,默认的区域信息解析器
  • FixedLocaleResolver:使用系统默认的区域信息
  • SessionLocaleResolver:使用session获取区域信息,可以将locale对象方法在session中,可以修改区域信息
  • CookieLocaleResolver:使用cookie获取区域信息,可以修改区域信息

使用SessionLocaleResolver实现国际化切换

首先将注册的区域信息解析器替换为SessionLocaleResolver,id仍然保持LocalResolver不变

<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">

</bean>

SessionLocaleResolver的resolveLocale方法从session的attibute中取出区域信息,属性名为localeAttributeName image.png

而localeAttribute有指向另一个变量 image.png 所以我们在将区域信息保存在session时设置的属性名也设置为

SessionLocaleResolver.class.getName() + ".LOCALE";

修改toLoginPage方法

@RequestMapping("/tologinpage")
public String toLoginPage(@RequestParam(value = "locale", defaultValue = "zh_CN") String areaInfo,
                          Locale locale, HttpSession session){
    // 如果请求地址中携带了区域信息,就进行国际化
    Locale l = null;
    if (areaInfo != null && !"".equals(areaInfo)){
        l = new Locale(areaInfo.split("_")[0], areaInfo.split("_")[1]);
    } else {
        l = locale;
    }
    // 区域信息存入session中
    session.setAttribute(SessionLocaleResolver.class.getName() + ".LOCALE", l);
    System.out.println(l.toString());
    return "login";
}

重启应用,依然可以实现点击中英文切换语言

SessionLocaleResolver+LocaleChangeInterceptor实现国际化切换

配置区域信息拦截器,拦截所有请求,通过拦截器中的preHandler方法设置区域信息

<mvc:interceptors>
    <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
</mvc:interceptors>

toLoginPage方法

@RequestMapping("/tologinpage")
public String toLoginPage(){
    return "login";
}

重新启动该应用,依然可以实现点击超链接切换语言

image.png

四、拦截器与Filter

如果实现的功能需要和其他组件配合使用,就需要使用到拦截器,基于Spring IOC可以非常方便的导入各种组件,除此之外可以使用Filter