【问题标题】:PHP: Where does setlocale's Value Come From?PHP:setlocale 的价值从何而来?
【发布时间】:2020-12-30 05:47:01
【问题描述】:

我注意到 PHP 的 str_word_count 在命令行和 Web 上的行为不同。行为似乎是由于每个环境中的默认语言环境值。如果我使用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 locale


    【解决方案1】:

    我假设“on the web”指的是 Linux 下的 Apache Web 服务器...

    在这种情况下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 命令检查它们的操作系统设置)。作为上述更改的结果,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 使用操作系统中的区域设置,您必须调用 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) 返回在您的操作系统上配置的值,例如de_CH.UTF-8 :-)

    【讨论】:

      【解决方案2】:

      你可以在php.ini中设置intl.default_locale

      【讨论】:

      • +1 获取有用信息——但它似乎没有回答我的问题。在我的 php 命令行以及我的 Web 服务器上,该值都是 intl.default_locale => no value => no value。另外——我不能 100% 确定 intl.default_locale 控制的事情与 setlocale 所做的相同。
      • nod 根据这个答案,国际语言环境与旧的 C 语言环境不同,控制不同的东西。 stackoverflow.com/a/45828833/4668
      【解决方案3】:

      看来 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 将 LANGLC_CTYPE 设置为 C -- 大概是因为只有人类才会对看到格式化为 UTF-8 的内容感兴趣。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-19
        • 2013-06-24
        • 2022-10-13
        • 1970-01-01
        • 2012-07-08
        • 1970-01-01
        • 2011-04-03
        相关资源
        最近更新 更多