程序的国际化(Java与SpringMVC)
Posted nuist__NJUPT
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了程序的国际化(Java与SpringMVC)相关的知识,希望对你有一定的参考价值。
程序的国际化(Java与SpringMVC)
国际化是商业软件的一个基本要求,因为当今的软件系统需要面对全球的浏览者。程序国际化的目的就是根据用户的语言环境的不同向用户输入与之相对应的页面,以示友好。
Java的国家化思想:
Java的国际化思想是将程序中的信息放到资源文件中,程序根据支持的国家以及语言环境读取相应的资源文件,资源文件是key-value,每个key是不变的,value随不同的国家/语言变化。
Java程序的国际化主要通过两个类来实现。
(1)java.util.Locale:用于提供本地信息,通常称为语言环境,不同的语言,不同的国家和地区采用不同的Locale对象来表示。
(2)java.util.ResourceBundle:该类称为资源包,包含特定语言环境的资源对象,与特定语言环境相关的信息则通过资源包来提供。
为了实现Java程序的国际化,必须实现提供程序所需的资源文件,资源文件的内容由很多的键值对组成,其中key是程序使用的部分,value是程序界面的显示。
资源文件的命名有如下三种方式:
1-baseName.properties
2-baseName_language.properties
3-baseName_language_country.properties
其中,baseName是资源文件的基本名称,有用户自定义,但是language和country必须是Java所支持的语言和国家/地区代码,例如:
中国大陆:basenName_zh_CN.properties
美国:baseName_en_US.properties
Java支持的语言和国家
实际上,Java并不能支持所有的语言和国家,如果需要获取Java所支持的语言和国家,需要使用Locale类的getAvailableLocales方法获取,该方法 返回一个Locale数组,该数组包含了Java所支持的国家和语言。
import java.util.Locale;
public class Main {
public static void main(String[] args) {
//返回Java所支持的语言的国家和数组
Locale [] locales = Locale.getAvailableLocales() ;
//遍历数组元素,依次获取所支持的国家和语言
for(int i=0; i<locales.length; i++){
//打印所支持的国家和语言
System.out.println(locales[i].getDisplayCountry() + "=" + locales[i].getCountry() + " " + locales[i].getDisplayLanguage() + "=" + locales[i].getLanguage()) ;
}
}
}
Java程序的国际化
假设有个简单的Java程序,如下所示:
public class Main {
public static void main(String[] args) {
System.out.println("我要向不同国家的人民问好:您好") ;
}
}
为了让程序支持国际化,我们需要将"我要向不同国家的人民问好:您好"对应不同语言的字符串,定义在不同的资源文件。
在src目录下,新建文件messageResource_zh_CN.properties和messageResource_en_US.properties
两个文件中中的资源分别为:
hello = 我要向不同国家的人民问好:您好!
hello = I want to say hello to all world!
然后编写程序,根据系统默认的语言环境加载资源文件,根据key,输出value,程序如下:
import java.util.Locale;
import java.util.ResourceBundle;
public class TestI18N {
public static void main(String[] args) {
//取得系统默认国家的语言环境
Locale lc = Locale.getDefault();
//根据国家语言环境加载资源文件
ResourceBundle rb = ResourceBundle.getBundle("messageResource", lc);
//打印从资源文件中获取的信息
System.out.println(rb.getString("hello"));
}
}
上述程序中语句打印的内容是从资源文件中读取的信息,如果在中文环境下运行程序,将打印 我要向不同国家的人民问好:您好!如果在控制面板将计算机的语言环境设置为美国,将打印I want to say hello to all world!
需要注意的是,如果程序找不到对应国家/语言的资源文件,系统将怎么办?假设以中文环境为例:
将依次搜索以下文件:
messageResource_zh_CN.properties
messageResource_zh.properties
messageResource.properties
如果上面三个文件都找不到,则系统将出现异常。
带占位符的国际化信息
在资源文件中消息文本可以带参数,例如::
welcome={0},欢迎学习SpringMVC,今天是星期{1}
花括号中的数字是一个占位符,可以动态的数据替换,在消息文本中占位符可以使用0-9的数字,也就是说消息文本中的参数最多只有10个。
如果要替换文本中的占位符,可以使用java.text.MessageFormat类,该类提供一个静态方法format,用来格式化带参数的文本。
import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;
public class TestFormat {
public static void main(String[] args){
//取得系统默认的国家语言环境
Locale lc = Locale.getDefault() ;
//根据国家语言环境 加载资源文件
ResourceBundle rb = ResourceBundle.getBundle("messageResource", lc) ;
//从资源文件中获取信息
String msg = rb.getString("welcome") ;
//替换占位符
String msgFor = MessageFormat.format(msg, "我", "5") ;
System.out.println(msgFor) ;
}
}
运行结果如下
SpringMVC的国际化
SpringMVC的国际化是建立在Java国际化基础之上的,SpringMVC框架的底层国际化与Java国际化是一致的,作为一个良好的MVC框架,SpringMVC将Java国际化的功能进行封装和简化,开发者使用起来会更加简单,快捷。
国际化和本地化应用程序时,需要具备以下两个条件:
1-将文本信息放到资源属性文件中。
2-选择和读取正确位置的资源属性文件。
SpringMVC中不能直接使用ResourceBundle加载资源文件,而是利用bean告知SpringMVC框架要将资源属性文件放到哪里。
语言区域的选择
在SpringMVC中可以使用语言区域解析器bean选择语言区域,该bean有3个常见的实现,即AcceptHeaderLocaleResolver,SessionLocaleResolver和CookieLocaleResolver。
使用SessionLocaleResolver和CookieLocaleResolver实现bean的定义,必须配置LocaleChangeInterceptor拦截器。
使用message标签显示国际化信息
在SpringMVC框架中可以使用Spring的message标签在JSP页面中显示国际化消息。在使用message标签的时候,需要在JSP页面前使用taglib指令声明spring标签,代码如下:
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
message标签有以下常用属性:
code:获得国际化消息的key
arguments:代表该标签的参数
argumentSeparator:用来分割该标签参数的字符,默认为逗号
text:code属性不存在,或者指定的key无法获取消息时显示默认文本信息。
用户自定义切换语言示例
在许多成熟的商业软件系统中,可以让用户自由切换语言,而不是修改浏览器的语言设置。
1-在IDEA中创建web应用ch15-2,在该应用的WEB-INF目录下创建目录lib,在lib目录下导入SpringMVC的相关jar包,并把ib添加为项目库。
2-创建国际化资源文件,在WEB-INF目录下创建英文和中文资源文件message_en_US.properties和message_zh_CN.properties
message_en_US.properties文件:
first = first
second = second
third = {0} third {1}
language.en = English
language.cn = Chinese
message_zh_CN.properties文件:
first = 第一页
second = 第二页
third = {0} 第三页 {1}
language.cn = 中文
language.en = 英文
3-创建视图JSP页面,在WEB-INF目录下创建jsp页面,即first.jsp second.jsp third.jsp
first.jsp:
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%--
Created by IntelliJ IDEA.
User: nuist__NJUPT
Date: 2021/8/13
Time: 17:25
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href = "${pageContext.request.contextPath}/i18nTest?locale=zh_CN">
<spring:message code = "language.cn"/>
</a>
<a href = "${pageContext.request.contextPath}/i18nTest?locale=en_US">
<spring:message code = "language.en"/>
</a>
<spring:message code = "first"/>
<a href = "${pageContext.request.contextPath}/my/second">
<spring:message code = "second"/>
</a>
</body>
</html>
second.jsp:
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%--
Created by IntelliJ IDEA.
User: nuist__NJUPT
Date: 2021/8/13
Time: 17:26
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<spring:message code = "second"/>
<a href = "${pageContext.request.contextPath}/my/third">
<spring:message code = "third" arguments="888,9999"/>
</a>
</body>
</html>
third.jsp:
<%--
Created by IntelliJ IDEA.
User: nuist__NJUPT
Date: 2021/8/13
Time: 17:26
To change this template use File | Settings | File Templates.
--%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<spring:message code = "third" arguments="888,9999"/>
<a href = "${pageContext.request.contextPath}/my/first">
<spring:message code = "first"/>
</a>
</body>
</html>
4-创建控制器类,在src目录下创建包controller,在该包中创建两个控制器I18NTestController和MyController,第1个控制器类用于处理语言种类选择请求,第2个控制类用于进行页面导航。
I18NTestController类:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Locale;
@Controller
public class I18NTestController {
@RequestMapping("/i18nTest")
public String first(Locale locale){
return "first" ;
}
}
MyController类:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/my")
public class MyController {
@RequestMapping("/first")
public String first(){
return "first" ;
}
@RequestMapping("/second")
public String second(){
return "second" ;
}
@RequestMapping("/third")
public String third(){
return "third" ;
}
}
5-在web.xml中部署DispatcherServlet,配置 CharacterEncodingFilter解决中文乱码问题。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
id = "WebApp_ID" version="4.0">
<!--部署DispatcherServlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/springmvc-servlet.xml</param-value>
</init-param>
<!--表示容器启动时加载的servlet-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--任意的请求都通过DispatcherServlet-->
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 配置 CharacterEncodingFilter解决中文乱码问题-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!-- 配置编码格式为UTF-8 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
6-创建配置文件,在WEB-INF目录下创建SpringMVC的配置文件,在该配置文件中扫描指定的包,使得注解生效,配置视图解析器,配置国际化拦截器,存储区域设置信息,加载国际化资源文件。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--使用扫描机制,扫描控制器类,使得注解生效-->
<context:component-scan base-package="controller"/>
<!--配置视图解析器-->
<bean class = "org.springframework.web.servlet.view.InternalResourceViewResolver" id = "internalResourceViewResolver">
<!--前缀-->
<property name = "prefix" value = "/WEB-INF/jsp/"/>
<!--后缀-->
<property name = "suffix" value = ".jsp"/>
</bean>
<!--国际化操作拦截器,如果采用 基于Session/Cookie则必须配置-->
<mvc:interceptors>
<bean class = "org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
</mvc:interceptors>
<!--存储区域设置,默认设置为中文环境-->
<bean id = "localeResolver" class = "org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale" value="zh_CN"></property>
</bean>
<!--加载国际化资源文件-->
<bean id = "messageSource" class = "org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name = "basename" value = "/WEB-INF/resource/messages"/>
<property name="defaultEncoding" value="GBK"/>
</bean>
</beans>
7-发布应用到tomacat,启动tomcat服务器,然后通过地址:http://localhost:8080/ch15_2_war_exploded/my/first
测试页面
中文环境下的前3页如下:
英文环境下的前3页:
以上是关于程序的国际化(Java与SpringMVC)的主要内容,如果未能解决你的问题,请参考以下文章