9

ブラウザの言語設定を確認し、サイトの言語バージョン (WP マルチサイト) にリダイレクトする小さなスクリプトを PHP で作成しました。

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 でテストすると、リダイレクトが機能していないように見えます。考慮する必要があるモバイル ブラウザーの受け入れ言語の特別な出力はありますか?

更新:さらにデバッグした後、私はこれを見つけました:

  • Mobile Safari は、HTTP_ACCEPT_LANGUAGE をエコーするときに正しい言語を表示しますが、リダイレクトしません。
  • モバイル 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) を比較してください。 )。
4

6 に答える 6

4

これを試して、出力をお知らせください

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
}
于 2015-06-29T04:54:17.850 に答える
2

以前の回答に更新

HTTP_ACCEPT_LANGUAGE はヘッダーを介して設定され、すべての人に異なる値を与えます。私の場合、私は南アメリカにいて、コンピューターを英語でセットアップしているため、言語ヘッダーには英語とスペイン語の設定があり、英語に偏っています。

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();
  }
}

セッション変数はリダイレクトロジックをバイパスしています。上記のコードを試して、すべてのデバイスからすべての Cookie とセッションをクリアして、$_SESSION['language']テスト中に設定した変数によって結果が台無しにならないようにしてください。あなたの側で何が起こるか教えてください。

于 2015-07-07T16:42:53.690 に答える
1

これは、デスクトップ ブラウザとモバイル デバイスで正常に動作します。私もデバイスでのみセッションの問題を経験しており、ほとんどの場合、実際には変数がまだ存在している場合、または単純に 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']);
    }
?>
于 2015-06-29T11:44:25.967 に答える
0

最初の 2 文字を取得することに依存するべきではありません。文字列全体を検査し、最良の言語選択がどうあるべきかを理解することに本当に頼る必要があります。これらの文字列値には特定の意味があります。たとえば、「問題のある」文字列のケースの 1 つでは、実際enにはsv. もちろん、accept 言語を分解し、構成要素を調査し、適切なアクションを実行するロジックを作成できますが、次のようなものを使用することも検討できます。

http_negotiate_language

あなたのためにこれを行うために。最初の 2 文字を見るよりも適切な方法でこのヘッダーを実際に操作するために、クイック Google 検索から利用できる他のスクリプトがおそらく数十あります。

また、同様の質問をここで確認できます: Using the PHP HTTP_ACCEPT_LANGUAGE server variable

于 2015-07-06T21:22:57.317 に答える