一、什么是i18n
i18n(其来源是英文单词 internationalization的首末字符i和n,18为中间的字符数)是“国际化”的简称。对于程序开发来说,i18n就是能够在不修改内部代码的情况下,能够根据不同的的语言和地区显示相应的界面。
在SringMVC中,DispatcherServelt会解析一个LocaleResolver接口对象,通过它来决定用户区域,读出对应的用户系统设定的语言或者用户选择的语言。简单来说,就是SpringMVC通过读取你的电脑设置的时区和地区来判断你身处何地,然后读取你所提供的对应地区的资源文件内容来渲染界面。
二、实现i18n
添加资源文件
一般放在类的加载路径下,Maven项目放到resources资源文件夹即可。这里给大家一个目录参考,里面也包含了要讲解的下一功能——主题切换的资源文件。
首先我们在resoures资源文件夹中新建messages包用来存放资源文件,在改包里面新建类型为Resource Bundle的文件。我创建了两个,一个放中文,一个放英文。里面允许使用占位符
language_en.properties
title=American Internet
order.id=ids
order.name=name
order.email=email
order.price=price
order.voice={0}hahahahahahahahahahaha
language_zh.properties
title=中国网
order.id=编号
order.name=名称
order.email=邮箱
order.price=价格
order.voice={0}哈哈哈哈哈哈
配置
在spring-web.xml配置文件加上以下配置
(ssm详细配置见https://blog.csdn.net/Black1499/article/details/83961684)
<!--实现i18n国际化-->
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale" value="zh" />
</bean>
<!--负责加载外部语言文件的-->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages/language" />
<property name="defaultEncoding" value="GBK" />
</bean>
新建Controller
@Controller
public class OrderController {
@GetMapping("/order")
public String orderIndex(Model model,Locale locale){
model.addAttribute("msg", "嘟噜噜");
return "orderForm";
}
@Autowired
private LocaleResolver localeResolver;
@GetMapping("/language/{lg}")
public String changeLanguage(@PathVariable("lg") String language, HttpServletRequest req, HttpServletResponse resp){
Locale locale = new Locale(language);
localeResolver.setLocale(req, resp, locale);
return "redirect: /order";
}
}
前台页面
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title><spring:message code="title"/></title>
</head>
<body>
<h1><spring:message code="order.voice" arguments="${msg}"/></h1>
<a href="/language/zh">中文</a>
<a href="/language/en">英文</a><br/>
<form:form>
<spring:message code="order.id"/>
<input type="text"><br/>
<spring:message code="order.name"/>
<input type="text"><br/>
<spring:message code="order.email"/>
<input type="text"><br/>
<spring:message code="order.price"/>
<input type="text"><br/>
<input type="submit" value="submit"/>
</form:form>
</body>
</html>
默认为中文页面
点击英文,切换为英文状态
三、拓展JSR303验证,把错误提示信息扔到资源文件里
上面我们发现了我们又使用了spring为我们提供的表单,这里我们可以思考一下,既然语言可以从资源文件中读取出来,那么我们把错误信息放到资源文件中,岂不是更好。需要更改错误提示信息时,就不用再到实体类里面更改了,方便又维护。
不懂JSR303的小伙伴,可以查看https://blog.csdn.net/Black1499/article/details/84333052
错误信息加入到资源文件中
这里我放到了默认中文的language_zh.properties的资源文件
err.id=id不可为空
err.name=这不是你的名字
err.email=邮箱不对
err.price=价格没有
更改实体类中的验证注解信息
public class Order {
@NotBlank(message = "{err.id}")
private String id;
@NotBlank(message = "{err.name}")
private String name;
@Email(message = "{err.email}")
private String email;
@Min(value = 100,message = "{err.price}")
private float price;
// .....get/set你懂得
}
新的表单
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title><spring:message code="title"/></title>
</head>
<body>
<h1><spring:message code="order.voice" arguments="${msg}"/></h1>
<a href="/language/zh">中文</a>
<a href="/language/en">英文</a><br/>
<form:form method="post" action="/addOrder" modelAttribute="order">
<spring:message code="order.id"/>
<form:input path="id"/> <!--预输入的内容-->
<form:errors path="id"/><br/>
<spring:message code="order.name"/>
<form:input path="name"/>
<form:errors path="name"/><br/>
<spring:message code="order.email"/>
<form:input path="email"/>
<form:errors path="email"/><br/>
<spring:message code="order.price"/>
<form:input path="price"/>
<form:errors path="price"/> <br/>
<input type="submit"/>
</form:form>
</body>
</html>
更新OrderController
@Controller
public class OrderController {
@PostMapping ("/addOrder")
public String order (@Valid Order order, BindingResult result) {
if(result.hasErrors()){
return "orderForm";
}
return "index";
}
@GetMapping("/order")
public String orderIndex(Model model,Locale locale){
model.addAttribute("msg", "嘟噜噜");
model.addAttribute("order",new Order("12","预输入","email",12));
return "orderForm";
}
@Autowired
private LocaleResolver localeResolver;
@GetMapping("/language/{lg}")
public String changeLanguage(@PathVariable("lg") String language, HttpServletRequest req, HttpServletResponse resp){
Locale locale = new Locale(language);
localeResolver.setLocale(req, resp, locale);
return "redirect: /order";
}
}
初始页面
故意输入不符要求的内容,提交后
可以看到我们在资源文件里设置的错误信息被读取出来,显示出来!
四、主题切换,继续通过SpringMVC操作资源文件
创建资源文件
在Resources资源文件夹力量面再创建一个themes包,目录结构去前面找。创建三个资源文件,里面放入css文件路径即可
default.properties
css.link=
blue.properties
css.link=../css/blue.css
yellow.properties
css.link=../css/yellow.css
配置spring-web.xml
<!--配置读取css的文件在哪-->
<bean id="themeSource" class="org.springframework.ui.context.support.ResourceBundleThemeSource">
<property name="basenamePrefix" value="themes/"/> <!-- 哪个文件夹里 -->
</bean>
<!-- 【可选】 -->
<!-- 默认情况下,使用的是 FixedThemeResolver 来确定主题名字,默认名字为 theme -->
<!-- 可以根据实际情况配置为 SessionThemeResovler/CookieThemeResolver -->
<bean id="themeResolver" class="org.springframework.web.servlet.theme.SessionThemeResolver">
<property name="defaultThemeName" value="default"/> <!-- 默认主题文件的名字,如果不设置,名为 theme -->
</bean>
更新OrderController
@Controller
public class OrderController {
@PostMapping ("/addOrder")
public String order (@Valid Order order, BindingResult result) {
if(result.hasErrors()){
return "orderForm";
}
return "index";
}
@GetMapping("/order")
public String orderIndex(Model model,Locale locale){
model.addAttribute("msg", "嘟噜噜");
model.addAttribute("order",new Order("12","预输入","email",12));
return "orderForm";
}
// 语言切换
@Autowired
private LocaleResolver localeResolver;
@GetMapping("/language/{lg}")
public String changeLanguage(@PathVariable("lg") String language, HttpServletRequest req, HttpServletResponse resp){
Locale locale = new Locale(language);
localeResolver.setLocale(req, resp, locale);
return "redirect: /order";
}
//主题切换
@Autowired
private ThemeResolver themeResolver;
@GetMapping("/themes/{css}")
public String changeCss(@PathVariable("css") String css, HttpServletRequest req, HttpServletResponse resp) {
themeResolver.setThemeName(req, resp, css);
return "redirect:/order";
}
}
页面配置
css文件夹放入blue.css和yellow.css即可
整合i18n的页面
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title><spring:message code="title"/></title>
<!--就在这拿到css连接-->
<link rel="stylesheet" href="<spring:theme code="css.link"/>"/>
</head>
<body>
<h1><spring:message code="order.voice" arguments="${msg}"/></h1>
<a href="/language/zh">中文</a>
<a href="/language/en">英文</a><br/>
<a href="/themes/yellow">黄色主题</a>
<a href="/themes/blue">蓝色主题</a>
<form:form method="post" action="/addOrder" modelAttribute="order">
<spring:message code="order.id"/>
<form:input path="id"/>
<form:errors path="id"/><br/>
<spring:message code="order.name"/>
<form:input path="name"/>
<form:errors path="name"/><br/>
<spring:message code="order.email"/>
<form:input path="email"/>
<form:errors path="email"/><br/>
<spring:message code="order.price"/>
<form:input path="price"/>
<form:errors path="price"/> <br/>
<input type="submit"/>
</form:form>
</body>
</html>
页面
默认主题
蓝色主题
蓝色主题