此文章在《OpenReports中文支持完全解决方案.doc》的基础上做优化,并贴出代码。已测试通过。
一、主要解决的问题
1 页面显示支持中文
2 与服务器或数据库的交互支持中文
3 查询结果支持中文
4 导出文件名及内容支持中文
二、解决方案及方法
1 增加的类
1.1 cn.ExportDelegate
直接来自原文件org.displaytag.filter.ExportDelegate,只是将文件名转码,
解决中文表格数据和导出中文文件名时,会产生乱码现象。被cn.ResponseOverrideFilter调用。
package cn; /** * 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. */ import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.util.Map; import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.displaytag.filter.BufferedResponseWrapper; import org.displaytag.tags.TableTag; import org.displaytag.tags.TableTagParameters; /** * Actually writes out the content of the wrapped response. Used by the j2ee filter and the Spring interceptor * implementations. * @author Fabrizio Giustina * @version $Revision: 1081 $ ($Author: fgiust $) */ public final class ExportDelegate { /** * logger. */ private static Log log = LogFactory.getLog(ExportDelegate.class); /** * Don?t instantiate. */ private ExportDelegate() { // unused } /** * Actually writes exported data. Extracts content from the Map stored in request with the * <code>TableTag.FILTER_CONTENT_OVERRIDE_BODY</code> key. * @param wrapper BufferedResponseWrapper implementation * @param response HttpServletResponse * @param request ServletRequest * @throws IOException exception thrown by response writer/outputStream */ protected static void writeExport(HttpServletResponse response, ServletRequest request, BufferedResponseWrapper wrapper) throws IOException { if (wrapper.isOutRequested()) { // data already written log.debug("Filter operating in unbuffered mode. Everything done, exiting"); return; } // if you reach this point the PARAMETER_EXPORTING has been found, but the special header has never been set in // response (this is the signal from table tag that it is going to write exported data) log.debug("Filter operating in buffered mode. "); Map bean = (Map) request.getAttribute(TableTag.FILTER_CONTENT_OVERRIDE_BODY); if (log.isDebugEnabled()) { log.debug(bean); } Object pageContent = bean.get(TableTagParameters.BEAN_BODY); if (pageContent == null) { if (log.isDebugEnabled()) { log.debug("Filter is enabled but exported content has not been found. Maybe an error occurred?"); } response.setContentType(wrapper.getContentType()); PrintWriter out = response.getWriter(); out.write(wrapper.getContentAsString()); out.flush(); return; } // clear headers if (!response.isCommitted()) { response.reset(); } String filename = (String) bean.get(TableTagParameters.BEAN_FILENAME); String contentType = (String) bean.get(TableTagParameters.BEAN_CONTENTTYPE); if (StringUtils.isNotBlank(filename)) { // response.setHeader("Content-Disposition", "attachment; filename="" + filename + """); String filename1 = new String(filename.getBytes("GBK"),("ISO8859-1")); response.setHeader("Content-Disposition", "attachment; filename="" + filename1 + """); } String characterEncoding = wrapper.getCharacterEncoding(); String wrappedContentType = wrapper.getContentType(); if (wrappedContentType != null && wrappedContentType.indexOf("charset") > -1) { // charset is already specified (see #921811) characterEncoding = StringUtils.substringAfter(wrappedContentType, "charset="); } if (characterEncoding != null && contentType.indexOf("charset") == -1) //$NON-NLS-1$ { contentType += "; charset=" + characterEncoding; //$NON-NLS-1$ } response.setContentType(contentType); if (pageContent instanceof String) { // text content if (characterEncoding != null) { response.setContentLength(((String) pageContent).getBytes(characterEncoding).length); } else { response.setContentLength(((String) pageContent).getBytes().length); } PrintWriter out = response.getWriter(); out.write((String) pageContent); out.flush(); } else { // dealing with binary content byte[] content = (byte[]) pageContent; response.setContentLength(content.length); OutputStream out = response.getOutputStream(); out.write(content); out.flush(); } } }
1.2 cn.ResponseOverrideFilter
直接来自原文件org.displaytag.filter.ResponseOverrideFilter,原有ResponseOverrideFilter路径指向新建Filter的路径,必须。
package cn; //============= /** * 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. */ import java.io.IOException; import java.util.HashMap; 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 org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.displaytag.Messages; import org.displaytag.filter.BufferedResponseWrapper; import org.displaytag.filter.BufferedResponseWrapper13Impl; import org.displaytag.tags.TableTag; import org.displaytag.tags.TableTagParameters; /** * <p> * Allow the author of an included JSP page to reset the content type to something else (like a binary stream), and then * write the new info back as the exclusive response, clearing the buffers of all previously added content. * </p> * <p> * This filter allows TableTag users to perform exports from pages that are run as includes, such as from Struts or a * jsp:include. If that is your intention, just add this Filter to your web.xml and map it to the appropriate requests, * using something like: * </p> * * <pre> * <filter> * <filter-name>ResponseOverrideFilter</filter-name> * <filter-class>org.displaytag.filter.ResponseOverrideFilter</filter-class> * </filter> * <filter-mapping> * <filter-name>ResponseOverrideFilter</filter-name> * <url-pattern>*.do</url-pattern> * </filter-mapping> * <filter-mapping> * <filter-name>ResponseOverrideFilter</filter-name> * <url-pattern>*.jsp</url-pattern> * </filter-mapping> * </pre> * * <p> * By default the filter buffers all the export content before writing it out. You can set an optional parameter * <code>buffer</code> to <code>false</code> to make the filter write directly to the output stream. This could be * faster and uses less memory, but the content length will not be set. * </p> * * <pre> * <filter> * <filter-name>ResponseOverrideFilter</filter-name> * <filter-class>org.displaytag.filter.ResponseOverrideFilter</filter-class> * <init-param> * <param-name>buffer</param-name> * <param-value>false</param-value> * </init-param> * </filter> * </pre> * * @author rapruitt * @author Fabrizio Giustina * @version $Revision: 1081 $ ($Author: fgiust $) */ public class ResponseOverrideFilter implements Filter { /** * Logger. */ private Log log; /** * Force response buffering. Enabled by default. */ private boolean buffer = true; /** * {@inheritDoc} */ public void init(FilterConfig filterConfig) { log = LogFactory.getLog(ResponseOverrideFilter.class); String bufferParam = filterConfig.getInitParameter("buffer"); if (log.isDebugEnabled()) { log.debug("bufferParam=" + bufferParam); } buffer = bufferParam == null || StringUtils.equalsIgnoreCase("true", bufferParam); log.info("Filter initialized. Response buffering is " + (buffer ? "enabled" : "disabled")); } /** * {@inheritDoc} */ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { if (servletRequest.getParameter(TableTagParameters.PARAMETER_EXPORTING) == null) { if (log.isDebugEnabled()) { log.debug(Messages.getString("ResponseOverrideFilter.parameternotfound")); //$NON-NLS-1$ } // don't filter! filterChain.doFilter(servletRequest, servletResponse); return; } HttpServletRequest request = (HttpServletRequest) servletRequest; BufferedResponseWrapper wrapper = new BufferedResponseWrapper13Impl((HttpServletResponse) servletResponse); Map contentBean = new HashMap(4); if (buffer) { contentBean.put(TableTagParameters.BEAN_BUFFER, Boolean.TRUE); } request.setAttribute(TableTag.FILTER_CONTENT_OVERRIDE_BODY, contentBean); // request.setAttribute("cn.ResponseOverrideFilter", contentBean); filterChain.doFilter(request, wrapper); ExportDelegate.writeExport((HttpServletResponse) servletResponse, servletRequest, wrapper); } /** * {@inheritDoc} */ public void destroy() { // nothing to destroy } }
1.3 cn.SetCharacterEncodingFilter
是一个标准的自定义字符集转换Filter,必须。
package cn; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class SetCharacterEncodingFilter implements Filter { /** * The default character encoding to set for requests that pass through * this filter. */ protected String encoding = null; /** * The filter configuration object we are associated with. If this value * is null, this filter instance is not currently configured. */ protected FilterConfig filterConfig = null; /** * Should a character encoding specified by the client be ignored? */ protected boolean ignore = true; public void destroy() { this.encoding = null; this.filterConfig = null; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // Conditionally select and set the character encoding to be used if (ignore || (request.getCharacterEncoding() == null)) { String encoding = selectEncoding(request); if (encoding != null) request.setCharacterEncoding(encoding); } chain.doFilter(request, response); } /** * Place this filter into service. * @param filterConfig The filter configuration object */ public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; this.encoding = filterConfig.getInitParameter("encoding"); String value = filterConfig.getInitParameter("ignore"); if (value == null) this.ignore = true; else if (value.equalsIgnoreCase("true")) this.ignore = true; else if (value.equalsIgnoreCase("yes")) this.ignore = true; else this.ignore = false; } protected String selectEncoding(ServletRequest request) { return (this.encoding); } }
1.4 org.displaytag.export.PdfView
/** * 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.export; import java.io.OutputStream; import java.util.Iterator; import javax.servlet.jsp.JspException; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; import org.displaytag.Messages; import org.displaytag.exception.BaseNestableJspTagException; import org.displaytag.exception.SeverityEnum; import org.displaytag.model.Column; import org.displaytag.model.ColumnIterator; import org.displaytag.model.HeaderCell; import org.displaytag.model.Row; import org.displaytag.model.RowIterator; import org.displaytag.model.TableModel; import org.displaytag.util.TagConstants; import com.lowagie.text.BadElementException; import com.lowagie.text.Cell; import com.lowagie.text.Chunk; import com.lowagie.text.Document; import com.lowagie.text.Element; import com.lowagie.text.Font; import com.lowagie.text.FontFactory; import com.lowagie.text.HeaderFooter; import com.lowagie.text.PageSize; import com.lowagie.text.Phrase; import com.lowagie.text.Rectangle; import com.lowagie.text.Table; import com.lowagie.text.pdf.PdfWriter; /** * PDF exporter using IText. This class is provided more as an example than as a "production ready" class: users * probably will need to write a custom export class with a specific layout. * @author Ivan Markov * @author Fabrizio Giustina * @version $Revision: 1081 $ ($Author: fgiust $) */ public class PdfView implements BinaryExportView { private TableModel model; private boolean exportFull; private boolean header; private boolean decorated; private Table tablePDF; private Font smallFont; public void setParameters(TableModel tableModel, boolean exportFullList, boolean includeHeader, boolean decorateValues) { this.model = tableModel; this.exportFull = exportFullList; this.header = includeHeader; this.decorated = decorateValues; } protected void initTable() throws BadElementException { this.tablePDF = new Table(this.model.getNumberOfColumns()); this.tablePDF.getDefaultCell().setVerticalAlignment(4); this.tablePDF.setCellsFitPage(true); this.tablePDF.setWidth(100.0F); this.tablePDF.setPadding(2.0F); this.tablePDF.setSpacing(0.0F); // smallFont = FontFactory.getFont(FontFactory.HELVETICA, 7, Font.NORMAL, new Color(0, 0, 0)); //Font name:宋体(中文字体) PDF Font name:STSong-Light PDF Encoding:UniGB-UCS2-H(简体中文) smallFont = FontFactory.getFont("STSong-Light", "UniGB-UCS2-H", Font.DEFAULTSIZE); } public String getMimeType() { return "application/pdf"; } /** * The overall PDF table generator. * @throws JspException for errors during value retrieving from the table model * @throws BadElementException IText exception */ protected void generatePDFTable() throws JspException, BadElementException { if (this.header) { generateHeaders(); } tablePDF.endHeaders(); generateRows(); } /** * @see org.displaytag.export.BinaryExportView#doExport(OutputStream) */ public void doExport(OutputStream out) throws JspException { try { // Initialize the table with the appropriate number of columns initTable(); // Initialize the Document and register it with PdfWriter listener and the OutputStream Document document = new Document(PageSize.A4.rotate(), 60, 60, 40, 40); document.addCreationDate(); HeaderFooter footer = new HeaderFooter(new Phrase(TagConstants.EMPTY_STRING, smallFont), true); footer.setBorder(Rectangle.NO_BORDER); footer.setAlignment(Element.ALIGN_CENTER); PdfWriter.getInstance(document, out); // Fill the virtual PDF table with the necessary data generatePDFTable(); document.open(); document.setFooter(footer); document.add(this.tablePDF); document.close(); } catch (Exception e) { throw new PdfGenerationException(e); } } /** * Generates the header cells, which persist on every page of the PDF document. * @throws BadElementException IText exception */ protected void generateHeaders() throws BadElementException { Iterator iterator = this.model.getHeaderCellList().iterator(); while (iterator.hasNext()) { HeaderCell headerCell = (HeaderCell) iterator.next(); String columnHeader = headerCell.getTitle(); if (columnHeader == null) { columnHeader = StringUtils.capitalize(headerCell.getBeanPropertyName()); } Cell hdrCell = getCell(columnHeader); hdrCell.setGrayFill(0.9f); hdrCell.setHeader(true); tablePDF.addCell(hdrCell); } } /** * Generates all the row cells. * @throws JspException for errors during value retrieving from the table model * @throws BadElementException errors while generating content */ protected void generateRows() throws JspException, BadElementException { // get the correct iterator (full or partial list according to the exportFull field) RowIterator rowIterator = this.model.getRowIterator(this.exportFull); // iterator on rows while (rowIterator.hasNext()) { Row row = rowIterator.next(); // iterator on columns ColumnIterator columnIterator = row.getColumnIterator(this.model.getHeaderCellList()); while (columnIterator.hasNext()) { Column column = columnIterator.nextColumn(); // Get the value to be displayed for the column Object value = column.getValue(this.decorated); Cell cell = getCell(ObjectUtils.toString(value)); tablePDF.addCell(cell); } } } /** * Returns a formatted cell for the given value. * @param value cell value * @return Cell * @throws BadElementException errors while generating content */ private Cell getCell(String value) throws BadElementException { Cell cell = new Cell(new Chunk(StringUtils.trimToEmpty(value), smallFont)); cell.setVerticalAlignment(Element.ALIGN_TOP); cell.setLeading(8); return cell; } /** * Wraps IText-generated exceptions. * @author Fabrizio Giustina * @version $Revision: 1081 $ ($Author: fgiust $) */ static class PdfGenerationException extends BaseNestableJspTagException { /** * D1597A17A6. */ private static final long serialVersionUID = 899149338534L; /** * Instantiate a new PdfGenerationException with a fixed message and the given cause. * @param cause Previous exception */ public PdfGenerationException(Throwable cause) { super(PdfView.class, Messages.getString("PdfView.errorexporting"), cause); //$NON-NLS-1$ } /** * @see org.displaytag.exception.BaseNestableJspTagException#getSeverity() */ public SeverityEnum getSeverity() { return SeverityEnum.ERROR; } } }
2 在web.xml中配置两个Filter,字符编码过滤器字符集设置为GBK
直接来自原文件及包,只是将字体设置为支持中文的PDF字体。
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <display-name>OpenReports</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext*.xml</param-value> </context-param> <context-param> <param-name>contextFactory</param-name> <param-value> com.tonbeller.wcf.controller.RequestContextFactoryImpl </param-value> </context-param> <filter> <filter-name>struts</filter-name> <filter-class> org.apache.struts2.dispatcher.FilterDispatcher </filter-class> </filter> <!-- support the chinese add filter start --> <!-- <filter> <filter-name>ResponseOverrideFilter</filter-name> <filter-class> org.displaytag.filter.ResponseOverrideFilter </filter-class> </filter> --> <filter> <filter-name>ResponseOverrideFilter</filter-name> <filter-class> cn.ResponseOverrideFilter<!-- org.displaytag.filter --> </filter-class> </filter> <filter> <filter-name>encodingFilter</filter-name> <filter-class> cn.SetCharacterEncodingFilter </filter-class> <init-param> <param-name>encoding</param-name> <param-value>GBK</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <!-- support the chinese add filter end--> <filter> <filter-name>JPivotController</filter-name> <filter-class> com.tonbeller.wcf.controller.RequestFilter </filter-class> <!-- <init-param> <param-name>indexJSP</param-name> <param-value>/index.html</param-value> <description> forward to this page if session is new </description> </init-param> <init-param> <param-name>errorJSP</param-name> <param-value>/error.jsp</param-value> <description>URI of error page</description> </init-param> <init-param> <param-name>busyJSP</param-name> <param-value>/busy.jsp</param-value> <description> This page is displayed if a the user clicks on a query before the previous query has finished </description> </init-param> <init-param> <param-name>forceExtension</param-name> <param-value>.faces</param-value> <description>replace .jsp with .faces</description> </init-param> --> </filter> <!-- support the chinese add mapping start --> <filter-mapping> <filter-name>ResponseOverrideFilter</filter-name> <url-pattern>*.action</url-pattern> </filter-mapping> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- support the chinese add mapping start --> <filter-mapping> <filter-name>JPivotController</filter-name> <url-pattern>/jpivot.action</url-pattern> </filter-mapping> <filter-mapping> <filter-name>JPivotController</filter-name> <url-pattern>/JPivot.jsp</url-pattern> </filter-mapping> <filter-mapping> <filter-name>ResponseOverrideFilter</filter-name> <url-pattern>*.action</url-pattern> </filter-mapping> <filter-mapping> <filter-name>struts</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- resources initializer --> <listener> <listener-class> com.tonbeller.tbutils.res.ResourcesFactoryContextListener </listener-class> </listener> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <servlet> <servlet-name>JspSupportServlet</servlet-name> <servlet-class> org.apache.struts2.views.JspSupportServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet> <servlet-name>fileServlet</servlet-name> <servlet-class> org.efs.openreports.dispatcher.FileDispatcher </servlet-class> <load-on-startup>99</load-on-startup> </servlet> <servlet> <servlet-name>MondrianXmlaServlet</servlet-name> <servlet-class> org.efs.openreports.dispatcher.XMLADispatcher </servlet-class> </servlet> <servlet> <servlet-name>XFireServlet</servlet-name> <display-name>XFire Servlet</display-name> <servlet-class> org.codehaus.xfire.spring.XFireSpringServlet </servlet-class> </servlet> <!-- jfreechart provided servlet --> <servlet> <servlet-name>DisplayChart</servlet-name> <servlet-class> org.jfree.chart.servlet.DisplayChart </servlet-class> </servlet> <!-- jfreechart provided servlet --> <servlet> <servlet-name>GetChart</servlet-name> <display-name>GetChart</display-name> <description> Default configuration created for servlet. </description> <servlet-class> com.tonbeller.jpivot.chart.GetChart </servlet-class> </servlet> <servlet> <servlet-name>Print</servlet-name> <display-name>Print</display-name> <description> Default configuration created for servlet. </description> <servlet-class> com.tonbeller.jpivot.print.PrintServlet </servlet-class> </servlet> <servlet-mapping> <servlet-name>DisplayChart</servlet-name> <url-pattern>/DisplayChart</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Print</servlet-name> <url-pattern>/Print</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>GetChart</servlet-name> <url-pattern>/GetChart</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>fileServlet</servlet-name> <url-pattern>/report-images/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>fileServlet</servlet-name> <url-pattern>/report-files/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>XFireServlet</servlet-name> <url-pattern>/services/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>MondrianXmlaServlet</servlet-name> <url-pattern>/xmla</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>/Login.jsp</welcome-file> </welcome-file-list> <taglib> <taglib-uri>http://www.tonbeller.com/wcf</taglib-uri> <taglib-location>/WEB-INF/wcf/wcf-tags.tld</taglib-location> </taglib> <taglib> <taglib-uri>http://www.tonbeller.com/jpivot</taglib-uri> <taglib-location> /WEB-INF/jpivot/jpivot-tags.tld </taglib-location> </taglib> </web-app>
3 增加PDF中文支持的JAR包
4 struts.properties配置文件字符编码改为GBK
## when set to true, Struts will act much more friendly for developers. This
### includes:
### - struts.i18n.reload = true
### - struts.configuration.xml.reload = true
### - raising various debug or ignorable problems to errors
### For example: normally a request to foo.action?someUnknownField=true should
### be ignored (given that any value can come from the web and it
### should not be trusted). However, during development, it may be
### useful to know when these errors are happening and be told of
### them right away.
struts.devMode=false
### Load custom default resource bundles
struts.custom.i18n.resources=LocalStrings
### This can be used to set your default locale and encoding scheme
#support the chinese start
#struts.locale=en_US
#struts.i18n.encoding=UTF-8
struts.locale=zh_CN
struts.i18n.encoding=GBK
#support the chinese start
### Parser to handle HTTP POST requests, encoded using the MIME-type multipart/form-data
struts.multipart.parser=org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest
5 国际化配置文件
屏蔽原来的:LocalStrings.properties文件,新增:LocalStrings_zh_CN.properties文件
翻译如下:
error.report.empty=The report is empty. Please try different parameters. error.validation.notsupported=Validation not supported on queries with parameters. error.exporttype.required=You must select at least one Export Type. error.invalid.password=Invalid Password: Both passwords must be equal. error.login.incomplete=Please Enter Both User Name and Password. error.login.invalid=Invalid User Name or Password! error.report.invalid=Invalid report. error.report.notauthorized=You are not authorized to view this Report. error.reportgroup.notauthorized=You are not authorized to view this Report Group. error.emailaddress.required=You must update your email address before scheduling reports! error.dateandtime.required=Start Date and Time required to schedule report. error.dateandtime.invalid=Start Time invalid. error.notauthorized=You are not authorized to perform this action. error.notloggedin=You are not currently logged into the system. error.invalid.user=You are not a valid OpenReports User. Please contact Administrator. error.chartquery.invalid=Invalid Chart Query error.alertquery.invalid=Invalid Alert Query error.testing.connection=Error testing connection, verify DataSource configuration and try again error.parameter.required=Please Fill Required Parameter error.chart.deletion=Report Chart must be removed from all reports before deletion. error.datasource.deletion=This DataSource is being used by Reports or Parameters and cannot be deleted. error.group.deletion=Report Group must be removed from all users before deletion.s error.parameter.deletion=Report Parameter must be removed from all reports before deletion. error.report.deletion=Report must be removed from all Report Groups before deletion. error.parameter.notfound=Parameter not found error.alert.deletion=This alert is associated with a user and can not be deleted. error.unique.constraint=This name is already in use. Please use a unique name. error.invalid.maxrows=QueryReport MaxRows must be set to a valid number. 500 is recommended. error.chart.invalid=Name, description, and query are required. error.xmla.properties.invalid=XMLA DataSource, URI, and Catalog properties must be set. error.serverside=There has been an error on the server. Please check the logs. error.settings.directories=Directories not configured correctly. Please recheck General Settings. alert.failed=Failed alert.passed=Passed message.schedule.successful=Report scheduled successfully... service.request.complete=COMPLETE application.title=u7F51u7EDCu81EAu5B9Au4E49u62A5u8868 banner.logoff=u6ce8u9500 banner.reports=u6211u7684u62a5u8868 banner.scheduledReports=u5b9au65f6u4efbu52a1u62a5u8868 banner.administration=u7cfbu7edfu7ba1u7406 banner.dashboard=Dashboard banner.preferences=u4feeu6539u7528u6237u4fe1u606f button.save=u4fddu5b58 button.cancel=u5220u9664 button.add=u589eu52a0 button.delete=u5220u9664 button.update=u66f4u65b0 button.refresh=u5237u65b0 button.submit=u63d0u4ea4 button.duplicate=u590du5236 button.validate=u6821u9a8c button.addGroup=u589eu52a0u62a5u8868u5206u7ec4 button.addDataSource=u589eu52a0u6570u636eu6e90 button.autoCreate=u81eau52a8u751fu6210 button.autoAdd=u81eau52a8u589eu52a0 button.addNew=u65b0u589e button.addChart=u589eu52a0u56feu8868 button.addReportFile=u589eu52a0u62a5u8868u6a21u677f button.addReports=u589eu52a0u62a5u8868 button.cleanup=u6e05u9664 button.export=u5bfcu51fa button.import=u5bfcu5165 label.username=u7528u6237u540Du79F0 label.password=u7528u6237u5bc6u7801 label.confirmPassword=u786eu8ba4u5bc6u7801 label.email=u90aeu7bb1u5730u5740 label.dashboardReport=Dashboard Report label.name=u540du79f0 label.externalId=External ID label.description=u63cfu8ff0 label.report=Report label.startDate=u8d77u59cbu65e5u671f label.scheduleType=u4efbu52a1u7c7bu578b label.scheduleState=State label.nextRun=Next Run label.runDate=Run Date label.alert=Alert label.operator=Operator label.limit=Limit label.status=Status label.startTime=u5f00u59cbu65f6u95f4 label.elapsedTime=Duration (sec) label.message=u4fe1u606f label.cronExpression=Cron Expression label.numberOfHours=# of Hours label.condition=Condition label.recipients=Recipients label.options=Options label.once=u4e00u6b21 label.daily=u6bcfu5929 label.weekdays=u6bcfu5468u67d0u65e5 label.weekly=u6bcfu5468 label.cron=Cron label.monthly=u6bcfu6708 label.hourly=u6bcfu5c0fu65f6 label.action=Action label.tags=Tags label.groups=Groups label.roles=Roles label.filter=Filter label.filterBy=Filter By label.required=u5fc5u987b label.class=u53c2u6570u7c7bu578b label.type=u7c7bu578b label.id=Id label.data=u6570u636e label.dataSource=u6570u636eu6e90 label.multipleSelect=u591au9009 label.useJNDI=u4f7fu7528u6570u636eu6e90 label.url=URL label.driver=u6570u636eu5e93u9a71u52a8u7a0bu5e8f label.maxIdle=u6700u5927u8fdeu63a5u6570 label.maxActive=u6700u5927u6d3bu8dc3u8fdeu63a5u6570 label.maxWait=u6700u5927u7b49u5f85u65f6u95f4 label.validationQuery=u68c0u9a8cu67e5u8be2u8bedu53e5 label.query=u67e5u8be2u8bedu53e5 label.chart=u56feu8868 label.hidden=u9690u85cf label.reportFile=u62a5u8868u6a21u677f label.exportTypes=u62a5u8868u7c7bu578b label.virtualization=Use Virtualization label.step=u6b65u9aa4 label.sortOrder=u6392u5e8fu987au5e8f label.reportParameter=u62a5u8868u53c2u6570 label.exportFormat=Export Format label.exportOption=Export Option label.chartType=u56feu8868u7c7bu578b label.width=u5bbd label.height=u9ad8 label.xAxisLabel=Xu5750u6807u8f74u540du79f0 label.yAxisLabel=Yu5750u6807u8f74u540du79f0 label.showTitle=u663eu793au6807u9898 label.showLegend=u663eu793au56feu4f8b label.showValues=u663eu793au503c label.plotOrientation=u56feu5f62u65b9u5411 label.drillDownReport=u4e0bu94bbu62a5u8868 label.horizontal=u6c34u5e73u65b9u5411 label.vertical=u6c34u5e73u65b9u5411 label.baseDirectory=Base Directory label.reportGenerationDirectory=Report Generation Directory label.tempDirectory=Temp Directory label.dateFormat=Date Format label.queryReportMaxRows=Query Report Max Rows label.mailHost=Mail Host label.useMailAuthenticator=Use Mail Authenticator label.mailAuthenticatorUser=Mail Authenticator UserName label.mailAuthenticatorPassword=Mail Authenticator Password label.xmlaURI=XMLA URI label.xmlaDataSource=XMLA DataSource label.xmlaCatalog=XMLA Catalog label.numberOfFiles=File Count label.directorySize=Directory Size label.reports=u6211u7684u62a5u8868 label.currentState=Current State label.hits=Hits label.user=User label.value=Value label.alerts=Alerts label.defaultValue=u9ed8u8ba4u503c link.back.groups=u8fd4u56deu62a5u8868u7ec4 link.back.reports=u8fd4u56deu62a5u8868 link.back.parameters=Back to Parameters link.back.charts=u8fd4u56deu56feu8868 link.back.dataSources=u8fd4u56deu6570u636eu6e90 link.back.users=Back to Users link.back.admin=u8fd4u56deu5230u7cfbu7edfu7ba1u7406 link.back.alerts=Back to Alerts link.delete=u5220u9664 link.update=u66f4u65b0 link.groups=u62a5u8868u7ec4 link.users=u7528u6237 link.admin.reports=u62a5u8868 link.admin.reportParameters=u62a5u8868u53c2u6570 link.admin.dataSources=u6570u636eu6e90 link.admin.charts=u56feu8868 link.admin.alerts=u8b66u62a5 link.admin.groups=u62a5u8868u7ec4 link.admin.users=u7528u6237 link.admin.scheduler=Scheduler link.admin.settings=u8bbeu7f6e link.admin.statistics=Statistics link.admin.logs=u67e5u770bu65e5u5fd7 link.admin.addUser=u65b0u589eu7528u6237 link.admin.addReport=u65b0u589eu62a5u8868 link.admin.addReportParameter=u65b0u589eu62a5u8868u53c2u6570 link.admin.addReportGroup=u65b0u589eu62a5u8868u7ec4 link.admin.addDataSource=u65b0u589eu6570u636eu6e90 link.admin.addChart=u65b0u589eu56feu8868 link.admin.addAlert=u65b0u589eu8b66u62a5 link.admin.uploadReport=u4e0au4f20u62a5u8868u6587u4ef6 link.admin.search=u641cu7d22 link.admin.import=u5bfcu5165u62a5u8868 link.admin.export=u5bfcu51fau62a5u8868 link.scheduleChart=Schedule ChartReport role.advancedScheduler=Advanced Scheduler role.chartAdmin=Chart Admin role.dataSourceAdmin=DataSource Admin role.uploader=File Uploader role.groupAdmin=Group Admin role.logViewer=Log Viewer role.parameterAdmin=Parameter Admin role.reportAdmin=Report Admin role.rootAdmin=Root Admin role.scheduler=Scheduler role.dashboard=Dashboard User role.schedulerAdmin=Scheduler Admin role.alerts=Alerts User role.alertAdmin=Alerts Admin login.title=u8bf7u767bu5f55 login.submit=u767bu5f55 reportGroup.title=Groups reportList.title=u62a5u8868 reportDetail.title=u53c2u6570: reportDetail.requiredParameters=* Indicates required parameters reportOptions.title=Export Options for: reportOptions.exportType=Export Type reportOptions.description=Email/File Description reportOptions.run=Run reportOptions.runNewWindow=u5728u65b0u7a97u53e3u6253u5f00 reportOptions.schedule=Schedule reportOptions.sendToFile=Send to File reportOptions.sendToEmail=Send to Email reportOptions.note=Only applies when 'Send to Email' or 'Send to File' is clicked. listScheduledReports.scheduledReports=u5b9au65f6u4efbu52a1u62a5u8868 listScheduledReports.generatedReports=Generated Reports userAdmin.preferences=u4feeu6539u7528u6237u4fe1u606f userAdmin.alerts=Alerts deleteReport.warning=This will remove the report from all groups and delete all entries for the report in the logs. deleteReport.title=Delete Report Confirmation deleteReportParameter.title=Delete Report Parameter Confirmation deleteDataSource.title=Delete DataSource Confirmation deleteAlert.title=Delete Alert Confirmation deleteAlert.warning=This will remove the alert and delete all entries for the alert in the logs. deleteChart.title=Delete Chart Confirmation deleteGroup.title=Delete Group Confirmation deleteUser.title=Delete User Confirmation deleteUser.warning=This will delete all entries for this user in the logs. deleteScheduledReport.title=Delete Scheduled Report Confirmation deleteGeneratedReport.title=Delete Generated Report Confirmation uploadReportFiles.uploadFile=u4e0au4f20u62a5u8868u6587u4ef6 uploadReportFiles.currentFiles=u5f53u524du62a5u8868u6587u4ef6 reportViewer.page=Page reportViewer.zoom=Zoom viewReportLogs.title=Log Filters viewReportLogs.warning=Log query results limited to 500 rows reportSchedule.title=u5b9au65f6u4efbu52a1u62a5u8868u9009u9879: reportSchedule.sendToFile=Send to File reportSchedule.message.hours=# of Hours only applies to Hourly scheduled Reports reportSchedule.message.cron=Cron Expression only applies to Cron scheduled Reports reportAdmin.tab.reportAdmin=u62a5u8868u7ba1u7406 reportAdmin.tab.userAdmin=u7528u6237u7ba1u7406 reportAdmin.tab.generalAdmin=u65e5u5e38u7ba1u7406 reportAdmin.message.reports=u589eu52a0u6216u4feeu6539u62a5u8868uff0cu4e0au4f20u62a5u8868u6a21u677fuff0cu5206u914du62a5u8868u5230u62a5u8868u7ec4. reportAdmin.message.search=u901au8fc7u5907u6ce8u6216u8bf4u660eu67e5u8be2u62a5u8868uff0cu62a5u8868u7ec4uff0cu7528u6237. reportAdmin.message.logs=u67e5u770bu62a5u8868u64cdu4f5cu65e5u5fd7uff0cu901au8fc7u65e5u671fu3001u62a5u8868u3001u7528u6237u6216u72b6u6001. reportAdmin.message.reportParameters=u589eu52a0u6216u4feeu6539u62a5u8868u53c2u6570. reportAdmin.message.dataSources=u589eu52a0u6216u4feeu6539u6570u636eu6e90. reportAdmin.message.alerts=Add or Modify Alerts. reportAdmin.message.charts=u589eu52a0u6216u4feeu6539u56feu6807. reportAdmin.message.groups=u589eu52a0u6216u4feeu6539u62a5u8868u7ec4uff0cu5206u914du7528u6237u5230u62a5u8868u7ec4. reportAdmin.message.users=u589eu52a0u6216u4feeu6539u7528u6237. reportAdmin.message.scheduler=Global Scheduler Administration reportAdmin.message.settings=u65e5u5e38u8bbeu7f6eu5305u62ecu90aeu4ef6u4e3bu673au548cu62a5u8868u76eeu5f55. reportAdmin.message.statistics=View Top Reports by user, date or status. reportAdmin.message.import=Import Report definitions from XML. reportAdmin.message.export=Export Report definitions to XML. queryReport.scheduleReport=Schedule Report: listSearchResults.title=Search by tag: editUser.addUser=u65b0u589eu7528u6237: editUser.selectedUser=u6240u9009u7684u7528u6237: editReportParameter.addReportParameter=Add Report Parameter: editReportParameter.selectedReportParameter=u9009u62e9u7684u62a5u8868u53c2u6570: editUser.selectedUser=u6240u9009u7684u7528u6237: editReportParameter.parameterValues=Parameter Values editReportGroups.title=Report Groups: editReport.tab.reportDefinition=u62a5u8868u5b9au4e49 editReport.tab.reportParameters=u62a5u8868u53c2u6570 editReport.tab.jasperReportOptions=u62a5u8868u5bfcu51fau9009u9879 editReport.parameters.autoAdd= <b>Auto Add</b> inspects the report design and adds all parameters that match the name of existing OpenReports parameters. editReport.parameters.autoCreate=<b>Auto Create</b> is the same as <b>Auto Add</b> except that it also creates new Text Parameters for all parameters where a match is not found. editReport.parameters.addNew=<b>u65b0u589e</b> u5f39u51fau65b0u589eu53c2u6570u7a97u53e3uff0cu65b0u5efau4e00u4e2au62a5u8868u53c2u6570u3002. editReport.jasperOption.removeEmptySpaceBetweenRows=Remove Empty Space Between Rows editReport.jasperOption.whitePageBackground=White Page Background editReport.jasperOption.onePagePerSheet=One Page Per Sheet editReport.jasperOption.wrapBreakWord=Wrap Break Word editReport.jasperOption.usingImagesToAlign=Using Images To Align editReport.jasperOption.autoDetectCellType=Auto Detect Cell Type editProperties.tab.generalSettings=General Settings editProperties.tab.tempFileCleanup=Temp File Cleanup editGroupUsers.title=Group User Assignment: editGroup.addReportsToGroup.title=Add Reports To Group editGroup.addGroup=Add Group: editGroup.selectedGroup=u9009u62e9u7684u7528u6237: editDataSource.addDataSource=Add DataSource: editDataSource.selectedDataSource=u9009u62e9u7684u6570u636eu6e90: editChart.addChart=Add Chart: editChart.selectedChart=u9009u62e9u7684u56feu8868: editAlert.addAlert=u65b0u589eu8b66u62a5: editAlert.selectedAlert=u9009u62e9u7684u8b66u62a5: addDataSourceDialog.title=u65b0u589eu6570u636eu6e90 addChartDialog.title=u65b0u589eu56feu8868 addReportFileDialog.title=u4e0au4f20u62a5u8868u6a21u677f addReportParameterDialog.title=u65b0u589eu62a5u8868u53c2u6570 changeScheduleState.title=Change Schedule State Confirmation analyzeReportLogs.title=Report Statistics analyzeReportLogs.query.topReports=Top Reports analyzeReportLogs.query.topReportsByUser=Top Reports By User analyzeReportLogs.query.topReports30Days=Top Reports - Last 30 Days analyzeReportLogs.query.topReports60Days=Top Reports - Last 60 Days analyzeReportLogs.query.topReports90Days=Top Reports - Last 90 Days analyzeReportLogs.query.topFailures=Top Failed Reports analyzeReportLogs.query.topEmpty=Top Empty Reports analyzeReportLogs.query.topAlerts=Top Alerts analyzeReportLogs.query.topAlertsByUser=Top Alerts - By User analyzeReportLogs.query.topTriggeredAlerts=Top Alerts - Triggered analyzeReportLogs.query.topNotTriggeredAlerts=Top Alerts - Not Triggered dashboard.message=Use the <a href="userAdmin.action">Preferences</a> link to add Alerts and set your Dashboard report. dataExport.title=Export Report Definitions dataImport.title=Import Report Definitions tooltip.parameter.class=The Java class of the parameter. Used for validation and passed to reports. tooltip.parameter.data=Enter SQL for Query parameters or pipe '|' seperated list of values for List parameters. tooltip.parameter.dataSource=Used only with Query parameters. tooltip.parameter.multiSelect=Determines if the parameter allows multiple selections. Valid only for Query and List parameters. tooltip.datasource.driver=JDBC Driver class. The JDBC driver containing this class must be in the OpenReports classpath. tooltip.datasource.jndi=Lookup JNDI DataSource. JNDI DataSources require only Name and URL. tooltip.datasource.maxActive=The maximum number of active connections that can be allocated from this pool at the same time, or negative for no limit. tooltip.datasource.maxIdle=The maximum number of active connections that can remain idle in the pool, without extra ones being released, or zero for no limit. tooltip.datasource.maxWait=The maximum number of milliseconds that the pool will wait (when there are no available connections) for a connection to be returned before throwing an exception, or -1 to wait indefinitely. tooltip.datasource.query=The SQL query that will be used to validate connections from this pool before returning them to the caller. If specified, this query MUST be an SQL SELECT statement that returns at least one row. tooltip.datasource.url=JNDI DataSource name or JDBC Database URL tooltip.report.chart=Select chart for use in ChartReports. tooltip.report.export=Export Types. Not all export types supported by all report engines. tooltip.report.file=Select the report template file. Not required for QueryReports or ChartReports. tooltip.report.hidden=If checked, this report will not be displayed to end users. Useful for DrillDown reports. tooltip.report.query=Enter SQL query for use with QueryReports or JXLS template. tooltip.report.virtualization=Enable Virtualization for JasperReports. tooltip.chart.plotOrientation=Plot Orientation. Only applicable for Bar and XY Charts tooltip.chart.query=Chart SQL Query. See OpenReports Adminstration Guide for valid Chart query formats. tooltip.chart.values=If this option is checked, the Chart Values will be displayed in a sortable table below the Chart. tooltip.chart.xlabel=X-Axis label. Not applicable for Pie Charts tooltip.chart.ylabel=Y-Axis label. Not applicable for Pie Charts tooltip.properties.baseDirectory=Full path to directory containing report files tooltip.properties.reportGenerationDirectory=Full path to directory used to store reports generated to files tooltip.properties.tempDirectory=Full path to directory for temp files tooltip.properties.maxRows=Maximum number of rows returned per QueryReport tooltip.properties.mailhost=Mail Host required for scheduled reports tooltip.properties.mailAuthenticator=Check this box if your Mail Host requires a UserName and Password tooltip.alert.query=Alert SQL Query. Must return an Integer. For example: SELECT count(*) FROM address
6修改displaytag.properties配置文件
翻译如下:
factory.decorator=org.efs.openreports.util.displaytag.SpringDecoratorFactory locale.resolver = org.efs.openreports.util.displaytag.DisplayTagI18nStruts2Adapter locale.provider = org.efs.openreports.util.displaytag.DisplayTagI18nStruts2Adapter basic.empty.showtable=true paging.banner.placement=bottom paging.banner.item_name=u8bb0u5f55 paging.banner.items_name=u8bb0u5f55 paging.banner.no_items_found=<span class ="pagebanner">u6ca1u6709{0}u627eu5230.</span> paging.banner.one_item_found=<span class ="pagebanner">u4e00u6761{0}u627eu5230.</span> paging.banner.all_items_found=<span class ="pagebanner">{0}{1}u627eu5230,u663eu793au5168u90e8{2}.</span> paging.banner.some_items_found=<span class ="pagebanner">u5171u627eu5230{0}{1},u663eu793a{2}u5230{3}.</span> paging.banner.full=<span class ="pagelinks">[<a href="{1}">u7b2cu4e00u9875</a>/<a href="{2}">u4e0au4e00u9875</a>] {0} [<a href="{3}">u4e0bu4e00u9875</a>/<a href="{4}">u6700u540eu4e00u9875</a>]</span> paging.banner.first=<span class ="pagelinks">[u7b2cu4e00u9875/u4e0au4e00u9875] {0} [<a href="{3}">u4e0bu4e00u9875</a>/<a href="{4}">u6700u540eu4e00u9875</a>]</span> paging.banner.last=<span class ="pagelinks">[<a href="{1}">u7b2cu4e00u9875</a>/<a href="{2}">u4e0au4e00u9875</a>] {0} [u4e0bu4e00u9875/u6700u540eu4e00u9875]</span> paging.banner.onepage=<span class ="pagelinks">{0}</span> paging.banner.page.selected=<strong>{0}</strong> paging.banner.page.link=<a.href="{1}" title+"u8f6cu5230u9875 {0}">{0}</a> paging.banner=<div class="explortlinks">u5bfcu51fau7c7bu578b:{0}</div>