Получить локаль по умолчанию для языка в 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);