设置阿拉伯数字系统区域设置不显示阿拉伯数字

Setting Arabic numbering system locale doesn't show Arabic numbers

我读了这篇文章:JDK 8 and JRE 8 Supported Locales,它说:

Numbering systems can be specified by a language tag with a numbering system ID ╔═════════════════════╦══════════════════════╦══════════════════╗ ║ Numbering System ID ║ Numbering System ║ Digit Zero Value ║ ╠═════════════════════╬══════════════════════╬══════════════════╣ ║ arab ║ Arabic-Indic Digits ║ \u0660 ║ ╚═════════════════════╩══════════════════════╩══════════════════╝

现在,为了演示这一点,我编写了以下代码:

import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Locale;

public class Main
{
    public static void main(String[] args)
    {
        Locale locale = new Locale("ar", "sa", "arab");
        DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(locale);
        NumberFormat numberFormat = NumberFormat.getNumberInstance(locale);
        System.out.println(dfs.getZeroDigit());
        System.out.println(numberFormat.format(123));
    }
}

我希望输出类似于:

٠
١٢٣

但是,输出如下:

0
123

这样做的主要目的是让 JavaFX GUI 显示阿拉伯数字而不是英语数字,因为它使用默认语言环境(我可以用 Locale.setDefault(...) 设置它)。

所以我的问题是,如何使用语言环境中的编号系统在 Java 中显示本地化数字?那么,是否可以在JavaFX上应用呢?

是的,我做到了!仔细阅读 Locale's JavaDoc 后,我能够生成所需的语言环境:

Locale arabicLocale = new Locale.Builder().setLanguageTag("ar-SA-u-nu-arab").build();

相当于:

Locale arabicLocale = new Locale.Builder().setLanguage("ar").setRegion("SA")
                   .setExtension(Locale.UNICODE_LOCALE_EXTENSION, "nu-arab").build();

请注意,我使用的是(Unicode locale/language 扩展名):

UTS#35, "Unicode Locale Data Markup Language" defines optional attributes and keywords to override or refine the default behavior associated with a locale. A keyword is represented by a pair of key and type.

The keywords are mapped to a BCP 47 extension value using the extension key 'u' (UNICODE_LOCALE_EXTENSION).

数字的扩展键是(nu),我使用的值是(arab)。


您可以看到所有扩展键的列表here

虽然已接受答案中的 LocaleNumberFormat 配合得很好; DateTimeFormatter(以及所有其他 java.time 格式化程序)无法正确使用它,至少在 JDK 10.

中引入 localizedBy() 之前是这样

因此,对于无法使用 JDK 10+ 并希望获得完全本地化的日期字符串表示形式的人,一种替代方法是 (Kotlin):

// code in the oh-so-sweet-and-sugary Kotlin
val locale = Locale.Builder()
                   .setLanguageTag("ar-SA-u-nu-arab")
                   .build()
val numFormat = NumberFormat.getNumberInstance(locale)
val formatter = DateTimeFormatter.ofPattern("yyyy MM dd", locale)
val str = formatter.format(OffsetDateTime.now())
// String.replace(Regex, noninline (MatchResult) -> CharSequence)
// this method is gold
str.replace(Regex("\d"), {numFormat.format(it.value.toInt())}))
println(str)

我觉得这可以用 better/more 优雅的方式完成。如果有人有,请分享。