自定义 i18n国际化
java服务器代码
本逻辑是为每一个httpsesion创建一个i18n对象,和用户登录无关
新建Tag标签类 I18nTag.java
import java.io.IOException;
import java.util.Map;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import org.apache.commons.lang3.StringUtils;
public class I18nTag extends SimpleTagSupport{
private String value;
@Override
public void doTag() throws JspException, IOException{
PageContext pageContext=(PageContext) super.getJspContext();
HttpSession session=pageContext.getSession();
@SuppressWarnings("unchecked")
Map<String,String> i18nMap=(Map<String, String>) session.getAttribute("i18n");
String result=getValue();
if(StringUtils.isBlank(result)) {
result="";
}else {
result=i18nMap.get(getValue());
if(StringUtils.isBlank(result)) {
result="";
}
}
pageContext.getOut().write(result);
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
新建i18n.tld文件
tld文件需要放在WEB-INF 下面
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">
<tlib-version>1.0</tlib-version>
<jsp-version>2.0</jsp-version>
<short-name>i18n</short-name>
<uri>http://java.sun.com/i18n</uri>
<tag>
<name>i18n</name>
<tagclass>com.shine.pb.taglib.I18nTag</tagclass>
<info>i18n</info>
<body-content>empty</body-content>
<attribute>
<name>value</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
<description>文档加载完毕了再执行脚本</description>
</attribute>
</tag>
</taglib>
新建i18n过滤器 I18nFilter.java
import java.io.IOException;
import java.util.Map;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang3.StringUtils;
import com.util.I18nUtils;
public class I18nFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse rsp, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) rsp;
String url = request.getRequestURI();
if (!(StringUtils.isNotBlank(url) && url.indexOf("i18nSet") > -1)) {
HttpSession session = request.getSession();
String i18nType = (String) session.getAttribute(I18nUtils.i18nType);
if (StringUtils.isBlank(i18nType) || !I18nObject.getLocaleType(session).equals(i18nType)) {
session.removeAttribute(I18nUtils.i18n);
session.removeAttribute(I18nUtils.i18nType);
I18nObject i18nObject = new I18nObject();
I18nObject.setLocaleType(session, i18nType);
Map<String, String> map = i18nObject.getShowDatas(session);
session.setAttribute(I18nUtils.i18n, map);
i18nType = StringUtils.isBlank(i18nType) ? I18nUtils.zh_CN : i18nType;
session.setAttribute(I18nUtils.i18nType, i18nType);
}
}
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
新建设置i18n参数的servlet,I18nSetTypeServlet.java
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.util.I18nUtils;
/**
* 设置i18n的参数
* @author callens
*
*/
public class I18nSetTypeServlet extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = -6378531597637970751L;
private Logger log = LoggerFactory.getLogger(I18nSetTypeServlet.class);
@Override
protected void doGet(HttpServletRequest rerquest, HttpServletResponse response) throws ServletException, IOException {
String i18nType=(String) rerquest.getParameter(I18nUtils.i18nType);
if(StringUtils.isBlank(i18nType)) {
}
if(StringUtils.isNotBlank(i18nType)&&(I18nUtils.zh_CN.equals(i18nType)||I18nUtils.en_US.equals(i18nType))) {
HttpSession session=rerquest.getSession();
session.setAttribute(I18nUtils.i18nType, i18nType);
}else {
log.error("i18nType param is error,i18nType value is {}",i18nType);
}
}
}
在web.xml里面配置
<filter><!-- 写入i18n -->
<filter-name>i18nFilter</filter-name>
<filter-class>com.filter.i18n.I18nFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>i18nFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>i18nSet</servlet-name>
<servlet-class>com.filter.i18n.I18nSetTypeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>i18nSet</servlet-name>
<url-pattern>/i18nSet</url-pattern>
</servlet-mapping>
新建i18n参数类,I18nUtils.java
package com.util;
public class I18nUtils {
public static final String i18nType="i18nType";
public static final String zh_CN="zh_CN";
public static final String en_US="en_US";
public static final String i18n="i18n";
}
创建i18存储的内存环境,I18nSingle.java
package com.filter.i18n;
import java.util.Map;
import java.util.WeakHashMap;
import javax.servlet.http.HttpSession;
/**
* why 为什么会出现这个类呢
* 是因为i18n的存储条件为httpSession范围
* 使用其单例模式,避免出现多对象
* 其存储了一个map对象,该map对象保存每个httpsession对应的i18n的类型
* 按理说也可以使用缓存技术的,但还是需要删除缓存,这个时间应该和session时间过期一致
* //map对象使用弱引用,省去了删除key键的操作
* //为何使用弱引用,是因为不知道httpSession何时销毁,这个销毁操作应该是tomcat容器进行控制的
* //如果使用tomcat容器的代码,势必会嵌入更多的逻辑,为其减少代码的逻辑量,在此处使用弱引用
* //何为弱引用,但key值没用对应的对象引用,则弱引用map会在gc回收的时候进行销毁此键值对
* @author callens
*
*/
public class I18nSingle {
private Map<HttpSession, String> map = new WeakHashMap<>();
// 使用volatile 保证其可见性,在多并发中保证其原子性
volatile private static I18nSingle i18nSingle = null;
public static I18nSingle getInstance() {
try {
if (i18nSingle != null) {
} else {
synchronized (I18nSingle.class) {
if (i18nSingle == null) {
i18nSingle = new I18nSingle();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return i18nSingle;
}
public String getLocaleType(HttpSession session) {
return map.get(session);
}
public void setLocaleType(HttpSession session,String localeType) {
map.put(session, localeType);
}
}
读取i18n的配置对象,I18nProperties.java
package com.filter.i18n;
import java.util.Locale;
import java.util.ResourceBundle;
/**
* 读取i18n的配置文件
* @author callens
*
*/
public class I18nProperties {
public ResourceBundle getLocale() {
Locale locale=new Locale("zh", "cn");//设置语言环境
ResourceBundle resource = ResourceBundle.getBundle("i18n",locale);
return resource;
}
public ResourceBundle getLocaleUS() {
Locale locale=new Locale("en", "US");//设置语言环境
ResourceBundle resource = ResourceBundle.getBundle("i18n",locale);
return resource;
}
}
创建i18n对象,I18nObject.java
package com.filter.i18n;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang3.StringUtils;
import com.util.I18nUtils;
/**
* 创建i18n对象
* @author callens
*
*/
public class I18nObject {
private I18nProperties properties=new I18nProperties();
public Map<String,String> getShowDatas(HttpSession session){
Map<String,String> datas=new HashMap<>();
ResourceBundle resource=getResource(session);
Enumeration<String> enumeration=resource.getKeys();
String key;
while(enumeration.hasMoreElements()) {
key=enumeration.nextElement();
datas.put(key, resource.getString(key));
}
return datas;
}
/**
* 获取配置文件
* @return
*/
private ResourceBundle getResource(HttpSession session) {
ResourceBundle resource;
String localeType=getLocaleType(session);
if(StringUtils.isNotBlank(localeType)) {
if(I18nUtils.zh_CN.equals(localeType)) {
resource=properties.getLocale();
}else {
resource=properties.getLocaleUS();
}
}else {
resource=properties.getLocale();
}
return resource;
}
public static String getLocaleType(HttpSession session) {
String localeType=I18nSingle.getInstance().getLocaleType(session);
return StringUtils.isBlank(localeType)?I18nUtils.zh_CN:localeType;
}
public static void setLocaleType(HttpSession session,String i18nType) {
I18nSingle.getInstance().setLocaleType(session, i18nType);
}
}
web 页面代码
切换中英文页面代码
<div class="nice-select" name="nice-select">
<input type="text" id="i18nValue" value="中" readonly="readonly" />
<ul>
<li class="on">中</li>
<li>English</li>
</ul>
</div>
i18页面样式
/*下拉框 start*/
.nice-select {
float:right;
width: 35px;
background: url(../images/wl2.png) 28px 10px no-repeat;
height: 24px;
line-height: 24px;
text-align: left;
position: relative;
cursor: pointer;
box-sizing: content-box;
padding-top: 9px;
margin-right: -10px;
margin-left: 10px;
}
.nice-select:hover{
background-position: 28px -14px;
}
.nice-select.on{
background-position: 28px -35px;
}
.nice-select input {
display: block;
width: 50px;
height: 24px;
line-height: 24px;
border: 0;
outline: 0;
background: none;
color: #999;
cursor: pointer;
text-align: center;
}
.nice-select ul {
width: 50px;
display: none;
position: absolute;
left: 0;
top: 26px;
overflow: hidden;
background-color: #fff;
z-index: 4;
border-radius: 3px;
box-shadow: 0 4px 10px rgba(0,0,0,0.1);
border: 1px solid #efefef;
top: 35px;
}
.nice-select ul li {
height: 32px;
line-height: 32px;
font-size: 12px;
color: #666;
overflow: hidden;
text-align: center;
cursor: pointer;
text-align: center;
}
.nice-select ul li:hover{
background: #fce8e9;
}
.nice-select ul .on,.nice-select ul li.on:hover {
cursor: default;
background-color: #fafafa;
color: #ccc;
}
i18n JS代码
$(document).ready(function(){
bindClick();
initI18n();
});
function bindClick(){
$('[name="nice-select"]').click(function(e) {
$('[name="nice-select"]').find('ul').hide();
$(this).find('ul').show();
$(this).addClass("on").siblings('[name="nice-select"]').removeClass("on")
e.stopPropagation(); //阻止冒泡事件
});
$('[name="nice-select"] li').click(function(e) {
$(this).addClass("on").siblings().removeClass("on");
$(this).parents('[name="nice-select"]').removeClass("on");
var val = $(this).text();
$(this).parents('[name="nice-select"]').find('input').val(val);
$('[name="nice-select"] ul').hide();
e.stopPropagation();
setI18nType(val);
});
$(document).click(function() {
$('[name="nice-select"]').removeClass("on")
$('[name="nice-select"] ul').hide();
});
}
function initI18n(){
if(i18nType!=""){
let i18nTypeValue="中";
if(i18nType=="en_US"){
i18nTypeValue="English";
}
$("#i18nValue").val(i18nTypeValue);
$('[name="nice-select"] li').each(function(i,value){
let i18Value=$(value).text();
if(i18Value==i18nTypeValue){
$(value).addClass("on").siblings().removeClass("on");
$(value).parents('[name="nice-select"]').removeClass("on");
$(value).parents('[name="nice-select"]').find('input').val(i18Value);
}
});
}
}
function setI18nType(value){
let i18nTypeValue="zh_CN";
if(value=="English"){
i18nTypeValue="en_US";
}
let url="/i18nSet?i18nType="+i18nTypeValue;
$.ajax({
type:"GET",
url:url,
success:function(result){
window.location.reload();
},
error:function(e){
console.log(e);
}
});
}
i18n在页面上如何进行使用
<!-- 引入标签 -->
<%@ taglib uri="http://java.sun.com/i18n" prefix="i18n" %><!-- prefix可以进行自定义 -->
<!-- 引入css -->
<link rel="stylesheet" href="i18n.css" />
<!-- 引入js -->
<script src="i18n.js" type="text/javascript"></script>
<script type="text/javascript">
//获取i18n的中英文类型,可以从session中进行获取到
var i18nType="${sessionScope.i18nType}";
</script>
// html 可以使用标签进行获取中英文的内容,如下
<div class="searchText"><i18n:i18n value="button.search" /></div>
//在src 下创建资源文件
i18n_en_US.properties
i18n_zh_CN.properties
//数据 button.search 为在资源文件中进行配置
button.search=Search
button.search=搜索
或者
也可以直接使用 ${i18n.button} ,但这使用这种方式的话,在properties的资源文件中的KEY必须以字母开头,并且不能包含
. - 等特殊字符,需要使用下划线进行连接,个人觉得还是使用上面的方式好一点,虽然需要多写一点代码,但没有这么多限制
当然了,你也可以使用
<div class="itemNum_${session.i18nType}"></div>
这种方式,使中英文显示不同的css样式,如 itemNum_en_US/itemNum_zh_CN