我正在使用 ISO 3166-1-alpha 2 代码传递给应用程序以检索本地化提要,例如美国的 /feeds/us。我有一个 switch 语句,它提供基于该 country_code 的提要。
有没有办法将该两位数字代码转换为语言代码,例如 en_US ?我想知道是否有一个标准/函数/库可以在 PHP 中执行此操作,或者我是否需要构建自己的数组?
正如其他人指出的那样,没有内置功能,因为这可能是由于许多国家拥有多种语言的现实。所以不幸的是,我不能将你指向一个这样做的库,但我确实继续编写了一个小函数来满足你的需求。
有两个警告,一个是如果没有提供语言,它只会选择列表中的第一个语言环境。为了解决这个问题,您必须在函数调用周围放置一些逻辑,以便为其提供适当的语言。另一个是它需要安装 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;
}
?>
You cannot automatically convert country code to language code because some countries use multiple languages. On the other hand, OS localization system may support multiple variants of a single language for different countries (for example, en_GB vs en_US).
For example, Switzerland (CH) has both German and French commonly used (64% and 20% of the population, according to http://en.wikipedia.org/wiki/Switzerland). If you have to decide a single language for country code CH either of those languages could make sense for some people. Note that some parts of the Switzerland use only German or French as the official language (but not both, see http://en.wikipedia.org/wiki/File:Sprachen_CH_2000_EN.svg for details).
If you MUST select a single language for each country, I'd suggest doing the selection by hand for every country you support. For an half-assed automatic implementation, you could scan through your available localizations and select the first one that has the matching country code after the underscore.
Also note the corollary: languages cannot be represented by national flags because languages and countries do not have 1:1 relation. One to many relations can be found in both directions.
正如其他答案所指出的,国家和语言之间没有一对一的映射。但是,如果您安装了 PHPIntl
扩展,则应该可以使用 Unicode CLDR可能的子标签数据来获取特定国家/地区的“默认”或“可能”语言:
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"
甚至联合国 M49代码:
getLanguage('003'); // "en"
getLanguage('013'); // "es"
getLanguage('039'); // "it"
getLanguage('155'); // "de"
您将需要交叉引用这些文件:
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 函数。
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";
}