【问题标题】:Simplest way to detect client locale in PHP在 PHP 中检测客户端语言环境的最简单方法
【发布时间】:2019-10-07 06:23:28
【问题描述】:

我希望能够使用 PHP 在我的网站上检测访问者来自哪个国家/地区。

请注意,我并没有试图将其用作安全措施或任何重要的事情,只是更改某些单词的拼写(美国人似乎认为“注册”这个词有 2 个 Ls... . crazy yanks),也许在“选择你的国家”列表中给出一个默认选项。

因此,使用地理定位数据库有点过头了,我真的不想为此烦恼安装新的 PHP 库,所以 什么是最简单/最简单的方法来找到什么访问者来自哪个国家/地区?

【问题讨论】:

标签: php locale


【解决方案1】:

PHP 自 5.3.0 起提供了一个函数,用于将 $_SERVER['HTTP_ACCEPT_LANGUAGE'] 变量解析为语言环境。

$locale = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
echo $locale; // returns "en_US"

文档:https://www.php.net/manual/en/locale.acceptfromhttp.php

【讨论】:

    【解决方案2】:

    不保证,但大多数浏览器都会提交一个 Accept-Language HTTP 标头,指定 en-us 是否来自美国。不过,一些较旧的浏览器只说它们是 en。并非所有机器都正确设置以指示他们喜欢哪种语言环境。但这是一个很好的初步猜测。

    基于English-UK 的用户通常将他们的系统或用户区域设置为English-UK,在默认浏览器配置中应该将en-gb 作为Accept Language 标头。 (此版本的早期版本是 en-uk;这是一个错字,抱歉。)其他国家也有 en 语言环境,例如 en-za(南非),而且主要从理论上讲,像 en-jp 这样的组合也是可能的。

    但是,基于 Geo-IP 的猜测在首选语言/区域设置上不太可能是正确的。 Google 认为基于 IP 地址地理位置的内容协商是有道理的,当我在日本或韩国时,这真的让我很恼火......

    【讨论】:

    • 客户的首选语言不是他所在地区的指标。
    • 取决于您所说的“语言环境”。假设您不是指“位置”,而是在软件国际化意义上使用它:Accept-Language 参数可以并且现在通常确实指定每种首选语言的完整区域设置,因为最常用的是语言字段指定国家(而不是语言变体)。语言加上国家的组合巧妙地对应于日期、时间、数字和货币约定的特定于区域设置的约定。如果没有国家信息,显然还不够完整。
    • 我讨厌网站向我显示基于语言环境而不是浏览器配置的语言。在你住在另一个国家之前,你不知道这是多么令人沮丧。如果我到达一个网站,但在 5 秒内找不到更改语言的选项,那我就离开了。
    • IKR 当我在日本的时候,我什至坚持要微软我想要 hotmail.ca,但没有我得到 hotmail.co.jp
    【解决方案3】:

    您可以查看大多数浏览器将发送的HTTP_ACCEPT_LANGUAGE 标头(来自$_SERVER)。

    Zend_Locale 为例,或者您甚至可能想要使用该库。

    【讨论】:

      【解决方案4】:

      您可以进行一些 IP 比较,而无需使用整个库。

      解决方案 #1

      使用 API,这样您就不需要任何东西。这是一个让您了解国家/地区的 Web API:

       Example: http://api.hostip.info/get_html.php?ip=12.215.42.19
       Return : Country: UNITED STATES (US)
      

      解决方案 #2

      但是,你有没有想过使用浏览器代理语言?你也许可以从中知道英语的类型。

      解决方案 #3

      这个名为BlockCountry 的网站让您拥有按国家/地区划分的IP 列表。当然,你不想屏蔽,但你可以使用IP列表并比较它们(获取所有美国IP......)这可能不准确......

      【讨论】:

      • 你有更多关于api.hostip.info的信息吗?谁运行它/它在性能和数据质量方面的可靠性如何?
      • 看起来不是很最新。我刚刚尝试了我所在国家/地区的三个不同 IP,但都无法找到其中任何一个的国家/地区!
      • hostip.info 看起来根本不可靠。我发现ipinfo.io 的信息要好得多,但是如果您需要查找大量 IP,则必须付费。
      【解决方案5】:

      鉴于您声明的目的,Accept-Language 标头是比基于 IP 的地理定位更合适的解决方案。事实上,这正是 Accept-Language 的预期目的。

      【讨论】:

      • 客户的首选语言不是他所在地区的指标。
      • 是的,但是 OP 声明想要使用语言环境的原因是“只是改变了一些单词的拼写(美国人似乎认为“注册”这个词有 2 个 Ls.... 疯狂的 yanks)” -他想要该语言环境,因此他可以将其用作首选语言的代理。
      • 查看我上面的评论...我认为最好使用客户的首选语言,而不是他所在位置的语言。
      【解决方案6】:

      我使用 HTTP_ACCEPT_LANGUAGE

          $localePreferences = explode(",",$_SERVER['HTTP_ACCEPT_LANGUAGE']);
          if(is_array($localePreferences) && count($localePreferences) > 0) {
             $browserLocale = $localePreferences[0];
             $_SESSION['browser_locale'] = $browserLocale;
          }
      

      【讨论】:

        【解决方案7】:

        解析 $_SERVER["HTTP_ACCEPT_LANGUAGE"] 以获取国家和浏览器的区域设置。

        【讨论】:

          【解决方案8】:

          为了识别您的访问者国家/地区,我使用了GeoIP 扩展,非常简单易用。

          【讨论】:

            【解决方案9】:

            http://countries.nerd.dk 服务是我用于 IP 到国家/地区映射的服务。它工作得非常好,并且基于 DNS,缓存也很好。

            如果您不想依赖外部服务,也可以下载数据库供本地使用。

            【讨论】:

              【解决方案10】:

              或者您可以执行以下操作:

              http://www.maxmind.com/app/geoip_country下载“geoip.dat”和geoip.inc

              在 geoip.inc 头文件中你会发现如何使用它(例如初始化和其余的......)

              【讨论】:

                【解决方案11】:

                GeoIP 扩展是不错的选择。

                【讨论】:

                  【解决方案12】:

                  一件事是查看者想要哪种语言,其次是您可以提供哪种语言:

                  $SystemLocales = explode("\n", shell_exec('locale -a'));
                  $BrowserLocales = explode(",",str_replace("-","_",$_SERVER["HTTP_ACCEPT_LANGUAGE"])); // brosers use en-US, Linux uses en_US
                  for($i=0;$i<count($BrowserLocales);$i++) {         
                    list($BrowserLocales[$i])=explode(";",$BrowserLocales[$i]); //trick for "en;q=0.8"
                    for($j=0;$j<count($SystemLocales);$j++) {
                      if ($BrowserLocales[$i]==substr($SystemLocales[$j],0,strlen($BrowserLocales[$i]))){
                        setlocale(LC_ALL, $SystemLocales[$j]);
                        break 2; // found and set, so no more check is needed
                      }
                    }
                  }
                  

                  例如,我的系统只服务:

                  • C
                  • POSIX
                  • pl_PL.UTF-8

                  我的浏览器语言是:pl、en-US、en => 所以唯一正确的语言环境是 pl_PL.UTF-8。

                  当没有找到成功的比较时 - 根本没有 setlocale。

                  【讨论】:

                    猜你喜欢
                    • 2011-02-11
                    • 1970-01-01
                    • 2021-02-23
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-03-22
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多