PHP: setlocale 的值从何而来?
PHP: Where does setlocale's Value Come From?
我注意到 PHP 的 str_word_count
is behaving differently on the command line vs. on the web. The behavior seems to due to the default locale value in each environment. If I use setlocale 查看当前语言环境 (echo setlocale(LC_ALL, 0);
),在命令行上我得到
C/en_US.UTF-8/C/C/C/C
而在网络上我得到
C
那么各种 PHP SAPI(cli、fpm、mod_php 等)从哪里获得这个默认值?
我的推测是看起来很奇怪的 C/en_US.UTF-8/C/C/C/C
语言环境所有六个语言环境类别都挤在一起,这告诉我 LC_CTYPE=en_US.UTF-8
和其他类别都设置了 C
语言环境——所以换一种方式来表达我的问题:为什么我的 php-fpm 服务器将所有语言环境类别默认设置为 C
,而我的命令行 PHP 只设置了一个语言环境至 en_US.UTF-8
您可以在 php.ini
中设置 intl.default_locale
似乎 PHP 从 shell 的环境中直接 获取这些值,LC_CTYPE
的值还将检查 LANG
的值
% cat test.php
<?php
echo setlocale(LC_ALL, 0),"\n";
% echo $LANG
en_US.UTF-8
% echo $LC_CTYPE
% php test.php
C/en_US.UTF-8/C/C/C/C
% LC_CTYPE=C php test.php
C
% LANG=C php test.php
C
% LANG=C LC_CTYPE=en_US.UTF-8 php test.php
C/en_US.UTF-8/C/C/C/C
因此,MacOS 似乎将用户个人 shell 的 LANG 设置为 en_US.UTF-8
。我的假设是当我通过
启动我的 php-fpm 实例时
brew services start php
那 -- LaunchAgent? -- 正在使用 shell,其中 LANG
或 LC_CTYPE
设置为 C
-- 大概是因为只有人类才会对 UTF-8 格式的东西感兴趣。
我假设“在网络上”指的是 Linux 下的 Apache 网络服务器 ...
在这种情况下,setlocale(LC_ALL, 0)
返回 C
的原因如下:
如果您从 Apache 服务器检查 /etc/apache2/envvars
,您会发现以下几行:
## The locale used by some modules like mod_dav
export LANG=C
## Uncomment the following line to use the system default locale instead:
#. /etc/default/locale
作为结果 phpinfo()
将产生以下输出:
如果将/etc/apache2/envvars
中的行修改如下...
## The locale used by some modules like mod_dav
# export LANG=C
## Uncomment the following line to use the system default locale instead:
. /etc/default/locale
并重新启动 Apache。然后 Apache 将使用您操作系统的区域设置和语言设置(您可以在终端中使用 locale
命令检查它们的 os 设置)。作为上述更改的结果,phpinfo()
将在定义了 de_CH.UTF-8
语言环境的系统上产生例如以下输出:
但您最终可能仍会 setlocale(LC_ALL, 0)
返回 C
或至少某些 LC_
变量被设置为 C
例如 LC_CTYPE=de_CH.UTF-8;LC_NUMERIC=C;LC_TIME=C;LC_COLLATE=C;LC_MONETARY=C;LC_MESSAGES=C;LC_PAPER=C;LC_NAME=C;LC_ADDRESS=C;LC_TELEPHONE=C;LC_MEASUREMENT=C;LC_IDENTIFICATION=C"
为了确保 PHP 使用 OS 中的区域设置,您必须调用 setlocale(LC_ALL, "")
。
https://www.php.net/manual/en/function.setlocale.php 下 setlocale
的手册说明如下:
// If locales is the empty string "", the locale names will be set from
// the values of environment variables with the same names as the above
// categories, or from "LANG".
// On Windows, setlocale(LC_ALL, '') sets the locale names from the
// system's regional/language settings (accessible via Control Panel).
最后是您的 setlocale(LC_ALL, 0)
returns 在您的操作系统上配置的值,例如de_CH.UTF-8
:-)
我注意到 PHP 的 str_word_count
is behaving differently on the command line vs. on the web. The behavior seems to due to the default locale value in each environment. If I use setlocale 查看当前语言环境 (echo setlocale(LC_ALL, 0);
),在命令行上我得到
C/en_US.UTF-8/C/C/C/C
而在网络上我得到
C
那么各种 PHP SAPI(cli、fpm、mod_php 等)从哪里获得这个默认值?
我的推测是看起来很奇怪的 C/en_US.UTF-8/C/C/C/C
语言环境所有六个语言环境类别都挤在一起,这告诉我 LC_CTYPE=en_US.UTF-8
和其他类别都设置了 C
语言环境——所以换一种方式来表达我的问题:为什么我的 php-fpm 服务器将所有语言环境类别默认设置为 C
,而我的命令行 PHP 只设置了一个语言环境至 en_US.UTF-8
您可以在 php.ini
中设置 intl.default_locale似乎 PHP 从 shell 的环境中直接 获取这些值,LC_CTYPE
的值还将检查 LANG
的值
% cat test.php
<?php
echo setlocale(LC_ALL, 0),"\n";
% echo $LANG
en_US.UTF-8
% echo $LC_CTYPE
% php test.php
C/en_US.UTF-8/C/C/C/C
% LC_CTYPE=C php test.php
C
% LANG=C php test.php
C
% LANG=C LC_CTYPE=en_US.UTF-8 php test.php
C/en_US.UTF-8/C/C/C/C
因此,MacOS 似乎将用户个人 shell 的 LANG 设置为 en_US.UTF-8
。我的假设是当我通过
brew services start php
那 -- LaunchAgent? -- 正在使用 shell,其中 LANG
或 LC_CTYPE
设置为 C
-- 大概是因为只有人类才会对 UTF-8 格式的东西感兴趣。
我假设“在网络上”指的是 Linux 下的 Apache 网络服务器 ...
在这种情况下,setlocale(LC_ALL, 0)
返回 C
的原因如下:
如果您从 Apache 服务器检查 /etc/apache2/envvars
,您会发现以下几行:
## The locale used by some modules like mod_dav
export LANG=C
## Uncomment the following line to use the system default locale instead:
#. /etc/default/locale
作为结果 phpinfo()
将产生以下输出:
如果将/etc/apache2/envvars
中的行修改如下...
## The locale used by some modules like mod_dav
# export LANG=C
## Uncomment the following line to use the system default locale instead:
. /etc/default/locale
并重新启动 Apache。然后 Apache 将使用您操作系统的区域设置和语言设置(您可以在终端中使用 locale
命令检查它们的 os 设置)。作为上述更改的结果,phpinfo()
将在定义了 de_CH.UTF-8
语言环境的系统上产生例如以下输出:
但您最终可能仍会 setlocale(LC_ALL, 0)
返回 C
或至少某些 LC_
变量被设置为 C
例如 LC_CTYPE=de_CH.UTF-8;LC_NUMERIC=C;LC_TIME=C;LC_COLLATE=C;LC_MONETARY=C;LC_MESSAGES=C;LC_PAPER=C;LC_NAME=C;LC_ADDRESS=C;LC_TELEPHONE=C;LC_MEASUREMENT=C;LC_IDENTIFICATION=C"
为了确保 PHP 使用 OS 中的区域设置,您必须调用 setlocale(LC_ALL, "")
。
https://www.php.net/manual/en/function.setlocale.php 下 setlocale
的手册说明如下:
// If locales is the empty string "", the locale names will be set from
// the values of environment variables with the same names as the above
// categories, or from "LANG".
// On Windows, setlocale(LC_ALL, '') sets the locale names from the
// system's regional/language settings (accessible via Control Panel).
最后是您的 setlocale(LC_ALL, 0)
returns 在您的操作系统上配置的值,例如de_CH.UTF-8
:-)