IT序号网

Spring国际化实现

qq123 2022年03月21日 编程语言 291 0

本文使用的环境:

Spring+SpringMvc+Mybatis+JSP

一、简介

本文主要介绍了Spring国际化的配置,以及java、jsp和js的使用。

所谓的国际化就是一个系统支持多种语言,可来回切换语言,本文以中英双语举例来实现国际化。

二、实现步骤

1、加载国际化的配置文件

在实现国际化之前,首先要加载相关的资源文件,即消息源,这个功能由Spring MVC提供的MessageSource接口完成,并且有四个非抽象的实现类:

  • StaticMessageSource:主要用于程序测试,它允许通过编程的方式提供国际化信息 ;
  • DelegatingMessageSource:消息源解析委派类(用户未指定时,SpringContext默认使用当前类),功能比较简单:将字符串和参数数组格式化为一个消息字符串 ;
  • ResourceBundleMessageSource:由JDK提供的Bundle实现,只能把文件放置在对应的类路径下,不具备热加载功能,只有重启系统才能重新加载;
  • ReloadavleResourceBundleMessageSource:可以把文件放置在任何地方,并且在不重启系统的前提下也能重新加载资源文件,这样就可以在程序运行期修改并重新加载资源文件;

2、配置国际化解析器

即解析当前使用什么语言,Spring MVC中提供了以下四个实现类:

  • AcceptHeaderLocaleResolver:spring默认的区域解析器,它通过校验http请求的accept-language头部来解析区域。这个头是由web浏览器根据底层操作系统的区域设置,这个区域无法改变用户的区域,所以只能根据操作系统设置而获取,一般不使用;
  • FixedLocaleResolver:使用固定的locale国际化,也是不可修改;
  • CookieLocaleResolver:根据cookie数据获取国际化数据,但是如果用户禁止或没有设置cookie,就会根据http头中的accept-language来获取;
  • SessionLocaleResolver:根据session进行国际化,即根据用户设置session的变量进行读取;

3、配置拦截器

为了修改语言,Spring MVC还提供了一个拦截器-LocaleChangeInterceptor,通过它可以获取参数,然后根据参数来改变语言;

三、配置实例

1、在Springmvc的配置文件中添加如下配置

<!--国际化配置 --> 
    <!-- 第一步:配置消息源MessageSource用来加载对应的国际化属性文件:bean的ID名称只能是messageSource --> 
    <!--配置ReloadableResourceBundleMessageSource:这种方式只能把资源文件放到任何位置,不需要重启就能加载文件,并且可以设置刷新时间 --> 
    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> 
        <!-- 默认编码方式 --> 
        <property name="defaultEncoding" value="UTF-8" /> 
        <!-- 资源文件的前缀:多了一个classpath,如果资源文件在一个文件夹下,还要加上文件夹路径,否则报错 --> 
        <!-- 一个资源文件配置方法 --> 
        <property name="basename" value="classpath:msg"></property> 
         
        <!-- 多个资源文件配置方法,如果配置了多个,程序会按照配置顺序从文件中查找,如果在第一个    文件中找到后,就直接返回了,不会再往下找 --> 
		<!-- <property name="basenames"> 
			<set> 
				<value>classpath:msg</value> 
				<value>classpath:dict</value> 
			</set> 
		</property> --> 
        <!-- 刷新时间 --> 
        <property name="cacheSeconds" value="3600" /> 
        <!--   设置“useCodeAsDefaultMessage”,默认为false,这样当Spring在ResourceBundle中找不到messageKey的话,就抛出NoSuchMessageException,   把它设置为True,则找不到不会抛出异常,而是使用messageKey作为返回值。由于我想看到报错但是又想要这个效果信息,所以此处不做配置,在获取值得工具类中手动写代码返回 --> 
        <!-- <property name="useCodeAsDefaultMessage" value="true" />--> 
    </bean> 
 
    <!-- 第二步:配置国际化解析器,有cookie和session两种方式,用户指定语言后,会把参数存到cookie或session中 --> 
	<!--配置session国际化解析器 --> 
    <!-- <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"> 
    	<property name="defaultLocale" value="zh_CN" /> 
    </bean> --> 
     
    <bean id="localeResolver" 
        class="org.springframework.web.servlet.i18n.CookieLocaleResolver"> 
        <!-- cookie变量的名称 --> 
        <property name="cookieName" value="fylanguage" /> 
        <!-- cookie超时时间,一个月 --> 
        <property name="cookieMaxAge" value="2592000" /> 
		<!-- 默认语言:默认使用简体英文,若果不配置默认值,就会使用浏览器请求头中accept-  
           language --> 
		<property name="defaultLocale" value="en_us" /> 
    </bean> 
	 
    <!-- 配置国际化拦截器,当用户访问系统带language参数时,就会把参数存到session中 --> 
    <mvc:interceptors> 
        <mvc:interceptor> 
            <mvc:mapping path="/**" /> 
            <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"> 
                <property name="paramName" value="language" /> 
            </bean> 
        </mvc:interceptor> 
    </mvc:interceptors>

2、在resources目录下新建一个文件夹叫msg如图(1),在msg目录下新建两个文件msg_en_US.properties和msg_zh_CN.properties,分别存中文和英文如图(2)和图(3)

图(1)

图(2)

图(3)

所有的配置到此完成,下面开始使用。

四、使用方法

1、java的获取方法

RequestContext requestContext = new RequestContext(R.getRequest()); 
String message=requestContext.getMessage("刷新");

2、jsp获取方法

可使用<spring:message>标签来获取值

(1)页面中引入Spring标签,

<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>

(2)使用方法

<spring:message code="刷新" />

页面:

执行结果:

五、优化使用方法

由于java和jsp的调用写法有点长,所以我写了一个工具类,工java、jsp和js来使用。

1、java工具类

package com.sicheng.common.utils; 
 
import com.sicheng.common.web.R; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.web.servlet.support.RequestContext; 
 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.nio.charset.StandardCharsets; 
import java.util.HashMap; 
import java.util.Map; 
import java.util.Properties; 
import java.util.Set; 
 
/** 
 * 翻译工具类(获取国际化配置文件的值) 
 * @author fanxiuixu 
 * @version 2019-11-20 
 */ 
public class FYUtils { 
	private static Logger logger = LoggerFactory.getLogger(FYUtils.class); 
 
	/** 
	 * 根据键和参数获取国际化值 
	 * @param key 键 
	 * @param params 参数,可变参数 
	 * @return 
	 */ 
	public static String fyParams(String key, String... params){ 
		String message=key; 
		try { 
			RequestContext requestContext = new RequestContext(R.getRequest()); 
			message=requestContext.getMessage("刷新"); 
	        message = requestContext.getMessage(key,params); 
		} catch (Exception e) { 
			message=key; 
			logger.error("获取国际化值发生错误",e); 
		} 
		return message; 
	} 
 
	/** 
	 * 根据键获取国际化值 
	 * @param key 键 
	 * @return 
	 */ 
	public static String fy(String key){ 
		return fyParams(key); 
	} 
 
	/** 
	 * 根据键获取国际化值 
	 * @param key 键 
	 * @param param 参数 
	 * @return 
	 */ 
	public static String fyParam(String key,String param){ 
		return fyParams(key,param); 
	} 
 
	/** 
	 * 获取resources文件夹下的porperties文件中的内容 
	 * @param name properties文件名称 
	 * @return 
	 */ 
	public static Map<String, String> getFYProperties(String name) { 
		Map<String, String> map = new HashMap<>(); 
		InputStream in = null; 
		Properties p = new Properties(); 
		try { 
			in = FYUtils.class.getClassLoader().getResourceAsStream(name); 
			p.load(new InputStreamReader(in, StandardCharsets.UTF_8));//properties文件,不用unicode编码的实现方法 
		} catch (Exception e) { 
			// TODO Auto-generated catch block 
			e.printStackTrace(); 
		} 
		Set<Map.Entry<Object, Object>> entrySet = p.entrySet(); 
		for (Map.Entry<Object, Object> entry : entrySet) { 
			map.put((String) entry.getKey(), (String) entry.getValue()); 
		} 
		return map; 
	} 
 
} 

2、jsp工具类

3、js工具类

(1)、写一个接口,读取后台的配置文件

@Controller 
@RequestMapping(value = "${frontPath}/fy") 
public class FYController extends BaseController { 
    private static Logger logger = LoggerFactory.getLogger(FYController.class); 
 
    /** 
     * 获取国际化properties文件内容 
     * @return 
     */ 
    @ResponseBody 
    @RequestMapping(value = "poperties") 
    public Map<String, Object> poperties() { 
        Map<String, String> cnMap = FYUtils.getFYProperties("msg/msg_zh_CN.properties"); 
        Map<String, String> enMap = FYUtils.getFYProperties("msg/msg_en_US.properties"); 
 
        Map<String,Object> dataMap=new HashMap<>(); 
        dataMap.put("cnMap",cnMap); 
        dataMap.put("enMap",enMap); 
        return dataMap; 
    } 
 
}

(2)、写一个js方法,用来获取值

(function(){ 
    //fy命名空间,起隔离作用,防止同名变量冲突 
    //fy是国际化翻译的简写 
    if(!window.fy) {window.fy={};} 
 
    //根据当前环境获取中文值或英文值 
    fy.getMsg=function (key, ...rest) { 
        if(localStorage.getItem("adminFycnMap")==null || localStorage.getItem("adminFyenMap")==null){ 
            $.ajax({ 
                type:"GET", 
                url:ctxa+"/fy/poperties.do", 
                data:{}, 
                async:false, 
                //请求成功 
                success : function(data) { 
                    localStorage.setItem("adminFycnMap",JSON.stringify(data.cnMap)); 
                    localStorage.setItem("adminFyenMap",JSON.stringify(data.enMap)); 
                } 
            }); 
        } 
 
        //先从cookike中获取值 
        var language=fdp.cookie('fylanguage'); 
        if(typeof(language)=="undefined" || language == null){ 
            language=navigator.language; 
        } 
        //中文 
        var fycnStr=localStorage.getItem('adminFycnMap'); 
        var fycnMap=JSON.parse(fycnStr); 
        //英文 
        var fyenStr=localStorage.getItem("adminFyenMap"); 
        var fyenMap=JSON.parse(fyenStr); 
        var str=""; 
        if('zh_CN'==language || "zh-CN"==language){ 
            str=fycnMap[key]; 
        }else{ 
            str=fyenMap[key]; 
        } 
        if(""==str){ 
            return key; 
        } 
        let arr = rest; 
        arr.forEach((item => { 
            console.log(item) 
            str = str.replace(/(\{\w\})/, item) 
        })) 
        return str; 
    } 
})(); 

4、使用方法

1、java调用方法:

//没有参数 
String fy1=FYUtils.fyParams("查询"); 
  
//一个参数 
String fy2=FYUtils.fyParams("关闭","参数"); 
  
//多个参数 
String fy3=FYUtils.fyParams("保存","参数1","参数2","参数3");

2、jsp调用方法

<!-- 没有参数 --> 
${fns:fy('查询')} 
  
<!-- 一个参数 --> 
${fns:fyParam('关闭','参数1')} 
  
<!-- 多个参数 --> 
${fns:fyParams('保存','参数1','参数2','参数3')}

3、js调用方法

//没有参数 
var name=fy.getMsg('查询'); 
  
//一个参数 
var str = fy.getMsg('关闭', '参数1'); 
  
//多个参数 
var str = fy.getMsg('保存', '参数1','参数2', '参数3');

评论关闭
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!