Jasper Reports 简明教程

JasperReports - Internationalization

有时,我们需要不同语言的报表。针对每种不同的语言编写相同的报表意味很多冗余工作。只有不同于不同语言的文本部分才应该单独编写,并在运行时根据语言环境设置加载到文本元素中。这就是报表国际化的目的。一旦编写了国际化报表,就可以在任何地方运行。

Sometimes, we need reports in different languages. Writing the same report for each different language implies a lot of redundant work. Only pieces of text differing from language to language should be written separately, and loaded into text elements at runtime, depending on locale settings. This is the purpose of the report internationalization. Internationalized reports, once written can run everywhere.

在下面的步骤中,我们列出了如何用不同的语言生成报表以及报表国际化的其他一些特性 -

In the following steps, we have listed how to generate a report in different languages and also some other features of report internationalization −

  1. Associate a resource bundle java.util.ResourceBundle with the report template. There are two ways to associate the java.util.ResourceBundle object with the report template. At design time, by setting the resourceBundle attribute of the report template object to the base name of the target resource bundle. A dynamic/runtime association can be made by supplying a java.util.ResourceBundle object as the value for the REPORT_RESOURCE_BUNDLE parameter at report-filling time. If the report needs to be generated in a locale that is different from the current one, the built-in REPORT_LOCALE parameter can be used to specify the runtime locale when filling the report.

  2. To facilitate report internationalization, a special syntax $R{} is available inside report expressions to reference java.lang.String resources placed inside a java.util.ResourceBundle object associated with the report. The $R{} character syntax extracts the locale-specific resource from the resource bundle based on the key that must be put between the brackets −

<textFieldExpression>
   $R{report.title}
</textFieldExpression>

上面的文本字段通过基于运行时提供的语言环境和 report.title 键从与报表模板关联的资源包中提取 String 值来显示报表的标题。

The above text field displays the title of the report by extracting the String value from the resource bundle associated with the report template based on the runtimesupplied locale and the report.title key.

  1. Formatting messages in different languages based on the report locale, there’s a built-in method inside the reports net.sf.jasperreports.engine.fill.JRCalculator. This method offers functionality similar to the java.text.MessageFormat class. This method, msg(), has three convenient signatures that allow you to use up to three message parameters in the messages.

  2. A built-in str() method (the equivalent of the $R{} syntax inside the report expressions), which gives access to the resource bundle content based on the report locale.

  3. For date and time formatting, the built-in REPORT_TIME_ZONE parameter can be used to ensure proper time transformations.

  4. In the generated output, the library keeps information about the text run direction so that documents generated in languages that have right-to-left writing (like Arabic and Hebrew) can be rendered properly.

  5. If an application relies on the built-in Swing viewer to display generated reports, then it needs to be internationalized by adapting the button ToolTips or other texts displayed. This is very easy to do since the viewer relies on a predefined resource bundle to extract locale-specific information. The base name for this resource bundle is net.sf.jasperreports.view.viewer.

Example

为了演示国际化,让我们编写新的报表模板(jasper_report_template.jrxml)。JRXML 的内容如下所示。将其保存到 C:\tools\jasperreports-5.0.1\test 目录。

To demonstrate internationalization, let’s write new report template (jasper_report_template.jrxml). The contents of the JRXML are as given below. Save it to C:\tools\jasperreports-5.0.1\test directory.

<?xml version = "1.0" encoding = "UTF-8"?>

<!DOCTYPE jasperReport PUBLIC "//JasperReports//DTD Report Design//EN"
   "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">

<jasperReport xmlns = "http://jasperreports.sourceforge.net/jasperreports"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://jasperreports.sourceforge.net/jasperreports
   http://jasperreports.sourceforge.net/xsd/jasperreport.xsd"
   name = "jasper_report_template" language = "groovy" pageWidth = "595"
   pageHeight = "842" columnWidth = "555" leftMargin = "20" rightMargin = "20"
   topMargin = "20" bottomMargin = "20" resourceBundle = "localizationdemo">

   <title>
      <band height = "552">

         <textField>
            <reportElement positionType = "Float" x = "150" y = "20"
               width = "400" height = "50"/>

            <textElement>
               <font size = "24"/>
            </textElement>

            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{REPORT_LOCALE}.getDisplayName ($P{REPORT_LOCALE})]]>
            </textFieldExpression>
         </textField>

         <textField isStretchWithOverflow = "true" isBlankWhenNull = "true">
            <reportElement positionType = "Float" x = "20" y = "125"
               width = "530" height = "20"/>

            <textElement textAlignment = "Justified">
               <font size = "14"/>
            </textElement>

            <textFieldExpression class = "java.lang.String">
               <![CDATA[$R{localization.text1}]]>
            </textFieldExpression>

         </textField>

      </band>
   </title>

</jasperReport>

在上面的文件中,<jasperReport> 元素的 resourceBundle 属性告诉 JasperReports 到哪里去获取供报表使用的本地化字符串。我们需要创建一个属性文件,其根名称与该属性值相匹配。填充报表时,此文件必须存在于 CLASSPATH 中的任意位置。在此示例中,属性文件 localizationdemo.properties 保存到目录 C:\tools\jasperreports-5.0.1\test 下。此文件的内容如下 -

In the above file, the resourceBundle attribute of the <jasperReport> element tells JasperReports where to get the localized strings to use for the report. We need to create a property file with a root name matching the value of the attribute. This file must exist anywhere in the CLASSPATH when filling the report. In this example, the property file localizationdemo.properties is saved under the directory C:\tools\jasperreports-5.0.1\test. The contents of this file are as follows −

localization.text1 = This is English text.

要使用不同的语言环境,该文件的文件名必须是 localizationdemo[locale].properties。在此,我们为西班牙语语言环境编写一个文件。将此文件另存为 - C:\tools\jasperreports-5.0.1\test\localizationdemo_es.properties 。此文件的内容如下 -

To use a different locale, the name of the file must be localizationdemo[locale].properties. Here, we will write a file for spanish locale. Save this file as − C:\tools\jasperreports-5.0.1\test\localizationdemo_es.properties. The contents of this file are as follow −

localization.text1 = Este texto es en Español.

获取 resourceBundle 属性值的语法为 $R{key}。

The syntax to obtain the value for resourceBundle properties is $R{key}.

为了让 JasperReports 知道我们希望使用的语言环境,我们需要给内置参数分配一个值。此参数的名称定义为一个常量 REPORT_LOCALE,此常量在 net.sf.jasperreports.engine.JRParameter 类中定义。此常量的值必须是 java.util.Locale 的一个实例。此逻辑被纳入到用于填充和生成报表的 Java 代码中。让我们将此文件 JasperReportFillI18.java 保存到目录 C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint 下。该文件的内容如下 -

To let JasperReports know what locale we wish to use, we need to assign a value to a built-in parameter. This parameter’s name is defined as a constant called REPORT_LOCALE, and this constant is defined in the net.sf.jasperreports.engine.JRParameter class. The constant’s value must be an instance of java.util.Locale. This logic is incorporated in java code to fill and generate the report. Let’s save this file JasperReportFillI18.java to C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint directory. The contents of the file are as follows −

package com.tutorialspoint;

import java.util.HashMap;
import java.util.Locale;

import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.JasperFillManager;

public class JasperReportFillI18 {

   public static void main(String[] args) {
      String sourceFileName = "C://tools/jasperreports-5.0.1/test/"
         + "jasper_report_template.jasper";
      HashMap parameterMap = new HashMap();
      if (args.length > 0) {
         parameterMap.put(JRParameter.REPORT_LOCALE, new Locale(args[0]));
      }
      try {
         JasperFillManager.fillReportToFile(sourceFileName, null,
            new JREmptyDataSource());
      } catch (JRException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }

   }
}

Report Generation

我们将使用常规 ANT 构建流程编译并执行上述文件。build.xml 文件(保存在 C:\tools\jasperreports-5.0.1\test 目录下)的内容如下。

We will compile and execute the above file using our regular ANT build process. The contents of the file build.xml (saved under directory C:\tools\jasperreports-5.0.1\test) are as given below.

导入文件 - baseBuild.xml 从第 Environment Setup 章中获取,并应放置在与 build.xml 相同的目录中。

The import file - baseBuild.xml is picked up from the chapter Environment Setup and should be placed in the same directory as the build.xml.

<?xml version = "1.0" encoding = "UTF-8"?>

<project name = "JasperReportTest" default = "viewFillReport" basedir = ".">
   <import file = "baseBuild.xml" />

   <target name = "viewFillReport" depends = "compile,compilereportdesing,run"
      description = "Launches the report viewer to preview the report stored
      in the .JRprint file.">

      <java classname = "net.sf.jasperreports.view.JasperViewer" fork = "true">
         <arg value = "-F${file.name}.JRprint" />
         <classpath refid = "classpath" />
      </java>
   </target>

   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">

      <taskdef name = "jrc" classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid="classpath" />
      </taskdef>

      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>

   </target>

</project>

接下来,让我们打开命令行窗口并转到放置 build.xml 的目录。最后,执行命令 ant -Dmain-class=com.tutorialspoint.JasperReportFillI18 (viewFullReport 是默认目标),如下所示 -

Next, let’s open command line window and go to the directory where build.xml is placed. Finally, execute the command ant -Dmain-class=com.tutorialspoint.JasperReportFillI18 (viewFullReport is the default target) as follows −

C:\tools\jasperreports-5.0.1\test>ant  -Dmain-class=com.tutorialspoint.JasperReportFillI18
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

clean-sample:
   [delete] Deleting directory C:\tools\jasperreports-5.0.1\test\classes
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jasper
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrprint

compile:
   [mkdir] Created dir: C:\tools\jasperreports-5.0.1\test\classes
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:28:
   warning: 'includeantruntime' was not set, defaulting to
   [javac] Compiling 1 source file to C:\tools\jasperreports-5.0.1\test\classes
   [javac] Note: C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\
      JasperReportFillI18.java
   uses unchecked or u
   [javac] Note: Recompile with -Xlint:unchecked for details.

compilereportdesing:
   [jrc] Compiling 1 report design files.
   [jrc] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [jrc] log4j:WARN Please initialize the log4j system properly.
   [jrc] log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig
      for more info.
   [jrc] File : C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml ... OK.

run:
   [echo] Runnin class : com.tutorialspoint.JasperReportFillI18
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

viewFillReport:
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

BUILD SUCCESSFUL
Total time: 3 minutes 28 seconds

作为上述编译的结果,一个 JasperViewer 窗口会打开,如以下给出的屏幕截图所示 -

As a result of above compilation, a JasperViewer window opens up as shown in the screen given below −

report i18 example