Получить локаль по умолчанию для языка в PHP

У меня есть php back-end, к которому несколько типов устройств общаются через публичный API. Запросы обычно содержат необходимый язык для ответа (например, " en " или " fr " или " ru " и т. д.)- но не в полном объеме. Это отлично сработало для всего, что мне было нужно за последние пару лет. Однако теперь мне нужно включить информацию о дате в ответ - и нужна локаль для форматирования дат.

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

3 ответов


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

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


возможно, вы могли бы использовать $_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 класс и то возможно то язык::acceptFromHttp метод

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


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

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

# Usage:

$locale = $localeMap[$lang];

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

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

l => ll

пока язык находится в двухбуквенном формате, выглядит для меня нормально (стандарт 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);