Обнаружение языка PHP - PullRequest
22 голосов
/ 29 августа 2009

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

Я использую этот фрагмент кода для определения языка пользователя. Если вы не выбрали язык, он будет включать ваш языковой файл, основанный на HTTP_ACCEPT_LANGUAGE, я не знаю, откуда он его получает, хотя ..

session_start();

if (!isset($_SESSION['lang'])) {
   $_SESSION['lang'] = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
}

elseif (isset($_GET['setLang']) && $_GET['setLang'] == 'en') $_SESSION['lang'] = "en";
elseif (isset($_GET['setLang']) && $_GET['setLang'] == 'sv') $_SESSION['lang'] = "sv";
elseif (isset($_GET['setLang']) && $_GET['setLang'] == 'pl') $_SESSION['lang'] = "pl";
elseif (isset($_GET['setLang']) && $_GET['setLang'] == 'fr') $_SESSION['lang'] = "fr";

include('languages/'.$_SESSION['lang'].'.php');

Это работает для меня и включает в себя файл польского языка. Но точен ли этот код? Или есть другой способ ?? Как вы думаете, YouTube делает это, например?

Было бы здорово, если бы кто-нибудь из английских, французских, шведских или польских людей мог зайти на мой сайт и посмотреть, содержит ли он нужный файл! Так что я знаю, что это не работает для меня :) http://jorm.homeftp.org/

В любом случае, вы думаете, я мог бы улучшить свой код? это будет выглядеть грязно, когда я добавлю больше языков со всеми остальными!

Спасибо

Ответы [ 8 ]

35 голосов
/ 29 августа 2009

Браузер обычно отправляет HTTP-заголовок с именем Accept-Language, который указывает, какие языки пользователь хочет получить.

Например, этот заголовок может быть:

Accept-Language: en-us,en;q=0.5

В нем есть понятие приоритета, кстати; -)

В PHP вы можете получить это в $_SERVER super global:

var_dump($_SERVER['HTTP_ACCEPT_LANGUAGE']);

достанет мне:

string 'en-us,en;q=0.5' (length=14)

Теперь вы должны разобрать это; -)


Если я отредактирую свои настройки в настройках браузера, чтобы сказать: «Я хочу французский, и если вы не можете служить мне по-французски, достаньте мне английский из США; а если вы не можете получить и меня, то просто получите меня». английский), заголовок будет:

Accept-Language: fr-fr,en-us;q=0.7,en;q=0.3

А из PHP:

string 'fr-fr,en-us;q=0.7,en;q=0.3' (length=26)


Для получения дополнительной информации вы можете взглянуть на раздел 14.4 HTTP RFC .

И вы, вероятно, можете найти множество примеров кода в PHP для анализа этого заголовка; например: Parse Accept-Language для определения языка пользователя

Веселись!

7 голосов
/ 29 августа 2009

Вот скрипт, который я использовал для двуязычного сайта. Он должен использоваться как index.php из mysite.com. Исходя из языковых предпочтений браузера пользователя, он будет перенаправлять на нужную языковую версию сайта или языковой сайт по умолчанию, если сайт в предпочитаемом им языке пользователя недоступен.

<?php
// List of available localized versions as 'lang code' => 'url' map
$sites = array(
    "en" => "http://en.mysite.com/",
    "bn" => "http://bn.mysite.com/",
);

// Get 2 char lang code
$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);

// Set default language if a `$lang` version of site is not available
if (!in_array($lang, array_keys($sites)))
    $lang = 'en';

// Finally redirect to desired location
header('Location: ' . $sites[$lang]);
?>
4 голосов
/ 17 ноября 2015

Я знаю, что там уже много хороших решений, но нашел свой способ решить эту проблему.

<?php
  $prefLocales = array_reduce(
    explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']), 
      function ($res, $el) { 
        list($l, $q) = array_merge(explode(';q=', $el), [1]); 
        $res[$l] = (float) $q; 
        return $res; 
      }, []);
    arsort($prefLocales);
    /*
    This get you from headers like this
      string 'en-US,en;q=0.8,uk;q=0.6,ru;q=0.4' (length=32)
    array like this
    array (size=4)
      'en-US' => float 1
      'en' => float 0.8
      'uk' => float 0.6
      'ru' => float 0.4
    */

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

4 голосов
/ 28 апреля 2015

Вы можете использовать: Locale::acceptFromHttp().

Пытается найти локаль, которая может соответствовать списку языков, запрашиваемому HTTP-заголовком «Accept-Language».

1 голос
/ 30 августа 2009

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

Насколько я могу судить, Youtube использует HTTP_ACCEPT_LANGUAGE, но в то же время использует IP-геолокацию, чтобы предложить изменение языка, если язык страны посетителя не соответствует этому. Определенно раздражает.

Просто придирки: если вы собираетесь добавить языки в список, оператор switch() может быть более читабельным.

0 голосов
/ 29 ноября 2017

Это тоже возможно. По умолчанию будет использоваться английский, если .php недоступен.

$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
(@include_once 'languages/'.$lang.'.php') or (@include_once 'languages/en.php'); 
0 голосов
/ 16 октября 2014
if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])){
    $parts=explode(';',$_SERVER['HTTP_ACCEPT_LANGUAGE']);
    $langs=explode(',',$parts[0]);
    var_dump($langs);
}
0 голосов
/ 20 марта 2013

Попробуйте это

function getUserLanguage() {
    $langs = array();

    if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
        // break up string into pieces (languages and q factors)
        preg_match_all(
            '/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i',
            $_SERVER['HTTP_ACCEPT_LANGUAGE'],
            $lang_parse
        );

        if (count($lang_parse[1])) {
            // create a list like 'en' => 0.8
            $langs = array_combine($lang_parse[1], $lang_parse[4]);

            // set default to 1 for any without q factor
            foreach ($langs as $lang => $val) {
                if ($val === '') {
                    $langs[$lang] = 1;
                }
            }
            // sort list based on value
            arsort($langs, SORT_NUMERIC);
        }
    }
    //extract most important (first)
    reset($langs);
    $lang = key($langs);

    //if complex language simplify it
    if (stristr($lang, '-')) {
        list($lang) = explode('-', $lang);
    }

    return $lang;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...