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

Differences in currency formatting using Number.toLocaleString()

我一直在研究 javascript 的区域设置感知数字格式,found that Number.toLocaleString and by extension Intl.NumberFormat 似乎是解决此问题的好方法。

特别是我更喜欢在已经实现的语言环境特定格式抽象之上构建,而不是重新发明轮子并为已经解决的问题提出另一种解决方案。


所以我在一些不同的 javascript 环境中调用了 Number.toLocaleString,发现货币格式似乎发生了变化:

(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.'

我想了解了解:

  1. 为什么 CHF 的位置在这些情况下不同?
    • 我知道这可能取决于可用的系统区域设置或浏览器。但是节点版本之间的变化似乎表明对我来说是最近的自愿变化。
  2. 是否有放置 CHF 的正确方法,或者这两种选择都适合 CH,或者更具体地说 fr-CH
    • 为此,最好有一个实际的来源,如论文或研究数据库,而不是道听途说或轶事。

更新(2019-05-16):

针对我的部分 我想说明:

所以我检查了 v8 source 看我是否能找到 Number.toLocaleString 行为的定义。

  • builtins-number.cc中我找到了使用Intl::NumberToLocaleString(…)BUILTIN(NumberPrototypeToLocaleString){…}
  • 这让我找到了 intl-objects.cc,它使用 icu::number::LocalizedNumberFormatter.
  • 实现了 Intl::NumberToLocaleString

因为 v8 使用 icu I checked out the 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 个月前首次为 fr_CH (3bfe134) 引入 currencyFormat 的提交。
    • 这可能在节点 v10v12 之间。
    • 我还看到在 curreencyFormat 添加到 fr_CH 之前回退到 de_CH 是有意义的,因此看到格式会改变它的方式.

提交提到 CLDR 32 alpha,我找到了 CLDR charts version 32。 但是,我目前无法弄清楚为 fr_CH.

定义 currencyFormat 的图表所在的位置

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

到目前为止我不明白为什么 glibcicu 在这里有差异,但这是我可以在特定项目的上下文中询问的问题。

我的印象是我仍然缺少导致 currencyFormat 实施的具体决定或 data-point - 如果我找到它,我会把它添加到这里并感到满意。

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>

2019-05-21更新:

出于好奇,我在 libc-locales list as well as on the closest ticket 上问了这个问题,我可以在 unicode-org 票务系统上找到。

这促使我进一步调查,在与朋友一起研究时,我们偶然发现了 Github 上的 cldr repo,它专注于 CLDR 数据,而不是像 icu 那样在其中包含 CLDR 相关数据.

我们发现提交 c5e7787 引入了第一个更改,导致 CHF 被放置在数字之后而不是之前,并且通过该提交更好地意识到两张票。 这些工单是 CLDR-9370 and CLDR-10755,其中第二个工单是清理一些格式的跟进。

虽然表面上 CLDR-9370 似乎主要讨论小数点分隔符,但也讨论了货币符号放置。

给出的来源之一是 CERN 发布的 typography guide (pdf),其中详细说明了如何书写数字。

对于 CHF,指南指出:

使用 google 翻译这翻译成:

Writing sums of money

The number is written in three-digit increments separated by a non-breaking space (no point or apostrophe of separation), and is followed (and never preceded) by the indication of the currency is long or abbreviated. For name abbreviations currency, we use the ISO code.