【问题标题】:Is there a simple way to get the language code from a country code in PHP有没有一种简单的方法可以从 PHP 中的国家代码中获取语言代码
【发布时间】:2012-04-27 20:57:44
【问题描述】:

我正在使用 ISO 3166-1-alpha 2 代码传递给应用程序以检索本地化提要,例如/feeds/us 代表美国。我有一个 switch 语句,它提供基于该 country_code 的提要。

有没有办法将该两位数字代码转换为语言代码,例如en_US ?我想知道是否有标准/函数/库可以在 PHP 中执行此操作,或者我是否需要构建自己的数组?

【问题讨论】:

  • “CH”应该使用哪种语言代码? “在”? “不”?
  • 看看新列表,答案中提供的列表已经过时了。这一个包含 422 - 460 个条目。 msdn.microsoft.com/en-us/library/cc233968.aspx
  • 我打算建议,如果您的目标是使用区域设置为本地市场格式化货币,那么有一个策略可以通过它:
  • 如果您的语言区域设置目标是正确显示货币值,我发现这个简单的 HACK 可以“正常”工作:在您的国家/地区代码前加上“en_”。货币显示将默认为该国家/地区的通用标准。 "; ?>

标签: php locale


【解决方案1】:

您需要交叉引用这些文件:

http://www.ethnologue.com/codes/LanguageIndex.tab http://www.ethnologue.com/codes/CountryCodes.tab http://www.ethnologue.com/codes/LanguageCodes.tab

..或者在这里将它们全部放在一个 zip 中: http://www.ethnologue.com/codes/Language_Code_Data_20110104.zip

据我所知,当前没有设置返回此数据的 PHP 函数。

【讨论】:

    【解决方案2】:

    您无法自动将国家/地区代码转换为语言代码,因为某些国家/地区使用多种语言。另一方面,操作系统本地化系统可能支持不同国家/地区的单一语言的多种变体(例如,en_GB 与 en_US)。

    例如,瑞士 (CH) 常用德语和法语(根据http://en.wikipedia.org/wiki/Switzerland 的数据,分别为 64% 和 20% 的人口)。如果您必须为国家/地区代码 CH 确定一种语言,那么这些语言中的任何一种对某些人来说都是有意义的。请注意,瑞士的某些地区仅使用德语或法语作为官方语言(但不能同时使用两者,详情请参阅http://en.wikipedia.org/wiki/File:Sprachen_CH_2000_EN.svg)。

    如果您必须为每个国家/地区选择一种语言,我建议您为您支持的每个国家/地区手动选择。对于半途而废的自动实施,您可以浏览可用的本地化并选择第一个在下划线后具有匹配国家/地区代码的本地化。

    还要注意推论:语言不能用国旗表示,因为语言和国家没有 1:1 的关系。可以在两个方向上找到一对多关系。

    【讨论】:

    • mikko,您了解世界并提供高质量的答案。作为瑞士人,我想说的是,在一个多语言国家,通常会选择其语言的县。我以苹果为例,它们在 CH_de 和 CH_fr 之间切换,或者在 Schweiz-German 和 Suisse-Français 之间拼写。
    • @endo.anaconda:我猜你的意思是 de_CH 和 fr_CH。我不知道使用国家名称后跟语言名称是一种常见的标签样式。在芬兰,语言环境 sv_FI 通常被称为“suomenruotsi”,直接翻译为“芬兰的瑞典语”而不是“芬兰的瑞典语”。
    【解决方案3】:

    正如其他人指出的那样,没有内置功能,因为这可能是由于许多国家/地区拥有多种语言的现实。所以不幸的是,我无法将您指向一个执行此操作的库,但我确实继续编写了一个小函数来满足您的需求。

    有两个警告,一个是如果没有提供语言,它只会选择列表中的第一个语言环境。为了解决这个问题,您必须在函数调用周围放置一些逻辑,以便为其提供适当的语言。另一个是需要安装php5-intl。

    <?php
    
    /**
    /* Returns a locale from a country code that is provided.
    /*
    /* @param $country_code  ISO 3166-2-alpha 2 country code
    /* @param $language_code ISO 639-1-alpha 2 language code
    /* @returns  a locale, formatted like en_US, or null if not found
    /**/
    function country_code_to_locale($country_code, $language_code = '')
    {
        // Locale list taken from:
        // http://stackoverflow.com/questions/3191664/
        // list-of-all-locales-and-their-short-codes
        $locales = array('af-ZA',
                        'am-ET',
                        'ar-AE',
                        'ar-BH',
                        'ar-DZ',
                        'ar-EG',
                        'ar-IQ',
                        'ar-JO',
                        'ar-KW',
                        'ar-LB',
                        'ar-LY',
                        'ar-MA',
                        'arn-CL',
                        'ar-OM',
                        'ar-QA',
                        'ar-SA',
                        'ar-SY',
                        'ar-TN',
                        'ar-YE',
                        'as-IN',
                        'az-Cyrl-AZ',
                        'az-Latn-AZ',
                        'ba-RU',
                        'be-BY',
                        'bg-BG',
                        'bn-BD',
                        'bn-IN',
                        'bo-CN',
                        'br-FR',
                        'bs-Cyrl-BA',
                        'bs-Latn-BA',
                        'ca-ES',
                        'co-FR',
                        'cs-CZ',
                        'cy-GB',
                        'da-DK',
                        'de-AT',
                        'de-CH',
                        'de-DE',
                        'de-LI',
                        'de-LU',
                        'dsb-DE',
                        'dv-MV',
                        'el-GR',
                        'en-029',
                        'en-AU',
                        'en-BZ',
                        'en-CA',
                        'en-GB',
                        'en-IE',
                        'en-IN',
                        'en-JM',
                        'en-MY',
                        'en-NZ',
                        'en-PH',
                        'en-SG',
                        'en-TT',
                        'en-US',
                        'en-ZA',
                        'en-ZW',
                        'es-AR',
                        'es-BO',
                        'es-CL',
                        'es-CO',
                        'es-CR',
                        'es-DO',
                        'es-EC',
                        'es-ES',
                        'es-GT',
                        'es-HN',
                        'es-MX',
                        'es-NI',
                        'es-PA',
                        'es-PE',
                        'es-PR',
                        'es-PY',
                        'es-SV',
                        'es-US',
                        'es-UY',
                        'es-VE',
                        'et-EE',
                        'eu-ES',
                        'fa-IR',
                        'fi-FI',
                        'fil-PH',
                        'fo-FO',
                        'fr-BE',
                        'fr-CA',
                        'fr-CH',
                        'fr-FR',
                        'fr-LU',
                        'fr-MC',
                        'fy-NL',
                        'ga-IE',
                        'gd-GB',
                        'gl-ES',
                        'gsw-FR',
                        'gu-IN',
                        'ha-Latn-NG',
                        'he-IL',
                        'hi-IN',
                        'hr-BA',
                        'hr-HR',
                        'hsb-DE',
                        'hu-HU',
                        'hy-AM',
                        'id-ID',
                        'ig-NG',
                        'ii-CN',
                        'is-IS',
                        'it-CH',
                        'it-IT',
                        'iu-Cans-CA',
                        'iu-Latn-CA',
                        'ja-JP',
                        'ka-GE',
                        'kk-KZ',
                        'kl-GL',
                        'km-KH',
                        'kn-IN',
                        'kok-IN',
                        'ko-KR',
                        'ky-KG',
                        'lb-LU',
                        'lo-LA',
                        'lt-LT',
                        'lv-LV',
                        'mi-NZ',
                        'mk-MK',
                        'ml-IN',
                        'mn-MN',
                        'mn-Mong-CN',
                        'moh-CA',
                        'mr-IN',
                        'ms-BN',
                        'ms-MY',
                        'mt-MT',
                        'nb-NO',
                        'ne-NP',
                        'nl-BE',
                        'nl-NL',
                        'nn-NO',
                        'nso-ZA',
                        'oc-FR',
                        'or-IN',
                        'pa-IN',
                        'pl-PL',
                        'prs-AF',
                        'ps-AF',
                        'pt-BR',
                        'pt-PT',
                        'qut-GT',
                        'quz-BO',
                        'quz-EC',
                        'quz-PE',
                        'rm-CH',
                        'ro-RO',
                        'ru-RU',
                        'rw-RW',
                        'sah-RU',
                        'sa-IN',
                        'se-FI',
                        'se-NO',
                        'se-SE',
                        'si-LK',
                        'sk-SK',
                        'sl-SI',
                        'sma-NO',
                        'sma-SE',
                        'smj-NO',
                        'smj-SE',
                        'smn-FI',
                        'sms-FI',
                        'sq-AL',
                        'sr-Cyrl-BA',
                        'sr-Cyrl-CS',
                        'sr-Cyrl-ME',
                        'sr-Cyrl-RS',
                        'sr-Latn-BA',
                        'sr-Latn-CS',
                        'sr-Latn-ME',
                        'sr-Latn-RS',
                        'sv-FI',
                        'sv-SE',
                        'sw-KE',
                        'syr-SY',
                        'ta-IN',
                        'te-IN',
                        'tg-Cyrl-TJ',
                        'th-TH',
                        'tk-TM',
                        'tn-ZA',
                        'tr-TR',
                        'tt-RU',
                        'tzm-Latn-DZ',
                        'ug-CN',
                        'uk-UA',
                        'ur-PK',
                        'uz-Cyrl-UZ',
                        'uz-Latn-UZ',
                        'vi-VN',
                        'wo-SN',
                        'xh-ZA',
                        'yo-NG',
                        'zh-CN',
                        'zh-HK',
                        'zh-MO',
                        'zh-SG',
                        'zh-TW',
                        'zu-ZA',);
    
        foreach ($locales as $locale)
        {
            $locale_region = locale_get_region($locale);
            $locale_language = locale_get_primary_language($locale);
            $locale_array = array('language' => $locale_language,
                                 'region' => $locale_region);
    
            if (strtoupper($country_code) == $locale_region &&
                $language_code == '')
            {
                return locale_compose($locale_array);
            }
            elseif (strtoupper($country_code) == $locale_region &&
                    strtolower($language_code) == $locale_language)
            {
                return locale_compose($locale_array);
            }
        }
    
        return null;
    }
    ?>
    

    【讨论】:

    • 你使用的这个列表是旧的,看看最新的版本,它包含大约 422 - 460 个条目。 msdn.microsoft.com/en-us/library/cc233968.aspx
    • 致命错误:在 php shell 代码中调用未定义函数 locale_get_region()
    • @talsibony 你安装了 intl 扩展吗?
    • 现在我有,apt install php7.2-intl
    【解决方案4】:

    answer from TheJF 非常好,但是我遇到了一些(一般)问题:

    • 如果你调用country_code_to_locale("FR"),他的代码将返回br-FR - 现在br(布列塔尼语)甚至不是维基百科的官方语言。虽然fr-FR 在列表中,但br-FR 是数组中的第一个。这也发生在许多其他国家。

    • 许多其他语言环境列表都在努力做到极致,并考虑所有可能的语言

    • 在这里很难划清界限,您当然希望为一个国家/地区保留多种语言的好例子是:加拿大和瑞士

    我采用了简单的方法

    • 只为大多数国家/地区保留了一种语言,并为一些国家/地区保留了多种语言,例如 BE、CA、CH、ZA。我保留了es-US,但我不确定(维基百科说:Official languages: None at federal level

    • 我还为我懒得研究或同时使用拉丁语和西里尔语的国家/地区保留了多种语言

    • 我添加了 shuffle($locales);,它将随机化数组,以便我们获得具有多种语言的国家/地区的随机语言环境。这对我的用例很有意义,但您可能想删除它。

    • 就我的目的而言,只有在网络上具有相关流行度的语言才会感兴趣。这份清单绝不是完整或正确的,而是务实的。

    这是我的语言环境列表:

    $locales = array('af-ZA',
                    'am-ET',
                    'ar-AE',
                    'ar-BH',
                    'ar-DZ',
                    'ar-EG',
                    'ar-IQ',
                    'ar-JO',
                    'ar-KW',
                    'ar-LB',
                    'ar-LY',
                    'ar-MA',
                    'ar-OM',
                    'ar-QA',
                    'ar-SA',
                    'ar-SY',
                    'ar-TN',
                    'ar-YE',
                    'az-Cyrl-AZ',
                    'az-Latn-AZ',
                    'be-BY',
                    'bg-BG',
                    'bn-BD',
                    'bs-Cyrl-BA',
                    'bs-Latn-BA',
                    'cs-CZ',
                    'da-DK',
                    'de-AT',
                    'de-CH',
                    'de-DE',
                    'de-LI',
                    'de-LU',
                    'dv-MV',
                    'el-GR',
                    'en-AU',
                    'en-BZ',
                    'en-CA',
                    'en-GB',
                    'en-IE',
                    'en-JM',
                    'en-MY',
                    'en-NZ',
                    'en-SG',
                    'en-TT',
                    'en-US',
                    'en-ZA',
                    'en-ZW',
                    'es-AR',
                    'es-BO',
                    'es-CL',
                    'es-CO',
                    'es-CR',
                    'es-DO',
                    'es-EC',
                    'es-ES',
                    'es-GT',
                    'es-HN',
                    'es-MX',
                    'es-NI',
                    'es-PA',
                    'es-PE',
                    'es-PR',
                    'es-PY',
                    'es-SV',
                    'es-US',
                    'es-UY',
                    'es-VE',
                    'et-EE',
                    'fa-IR',
                    'fi-FI',
                    'fil-PH',
                    'fo-FO',
                    'fr-BE',
                    'fr-CA',
                    'fr-CH',
                    'fr-FR',
                    'fr-LU',
                    'fr-MC',
                    'he-IL',
                    'hi-IN',
                    'hr-BA',
                    'hr-HR',
                    'hu-HU',
                    'hy-AM',
                    'id-ID',
                    'ig-NG',
                    'is-IS',
                    'it-CH',
                    'it-IT',
                    'ja-JP',
                    'ka-GE',
                    'kk-KZ',
                    'kl-GL',
                    'km-KH',
                    'ko-KR',
                    'ky-KG',
                    'lb-LU',
                    'lo-LA',
                    'lt-LT',
                    'lv-LV',
                    'mi-NZ',
                    'mk-MK',
                    'mn-MN',
                    'ms-BN',
                    'ms-MY',
                    'mt-MT',
                    'nb-NO',
                    'ne-NP',
                    'nl-BE',
                    'nl-NL',
                    'pl-PL',
                    'prs-AF',
                    'ps-AF',
                    'pt-BR',
                    'pt-PT',
                    'ro-RO',
                    'ru-RU',
                    'rw-RW',
                    'sv-SE',
                    'si-LK',
                    'sk-SK',
                    'sl-SI',
                    'sq-AL',
                    'sr-Cyrl-BA',
                    'sr-Cyrl-CS',
                    'sr-Cyrl-ME',
                    'sr-Cyrl-RS',
                    'sr-Latn-BA',
                    'sr-Latn-CS',
                    'sr-Latn-ME',
                    'sr-Latn-RS',
                    'sw-KE',
                    'tg-Cyrl-TJ',
                    'th-TH',
                    'tk-TM',
                    'tr-TR',
                    'uk-UA',
                    'ur-PK',
                    'uz-Cyrl-UZ',
                    'uz-Latn-UZ',
                    'vi-VN',
                    'wo-SN',
                    'yo-NG',
                    'zh-CN',
                    'zh-HK',
                    'zh-MO',
                    'zh-SG',
                    'zh-TW');
    

    和代码:

    function country_code_to_locale($country_code)
    {
        $locales = ...
    
        // randomize the array, such that we get random locales
        // for countries with multiple languages (CA, CH)
        shuffle($locales);
    
        foreach ($locales as $locale) {
            $locale_region = locale_get_region($locale);
    
            if (strtoupper($country_code) == $locale_region) {
                return $locale;
            }
        }
    
        return "en-US";
    }
    

    【讨论】:

      【解决方案5】:

      正如其他答案所指出的,国家和语言之间没有一对一的映射。但是,如果您安装了 PHP Intl 扩展,则应该可以使用 Unicode CLDR likely subtags data 来获取特定国家/地区的“默认”或“可能”语言:

      function getLanguage(string $country): string {
          $subtags = \ResourceBundle::create('likelySubtags', 'ICUDATA', false);
          $country = \Locale::canonicalize('und_'.$country);
          $locale = $subtags->get($country) ?: $subtags->get('und');
          return \Locale::getPrimaryLanguage($locale);
      }
      

      现在,当您使用国家/地区代码调用 getLanguage() 函数时,您会返回相应的语言代码:

      getLanguage('US'); // "en"
      getLanguage('GB'); // "en"
      getLanguage('DE'); // "de"
      getLanguage('CH'); // "de"
      getLanguage('IN'); // "hi"
      getLanguage('NO'); // "nb"
      getLanguage('BR'); // "pt"
      

      这也适用于三个字母的国家/地区代码:

      getLanguage('USA'); // "en"
      getLanguage('GBR'); // "en"
      getLanguage('AUT'); // "de"
      getLanguage('FRA'); // "fr"
      

      甚至UN M49代码:

      getLanguage('003'); // "en"
      getLanguage('013'); // "es"
      getLanguage('039'); // "it"
      getLanguage('155'); // "de"
      

      【讨论】:

      • 在 PHP 7.4/windows 上,您的代码为上述所有示例返回“en”(无论输入如何,您的方法中的 $locale 总是得到 'en_Latn_US')
      • @atyachin 请检查以下代码在您的系统上打印的内容:print_r(iterator_to_array(\ResourceBundle::create('likelySubtags', 'ICUDATA', false))); 它应该看起来像这样:3v4l.org/lLgMd
      • 问题在于返回格式 _US 的 canonicalize 方法。可以通过以下方式修复:$locale = $subtags-&gt;get("und_".strtoupper($country)) ?: $subtags-&gt;get('und');
      • @atyachin 如果\Locale::canonicalize('und_de') 在您的系统中返回'en_US',我很确定设置有问题。你能用\Locale::canonicalize('und_gb')\Locale::canonicalize('en_GB') 测试输出是什么吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-17
      • 1970-01-01
      • 1970-01-01
      • 2011-03-07
      • 1970-01-01
      相关资源
      最近更新 更多