【问题标题】:Get default locale for language in PHP获取 PHP 中语言的默认语言环境
【发布时间】:2011-12-19 23:06:21
【问题描述】:

我有一个 PHP 后端,多种类型的设备通过公共 API 与之通信。请求通常包含响应所需的语言(例如“en”或“fr”或“ru”等) - 但不是完整的语言环境。在过去的几年里,这对我需要的一切都很有效。但是现在我需要在响应中包含日期信息 - 并且需要一个语言环境来格式化日期。

如何从语言中获取语言环境?我确实明白一种语言不足以唯一地标识一个语言环境,但我至少需要一些东西。如果我能得到至少一个语言环境,例如en_GB 表示 'en' 或 'ru_RU' 表示 'ru' 等 - 就足够了。

【问题讨论】:

    标签: php locale


    【解决方案1】:

    在对问题和我的特定设置进行了更多思考后,我想出了这个解决方案,它似乎有效。请注意,我无法控制我需要支持哪些语言:翻译文件被放入预定义的位置,系统语言环境由其他人安装。在运行时,如果存在相应的翻译文件并且安装了系统语言环境,我需要支持特定的语言。这让我得到了这个解决方案:

    function getLocale($lang)
    {
        $locs = array();
        exec('locale -a', $locs);
    
        $locale = 'en_GB';
        foreach($locs as $l)
        {
            $regex = "/$lang\_[A-Z]{2}$/";
            if(preg_match($regex, $l) && file_exists(TRANSROOT . "/$lang.php"))
            {
                $locale = $l;
                break;
            }
        }
    
        return $locale;
    }
    

    如果我无法解析语言环境,我会默认使用 en_GB,因为我确定已安装 en_GB(我们的服务器位于英国)。

    【讨论】:

    • 没有看到你的答案提出了类似的东西,但包装在一个封装System->getLocales() 方法的System 类中。但它的工作原理相同。
    【解决方案2】:

    也许您可以使用$_SERVER['HTTP_ACCEPT_LANGUAGE']; 而不是提供的语言来获取语言环境。通常,这将包含带有连字符而不是下划线的实际语言环境。

    例如$_SERVER['HTTP_ACCEPT_LANGUAGE']:

    en-ca,en;q=0.8,fr-ca;q=0.5,fr;q=0.3

    只需在第一个 , 之前获取所有内容,一切就绪。这也比填充一组语言环境更好,因为它让浏览器告诉服务器它喜欢什么语言,而不是相反,但是应该使用 hakre 的答案中的数组作为备份系统,以防无效/空/提供了缺少的$_SERVER['HTTP_ACCEPT_LANGUAGE']

    您可能还想研究一下locale 类和locale::acceptFromHttp 方法

    此外,您可能需要考虑修改您的 API 以允许用户明确设置他们的语言环境,只要确保它能够优雅地回退到您现在选择实施的任何系统。

    【讨论】:

    • 感谢您的回答。这可能是一个不错的技巧,但它不适用于所有情况。想象一个顶部有语言选择的网站。我可能坐在英国的电脑前,只有英语作为“accepted_language”,但我将网站切换到法语。我期待法语的结果,但是$_SERVER['HTTP_ACCEPT_LANGUAGE']Locale::acceptFromHttp 方法都会返回en_GB。当然,如果一切都像网站一样简单,我不会有问题。
    【解决方案3】:

    您是否只需要一张从语言(如en)到语言环境(如en_GB)的地图?如果是这样,您可以为您使用的语言编译一个:

    $localeMap = array(
        'en' => 'en_GB',
        'fr' => 'fr_FR',
        # ...  
    );
    
    # Usage:
    
    $locale = $localeMap[$lang];
    

    但这太琐碎了,我不确定我是否正确理解了你的问题。

    如果您不确定一种语言的区域设置,只需选择应该是有效区域设置的语言本身,只是没有国家/地区:

    l => ll

    只要语言是两个字母的格式,我觉得很好(ISO 标准 639,“语言名称的表示代码”),另请参阅 Tags for the Identification of Languages (RFC 1766)

    $locale = isset($localeMap[$lang]) ? $localeMap[$lang] : $lang;
    

    但是,这可能会有所不同,具体取决于您所使用的函数所期望的语言环境格式。


    class System
    {
        /**
         * @return array
         */
        public function getLocales()
        {
            $locales = array();
            exec('locale -a', $locales, $retCode);
            !$retCode || $locales = array();
            return $locales;
        }
        /**
         * @return string something matching 
         * @note Improve by creating your system aware locale class to move
         *       away the responsibility to map system locales onto strings
         *       of certain kinds and to deal with the different locale types.
         */
        public function getLocaleByLang($lang)
        {
            ...
        }
    }
    
    
    $lang = ...
    $system = new System;
    $locale = $system->getLocaleByLang($lang);
    

    【讨论】:

    • 是的,这是我的第一个想法,但是我事先并不知道我使用的所有语言,因为翻译是由第三方提供的,并且语言环境是由系统管理员安装在系统上的.因此,理论上,我必须在运行时动态枚举可用的语言环境并在那个阶段选择一个。实际上,这本身可能不是一个坏主意……
    • 您使用的是哪种语言环境格式?出于什么目的/在什么功能中?另见Tags for the Identification of Languages (RFC 1766)
    • 感谢您的澄清。我的语言是标准的两个字母格式。在调用 strftime 之前,我需要 setlocale 的语言环境
    猜你喜欢
    • 2016-07-13
    • 2014-03-31
    • 1970-01-01
    • 2020-04-05
    • 2011-10-29
    • 2016-09-07
    • 1970-01-01
    • 2014-03-09
    相关资源
    最近更新 更多