intl扩展不控制PHP locale,locale_get_default()读取环境变量而非intl配置;NumberFormatter等行为取决于构造时指定的locale,非系统locale;解析日期需严格匹配格式模式;MessageFormatter占位符禁用下划线。
为什么
扩展启用后
还是返回
PHP 的
扩展本身不接管系统 locale 设置,它只是提供 ICU 库的封装;
读的是 PHP 启动时的环境变量(如
或
),不是
的配置。
启动前必须确保系统级 locale 存在,比如 Linux 上运行
能查到才可用
PHP-FPM 场景下,不能只改
,还得在
里加
对
函数无影响,但会影响
等传统函数——别混用
格式化数字时小数点变成逗号,怎么切回英文习惯
默认行为取决于构造时传入的 locale,不是 PHP 当前 locale。哪怕服务器设成中文,只要初始化时指定
,就用英文标点。
错误写法:
→ 输出
(中文千分位+英文小数点,混乱)
正确写法:
→ 固定输出
注意:ICU 版本差异会影响某些 locale 的行为,例如
在 ICU 69+ 中对负数格式有调整,建议锁定 ICU 版本或显式测试边界值
解析日期字符串失败,报错
这个错误几乎都因为输入字符串和格式模式不严格匹配,
不做容错推断,连空格、中英文标点、年份位数都必须一致。
PHP 8.5.5
PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。
下载
避免用
解析用户输入,它只适合格式化输出;解析请用
或自定义模式,如
中文环境下用户可能输「2024年03月15日」,但 ICU 没有内置“年/月/日”字面量支持,得用
模式,且必须用 Unicode CLDR 的语法(
是年,
是月,
是日)
时区容易被忽略:
默认按系统时区解释,如果传入带时区的字符串(如
),要先用
再手动转换
用
做翻译时,占位符变量名含下划线就报错
ICU 的消息格式语法(MessageFormat)不支持下划线作为占位符标识符,只认字母、数字和美元符号,且必须以字母开头。
立即学习
“
PHP免费学习笔记(深入)
”;
错误示例:
→ 直接失败
正确写法:把键名改成
或
改为
(不行)→ 必须是
或
等合法标识符
更稳妥的方式是不用关联数组,改用索引数组:
+ 模板
,避开命名问题
注意:PHP 8.2+ 对
的参数类型检查更严,传非数组会直接 TypeError,不是静默失败
事情说清了就结束。真正麻烦的从来不是调哪个函数,而是 locale 数据在系统、ICU、PHP、Web 服务器之间漏了一环,就全盘失效。
intllocale_get_default()Cintllocale_get_default()LC_ALLLANGintllocale -a | grep zh_CN.utf8php.iniwww.confenv[LC_ALL] = zh_CN.UTF-8setlocale(LC_ALL, 'zh_CN.UTF-8')intlstrftime()NumberFormatter'en_US'$fmt = new NumberFormatter('zh_CN', NumberFormatter::DECIMAL)123,456.78$fmt = new NumberFormatter('en_US', NumberFormatter::DECIMAL)123,456.78de_DEIntlDateFormatterdatefmt_parse: error (U_PARSE_ERROR)IntlDateFormatterIntlDateFormatter::FULLIntlDateFormatter::MEDIUM'yyyy-MM-dd HH:mm:ss''y年M月d日'yMdparse()'2024-03-15T14:30:00+08:00'IntlDateFormatter::create(..., 'UTC')MessageFormattermsgfmt_format_message: error (U_ILLEGAL_ARGUMENT_ERROR)MessageFormatter::formatMessage('en_US', 'Hello {user_name}!', ['user_name' => 'Alice'])userNameuser_nameuser_nameuserNameuser1['Alice']'Hello {0}!'MessageFormatter::format()