有没有一种简单的方法可以从PHP中的国家代码获取语言代码

问题描述 投票:0回答:5

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

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

php locale
5个回答
18
投票

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

有两个警告,一个是如果没有提供语言,它只会选择列表中的第一个区域设置。为了解决这个问题,您必须在函数调用周围添加一些逻辑,以为其提供适当的语言。另外就是需要安装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;
}
?>

10
投票

正如其他答案所指出的,国家和语言之间没有一对一的映射。但是,如果您安装了 PHP

Intl
扩展,则应该可以使用 Unicode CLDR 可能的子标签数据 来获取特定国家/地区的“默认”或“可能”语言:

function getLanguage(string $country): string {
    $subtags = \ResourceBundle::create('likelySubtags', 'ICUDATA', false);
    $country = \Locale::canonicalize('und_'.$country);
    if (($country[0] ?? null) === '_') {
        $country = '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"

6
投票

您无法自动将国家/地区代码转换为语言代码,因为某些国家/地区使用多种语言。另一方面,操作系统本地化系统可能支持不同国家/地区的单一语言的多种变体(例如,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 的关系。在两个方向上都可以找到一对多关系。


1
投票

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

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

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

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


1
投票

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

  • 如果你调用

    br-FR
    ,他的代码将返回
    country_code_to_locale("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"; }
    
© www.soinside.com 2019 - 2024. All rights reserved.