JDK 软件国际化概述
简介
全球化的互联网要求全球化的软件 - 即,软件可以独立于用户的国家或语言进行开发,然后可以进行多个国家和地区的本地化。JDK(全称 Java Development Kit,即 Java 开发工具包)软件提供大量开发全球化应用程序的 API(应用程序接口)。这些国际化 API 基于 Unicode 2.0 字符编码,可以使文本、数字、日期、货币和用户定义的对象适合任意国家的习惯。
本文总结了国际化 API 和 JDK 软件的功能。有关编码示例和详细指导的信息,参见 Java 教程。API 的详细信息,参见 Java 平台 API 规范。
有关其它信息,参见 JDK 国际化主页。
Locale
在 Java 平台中,locale 仅仅是语言和地区的某种组合的标识符。它不是与 locale 有关的属性的集合。每个对 locale 敏感的类都保存它自己的与 locale 有关的信息。这样,用户和系统对象对自己的与 locale 有关的资源进行保存的方式是没有差别的。它们都使用标准本地化机制。
Java 程序不指定某一全球化 locale。所有对 locale 敏感的操作都可以明确指定 locale 作为其参数。这大大简化了多语言程序。虽然不强制指定全球化 locale,但那些不希望明确管理 locale 的程序仍可使用缺省 locale。缺省 locale 也可以用一次选择去影响全部表示。
Java locale 充当来自另一对象的对某种行为的请求。例如,传入 Calendar 对象的法语区加拿大 locale 要求 Calendar 正确操作以符合魁北克的习惯。对象应该接受 locale 的要求并作出正确反应。如果对象尚未对某一 locale 进行本地化,它将试图找到一个与之“最接近”匹配的已本地化的 locale。因此,如果 Calendar 对象尚未针对法语区加拿大进行本地化,但通常已有法语的本地化版本,则它将使用法语本地化。
Locale 类
对象表示某一特定的地理、政治或文化区域。需要 locale 执行其任务的操作称为对 locale 敏感的操作,该操作使用 Locale 对象为用户提供适当信息。例如,显示数字是一种对 locale 敏感的操作 - 数字应根据用户的国家、地区或文化的习惯和风俗进行格式化。支持的 Locale
在 Java 平台中,不需有一个受支持的 locale 的单个集合,因为每个类都有其自己的本地化。尽管如此,仍有一个 JDK 软件类支持的本地化集合。Java 平台的其它实现可以支持不同的 locale。JDK 软件支持的 Locale 在网页支持的 Locale 中进行了总结。JDK 软件的以后版本还会包括其它 locale。
本地化资源
所有对 locale 敏感的类必须能够访问为它们支持的
locale 而定制的资源。在本地化过程中,它帮助将这些资源按 locale 分组,
并与程序中与 locale 无关的部分分开。
ResourceBundle 类
类 ResourceBundle 是抽象基本类,表示资源的容器。程序员创建 ResourceBundle 的子类,其中包含特定 locale 的资源。可以将新资源添加到 ResourceBundle 的实例中,或将 ResourceBundle 的新实例添加到系统中,而不影响使用它们的代码。将资源包装为类可以使开发人员能够利用 Java 的类加载机制来查找资源。
资源包包含与 locale 有关的对象。当程序需要与 locale 有关的资源(例如 String 对象)时,该程序可以从当前用户的 locale 对应的资源包中加载它。用这种方式使程序员编写的代码可以在很大程度上摆脱用户 locale 的限制,而用户 locale 同资源包中的大部分(若非全部)与 locale 有关的信息是隔离的。
方便地进行本地化或被翻译为不同语言一次处理多个 locale
易于修改,以便支持更多的 locale
ListResourceBundle 类
ListResourceBundle 是 ResourceBundle 的抽象子类,在一个便利并易于使用的列表中管理某一 locale 的资源。
是 ResourceBundle 的抽象子类,在一个便利并易于使用的列表中管理某一 locale 的资源。PropertyResourceBundle 类
PropertyResourceBundle 是 ResourceBundle 的具体子类,它用属性文件中的静态字符串集来管理某一 locale 的资源。
是 ResourceBundle 的具体子类,它用属性文件中的静态字符串集来管理某一 locale 的资源。日历和时区支持
JDK 软件的 1.0 版引入了 java.util.Date 类表示日期和时间。java.util.Date 类允许将日期解释为年、月、日、小时、分钟和秒等值,并且对日期字符串进行格式化和解析。但是,这些功能的 API 却不支持国际化。JDK 软件的 1.1 版仅保留了该类的“表示”部分。
在 JDK 软件的 1.1 版,Date 类应仅仅被用作日期或时间的 wrapper。这就是说,Date 对象以毫秒的精度表示时间的某一特定时刻。但是,程序员应使用 Calendar 类在日期和时间域之间进行转换,并使用 DateFormat 类来对日期字符串进行格式化和解析。JDK 软件 1.0 版中 Date 类的相应方法已废弃。
Calendar 类
类 Calendar 是抽象基本类,它可以在时间的某一点(从 1970 年 1 月 1 日 00:00:00 GMT 起表示为毫秒)和表示年、月、星期等的整数集之间进行转换。GregorianCalendar 是 Calendar 的具体子类,它根据罗马日历的规则进行这种转换。
Calendar 及其子类可用于对时间值的不同处理。可以在 Calendar 对象的域上执行算法,然后确定所得日期。Calendar 对象可以产生对某一种语言和日历风格实现日期-时间格式化时所需的所有时间域值。
TimeZone 类
抽象类 TimeZone 封装了 UTC(世界标准时间)的时区偏移量和可能的夏时制的偏移量。类 SimpleTimeZone 是具体子类,它封装了一些关于夏时制的简单规则。这些规则不考虑影响夏时制的法则的历史变化。Calendar 类及其子类使用 TimeZone 和 SimpleTimeZone 类在本地时间和 UTC 之间进行转换,UTC 是 Date 对象所用的内部表示。大部分程序都无需直接处理 TimeZone 对象。
格式化
许多文化习惯都要求格式化输出数据。数字、日期、时间和消息在显示前可能都需要格式化。Java 平台提供一系列灵活的格式化类,既可处理标准 locale 格式,也可处理程序员自定义的格式。这些格式化类也可以将已格式化字符串解析为组成它们的对象。
Format 类
类 Format 是抽象基本类,负责格式化对 locale 敏感的信息,例如日期、时间、消息和数字。它提供了三个主要子类: DateFormat、NumberFormat 和 MessageFormat。这三个子类也有自己的子类。
DateFormat 类
日期和时间在内部以独立于 locale 的方式存储,但为了以对 locale 敏感的方式显示,必须格式化。例如,同一日期应被格式化为:
November 3, 1997(英语)3 novembre 1997(法语)
类 DateFormat 是抽象基本类,以独立于 locale 的方式对日期和时间值进行格式化和解析。它有许多静态工厂方法来获得给定 locale 的标准时间格式。
DateFormat 对象使用 Calendar 和 TimeZone 对象来解释时间值。在缺省情况下,给定 locale 的 DateFormat 对象将使用该 locale 的相应 Calendar 对象和系统缺省的 TimeZone 对象。程序员如果愿意,可以覆盖这些选项。
SimpleDateFormat 类
类 SimpleDateFormat 是具体类,以对 locale 敏感的方式对日期和时间进行格式化和解析。它允许格式化(毫秒到文本)、解析(文本到毫秒)和标准化。
DateFormatSymbols 类
类 DateFormatSymbols 用来封装可进行本地化的日期-时间格式数据,例如月名、星期名、一天中的时间和时区数据。DateFormat 和 SimpleDateFormat 类都使用 DateFormatSymbols 类来封装该信息。
程序员通常不直接使用 DateFormatSymbols。他们用 DateFormat 类的工厂方法实现格式化。
NumberFormat 类
类 NumberFormat 是抽象基本类,用来对数字数据进行格式化和解析。它有许多静态工厂方法来获得不同的与 locale 有关的数字格式。
NumberFormat 类有助于程序员对任意 locale 的数字进行格式化和解析。使用该类的代码可以完全独立于小数点、千分位符、特殊的十进制数字,甚至与数字格式是否为十进制也完全无关。应用程序也可以以标准十进制数字、货币或百分比的形式显示数字:
1234.5(十进制数字)$1,234.50(美国货币)
Fr1.234,5(法语货币)
123450%(百分比)
DecimalFormat 类
数字在内部以独立于 locale 的方式存储,但为了以对 locale 敏感的方式显示,必须格式化。例如,当使用“#,###.00”形式时,同一数字可格式化为:
1.234,56(德语)1,234.56(英语)
类 DecimalFormat 是 NumberFormat 类的具体子类,可以格式化十进制数字。程序员通常并不直接实例化该类,而是用它提供的工厂方法。
DecimalFormat 类可以根据模式字符串指定如何格式化数字。模式指定属性,例如数字的精确度,是否显示前导零以及使用什么货币符号。如果程序需要创建自定义格式,则可以更改模式字符串。
DecimalFormatSymbols 类
类 DecimalFormatSymbols 表示 DecimalFormat 用来格式化数字的符号集(例如十进制分隔符、分组分隔符等)。DecimalFormat 从它的 locale 数据中为自己创建 DecimalFormatSymbols 的实例。需要更改这些符号的程序员可以从 DecimalFormat 对象中获得 DecimalFormatSymbols 对象,然后修改它。
ChoiceFormat 类
类 ChoiceFormat 是 NumberFormat 类的具体子类。ChoiceFormat 类允许程序员对一系列数字应用格式。它通常在 MessageFormat 对象中用于处理多于俩个数字的情况。有关详细信息,参见下面的“MessageFormat 类”一节。
MessageFormat 类
程序经常需要根据一个字符串、数字和其它数据的序列来构建消息。例如,显示磁盘驱动器中文件数量的消息文本是不同的:
磁盘 C 包含 100 个文件。磁盘 D 包含 1 个文件。
磁盘 F 包含 0 个文件。
如果根据字符串和数字顺序构建的消息已进行硬编码,则它不能再翻译成其它语言。例如,注意参数“3”和“G”在以下译文中的位置:
The disk G contains 3 files. (英语)Il y a 3 fichiers sur le disque G.(法语)
类 MessageFormat 提供了一种方法,以独立于语言的方式产生连续消息。MessageFormat 对象接受一组对象,将其格式化,然后将已格式化的字符插入模式中的相应位置。
ParsePosition 类
Format 类及其子类使用类 ParsePosition,以在解析过程中跟踪当前位置。Format 类中的 parseObject() 方法需要将 ParsePosition 对象作为参数。
FieldPosition 类
Format 及其子类使用 FieldPosition 类来标识格式化输出中的域。Format 类中有一种版本的 format() 方法需要将 FieldPosition 对象作为参数。
对 Locale 敏感的字符串操作
程序经常需要操作字符串。在字符串上的普通操作包括搜索和排序。某些任务(例如整理字符串或查找文本中的不同边界)很难正确完成,而当需要考虑多种语言时就更为困难。JDK 软件提供了一些类,可以以对 locale 敏感的方式处理许多普通字符串操作。
Collator 类
类执行对 locale 敏感的字符串的排序操作。程序员使用该类构建自然语言文本的搜索和按字母顺序排序例程。Collator 是抽象基本类。它的子类实现特定排序原则。JDK 软件当前提供的一个子类 RuleBasedCollator 适用于多种语言。可以创建其它子类来处理更特定的需求。RuleBasedCollator 类
类是 Collator 类的具体子类,提供一个简单的,数据驱动的表排序类。程序员可以使用 RuleBasedCollator 创建自定义的基于表的排序类。例如,程序员可以构建一个排序类,使它忽略(或考虑)大写字母、重音和 Unicode 组合字符。CollationElementIterator 类
类可作为迭代器,在国际化字符串的每个字符之间移动。程序员使用迭代器返回已定位字符的优先顺序。字符或关键字的优先顺序定义如何在给定 Collator 对象中排序字符。RuleBasedCollator 类的 compare() 方法使用 CollationElementIterator 类。CollationKey 类
对象表示一个遵循特定 Collator 对象规则的字符串。对两个 CollationKey 对象的比较返回它们所代表的字符串的相对顺序。用 CollationKey 对象来比较字符串通常比使用 Collator.compare() 方法快。因此,当必须对字符串进行多次比较时(例如排序一列字符串时),使用 CollationKey 对象更为有效。BreakIterator 类
BreakIterator 类间接实现在文本字符串中查找以下类型边界的位置的方法:
类间接实现在文本字符串中查找以下类型边界的位置的方法: 可能的换行符句
单词
字符
各种语言中,行、句、单词和字符如何结束的习惯不同。因为 BreakIterator 类对 locale 敏感,所以程序可以使用它执行文本操作。例如,考虑一个字处理程序,它可以高亮显示字符、剪切单词、将光标移动到下一句或在行末折词。这种字处理程序使用分隔迭代器来确定文本中的逻辑边界,使它可以以对 locale 敏感的方式执行文本操作。
StringCharacterIterator 类
类可以在 Unicode 字符串中双向移动。该类使用光标在一段文本内移动,可以返回各个字符或其索引值。StringCharacterIterator 类实现 CharacterIterator 接口的字符迭代器功能。CharacterIterator 接口
接口定义在 Unicode 字符中双向移动的协议。如果某些类要在一段文本内移动,并返回各个 Unicode 字符或其索引值,则应实现此接口。用于搜索的 CharacterIterator 执行字符搜索时有用。字符集转换
Java 平台使用 Unicode 作为其本地字符编码;但是许多 Java 程序仍需处理以其它编码方式存在的文本数据。因此,Java 提供了一组类,它可以在许多标准字符编码和 Unicode 之间来回转换。需要处理非 Unicode 文本数据的 Java 程序通常将数据转换为 Unicode,以 Unicode 方式处理数据,然后再将结果转换回外部字符编码。InputStreamReader 和 OutputStreamWriter 类提供的方法可以在其它字符编码和 Unicode 之间进行转换。
支持的编码
InputStreamReader、OutputStreamWriter 和 String 类可以在 Unicode 和网页支持的编码中列出的以下字符编码之间进行转换。
AWT 属性
为了更好地进行程序 GUI 的国际化,JDK 软件为 Component 类提供这两个属性: Name 和 Locale。
Name 属性
Name 属性是 String 对象,它是 Component 对象的非本地化标识符。Component 类及其子类的新构造函数允许设置 Name 属性。如果不使用这些构造函数,则缺省 Name 将被分派给 Component 对象。可以使用 Component.getName() 方法检查 Component 对象的 Name 属性。
Name 属性在编写 Action 处理例程时特别有用,在该类例程中无法提前知道对目标的引用。这种 Action 处理程序通常由 GUI 构造器生成。以前,这些例程试图通过查看目标 Component 的标签字符串来标识它。标签字符串被本地化后,这种方法即失败。象 JDK 软件的 1.1 版一样,程序员应代替使用 Component.getName() 方法。
Locale 属性
Component 类现在包含 Locale 属性。该属性由方法 getLocale() 和 setLocale()methods 访问。如果 Component 对象的 Locale 未明确设置,其值缺省为 Component 对象的父类的 Locale。如果层次中没有带明确 Locale 的 Component,缺省为 Locale.getDefault() 的值。
Component 的 Locale 属性允许 GUI(或 GUI 的一部分)保持它自己的缺省 locale。这会是很有用的,例如,浏览器的其它部分使用 American locale 而 applet 仍可使用 Japanese locale。
流 I/O
JDK 软件在 java.io 包中提供改善字符日期处理的功能: 新的 Reader 和 Writer 类,以及 PrintStream 类的增强功能。
Reader 和 Writer 类
和 类集合可以在字符流上执行 I/O 操作。这些集合将 InputStream 和 OutputStream 类层次并行起来,但在字符流上操作,而不是在字节流上操作。字符流使编写不依赖于特定字符编码的程序更容易,因此更易于国际化。Reader 和 Writer 类也可以在 Unicode 和其它字符编码之间进行转换。有关 Reader 和 Writer 类层次的详细信息,参见文档。PrintStream 类
PrintStream 已增强为使用系统缺省字符编码和行终止符产生输出。这种变化允许诸如 System.out.println() 的方法对非 ASCII 数据执行更为合理的操作。
已增强为使用系统缺省字符编码和行终止符产生输出。这种变化允许诸如 System.out.println() 的方法对非 ASCII 数据执行更为合理的操作。字符分类
Java 平台以 Unicode(一种国际字符集标准)方式存储字符数据。Unicode 标准使用 16 位编码支持世界各地的所有主要字符集,也包括通用技术符号。大部分 Java 代码是用 ASCII(7 位标准)或 ISO-Latin-1(8 位标准)编写的,但在处理前都转换为 Unicode。因此,Java 字符集总是由 Unicode 表示。
JDK 软件的 1.0 版引入了 Character 类作为字符基本类型的对象 wrapper。Character 类也包含一些诸如 isLowerCase() 和 isDigit() 的静态方法,以便确定字符的属性。这套方法已在 JDK 软件的 1.1 版中作了扩展,能够允许访问所有 Unicode 2.0 定义的字符属性。
输入法
因为中文、日语和韩国语的字符集很大,所以对它们作键盘映射是不可行的。为在应用程序中输入文本,用户经常使用称为输入法的前端工具。输入法允许用户预先制作亚洲字符集,然后送入应用程序中。
术语“输入法”指的不是 Java 编程语言中的类方法。主机平台(例如 Solaris 或 Windows)提供对输入法的支持。JDK 软件的当前版本 (1.2.0) 不包含输入法的引擎。
在与 JDK 软件的 1.1 版兼容的版本中,用户可以使用输入法在 TextField 和 TextArea AWT 组件中输入文本。
Swing 中的 on-the-spot 输入支持
JDK 软件的 1.2 版通过输入法框架支持 on-the-spot(内联)编辑。 on-the-spot 编辑是输入法的一种功能,它允许用户直接将文本输入到文本域中。当用户用 on-the-spot 编辑输入文本时,输入法将文本直接插入文本组件中。应用程序开发人员不必协调输入法和文本组件之间的动作。当文本组件被启用来进行 on-the-spot 编辑时,JDK 软件处理所需的协调工作。但是,当必须提交所有文本时(例如保存或打印文档时),开发人员应调用 InputContext.endCompostion。InputContext 类是输入法框架中的一部分。
输入法框架
输入法框架是 JDK 软件的 1.2 版所提供的一组 API。输入法框架启用文本编辑组件来与输入法交互。开发文本编辑组件的程序员应使用输入法框架。应用程序开发人员通常不使用输入法框架。但是,当必须提交所有文本时(例如保存或打印文档时),应用程序开发人员应调用 InputContext.endCompostion。
输入法框架网页中包含与规范和 API 文档的链接。