Java 中文官方教程 2022 版(二十八)(4)

简介: Java 中文官方教程 2022 版(二十八)

Java 中文官方教程 2022 版(二十八)(3)https://developer.aliyun.com/article/1486870

在国际化之前

原文:docs.oracle.com/javase/tutorial/i18n/intro/before.html

假设你已经编写了一个显示三条消息的程序,如下所示:

public class NotI18N {
    static public void main(String[] args) {
        System.out.println("Hello.");
        System.out.println("How are you?");
        System.out.println("Goodbye.");
    }
}

你已经决定这个程序需要为居住在法国和德国的人显示相同的消息。不幸的是,你的编程人员不懂多种语言,所以你需要帮助将这些消息翻译成法语和德语。由于翻译人员不是程序员,你需要将消息从源代码中移出,放入文本文件供翻译人员编辑。此外,程序必须足够灵活,以便能够显示其他语言的消息,但目前没有人知道那些语言会是什么。

看起来这个程序需要国际化。

国际化后

原文:docs.oracle.com/javase/tutorial/i18n/intro/after.html

国际化程序的源代码如下。请注意,消息的文本未包含在软件代码中。

import java.util.*;
public class I18NSample {
    static public void main(String[] args) {
        String language;
        String country;
        if (args.length != 2) {
            language = new String("en");
            country = new String("US");
        } else {
            language = new String(args[0]);
            country = new String(args[1]);
        }
        Locale currentLocale;
        ResourceBundle messages;
        currentLocale = new Locale(language, country);
        messages = ResourceBundle.getBundle("MessagesBundle", currentLocale);
        System.out.println(messages.getString("greetings"));
        System.out.println(messages.getString("inquiry"));
        System.out.println(messages.getString("farewell"));
    }
}

要编译和运行此程序,您需要这些源文件:

  • I18NSample.java
  • MessagesBundle.properties
  • MessagesBundle_de_DE.properties
  • MessagesBundle_en_US.properties
  • MessagesBundle_fr_FR.properties

运行示例程序

原文:docs.oracle.com/javase/tutorial/i18n/intro/run.html

国际化程序是灵活的;它允许最终用户在命令行上指定语言和国家。在下面的示例中,语言代码是fr(法语),国家代码是FR(法国),因此程序会以法语显示消息:

% java I18NSample fr FR
Bonjour.
Comment allez-vous?
Au revoir.

在下一个示例中,语言代码是en(英语),国家代码是US(美国),因此程序会以英语显示消息:

% java I18NSample en US
Hello.
How are you?
Goodbye.

国际化示例程序

原文:docs.oracle.com/javase/tutorial/i18n/intro/steps.html

如果你查看国际化的源代码,你会注意到硬编码的英文消息已经被移除。因为消息不再是硬编码的,而且语言代码在运行时指定,同一个可执行文件可以在全球范围内分发。本地化不需要重新编译。该程序已经国际化。

你可能想知道消息的文本发生了什么变化,或者语言和国家代码的含义是什么。别担心。当你逐步学习国际化示例程序的过程中,你会了解这些概念。

1. 创建属性文件

一个属性文件存储了关于程序或环境特性的信息。属性文件是纯文本格式。你可以用几乎任何文本编辑器创建这个文件。

在示例中,属性文件存储了要显示的可翻译消息的文本。在程序国际化之前,这些文本的英文版本是硬编码在System.out.println语句中的。默认的属性文件名为MessagesBundle.properties,包含以下内容:

greetings = Hello
farewell = Goodbye
inquiry = How are you?

现在消息已经在一个属性文件中,它们可以被翻译成各种语言。不需要对源代码进行任何更改。法语翻译者创建了一个名为MessagesBundle_fr_FR.properties的属性文件,其中包含以下内容:

greetings = Bonjour.
farewell = Au revoir.
inquiry = Comment allez-vous?

注意等号右侧的值已经被翻译,但左侧的键没有改变。这些键不能改变,因为当你的程序获取翻译后的文本时会引用这些键。

属性文件的名称很重要。例如,MessagesBundle_fr_FR.properties文件的名称包含了fr语言代码和FR国家代码。在创建Locale对象时也会使用这些代码。

2. 定义 Locale

Locale对象标识特定的语言和国家。以下语句定义了一个Locale,其中语言为英语,国家为美国:

aLocale = new Locale("en","US");

下一个示例创建了法语语言在加拿大和法国的Locale对象:

caLocale = new Locale("fr","CA");
frLocale = new Locale("fr","FR");

该程序是灵活的。程序不再使用硬编码的语言和国家代码,而是在运行时从命令行获取它们:

String language = new String(args[0]);
String country = new String(args[1]);
currentLocale = new Locale(language, country);

Locale对象只是标识符。在定义了一个Locale之后,你可以将它传递给执行有用任务的其他对象,比如格式化日期和数字。这些对象是区域敏感的,因为它们的行为根据Locale的不同而变化。ResourceBundle就是一个区域敏感的对象的例子。

3. 创建 ResourceBundle

ResourceBundle对象包含特定于区域设置的对象。你可以使用ResourceBundle对象来隔离与区域设置相关的数据,比如可翻译的文本。在示例程序中,ResourceBundle由包含我们想要显示的消息文本的属性文件支持。

ResourceBundle的创建方式如下:

messages = ResourceBundle.getBundle("MessagesBundle", currentLocale);

传递给getBundle方法的参数标识将要访问的属性文件。第一个参数MessagesBundle指的是这一系列属性文件:

MessagesBundle_en_US.properties
MessagesBundle_fr_FR.properties
MessagesBundle_de_DE.properties

LocalegetBundle的第二个参数,指定了选择哪个MessagesBundle文件。创建Locale时,语言代码和国家代码被传递给其构造函数。请注意,语言和国家代码在属性文件的名称中跟随MessagesBundle

现在你只需要从ResourceBundle中获取翻译后的消息即可。

4. 从 ResourceBundle 中获取文本

属性文件包含键值对。值包含了程序将显示的翻译文本。在从ResourceBundle中获取翻译后的消息时,你需要使用getString方法指定键。例如,要检索由greetings键标识的消息,你可以这样调用getString

String msg1 = messages.getString("greetings");

示例程序使用了键greetings,因为它反映了消息的内容,但也可以使用另一个String,比如s1msg1。只需记住,键是硬编码在程序中的,必须存在于属性文件中。如果你的翻译人员意外修改了属性文件中的键,getString将无法找到消息。

结论

这就是全部。正如你所看到的,国际化一个程序并不太困难。它需要一些规划和一点额外的编码,但好处是巨大的。为了让你了解国际化过程的概况,本课程中的示例程序被故意保持简单。在接下来的课程中,你将了解 Java 编程语言更高级的国际化特性。

检查表

原文:docs.oracle.com/javase/tutorial/i18n/intro/checklist.html

许多程序在最初编写时并未国际化。这些程序可能最初是原型,或者可能并非用于国际分发。如果你必须国际化现有程序,请执行以下步骤:

识别文化相关数据

文本消息是随文化变化最明显的数据形式。然而,其他类型的数据可能会随地区或语言而变化。以下列表包含了文化相关数据的例子:

  • 消息
  • GUI 组件上的标签
  • 在线帮助
  • 声音
  • 颜色
  • 图形
  • 图标
  • 日期
  • 时间
  • 数字
  • 货币
  • 测量
  • 电话号码
  • 敬语和个人头衔
  • 邮政地址
  • 页面布局

在资源包中隔离可翻译文本

翻译是昂贵的。你可以通过将必须翻译的文本隔离在ResourceBundle对象中来帮助降低成本。可翻译的文本包括状态消息、错误消息、日志文件条目和 GUI 组件标签。这些文本包含在尚未国际化的程序中。你需要找到所有显示给最终用户的包含文本的出现。例如,你应该清理这样的代码:

String buttonLabel = "OK";
// ...
JButton okButton = new JButton(buttonLabel);

详细信息请参见隔离特定区域数据部分。

处理复合消息

复合消息包含可变数据。在消息"The disk contains 1100 files."中,整数 1100 可能会变化。这个消息很难翻译,因为整数在句子中的位置在所有语言中都不相同。下面的消息是不可翻译的,因为句子元素的顺序是由串联固定的:

Integer fileCount;
// ...
String diskStatus = "The disk contains " + fileCount.toString() + " files";

尽可能避免构建复合消息,因为它们很难翻译。然而,如果你的应用程序需要复合消息,你可以使用消息部分中描述的技术来处理它们。

格式化数字和货币

如果你的应用程序显示数字和货币,你必须以与地区无关的方式格式化它们。以下代码尚未国际化,因为它在所有国家中都不会正确显示数字:

Double amount;
TextField amountField;
// ...
String displayAmount = amount.toString();
amountField.setText(displayAmount);

你应该用一个能正确格式化数字的例程替换前面的代码。Java 编程语言提供了几个格式化数字和货币的类。这些类在数字和货币部分有讨论。

格式化日期和时间

日期和时间格式因地区和语言而异。如果你的代码包含如下语句,你需要进行更改:

Date currentDate = new Date();
TextField dateField;
// ...
String dateString = currentDate.toString();
dateField.setText(dateString);

如果你使用日期格式化类,你的应用程序可以在全球范围内正确显示日期和时间。有关示例和说明,请参见日期和时间部分。

使用 Unicode 字符属性

以下代码尝试验证一个字符是否为字母:

char ch;
// This code is incorrect
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))

注意类似这样的代码,因为它在除英语以外的语言中无法正常工作。例如,if语句在德语单词 Grün 中漏掉了字符ü。

Character比较方法使用 Unicode 标准来识别字符属性。因此,您应该用以下代码替换先前的代码:

char ch;
// ...
if (Character.isLetter(ch))

有关Character比较方法的更多信息,请参阅检查字符属性部分。

正确比较字符串

在对文本进行排序时,通常需要比较字符串。如果文本是显示的,您不应该使用String类的比较方法。一个未国际化的程序可能会这样比较字符串:

String target;
String candidate;
// ...
if (target.equals(candidate)) {
// ...
if (target.compareTo(candidate) < 0) {
// ...

String.equalsString.compareTo方法执行二进制比较,在大多数语言中排序时效率低下。相反,您应该使用Collator类,该类在比较字符串部分有描述。

转换非 Unicode 文本

Java 编程语言中的字符是以 Unicode 编码的。如果您的应用程序处理非 Unicode 文本,您可能需要将其转换为 Unicode。有关更多信息,请参阅转换非 Unicode 文本部分。

课程:设置区域设置

原文:docs.oracle.com/javase/tutorial/i18n/locale/index.html

一个国际化的程序可以在世界各地以不同方式显示信息。例如,该程序将在巴黎、东京和纽约显示不同的消息。如果本地化过程已经经过精细调整,该程序将显示不同的消息在纽约和伦敦,以考虑美式英语和英式英语之间的差异。一个国际化的程序如何识别其最终用户的适当语言和地区?简单。它引用一个Locale对象。

一个Locale对象是特定语言和地区组合的标识符。如果一个类根据Locale变化其行为,那么它被称为区域敏感。例如,NumberFormat类是区域敏感的;它返回的数字格式取决于Locale。因此,NumberFormat可能会将数字返回为 902 300(法国)、902.300(德国)或 902,300(美国)。Locale对象只是标识符。真正的工作,比如格式化和检测单词边界,是由区域敏感类的方法执行的。

以下各节解释了如何使用Locale对象:

创建一个 Locale

在创建Locale对象时,通常会指定语言代码和国家代码。第三个参数,变体,是可选的。

BCP 47 扩展

本节向您展示如何向Locale添加 Unicode 区域扩展或私有使用扩展。

识别可用的 Locale

区域敏感类仅支持特定的Locale定义。本节将向您展示如何确定支持哪些Locale定义。

语言标签过滤和查找

本节描述了语言标签、语言标签过滤和语言标签查找的国际化支持。

Locale 的范围

在 Java 平台上,您不需要通过在运行应用程序之前设置环境变量来指定全局Locale。相反,您要么依赖于默认 Locale,要么为每个区域敏感对象分配一个Locale

区域敏感服务 SPI

本节解释了如何启用依赖于区域设置的数据和服务的插件。这些 SPI(服务提供者接口)提供了对当前可用区域设置之外更多区域设置的支持。

创建 Locale

原文:docs.oracle.com/javase/tutorial/i18n/locale/create.html

有几种方法可以创建 Locale 对象。无论使用哪种技术,创建可以简单地指定语言代码。但是,您还可以通过设置区域(也称为“国家”)和变体代码来进一步区分区域。如果您使用 JDK 7 发布或更高版本,还可以指定脚本代码和 Unicode 区域扩展。

创建 Locale 对象的四种方法是:

  • Locale.Builder
  • Locale 构造函数
  • Locale.forLanguageTag 工厂方法
  • Locale 常量

版本说明: Locale.Builder 类和 forLanguageTag 方法是在 Java SE 7 发布中添加的。


LocaleBuilder

Locale.Builder 实用类可用于构造符合 IETF BCP 47 语法的 Locale 对象。例如,要指定法语和加拿大国家,您可以调用 Locale.Builder 构造函数,然后链接设置器方法如下:

Locale aLocale = new Locale.Builder().setLanguage("fr").setRegion("CA").build();

下一个示例创建了英语在美国和英国的 Locale 对象:

Locale bLocale = new Locale.Builder().setLanguage("en").setRegion("US").build();
Locale cLocale = new Locale.Builder().setLanguage("en").setRegion("GB").build();

最后一个示例创建了俄语的 Locale 对象:

Locale dLocale = new Locale.Builder().setLanguage("ru").setScript("Cyrl").build();

Locale 构造函数

Locale 类有三个可用的构造函数用于创建 Locale 对象:

以下示例创建了法语在加拿大,英语在美国和英国,以及俄语的 Locale 对象。

aLocale = new Locale("fr", "CA");
bLocale = new Locale("en", "US");
cLocale = new Locale("en", "GB");
dLocale = new Locale("ru");

在 JDK 7 之前的版本中,无法在 Locale 对象上设置脚本代码。

forLanguageTag 工厂方法

如果您有符合 IETF BCP 47 标准的语言标记字符串,可以使用在 Java SE 7 发布中引入的 forLanguageTag(String) 工厂方法。例如:

Locale aLocale = Locale.forLanguageTag("en-US");
Locale bLocale = Locale.forLanguageTag("ja-JP-u-ca-japanese");

Locale 常量

为了方便起见,Locale 类为一些语言和国家提供了常量。例如:

cLocale = Locale.JAPAN;
dLocale = Locale.CANADA_FRENCH;

当您指定语言常量时,Locale 的区域部分是未定义的。下面的三个语句创建等效的 Locale 对象:

j1Locale = Locale.JAPANESE;
j2Locale = new Locale.Builder().setLanguage("ja").build();
j3Locale = new Locale("ja");

由以下三个语句创建的Locale对象也是等效的:

j4Locale = Locale.JAPAN;
j5Locale = new Locale.Builder().setLanguage("ja").setRegion("JP").build();
j6Locale = new Locale("ja", "JP");

代码

以下部分讨论语言代码和可选的脚本、地区和变体代码。

语言代码

语言代码是符合 ISO 639 标准的两个或三个小写字母。您可以在www.loc.gov/standards/iso639-2/php/code_list.php找到 ISO 639 代码的完整列表。

以下表格列出了一些语言代码。

示例语言代码

语言代码 描述
de 德语
en 英语
fr 法语
ru 俄语
ja 日语
jv 爪哇语
ko 韩语
zh 中文

脚本代码

脚本代码以大写字母开头,后跟三个小写字母,并符合 ISO 15924 标准。您可以在unicode.org/iso15924/iso15924-codes.html找到 ISO 15924 代码的完整列表。

以下表格列出了一些脚本代码。

示例脚本代码

脚本代码 描述
Arab 阿拉伯语
Cyrl 西里尔字母
Kana 片假名
Latn 拉丁字母

有三种方法可以检索Locale的脚本信息:

  • getScript() – 返回Locale对象的 4 字母脚本代码。如果未为区域设置定义脚本,则返回空字符串。
  • getDisplayScript() – 返回适合显示给用户的区域设置脚本的名称。如果可能,名称将针对默认区域设置进行本地化。因此,例如,如果脚本代码是"Latn",则返回的显示脚本名称将在英语语言区域设置下为"Latin"。
  • getDisplayScript(Locale) – 返回指定Locale的显示名称,如果可能的话进行本地化。

地区代码

地区(国家)代码由符合 ISO 3166 标准的两个或三个大写字母组成,或者符合 UN M.49 标准的三个数字。代码的副本可以在www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html找到。

以下表格包含几个示例国家和地区代码。

示例地区代码

A-2 代码 A-3 代码 数字代码 描述
AU AUS 036 澳大利亚
BR BRA 076 巴西
CA CAN 124 加拿大
CN CHN 156 中国
DE DEU 276 德国
FR FRA 250 法国
IN IND 356 印度
RU RUS 643 俄罗斯联邦
US USA 840 美国

变体代码

可选的variant代码可用于进一步区分您的Locale。例如,变体代码可用于指示区域代码未涵盖的方言差异。


版本说明: 在 Java SE 7 发布之前,变体代码有时用于标识不特定于语言或区域的差异。例如,它可能已用于标识计算平台之间的差异,如 Windows 或 UNIX。根据 IETF BCP 47 标准,不鼓励此用法。

要定义与您的环境相关的非语言特定变体,请使用扩展机制,如 BCP 47 扩展中所解释的那样。


自 Java SE 7 发布以来,符合 IETF BCP 47 标准的变体代码专门用于指示定义语言或其方言的附加变体。IETF BCP 47 标准对变体子标记施加了语法限制。您可以在www.iana.org/assignments/language-subtag-registry上查看变体代码列表(搜索变体)。

例如,Java SE 使用变体代码支持泰语。按照惯例,thth_TH 区域设置的NumberFormat对象将使用常见的阿拉伯数字形状或阿拉伯数字来格式化泰国数字。然而,th_TH_TH 区域设置的NumberFormat将使用泰国数字形状。ThaiDigits.java中的摘录演示了这一点:

String outputString = new String();
Locale[] thaiLocale = {
             new Locale("th"),
             new Locale("th", "TH"),
             new Locale("th", "TH", "TH")
         };
for (Locale locale : thaiLocale) {
    NumberFormat nf = NumberFormat.getNumberInstance(locale);
    outputString = outputString + locale.toString() + ": ";
    outputString = outputString + nf.format(573.34) + "\n";
}

以下是此示例的屏幕截图:



相关文章
|
7月前
|
JavaScript NoSQL Java
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
363 96
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
|
3月前
|
Oracle Java 关系型数据库
java 编程基础入门级超级完整版教程详解
这份文档是针对Java编程入门学习者的超级完整版教程,涵盖了从环境搭建到实际项目应用的全方位内容。首先介绍了Java的基本概念与开发环境配置方法,随后深入讲解了基础语法、控制流程、面向对象编程的核心思想,并配以具体代码示例。接着探讨了常用类库与API的应用,如字符串操作、集合框架及文件处理等。最后通过一个学生成绩管理系统的实例,帮助读者将理论知识应用于实践。此外,还提供了进阶学习建议,引导学员逐步掌握更复杂的Java技术。适合初学者系统性学习Java编程。资源地址:[点击访问](https://pan.quark.cn/s/14fcf913bae6)。
306 2
|
8月前
|
消息中间件 Java 数据库
自研Java框架 Sunrays-Framework使用教程「博客之星」
### Sunrays-Framework:助力高效开发的Java微服务框架 **Sunrays-Framework** 是一款基于 Spring Boot 构建的高效微服务开发框架,深度融合了 Spring Cloud 生态中的核心技术组件。它旨在简化数据访问、缓存管理、消息队列、文件存储等常见开发任务,帮助开发者快速构建高质量的企业级应用。 #### 核心功能 - **MyBatis-Plus**:简化数据访问层开发,提供强大的 CRUD 操作和分页功能。 - **Redis**:实现高性能缓存和分布式锁,提升系统响应速度。 - **RabbitMQ**:可靠的消息队列支持,适用于异步
自研Java框架 Sunrays-Framework使用教程「博客之星」
|
9月前
|
移动开发 前端开发 Java
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
8426 5
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
|
8月前
|
Java 数据库连接 数据处理
探究Java异常处理【保姆级教程】
Java 异常处理是确保程序稳健运行的关键机制。它通过捕获和处理运行时错误,避免程序崩溃。Java 的异常体系以 `Throwable` 为基础,分为 `Error` 和 `Exception`。前者表示严重错误,后者可细分为受检和非受检异常。常见的异常处理方式包括 `try-catch-finally`、`throws` 和 `throw` 关键字。此外,还可以自定义异常类以满足特定需求。最佳实践包括捕获具体异常、合理使用 `finally` 块和谨慎抛出异常。掌握这些技巧能显著提升程序的健壮性和可靠性。
133 4
|
8月前
|
存储 移动开发 算法
【潜意识Java】Java基础教程:从零开始的学习之旅
本文介绍了 Java 编程语言的基础知识,涵盖从简介、程序结构到面向对象编程的核心概念。首先,Java 是一种高级、跨平台的面向对象语言,支持“一次编写,到处运行”。接着,文章详细讲解了 Java 程序的基本结构,包括包声明、导入语句、类声明和 main 方法。随后,深入探讨了基础语法,如数据类型、变量、控制结构、方法和数组。此外,还介绍了面向对象编程的关键概念,例如类与对象、继承和多态。最后,针对常见的编程错误提供了调试技巧,并总结了学习 Java 的重要性和方法。适合初学者逐步掌握 Java 编程。
145 1
|
9月前
|
NoSQL Java 关系型数据库
Liunx部署java项目Tomcat、Redis、Mysql教程
本文详细介绍了如何在 Linux 服务器上安装和配置 Tomcat、MySQL 和 Redis,并部署 Java 项目。通过这些步骤,您可以搭建一个高效稳定的 Java 应用运行环境。希望本文能为您在实际操作中提供有价值的参考。
556 26
|
8月前
|
前端开发 Java 开发工具
Git使用教程-将idea本地Java等文件配置到gitte上【保姆级教程】
本内容详细介绍了使用Git进行版本控制的全过程,涵盖从本地仓库创建到远程仓库配置,以及最终推送代码至远程仓库的步骤。
415 0
|
9月前
|
安全 Java 编译器
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
|
9月前
|
Java 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)

热门文章

最新文章