PHP или htaccess переписать URL с помощью Accept-Language? - PullRequest
2 голосов
/ 19 сентября 2011

Я настроил свой сайт, поэтому мне просто нужно добавить «? Lang = en» или «? Lang = es» для смены языков английский / испанский.

Когда я захожу на сайт с, например, «http://domain.com/something/something_else?lang=es",», устанавливается cookie, поэтому я продолжаю навигацию по сайту на этом языке.

Я хотел бы сначала перенаправить своих пользователей по значению «Accept-Language» своего браузера, но затем разрешить им продолжать навигацию по сайту на другом языке, если они этого захотят.

Как лучше всего это сделать? Будет ли .htaccess работать вместе с файлом cookie, установленным при выборе языка?

РЕДАКТИРОВАТЬ: Вот мой обновленный код с ответом Пола:

EDIT2: О, у меня просто есть языки "en" и "es". Я не уверен, как этот код будет выбирать только между этими двумя или устанавливать по умолчанию ...: /

    if (isset($_GET["lang"]))
        $this->setLanguage($_GET["lang"]);
    elseif (isset($_COOKIE["language"]))
        $this->setLanguage($_COOKIE["language"]);
    elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
        {
        // Parse the Accept-Language according to:
        // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
        preg_match_all(
           '/([a-z]{1,8})' . // First part of language e.g en
           '(-[a-z]{1,8})*\s*' . // other parts of language e.g -us
           // Optional quality factor
           '(;\s*q\s*=\s*((1(\.0{0,3}))|(0(\.[0-9]{0,3}))))?/i',
           $_SERVER['HTTP_ACCEPT_LANGUAGE'],
           $langParse);

        $langs = $langParse[1];
        $quals = $langParse[4];

        $numLanguages = count($langs);
        $langArr = array();

        for ($num = 0; $num < $numLanguages; $num++)
        {
           $newLang = strtoupper($langs[$num]);
           $newQual = isset($quals[$num]) ?
              (empty($quals[$num]) ? 1.0 : floatval($quals[$num])) : 0.0;

           // Choose whether to upgrade or set the quality factor for the
           // primary language.
           $langArr[$newLang] = (isset($langArr[$newLang])) ?
              max($langArr[$newLang], $newQual) : $newQual;
        }

        // sort list based on value
        arsort($langArr, SORT_NUMERIC);
        $acceptedLanguages = array_keys($langArr);
        $preferredLanguage = reset($acceptedLanguages);

        $this->setLanguage($preferredLanguage);
     }
     else
        $this->setLanguage("en");

Ответы [ 2 ]

2 голосов
/ 19 сентября 2011

Я делаю это на PHP.Accept-Language - сложная вещь.Браузер может предложить более одного языка, который он хотел бы принять (каждый с показателем качества, который показывает, какой он предпочитает).Для моего сайта у меня есть язык по умолчанию для отображения (который отображается, когда ни один из языков Accept-Languages ​​отсутствует в моем списке переводов).В противном случае, если язык не установлен (setLang), я выбираю его на основе наиболее приемлемого для браузера, анализируя Accept-Language.Ниже я использую функцию (в ней содержится мой менеджер сеансов для установки файлов cookie - но вы можете переопределить это с прямыми вызовами $ _SESSION [etc] = $ foo;).

Edit :К сожалению, мой веб-сайт имеет переводы только для основных языков (EN, ES, FR), а не (en_US, en_GB, es_MX, es_ES), поэтому я выбираю самый высокий коэффициент качества, указанный в них для основного языка.

   public function setLanguage($setLang='')
   {
      if (!empty($setLang))
      {
         $this->setup['Session']->set($this->setup['Lang_Key'], $setLang);
      }
      else
      {
         if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
         {
            // Parse the Accept-Language according to:
            //    http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
            preg_match_all(
               '/([a-z]{1,8})' . // First part of language e.g en
               '(-[a-z]{1,8})*\s*' . // other parts of language e.g -us
               // Optional quality factor
               '(;\s*q\s*=\s*((1(\.0{0,3}))|(0(\.[0-9]{0,3}))))?/i',
               $_SERVER['HTTP_ACCEPT_LANGUAGE'],
               $langParse);

            $langs = $langParse[1];
            $quals = $langParse[4];

            $numLanguages = count($langs);
            $langArr = array();

            for ($num = 0; $num < $numLanguages; $num++)
            {
               $newLang = strtoupper($langs[$num]);
               $newQual = isset($quals[$num]) ?
                  (empty($quals[$num]) ? 1.0 : floatval($quals[$num])) : 0.0;

               // Choose whether to upgrade or set the quality factor for the
               // primary language.
               $langArr[$newLang] = (isset($langArr[$newLang])) ?
                  max($langArr[$newLang], $newQual) : $newQual;
            }

            // sort list based on value
            arsort($langArr, SORT_NUMERIC);
            $acceptedLanguages = array_keys($langArr);
            $preferredLanguage = reset($acceptedLanguages);

            $this->setup['Session']->set(
               $this->setup['Lang_Key'], $preferredLanguage);
         }
         else
         {
            $this->setup['Session']->set(
               $this->setup['Lang_Key'], $this->setup['Default_Language']);
         }
      }

      return $this->setup['Session']->get($this->setup['Lang_Key']);
   }
0 голосов
/ 21 сентября 2011

Я делаю это на PHP.Accept-Language - сложная вещь.Браузер может предложить более одного языка, который он хотел бы принять (каждый с показателем качества, который показывает, какой он предпочитает).

К сожалению, на моем веб-сайте есть переводы только для основных языков (EN, ES, FR)вместо (en_US, en_GB, es_MX, es_ES), поэтому я выбираю самый высокий коэффициент качества, указанный в них для основного языка.

Ниже приведено непроверенное редактирование, которое должно удалить большинство или все зависимости из моего кода.Извините, все путалось с моим предыдущим ответом.У меня было несколько обращений к моей функции, некоторые проверки языков выполнялись в другом месте.Приведенный ниже код должен установить переменную языка сеанса, которую вы должны использовать в другом месте для определения правильного перевода.

Это кажется намного менее сложным, чем мой предыдущий ответ, и мне придется вскоре реализовать это в моем собственном коде,Для людей, которым нужны конкретные переводы (EN_US, EN_GB), приведенный ниже код следует изменить, чтобы учесть совпадение 2 в preg_match_all.

$websiteLanguages = array('EN', 'ES');
session_start();

// The user wants a specific language regardless of their accept settings.
if (isset($_GET["lang"]))
{
    $_SESSION["language"] = $_GET["lang"];
    return;
}

// A language has already been decided upon.
if (isset($_SESSION["language"]))
{
   return;
}

// No language has been chosen we should choose from the accept language.  
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
{
    // Parse the Accept-Language according to:
    // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
    preg_match_all(
       '/([a-z]{1,8})' . // M1 - First part of language e.g en
       '(-[a-z]{1,8})*\s*' . // M2 -other parts of language e.g -us
       // Optional quality factor M3 ;q=, M4 - Quality Factor
       '(;\s*q\s*=\s*((1(\.0{0,3}))|(0(\.[0-9]{0,3}))))?/i',
       $_SERVER['HTTP_ACCEPT_LANGUAGE'],
       $langParse);

    $langs = $langParse[1]; // M1 - First part of language
    $quals = $langParse[4]; // M4 - Quality Factor

    $numLanguages = count($langs);
    $langArr = array();

    for ($num = 0; $num < $numLanguages; $num++)
    {
       $newLang = strtoupper($langs[$num]);
       $newQual = isset($quals[$num]) ?
          (empty($quals[$num]) ? 1.0 : floatval($quals[$num])) : 0.0;

       // Choose whether to upgrade or set the quality factor for the
       // primary language.
       $langArr[$newLang] = (isset($langArr[$newLang])) ?
          max($langArr[$newLang], $newQual) : $newQual;
    }

    // sort list based on value
    // langArr will now be an array like: array('EN' => 1, 'ES' => 0.5)
    arsort($langArr, SORT_NUMERIC);

    // The languages the client accepts in order of preference.
    $acceptedLanguages = array_keys($langArr);

    // Set the most preferred language that we have a translation for.
    foreach ($acceptedLanguages as $preferredLanguage)
    {
        if (in_array($preferredLanguage, $websiteLanguages))
        {
           $_SESSION['Language'] = $preferredLanguage;
           return;
        }
    }
 }

 // We will have returned by now if a language could be chosen, otherwise use
 // our default language.
 $_SESSION['Language'] = "EN";
...