Java 中的国际化 - Sip of Java
Billy Korando,2022 年 8 月 17 日
Java 应用程序通常需要与世界各地的用户和数据协作。随着国家和语言应用程序的交叉,我们的应用程序需要能够无缝处理语言、文本格式、货币类型等方面的差异。幸运的是,Java 提供了多个 SPI 来帮助满足这些需求。让我们看看 Java 如何处理国际化 (i18n)!
查找合适的语言环境
Java 的大部分国际化行为都是通过 java.util.Locale
类驱动的。Locale
实现了 IETF BCP 47 标准,该标准对人类语言的识别和数据交换进行了编纂。
Locale
有三个构造函数
Locale(String language)
Locale(String language, String country)
Locale(String language, String country,
String variant)
参数 language
、country
和 variant
由 IETF BCP 47 标准定义,用于识别人类语言。这可以允许对特定语言方言进行细化,例如美式英语 new Locale("en", "US")
、英式英语 new Locale("en", "GB")
,视需要而定。有关受支持语言环境的完整列表,请查看文章末尾的链接。
所有 SPI 都具有无参数静态工厂方法,用于使用 JVM 提供的默认 Locale
或采用 Locale
作为参数的静态工厂方法创建实例,在某些情况下还采用其他参数。
BreakIterator
java.text.BreakIterator
类提供了一种 Locale
敏感的方式来查找文本中的边界。这可以在字符、单词、句子和行级别完成。请注意,“行”是指可以进行换行以进行文本包装的位置,而不是换行符在所提供文本中出现的位置。并且所提供文本中的换行符被视为句子终止符。考虑观看嵌入式视频,了解如何使用不同的 BreakIterator
设置来分解以下文本。
Java is
great!
Collator
java.text.Collator
类提供了一种区分大小写的 Locale
方式来比较字符串。字符串可以在 PRIMARY
、SECONDARY
、TERTIARY
和 IDENTICAL
差异上进行比较。例如,在英语中,ñ
和 n
将被视为 SECONDARY
差异,而在西班牙语中,它将是 PRIMARY
。以下示例显示了基于 Locale
和匹配强度,Collator
行为的差异。
Collator EN_COLLATOR =
Collator.getInstance(ENGLISH);
Collator ES_COLLATOR =
Collator.getInstance(SPANISH);
EN_COLLATOR.setStrength(Collator.PRIMARY);
ES_COLLATOR.setStrength(Collator.PRIMARY);
//ñ is not a primary difference in English,
but it is in Spanish
EN_COLLATOR.compare("nino", "niño");//0
ES_COLLATOR.compare("nino", "niño");//-1
EN_COLLATOR.setStrength(Collator.SECONDARY);
ES_COLLATOR.setStrength(Collator.SECONDARY);
//ñ is a secondary difference in English
EN_COLLATOR.compare("nino", "niño");//-1
ES_COLLATOR.compare("nino", "niño");//-1
日期和数字格式化
java.text.DateFormat
和 java.text.NumberFormat
类提供了一种区分大小写的 Locale
方式,根据提供的 Locale
规则对日期和数字进行格式化。一个常见的困惑来源是按国家/地区格式化日期的方式。在美国,日期通常格式化为 mm/dd/yyyy
,而许多其他国家/地区使用 dd/mm/yyyy
。DateFormat
可以无缝地处理此问题,如下例所示
US_DATE_FORMAT.format(new Date());
"8/15/22"
FRANCE_DATE_FORMAT.format(new Date());
"15/08/2022"
日期和数字符号
java.text.DateFormatSymbols
和 java.text.DecimalFormatSymbols
类提供了一种区分大小写的 Locale
方式,用于提供星期几、月份、货币符号等值。
DateFormatSymbols
在以下示例中,DateFormatSymbols
可用于根据 Locale
检索星期几的名称。但请注意,星期几的第一天始终是星期日,最后一天是星期六,这可能与该国家/地区通常的星期几顺序不符。
DateFormatSymbols.getInstance(US)
.getWeekdays();
{"","Sunday","Monday","Tuesday", "Wednesday",
"Thursday","Friday","Saturday"}
DateFormatSymbols.getInstance(MEXICO)
.getWeekdays();
{"","domingo","lunes","martes","miércoles",
"jueves", "viernes","sábado" }
DecimalFormatSymbols
在以下示例中,DecimalFormatSymbols
可用于检索与数字处理相关的符号。当存在细微差异时,这可能特别有用。在下面的示例中,法国和德国都使用 € 作为其货币符号,但法国使用空格“ ”作为分组分隔符,而德国使用句点“.”。
DecimalFormatSymbols.getInstance(GERMANY)
.getCurrencySymbol()
"€"
DecimalFormatSymbols.getInstance(FRANCE)
.getCurrencySymbol()
"€"
DecimalFormatSymbols.getInstance(GERMANY)
.getGroupingSeparator()
"."
DecimalFormatSymbols.getInstance(FRANCE)
.getGroupingSeparator()
" "
java.time 包
此外,请务必查看 java.time
包下的类。它提供了使用一致的 API 存储和格式化日期的多种选项。
附加阅读
编码愉快!