修改货币后NumberFormatter::getSymbol返回旧符号的问题
NumberFormatter修改货币代码后getSymbol返回旧符号的问题
问题现象
在Debian 10 + PHP 8.3环境中,使用NumberFormatter修改货币代码后,调用getSymbol(NumberFormatter::CURRENCY_SYMBOL)返回的仍是原区域设置的货币符号;但相同代码在Ubuntu 22.04 + PHP 8.3环境中表现正常。另外,format()方法能正确使用新货币符号格式化数字。
重现代码
// 创建亚美尼亚语区域的货币格式化器 $currencyFormatter = new NumberFormatter('hy_AM', NumberFormatter::CURRENCY); // 修改货币代码为USD $currencyFormatter->setTextAttribute(NumberFormatter::CURRENCY_CODE, 'USD'); // 获取货币符号 $symbol = $currencyFormatter->getSymbol(NumberFormatter::CURRENCY_SYMBOL); // 预期返回 "$",Debian 10上实际返回 "֏"(亚美尼亚德拉姆符号) echo $symbol; // 但format方法正常,会输出带$的金额 echo $currencyFormatter->format(100);
原因分析
核心原因是ICU库版本差异:
- Ubuntu 22.04默认携带的ICU库版本较高(通常是ICU 70+),支持修改
CURRENCY_CODE后自动同步更新CURRENCY_SYMBOL属性。 - Debian 10的ICU库版本较旧(ICU 63左右),存在设计限制:修改
CURRENCY_CODE后,CURRENCY_SYMBOL不会自动刷新,仍保留初始化时的符号;而format()方法是实时基于当前CURRENCY_CODE获取符号进行格式化,所以结果正确。
解决方案
方案1:手动设置CURRENCY_SYMBOL
修改货币代码后,手动对应设置货币符号:
$currencyFormatter = new NumberFormatter('hy_AM', NumberFormatter::CURRENCY); $currencyFormatter->setTextAttribute(NumberFormatter::CURRENCY_CODE, 'USD'); // 手动设置美元符号 $currencyFormatter->setSymbol(NumberFormatter::CURRENCY_SYMBOL, '$'); $symbol = $currencyFormatter->getSymbol(NumberFormatter::CURRENCY_SYMBOL); // 返回 "$"
方案2:创建新的NumberFormatter实例
直接在初始化时指定货币代码(通过构造函数的第三个参数):
// 直接创建USD的货币格式化器,基于hy_AM区域的格式规则 $currencyFormatter = new NumberFormatter('hy_AM', NumberFormatter::CURRENCY, 'USD'); $symbol = $currencyFormatter->getSymbol(NumberFormatter::CURRENCY_SYMBOL); // 返回 "$"
方案3:升级Debian系统的ICU库
如果系统允许,可以通过第三方源或编译升级ICU库到较新版本,从底层解决兼容性问题。
内容的提问来源于stack exchange,提问作者Ashes
相关产品推荐
相关产品推荐

