2015-06-29 15 views
8

Ho messo insieme un piccolo script in PHP che controlla le impostazioni di lingua del browser e li reindirizza ad una versione in lingua del sito (WP multisito),Lingua reindirizzamento funziona sul desktop, ma non il browser del cellulare

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

Durante il test con Mobile Safari o Mobile Chrome il reindirizzamento non sembra funzionare. Esiste un output speciale per la lingua accettata per i browser per dispositivi mobili che devo prendere in considerazione?

Aggiornamento: Dopo un po 'di più di debug ho scoperto questo:

  • Safari Mobile visualizza la lingua corretta quando l'eco HTTP_ACCEPT_LANGUAGE ma non reindirizzamento.
  • Mobile Chrome (solo iOS, funziona su Android) non visualizza la lingua corretta (il valore predefinito è "en").
  • iOS analizza i dati dell'intestazione http in un ordine diverso, confronta iOS Chrome (en-US, en; q = 0.8, sv; q = 0.6) e OSX Chrome (sv, en-US; q = 0.8, en; q = 0,6).
+0

Echo il 'HTTP_ACCEPT_LANGUAGE' dal tuo dispositivo mobile è lì? – chris85

+0

Mi dispiace, ho dimenticato di dirlo - echeggiare questo mi dà "en" come risultato sia per Mobile Safar che per Mobile Chrome (iOS 8). –

+0

Sembra che 'HTTP_ACCEPT_LANGUAGE' non funzioni sui dispositivi mobili. Puoi chiedere all'utente la loro lingua o provare qualche altro metodo quando l'UA è mobile. – chris85

risposta

1

UPDATE per la mia risposta precedente

Il HTTP_ACCEPT_LANGUAGE viene impostato tramite header e darà valori diversi per tutti. Nel mio caso sono in Sud America su una configurazione del computer in inglese, quindi le mie intestazioni lang hanno impostazioni in inglese e spagnolo con una preferenza per l'inglese.

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 
} 

Nel mio caso, tutti i dispositivi reindirizzano correttamente. La mia ipotesi è che ci sia qualcosa che accade sulla logica che chiama redirect()

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

e la var sessione di bypassa la logica di reindirizzamento. Prova il codice qui sopra e cancella tutti i cookie e le sessioni da tutti i dispositivi in ​​modo che la variabile $_SESSION['language'] impostata durante il test non comprometta i risultati. Facci sapere cosa succede nella tua parte.

4

Prova questo e fateci sapere l'uscita si prega

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 
} 
+0

Ok. L'output non è nulla (stesso browser, iOS8). –

+0

Cordiali saluti, posso ottenere l'output correttamente su Android (utilizzando il browser mobile Chrome o nativo Android). –

+0

Errore di sintassi 'die ('Posizione predefinita)' manca la citazione di chiusura. – chris85

1

Questo funziona bene sul mio browser desktop e dispositivi mobili. Anch'io stavo riscontrando problemi di sessione solo sui dispositivi e, più spesso, mi stavo affidando a una variabile di sessione vuota per soddisfare i requisiti della mia condizione, quando in realtà la variabile era ancora esistente o semplicemente non era presente un'istanza session_id().

? Reset cancella la sessione.

Inoltre, eseguirà il reindirizzamento se la lingua è cambiata.

<?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']); 
    } 
?> 
+1

'substr ($ _SERVER [" HTTP_ACCEPT_LANGUAGE "], 0,2)' è esattamente lo stesso codice utilizzato dall'OP che non funziona per i suoi casi mobili. – Drakes

+1

Questo non è il problema con il reindirizzamento, che è il problema. Nel caso OP la variabile $ language è assegnata "http://www.example.com/" se il dispositivo non riesce a restituire substr ($ _SERVER ["HTTP_ACCEPT_LANGUAGE"], 0,2). Non ha senso rimuoverlo. – pokeybit

0

Davvero non dovresti affidarti ai primi due personaggi. Hai davvero bisogno di fare affidamento sull'ispezione dell'intera stringa e sulla comprensione della migliore scelta linguistica. Questi valori stringa hanno un significato specifico e, ad esempio, in uno dei casi in cui si verificano le stringhe "problematiche", si farebbe effettivamente il comportamento più appropriato per mostrare en anziché sv. Si può ovviamente scrivere la logica di spezzare la lingua accettare, indagare gli elementi costitutivi, e prendere i provvedimenti opportuni, ma si potrebbe anche considerare l'utilizzo di qualcosa come:

http_negotiate_language

di fare questo per voi. Probabilmente ci sono dozzine di altri script disponibili dalla ricerca rapida su google per lavorare davvero con questa intestazione in un modo più appropriato rispetto ai soli due primi caratteri.

Inoltre, è possibile controllare domanda simile qui: Using the PHP HTTP_ACCEPT_LANGUAGE server variable

1

Si dovrebbe davvero darci esempi di ciò che è il valore di $_SERVER["HTTP_ACCEPT_LANGUAGE"] per i tre casi.

In ogni caso, si noti che in base allo RFC2616 of HTTP/1.1, la scelta di una lingua è molto più complicata rispetto alla semplice acquisizione dei primi due caratteri dell'intestazione.

Ogni lingua-gamma può essere dato un valore di qualità associata che rappresenta una stima della preferenze dell'utente per le lingue specificati da tale intervallo. Il valore di qualità è impostato su "q = 1". Ad esempio,

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

significherebbe: "Preferisco danese, ma accetterò l'inglese britannico e altri tipi di inglese."

Nulla dice che quelle intestazioni sono ordinate, né che la lingua preffered dell'utente è la prima nell'elenco. E la configurazione della lingua potrebbe anche non essere configurata nel browser o nel sistema operativo.

Idealmente, per selezionare il miglior linguaggio, bisogna analizzare questa intestazione in questo modo:

  • dividere la stringa su virgole
  • Split ogni sottostringa dal carattere virgola
  • Quando un valore numerico non viene fornito, utilizzare il valore predefinito 1,0
  • Ordinare il risultato utilizzando questo valore numerico
  • Confronta questo elenco all'elenco delle lingue disponibili sul tuo sito web e trova il il migliore.
Problemi correlati