Есть простой способ получить код языка из кода страны в PHP

Я использую коды ISO 3166-1-alpha 2 для передачи в приложение для извлечения локализованного фида, например. /feeds/us для США. У меня есть оператор switch, который служит для подачи на основе этого country_code.

Есть ли способ конвертировать этот двухзначный код в код языка, например. ru_US? Мне интересно, есть ли стандартная/функция/библиотека для этого в PHP или мне нужно создать собственный массив?

Ответ 1

Как указывали другие, нет встроенной функции, поскольку это возможно из-за реальности многих стран, имеющих несколько языков. К сожалению, я не могу указать вам на библиотеку, которая делает это, но я пошел вперед и написал небольшую функцию, которая делает то, что вы хотите.

Есть два оговорки: один, если не предоставляется язык, он просто выбирает первую локаль в списке. Чтобы обойти это, вам придется поместить некоторую логику вокруг вызова функции, чтобы предоставить ей соответствующий язык. Другим является то, что он должен установить 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;
}
?>

Ответ 2

Вы не можете автоматически конвертировать код страны в код языка, потому что некоторые страны используют несколько языков. С другой стороны, система локализации ОС может поддерживать несколько вариантов одного языка для разных стран (например, en_GB vs en_US).

Например, в Швейцарии (CH) используются как немецкие, так и французские языки (64% и 20% населения, согласно http://en.wikipedia.org/wiki/Switzerland). Если вам нужно решить один язык для кода страны CH, любой из этих языков может иметь смысл для некоторых людей. Обратите внимание, что некоторые части Швейцарии используют только немецкий или французский язык как официальный язык (но не оба, см. http://en.wikipedia.org/wiki/File:Sprachen_CH_2000_EN.svg для деталей).

Если вы ДОЛЖНЫ выбрать один язык для каждой страны, я предлагаю сделать выбор вручную для каждой страны, которую вы поддерживаете. Для автоматизированной реализации с половиной осевого сканирования вы можете просканировать доступные локализации и выбрать первый, который имеет соответствующий код страны после подчеркивания.

Ответ 3

Вы захотите перекрестно ссылаться на эти файлы:

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 PHP, которая возвращает эти данные, о которых я знаю.

Ответ 4

ответ от TheJF довольно хорош, однако есть несколько (общих) проблем, с которыми я столкнулся:

  • его код вернет br-FR, если вы назовете country_code_to_locale("FR") - now br (Breton), даже не является официальным языком в соответствии с Википедией. Хотя fr-FR находится в списке, br-FR является первым в массиве. это происходит и со многими другими странами.

  • многие другие языковые списки пытаются быть чрезвычайно полными и учитывать все возможные языки

  • Трудно нарисовать линию здесь, хорошие примеры, где вы, конечно же, хотите сохранить несколько языков для страны: Канада и Швейцария

Я пошел с простым подходом:

  • Я держал только один язык для большинства стран и оставил несколько для некоторых стран, таких как BE, CA, CH, ZA. Я сохранил es-US, но я не уверен в этом (Wikipedia говорит: 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";
}