我试图使用 intl 包中的 NumberFormatter 类将整数拼写成斯洛文尼亚语单词(用于邮政声明),但结果是完全错误的,没有任何意义。
$fmt = new NumberFormatter('sl', NumberFormatter::SPELLOUT);
$fmt->format(561);
结果是"petsto šestdeset ena",而它应该是"petsto enainšestdeset"。看起来像婴儿说话。
在克罗地亚语中,结果似乎还可以("petsto šezdeset i jedan")。
这是 PHP 中做得不好的翻译还是基于我的系统区域设置?我使用的是 PHP 5.3.10/Ubuntu 12.04。
编辑:
intl 是 1.1.0 版,当前是 3.0.0,所以也许它已被修复?
免责声明 - 我不会说斯洛文尼亚语或克罗地亚语。
看起来PHP扩展用于这些语言中的数字的模式中存在一些差距。要理解我的意思,您可以显示运行使用的模式:
$fmt = new NumberFormatter('sl', NumberFormatter::SPELLOUT);
echo $fmt->getPattern();
如果你看一下这个的输出,你可能会发现"%spellout-cardinal-masculine:"的一部分,它似乎从大约30跳到100。
...
21: dvaset >%spellout-cardinal-masculine>;
30: <%spellout-cardinal-masculine<deset;
31: <%spellout-cardinal-masculine<deset >%spellout-cardinal-masculine>;
100: sto;
101: sto >%spellout-cardinal-masculine>;
200: dvjesto;
...
这意味着没有为 31 以上和 100 以下的数字定义规则。您输出的数字中的"61"部分属于此间隙。
您可以生成自己的模式来解决此问题 - 我粘贴了 en-US 格式化程序的模式并对其进行了一点摆弄,因此它看起来像这样:
...
21: dvaset >%spellout-cardinal-masculine>;
30: <%spellout-cardinal-masculine<deset;
31: <%spellout-cardinal-masculine<deset >%spellout-cardinal-masculine>;
40: forty;
41: forty->%spellout-cardinal-masculine>;
50: fifty;
51: fifty->%spellout-cardinal-masculine>;
60: sixty;
61: sixty->%spellout-cardinal-masculine>;
70: seventy;
71: seventy->%spellout-cardinal-masculine>;
80: eighty;
81: eighty->%spellout-cardinal-masculine>;
90: ninety;
91: ninety->%spellout-cardinal-masculine>;
100: sto;
101: sto >%spellout-cardinal-masculine>;
200: dvjesto;
...
现在,如果我使用 UTF-8 编码将其保存在名为 sl.txt 的新文件中,我可以将其加载到 NumberFormatter 中:
$pattern = file_get_contents('sl.txt')
$fmt = new NumberFormatter('sl', NumberFormatter::PATTERN_RULEBASED, $pattern);
echo($fmt->format(561));
这给了我以下输出:
petsto sixty-ena
当然,这是错误的 - 它是斯洛文尼亚语和英语的混合体,但我认为如果您将格式编辑为如下所示:
...
61: >%spellout-cardinal-masculine>inšestdeset;
...
正如我所说,我不会说斯洛文尼亚语,所以你可能想检查一下。但这将为您提供以下输出:
petsto enainšestdeset
您需要为 31-100 中的每个缺失数字块添加此规则。您可能还需要检查 ICU 文档中基于规则的格式,以确保其正确无误。
这是一个错误,但在PHP中不是 - 如果你想修复它,那么问题在这个文件中的Unicode公共语言环境数据存储库中。PHP的intl使用ICU,ICU使用CLDR数据。