繁体   English   中英

语言重定向适用于桌面,但不适用于移动浏览器

[英]Language redirect works on desktop but not mobile browser

我在PHP中编写了一个小脚本,用于检查浏览器的语言设置并将其重定向到站点的语言版本(WP多站点),

function redirect() {
  $language = substr( $_SERVER["HTTP_ACCEPT_LANGUAGE"],0,2 );
  switch( $language ) {
    case 'sv':
      header( 'Location: http://www.example.com/sv/' );
      break;
    case 'no':
      header( 'Location: http://www.example.com/no/' );
      break;
    case 'da':
      header( 'Location: http://www.example.com/da/' );
      break;
    default:
      header( 'Location: http://www.example.com/' );
      break;
  }
}
if ( strlen($url) < 4 ) {
  session_start();
  if ( empty($_SESSION[ 'language' ]) ) {
    $_SESSION[ 'language' ] = true;
    redirect();
  }
}

使用Mobile Safari或Mobile Chrome进行测试时,重定向似乎不起作用。 我需要考虑移动浏览器的接受语言是否有任何特殊输出?

更新:经过一些调试后我发现了这个:

  • 回显HTTP_ACCEPT_LANGUAGE时,Mobile Safari会显示正确的语言,但不会重定向。
  • 移动Chrome(仅适用于iOS,适用于Android)无法显示正确的语言(默认为“en”)。
  • iOS以不同的顺序解析http标头数据,比较iOS Chrome(en-US,en; q = 0.8,sv; q = 0.6)和OSX Chrome(sv,en-US; q = 0.8,en; q = 0.6 )。

试试这个,请告诉我们输出结果

function redirect() {
  $language = substr( $_SERVER["HTTP_ACCEPT_LANGUAGE"],0,2 );

  switch( $language ) {
    case 'sv':
      header( 'Location: http://www.example.com/sv/' );
      break;
    case 'no':
      header( 'Location: http://www.example.com/no/' );
      break;
    case 'da':
      header( 'Location: http://www.example.com/da/' );
      break;
    default:
      die('Default location');
   /* if you get this message on mobile devices, then this line  

          $language = substr( $_SERVER["HTTP_ACCEPT_LANGUAGE"],0,2 );

      is faulty. Perhaps as @chris85 mentioned, HTTP_ACCEPT_LANGUAGE is
      not populated so mobile behaves as a default by not redirecting to
      other languages. If this is the case, fix that line
      and remove the die();*/
      header( 'Location: http://www.example.com/' );
      break;
  }
  die(); // leave this one in. It forces the server to flush data to the browser
}

更新到我之前的答案

HTTP_ACCEPT_LANGUAGE通过标头设置,并为每个人提供不同的值。 在我的情况下,我在南美洲的英语计算机设置,所以我的lang标题有英语和西班牙语设置偏向英语。

session_start();

function redirectToLang($langCode){
    // use if's instead of switch so that you can
    // check exact matches and presence of a substring
    if ($langCode == 'sv'){
        $langPath = 'sv';
    }else if (strpos($langCode, 'en') !== false){ // this would match en, en-CA, en-US
        $langPath = 'en';
    }else if ($langCode == 'no'){
        $langPath = 'no';
    }else{
        $langPath = 'en';
    }

    // you should have no output from the server before this line!
    // that is no echoes, print_r, var_dumps, headers, etc
    header( 'Location: http://www.example.com/' . $langPath .'/' );
    die();
}

function parseLang(){
    // echo $_SERVER['HTTP_ACCEPT_LANGUAGE']; in my case
    // Chrome Mac OS:        en,es;q=0.8
    // Chrome Android 5.1:   en-US;en;q=0.8,es;q=0.6
    // IE Windows Phone 8.1: en-US,en;q=0.5
    // Safari iOS:           en-US
    // Chrome iOS:           en-US,en;q=0.8

    // get the lang and set a default
    $lang = isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : 'en';

    // parse the lang code. This can be as simple or as complex as you want

    // Simple
    $langCode = substr($lang, 0, 2); // in my case 'en'

    // Semi Complex (credits to http://www.thefutureoftheweb.com/blog/use-accept-language-header)
    $languages = array();
    preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $lang, $parsed);

    if (count($parsed[1])) {
        $languages = array_combine($parsed[1], $parsed[4]);
        foreach ($languages as $lang => $val) {
            if ($val === '') $languages[$lang] = 1;
        }
        arsort($languages, SORT_NUMERIC);
    }
    // var_dump($languages); in my case
    // array (size=2)
    //  'en' => int 1
    //  'es' => string '0.8'


    $langCode = key($languages); // in my case 'en'

    return $langCode;
}


if (!isset($_SESSION['lang'])){
    $langCode = parseLang();
    $_SESSION['lang'] = $langCode;
    redirectToLang($langCode);
}else{
    // we already know the language and it is in $_SESSION
    // no need to parseLang nor redirect
}

在我的情况下,所有设备都正确重定向。 我的猜测是,调用redirect()的逻辑上发生了一些事情

// this part
if ( strlen($url) < 4 ) {
  session_start();
  if ( empty($_SESSION[ 'language' ]) ) {
    $_SESSION[ 'language' ] = true;
    redirect();
  }
}

并且会话var绕过重定向逻辑。 尝试上面的代码并清除所有设备上的所有cookie和会话,以便在测试期间设置的$_SESSION['language'] var不会弄乱结果。 让我们知道你最终会发生什么。

我引用了......“更现代的方法是使用http_negotiate_language():”

你看过这个吗? 使用PHP HTTP_ACCEPT_LANGUAGE服务器变量

这在我的桌面浏览器和移动设备上运行良好。 我也只是在设备上遇到会话问题,而且最常见的是,我依赖于一个空的会话变量来满足我的条件的要求,而实际上变量仍然存在,或者根本没有实例化session_id()。

?reset将清除会话。

如果语言已更改,它还将运行重定向。

<?php
    session_start();

    if (isset($_REQUEST['reset'])) {
      unset($_SESSION);
      $_SESSION['PREVIOUS_SESSION'] = '&cleared=1';
    }

    function redirect($loc) {
        $_SESSION[ 'language' ] = true;
        $_SESSION['last_language'] = $language;
        header( 'Location: ?r='.$loc.$_SESSION['PREVIOUS_SESSION']);
    }

    $language = substr( $_SERVER["HTTP_ACCEPT_LANGUAGE"],0,2 );

    if (( empty($_SESSION[ 'language' ]) ) || ($_SESSION['last_language'] != $language)) {
        redirect($language);
    }

    echo '<pre>';
    print_r($_SESSION);
    echo '</pre>';

    if (!empty($_SESSION['PREVIOUS_SESSION'])) {
        unset($_SESSION['PREVIOUS_SESSION']);
    }
?>

你应该给我们举例说明三种情况下$_SERVER["HTTP_ACCEPT_LANGUAGE"]的值是什么。

无论如何,请注意,根据HTTP / 1.1RFC2616,语言的选择要比仅使用头部的两个第一个字符复杂得多。

可以给每个语言范围赋予相关的质量值,该值表示用户对该范围指定的语言的偏好的估计。 质量值默认为“q = 1”。 例如,

  Accept-Language: da, en-gb;q=0.8, en;q=0.7 

意思是:“我更喜欢丹麦语,但会接受英国英语和其他类型的英语。”

没有什么说这些标题是排序的,也没有说用户的优先语言是列表中的第一个。 并且也无法在浏览器或操作系统中配置语言配置。

理想情况下,要选择最佳语言,您必须以这种方式解析此标头:

  • 在逗号上拆分字符串
  • 拆分分号字符上找到的每个子字符串
  • 如果未给出数值,请使用默认值1.0
  • 使用此数值对结果进行排序
  • 将此列表与您网站上可用的语言列表进行比较,找到最合适的语言。

你真的不应该依赖前两个字符。 你真的需要依靠检查整个字符串并理解最佳语言选择应该是什么。 这些字符串值具有特定含义,例如,在您的“问题”字符串的一个案例中,您实际上将执行最合适的行为来显示en而不是sv 显然,您可以编写逻辑来拆分接受语言,调查组成部分并采取适当的操作,但您也可以考虑使用以下内容:

http_negotiate_language

为你做这个。 可能有很多其他脚本可以通过快速谷歌搜索以更合适的方式真正使用此标题,而不仅仅是查看两个第一个字符。

此外,您可以在此处查看类似的问题: 使用PHP HTTP_ACCEPT_LANGUAGE服务器变量

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM