利用数据库管理国际化资源配置以及自定义标签实现国际化效果
对于国际化资源的管理一般采用.properties进行配置,对于资源信息的修改或新增国际化资源文件均需要重启服务才能生效,将包括国际化资源在内的系统信息存储在数据库中,并在启动服务的同时读取并纳入缓存,即可以实现系统配置信息的即时生效。
对于国际化资源的存储表结构如下:
基于国际化资源表建立国际化资源管理的增删改查模块,一经修改即更新缓存,同时利用自定义标签更新国际化效果。后端的国际化即是从缓存中读取资源,然后对应替换。以下自定义标签的国际化实现方案主要针对页面以及js。
获取国际化资源的方法:
/** * 获取所有国际化资源 * @author chao.gao * @date 2013-12-30 上午10:51:39 * @return Map<language,Map<moduleName,Map<key,value>>> */ private Map<String,Map<String,String>> getAllMsgs() { Map<String, Map<String, String>> i8nMap = new HashMap<String, Map<String, String>>(); Map<String, String> map = new HashMap<String, String>(); Locale defaultLocale = Locale.getDefault(); I18nresourceEntity queryEntity = new I18nresourceEntity(); queryEntity.setLanguage(defaultLocale.getLanguage()); List<I18nresourceEntity> i18nresourceEntityListLocacle = queryI18nresourceList(queryEntity); if (!CollectionUtils.isEmpty(i18nresourceEntityListLocacle)) { for (I18nresourceEntity entity : i18nresourceEntityListLocacle) { map.put(entity.getI18nKey(), entity.getI18nValue()); i8nMap.put(entity.getModuleName(), map); } } return i8nMap; }
下面介绍一下利用JSP2.0提供的tagext功能的自定义标签实现页面的国际化效果。tagext 包是提供自定义标签的相关类, 当你需要开发JSP的自定义标签,那你的tablib的类就必须继承或者实现tagext 包中的类。tagext 即对tag的扩展。
首先,我们自定义标签类,必须继承SimpleTagSupport
本例中,自定义标签定义类代码如下:
/** * * JS国际化标签 * @author chao.gao * @date 2014-1-14 下午2:14:22 * @version <b>1.0.0</b> */ public class I18nJsTag extends SimpleTagSupport implements IJspTag { private String id; private String moduleName; /** * @author chao.gao * @date 2013-12-31 下午1:31:25 * @see javax.servlet.jsp.tagext.SimpleTagSupport#doTag() * @throws JspException * @throws IOException */ public void doTag() throws JspException, IOException { I18nJsTagAdapter.getI18njsptagAdapter().doTag(this, getJspContext()); } /** * 获得id * @return String */ public String getId() { return id; } /** * 设置id * @param id */ public void setId(String id) { this.id = id; } /** * 获得moduleName * @return String */ public String getModuleName() { return moduleName; } /** * 设置moduleName * @param moduleName */ public void setModuleName(String moduleName) { this.moduleName = moduleName; } }
自定义标签处理类,简单自定义标签可以直接在doTag中定义该逻辑
/** * @author chao.gao * @date 2013-12-31 下午3:58:06 * @version <b>1.0.0</b> */ public class I18nJspTagAdapter { private static final Map<String, Map<String, String>> I18NMAP = new ConcurrentHashMap<String, Map<String, String>>(); private static final I18nJspTagAdapter I18NJSPTAGADAPTER = new I18nJspTagAdapter(){}; private I18nJspTagAdapter() { } /** * * @author chao.gao * @date 2013-12-12 下午9:54:27 * @see com.gaochao.platform.web.tag.IJspTagSpi#doTag(com.fx.platform.web.tag.IJspTag, javax.servlet.jsp.JspContext) * @param jspTag * @param jspContext * @throws IOException */ public void doTag(IJspTag jspTag, JspContext jspContext) throws IOException { I18nTag i18nTag = (I18nTag) jspTag; String moduleName = i18nTag.getModuleName(); String key = i18nTag.getKey(); if (StringUtils.isBlank(moduleName) || StringUtils.isBlank(key) || StringUtils.isEmpty(moduleName) || StringUtils.isEmpty(key)) { return; } String message = I18NMAP.get(moduleName) == null ? "" : I18NMAP.get(moduleName).get(key); jspContext.getOut().write(message); } public static I18nJspTagAdapter getI18njsptagAdapter() { return I18NJSPTAGADAPTER; } public void putI18nresourceMap(Map<String, Map<String, String>> i18nMap) { I18nJspTagAdapter.I18NMAP.putAll(i18nMap); } }
然后编写描述符配置文件tagext.tld放置在META-INF下
<?xml version="1.0" encoding="UTF-8"?> <taglib 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/j2eeweb-jsptaglibrary_2_0.xsd" version="2.0"> <description>fx jsp tag </description> <tlib-version>2.2</tlib-version> <short-name>gaochao</short-name> <jsp-version>2.0</jsp-version> <uri>/gaochao</uri> <tag> <name>i18n</name> <tag-class>com.gaochao.platform.web.tag.impl.I18nTag</tag-class> <body-content>empty</body-content> <attribute> <name>moduleName</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>id</name> <required>false</required> </attribute> <attribute> <name>key</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag> <tag> <name>i18nJs</name> <tag-class>com.gaochao.platform.web.tag.impl.I18nJsTag</tag-class> <body-content>empty</body-content> <attribute> <name>moduleName</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>id</name> <required>false</required> </attribute> </tag> </taglib>
先行添加国际化信息language=”zh”,moduleName=”sys”,key=”type”,value=”类型:”
然后在jsp页面添加
<%@ taglib uri="/gaochao" prefix="g"%>
原代码:
<td>类型:</td>
替换后:
<td><p:i18n moduleName=”sys” key=”type”></td>
以上是jsp页面的国际化标签,下面是js的自定义标签逻辑处理类,其定义类基本与jsp自定义标签相同,而描述信息在上文的tagext.tld中已有定义。
/** * * @author chao.gao * @date 2013-12-12 下午9:54:27 * @see com.gaochao.platform.web.tag.IJspTagSpi#doTag(com.fx.platform.web.tag.IJspTag, javax.servlet.jsp.JspContext) * @param jspTag * @param jspContext * @throws IOException */ public void doTag(IJspTag jspTag, JspContext jspContext) throws IOException { I18nJsTag i18nTag = (I18nJsTag) jspTag; String moduleName = i18nTag.getModuleName(); if (StringUtils.isBlank(moduleName) || StringUtils.isEmpty(moduleName)) { return; } Map<String, String> message = I18NMAP.get(moduleName); StringBuilder msgObject = new StringBuilder(""); msgObject.append("<script type=‘text/javascript‘> \n"); if(message != null){ msgObject.append("var i18nJs={"); Iterator<String> it = message.keySet().iterator(); while(it.hasNext()){ String element = it.next(); msgObject.append("\"" + element + "\":\"" + message.get(element) + "\","); } msgObject.deleteCharAt(msgObject.length() - 1); msgObject.append("}"); } msgObject.append("</script>"); jspContext.getOut().write(msgObject.toString()); }
从以上的逻辑可以看出,通过该自定义标签,我们生成一段js代码,在代码中定义了一个类似map的变量,在该jsp中引用的js均可以利用i18nJs这个变量获取想要的国际化信息。