Получить локаль по умолчанию для языка в PHP - PullRequest
9 голосов
/ 20 декабря 2011

У меня есть серверная часть PHP, с которой несколько типов устройств взаимодействуют через публичный API.Запросы обычно содержат требуемый язык для ответа (например, 'en' или 'fr' или 'ru' и т. Д.), Но не полную локаль.Это работало отлично для всего, что мне было нужно в последние пару лет.Однако теперь мне нужно включить информацию о дате в ответ - и мне нужна локаль для форматирования дат.

Как я могу получить локаль из языка?Я понимаю, что языка недостаточно для однозначной идентификации локали, но мне нужно хоть что-то.Если бы я мог получить хотя бы одну локаль, например, en_GB для «en» или «ru_RU» для «ru» и т. Д. - этого было бы достаточно.

Ответы [ 3 ]

6 голосов
/ 20 декабря 2011

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

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 установлен (мы находимся в Великобритании, как и наши серверы).

1 голос
/ 20 декабря 2011

Возможно, вы могли бы использовать $_SERVER['HTTP_ACCEPT_LANGUAGE']; вместо поставляемого языка, чтобы получить локаль.Довольно часто это будет содержать реальный языковой стандарт с дефисом вместо подчеркивания.

Пример $_SERVER['HTTP_ACCEPT_LANGUAGE']:

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

Просто получите все до первого , и все готово.Это также лучше, чем заполнение массива локалей, потому что он позволяет браузеру сообщать серверу, какой язык он предпочитает, а не наоборот, однако массив, как в ответе хакре, должен использоваться в качестве системы резервного копирования на случай, если неверный / пустой /отсутствует пропущенный $_SERVER['HTTP_ACCEPT_LANGUAGE'].

Еще вы можете захотеть взглянуть на класс locale и, возможно, locale :: acceptFromHttp метод

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

1 голос
/ 20 декабря 2011

Правильно ли я вас понимаю, что вам нужна только карта от языка (например, en) до локали (например, en_GB)? Если это так, вы можете скомпилировать один для языков, которые вы используете:

$localeMap = array(
    'en' => 'en_GB',
    'fr' => 'fr_FR',
    # ...  
);

# Usage:

$locale = $localeMap[$lang];

Но это так тривиально, что я не уверен, правильно ли я понял твой вопрос.

Если вы не уверены, какой язык используется для языка, просто возьмите язык, который должен быть действительным языком, только без страны:

l => l l

Пока язык в двухбуквенном формате мне подходит (стандарт ISO 639, «Код для представления названий языков»), смотрите также Теги для идентификации языков (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);
...