使用Number.toLocaleString()的货币格式差异

时间:2019-05-09 10:50:01

标签: javascript unicode localization currency icu

我一直在研究javascript和found的语言环境感知数字格式,let items = { id: 1, name: "name1", currency: "usd" } Object.keys(items).forEach(function(key, index) { console.log("key=>", key, ", index=>", index,", value=>", items[key]); })extension Intl.NumberFormat似乎是解决此问题的好方法。

特别是,我宁愿在已实现的抽象之上构建特定于区域设置的格式,而不是重新发明轮子并为已经解决的问题提出另一种解决方案。


因此,我在某些不同的JavaScript环境中调用了Number.toLocaleString,发现货币格式似乎已经改变:

Number.toLocaleString
  • IE 11与其他版本不同,但是考虑到它的年龄,这并不令我感到惊讶。
  • 令我惊讶的是,(5).toLocaleString('fr-CH', {currency: 'CHF', style: 'currency'}); // Node v10.15.1: 'CHF 5.00' // Node v12.1.0: '5.00 CHF' // Firefox 66.0.2: '5.00 CHF' // Chrome 73.0.…: '5.00 CHF' // Safari 12.0.3: '5.00 CHF' // IE 11: '5.00 fr.' CHF的格式似乎在节点版本fr-CH10之间发生了变化。
  • 为了进行比较,我查看了fr_CH的glibc LC_MONETARY设置,发现它似乎将12放置在至少约1997的位置之前。这尤其令人困惑。 CHF对于大多数当前的浏览器似乎有所不同。

我想了解和理解:

  1. 在这些情况下,CHF的位置为什么不同?
    • 我知道这可能取决于可用的系统区域设置或浏览器。但是节点版本之间的更改似乎表明对我来说是最新的自愿更改。
  2. 是否存在放置CHF的正确方法,或者CH都可以接受两个选择,或更具体地说CHF
    • 为此,拥有诸如纸质或研究数据库之类的实际资源,而不是传闻证据或轶事,真是太好了。

更新(2019-05-16):

针对我的部分answer,我想指定:

  • fr-CH的格式设置决定在提交3bfe134中以fr_CH的形式给出,但是我仍然缺少该决定的来源,并且很想知道。

1 个答案:

答案 0 :(得分:3)

因此,我检查了v8 source,以查看是否可以定义Number.toLocaleString的行为。

  • builtins-number.cc中,我发现了BUILTIN(NumberPrototypeToLocaleString){…},它使用了Intl::NumberToLocaleString(…)
  • 这导致我进入intl-objects.cc并使用Intl::NumberToLocaleString实现icu::number::LocalizedNumberFormatter

由于v8使用icu,所以我签出了source继续搜索。

  • 我第一次尝试寻找数字格式的来源,这使我首先研究了decimfmtnumfmt,但是我一直不知所措。
  • 然后我想到,将格式定义与其余代码区分开来可能很有意义。通过浏览网站和来源,我终于找到了icu4c/source/data/locales/de_CH.txticu4c/source/data/locales/fr_CH.txt
    • de_CH.txtcurrencyFormat{"¤ #,##0.00;¤-#,##0.00"}
    • fr_CH.txtcurrencyFormat{"#,##0.00 ¤ ;-#,##0.00 ¤"}
  • 现在使用git,我发现19个月前第一次为currencyFormat3bfe134)引入了fr_CH的提交。
    • 这似乎是在节点v10v12之间。
    • 我还可以看到在将de_CH添加到curreencyFormat之前退回到fr_CH是有意义的,因此,可以看到格式会改变它的方式。 / li>

该提交提到CLDR 32 alpha,我发现了CLDR charts version 32。 但是,我目前无法找出为currencyFormat定义fr_CH的图表所在的位置。

我觉得通过找到fr_CH currencyFormat的变化,我发现并理解了导致不同节点版本之间行为改变的变化。

到目前为止,我不明白为什么glibcicu在这里有区别,但这是我可以在特定项目的背景下提出的。

我的印象是,我仍然缺少导致currencyFormat实现的特定决策或数据点-如果找到它,我会在这里添加它并感到满意。

更新2019-05-18:

  • CLDR 32数据可以在cldr.unicode.org下的下载部分中找到。
    • 我可以从there下载cldr-common-32.zip,其中包括文件common/main/fr_CH.xml,在其中定义了货币格式,如下所示:
<currencyFormats numberSystem="latn">
  <currencyFormatLength>
    <currencyFormat type="standard">
      <pattern draft="contributed">#,##0.00 ¤ ;-#,##0.00 ¤</pattern>
    </currencyFormat>
  </currencyFormatLength>
</currencyFormats>

Screenshot of number formatting decisions for fr_CH

更新2019-05-21:

出于好奇,我在libc-locales列表以及我可以在unicode-org票务系统上找到的closest ticket列表中都询问过这个问题。

这促使我进行进一步的研究,当与一个朋友进行研究时,我们偶然发现Github上的cldr repo专注于CLDR数据,而不是像icu那样具有CLDR相关数据。

我们发现,提交c5e7787引入了第一个更改,导致将CHF置于数字之后而不是数字之前,并且提交使槽更好地了解了两张票。 这些票证分别为CLDR-9370CLDR-10755,其中第二个票证是对后续工作进行了清理,以清除某些格式。

在表面上,CLDR-9370似乎主要讨论了十进制分隔符,同时还讨论了货币符号的放置。

给出的来源之一是欧洲核子研究组织(CERN)发布的typography guide (pdf),其中提供了有关写数字方式的详细说明。

对于CHF,该指南指出: Screenshot from the CERNs typography guide, the section on writing sums of money

使用google将其翻译为:

  

写钱

     

数字以三位数递增,并以   不间断的空间(没有点或撇号),并且是   在货币指示之后(且从未在其后)是   长或缩写。对于名称缩写货币,我们使用ISO   代码。