У меня есть PHP-сервер, с которым взаимодействует несколько типов устройств через открытый API. Обычно запросы содержат требуемый язык для ответа (например, «en» или «fr» или «ru» и т. Д.), Но не полный язык. За последние пару лет это отлично справилось со всем, что мне нужно. Однако теперь мне нужно включить информацию о дате в ответ – и мне нужен языковой стандарт для форматирования дат.
Как я могу получить языковой стандарт? Я понимаю, что языка недостаточно, чтобы однозначно идентифицировать локаль, но мне нужно хотя бы что-то. Если я могу получить хотя бы один язык, например en_GB для 'en' или 'ru_RU' для 'ru' и т. Д., Этого было бы достаточно.
Подумав больше о проблеме и конкретной установке, которую я имею, я придумал это решение, которое, похоже, работает. Обратите внимание, что я не контролирую, какие языки мне нужно поддерживать: файлы перевода упали в предопределенное место и локали системы, установленные кем-то другим. Во время выполнения я должен поддерживать определенный язык, если существует соответствующий файл перевода и установлен языковой стандарт системы. Это привело меня к такому решению:
function getLocale($lang) { $locs = array(); exec('locale -a', $locs); $locale = 'en_GB'; foreach($locs as $l) { $regex = "/$lang\_[AZ]{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
Просто получите все до первого ,
и все готово. Это также лучше, чем заполнение массива локалей, поскольку он позволяет браузеру сообщать серверу, какой язык он предпочитает, а не наоборот, однако массив, как в ответе hakre, должен использоваться как резервная система в случае недопустимого / пустого / отсутствует $_SERVER['HTTP_ACCEPT_LANGUAGE']
.
Что-то еще, что вы можете захотеть изучить, – это класс локали и, возможно, метод locale :: acceptFromHttp
Кроме того, вы можете захотеть изменить свой API, чтобы пользователи могли явно установить их локаль, просто убедитесь, что он будет грамотно отпадать в любую систему, которую вы решили реализовать сейчас.
Я правильно понимаю, что вам нужна только карта с языка (например, 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);