使用displaytag中的titleKey无效?????????????不显示???????无法国际化???????
如何使用国际化??????
我先是尝试了网上的方法,修改属性文件中的locale.provider、locale.resolver的值为新建的I18nStruts2Adapter。。。
屡屡尝试不得结果。。。决心使用系统默认的jstl国际化方案。。。
首先,在源码中可以看到:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package testList;
/**
* Licensed under the Artistic License; you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://displaytag.sourceforge.net/license.html
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
//package org.displaytag.localization;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.jstl.core.Config;
import javax.servlet.jsp.jstl.fmt.LocalizationContext;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.taglibs.standard.tag.common.fmt.BundleSupport;
import org.displaytag.Messages;
import org.displaytag.localization.I18nResourceProvider;
import org.displaytag.localization.LocaleResolver;
/**
* JSTL implementation of a resource provider and locale resolver. It will make the <code>titleKey</code>
attribute of
* column tag works the same as fmt:message's <code>key property</code>. This tag must be the descendant of a
* <code>fmt:bundle</code> tag in order to use the titleKey. This is just a shortcut, which makes
*
* <pre>
* <display:column titleKey="bar"/>
* </pre>
*
* behave the same as
*
* <pre>
* <c:set var="foo">
* <fmt:message key="bar"/>
* </c:set>
* <display:column title="${foo}"/>
* </pre>
*
* If you don't define either <code>titleKey</code> or <code>titleKey</code> property on your column, first the
tag
* will attempt to look up the <code>property</code> property in your ResourceBundle. Failing that, it will fall
back
* to the parent class's behavior of just using the property name.
* @author Fabrizio Giustina
* @version $Revision: 1081 $ ($Author: fgiust $)
*/
public class I18nJstlAdapter implements I18nResourceProvider, LocaleResolver
{
/**
* prefix/suffix for missing entries.
*/
public static final String UNDEFINED_KEY = "???"; //$NON-NLS-1$
/**
* logger.
*/
private static Log log = LogFactory.getLog(I18nJstlAdapter.class);
/**
* Instantiates a new I18nJstlAdapter. Throw a NoClassDefFound error if BundleSupport is not available.
*/
public I18nJstlAdapter()
{
// this will check if BundleSupport is available
// if a NoClassDefFound error is thrown, the I18nJstlAdapter will not be used
BundleSupport.class.hashCode();
}
/**
* @see LocaleResolver#resolveLocale(HttpServletRequest)
*/
public Locale resolveLocale(HttpServletRequest request)
{
//System.out.println("....sdsa.f.af.as.fas.fa.....................");
Locale locale = (Locale) Config.get(request.getSession(), Config.FMT_LOCALE);
if (locale == null)
{
locale = request.getLocale();
}
return locale;
}
/**
* @see I18nResourceProvider#getResource(String, String, Tag, PageContext)
*/
public String getResource(String resourceKey, String defaultValue, Tag tag, PageContext pageContext)
{
// if titleKey isn't defined either, use property
// System.out.println("resourceKey.....................:"+resourceKey);
// System.out.println("defaultValue.....................:"+defaultValue);
String key = (resourceKey != null) ? resourceKey : defaultValue;
String title = null;
ResourceBundle bundle = null;
// jakarta jstl implementation, there is no other way to get the bundle from the parent fmt:bundle tag
Tag bundleTag = TagSupport.findAncestorWithClass(tag, BundleSupport.class);
if (bundleTag != null)
{
BundleSupport parent = (BundleSupport) bundleTag;
if (key != null)
{
String prefix = parent.getPrefix();
if (prefix != null)
{
key = prefix + key;
}
}
bundle = parent.getLocalizationContext().getResourceBundle();
}
// resin jstl implementation, more versatile (we don't need to look up resin classes)
if (bundle == null)
{
Object cauchoBundle = pageContext.getAttribute("caucho.bundle"); //$NON-NLS-1$
if (cauchoBundle != null && cauchoBundle instanceof LocalizationContext)
{
bundle = ((LocalizationContext) cauchoBundle).getResourceBundle();
// handle prefix just like resin does
String prefix = (String) pageContext.getAttribute("caucho.bundle.prefix"); //$NON-NLS-1$
if (prefix != null)
{
key = prefix + key;
}
}
}
// standard jstl localizationContest
if (bundle == null)
{
// check for the localizationContext in applicationScope, set in web.xml
LocalizationContext localization = BundleSupport.getLocalizationContext(pageContext);
if (localization != null)
{
bundle = localization.getResourceBundle();
}
}
if (bundle != null)
{
try
{
title = bundle.getString(key);
}
catch (MissingResourceException e)
{
log.debug(Messages.getString("Localization.missingkey", key)); //$NON-NLS-1$
// if user explicitely added a titleKey we guess this is an error
if (resourceKey != null)
{
title = UNDEFINED_KEY + resourceKey + UNDEFINED_KEY;
}
}
}
return title;
}
}
留意当中提到的,<display:column titleKey="bar"/>等效于<c:set var="foo"><fmt:message key="bar"/></c:set>
<display:column title="${foo}"/>
接着,我们需要确定一点,使用c:set、fmt:message 需要什么?
显然,在页面中需要导入包:
<%@ taglib uri="http://displaytag.sf.net/el" prefix="display" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
< uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
再者,我们根据上面的注释,可以得到:
有title则不会看titleKey,看titleKey时会去看你的resourceBundle。。。resourceBundle取决于你在displaytag.properties
中的对locale.provider的设定,当然,如果不设定,默认值locale.provider=org.displaytag.localization.I18nJstlAdapter
,而locale.resolver默认值为空。当然,你可以自定义国际化的方式,比如使用struts1.x,webwork等。但是struts2好像不支
持,网上有些参考代码,我前面试了,但是好像不能解决这个问题。
若以上国际化方式均失败了,则会去看property。。。。。。即数据库中的列名。。。。
再看看我自己的jsp代码:
<%--
Document : newjsp
Created on : 2011-3-5, 21:35:39
Author : xtz
--%>
< contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="http://displaytag.sf.net/el" prefix="display" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
< uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
< import="java.util.*,testList.Test" %>
<html>
<head>
<link rel="stylesheet" type="text/css" href="css/screen.css" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>displaytag</title>
</head>
<body>
<h1>Hello Displaytag!</h1>
<%
List pageList = new ArrayList();
for(int i=0;i<40;i++)
pageList.add(i, new Test("123","1","1"));
request.setAttribute("pageList", pageList);
%>
<s:form >
<s:textfield key="test" />
</s:form>
<fmt:setLocale value="en_US"/><%--格式:en_US zh_CN--%>
<fmt:bundle basename="testList.titleKeyResource"><!--资源文件的名字,注意要放在CLASSES下面-->
<fmt:message key="test" />
<display:table name="pageList" id="row" class="table" pagesize="20" export="true">
<%--注意上面:需要完整路径!--%>
<%-- title="struts2Id" title="struts2Name" 似乎是直接用来显示的,titleKey才是国际化关键key~~~
value="struts2IdValue" 不知道有什么用 --%>
<c:set var="foo">
<fmt:message key="test"/>
</c:set>
<display:column property="id" title="${foo}" />
<display:column property="name" titleKey="test" value="aa" title="${test}" />
<display:column property="address" title="new address"/>
<c:set var="foo">
<fmt:message key="struts2IdKey"/>
</c:set>
<display:column property="remark" title="${foo}"/>
<display:setProperty name="export.rtf.filename" value="example.rtf"/>
<display:setProperty name="export.pdf" value="false" />
</display:table>
</fmt:bundle>
</body>
</html>
不知道为什么,jstl本身的国际化可以显示,而display标签中的就是不显示?????????不工作?????
仔细检查代码,首先我用的是系统默认的国际化方式,即jstl。。。。所以displaytag属性文件基本上不用改。。。。
而我对jstl的使用格式是正确的。。。相关包也导入了。。。我甚至把I18nJstlAdapter拉了出来测试。。。。
当然都无果而终。。。。囧。。。。。
情急之下,甚至上google 英文进行搜索,搜英文的。。。很多网页开不了。。。。。
悲愤之中。。。看见网上有些达人写的原创博文较多,而且能解决很多问题。。。
其中某某还在博文内附上了联系邮箱。。。一种发邮件请教的冲动油然而生。。。。。。。
邮件写好了,想着最好附上代码,发觉代码很乱,决定整理一下,弄个简化的发过去。。。。
整理ing。。。。。。。
简化:
< contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="http://displaytag.sf.net/el" prefix="display" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
< uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
< import="java.util.*,testList.Test" %>
<html>
<head>
<link rel="stylesheet" type="text/css" href="css/screen.css" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>displaytag</title>
</head>
<body>
<h1>Hello Displaytag!</h1>
<%
List pageList = new ArrayList();
for(int i=0;i<40;i++)
pageList.add(i, new Test("123","1","1"));
request.setAttribute("pageList", pageList);
%>
<s:form >
<s:textfield key="test" />
</s:form>
<fmt:setLocale value="zh_CN"/><%--格式:en_US zh_CN--%>
<fmt:bundle basename="testList.titleKeyResource"><!--资源文件的名字,注意要放在CLASSES下面-->
<fmt:message key="test" />
<display:table name="pageList" id="row" class="table" pagesize="20" export="true">
<%--注意上面:需要完整路径!--%>
<%-- title="struts2Id" title="struts2Name" 似乎是直接用来显示的,会覆盖属性文件中titleKey对应的值,
titleKey才是国际化关键key~~~
value="struts2IdValue" 不知道有什么用 --%>
<display:column property="id" titleKey="struts2Id" />
<display:column property="name" titleKey="struts2Name" />
<display:column property="address" title="struts2AddressXX" titleKey="struts2Address" />
<display:column property="remark" />
</display:table>
</fmt:bundle>
</body>
</html>
- -!
发现杯具了。。。。。。原来之前自己为了汉化displaytag显示的页面,所以建过一个displaytag_zh_CN.properties文件。。。
而当中的provider正是我之前尝试过的I18nStruts2Adapter。。。。。而且I18nStruts2Adapter后面还多打了一个r。。。。
因为浏览器的locale是zh_CN,所以它读取的displaytag_zh_CN.properties,而不是displaytag.properties。。。。
所以就算我使用了默认的jstl解决方案也不能解决,因为配错了属性。而之前的I18nStruts2Adapter也写多了个r。。。
搞到两边都错了。。。。。。。。
杯具啊。。。。。。。
改正后,发现jstl起效了。
修改locale后,发现属性文件都有效果了。。。。。。
再试试在网上找来的I18nStruts2Adapter,发现都能用。。。。
在进行进一步检查,发现有些导入是多余的,比如<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>,
但是<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>在jstl中是必需的,因为要用到。而如果使用
struts2,则不需要了。
另外属性文件中的locale.resolver好像不需要配置。
还有 <fmt:setLocale value="zh_CN"/>好像是用于设置浏览器的locale,而属性文件在你的程序刚开始运行时,好像是根据你
的系统的locale来加载的,所以二者是两码事,别弄混了。
到头来问题终究是解决了~~~~~~~~~~~喵了个咪的~~~~~~~~~~~~
大家如果觉得还有什么问题,可以告诉我。