Detect browser language and redirect

Asked

Viewed 4,269 times

5

I am using Wordpress and wanted to redirect my page to the "/br/","/es/" versions, when the browser language is one of these and when it is not it stay in the default page, that is the ". with".

I tried to use that code, but it didn’t work:

function idiomaUsuario(){
    $idioma = substr($_SERVER["HTTP_ACCEPT_LANGUAGE"], 0, 2);
    return $idioma; 
}


    function redirecionaPaginaIdioma($idioma){
        switch($idioma){
            case 'pt': //Caso seja português
                header('Location: http://www.seusite.com.br/pt/');
                break;
            case 'es': //Caso seja espanhol
                header('Location: http://www.seusite.com.br/es/');
                break;
            default:
                header('Location: http://www.seusite.com.br/en/');
                break;
        }
    }

I don’t know if it changes anything do this with PHP or JS, but any solution serves.

Note: I put this code at the beginning of Index.php of the Wordpress theme.

  • Where did you put the method calls?

  • In this code is as methods, but when I tested I took and left straight without the functions.

  • Ever tried using a plugin? I use Transposh. Very good.

  • @Marcosregis I believe that this Plugin makes the translation of the site, however I am making a site with three different languages and with different content. With this Plugin you indicated me I could not put together differentiated pages for each language. (Or even could, but would have to work with some conditions, so that certain content only appear according to language, however is a dynamic site, everything needs to be easily changed via Wordpress.)

  • It allows both machine translation and content management in other languages. I find it easier to use it to manage which language the user wants to see for example on the main page and for each page with different language create the site specific map of the language using (it already comes with some ready as the flags) in the permalink what you want. It’s just a suggestion. It has its advantages and disadvantages.

  • @Marcosregis My current problem, in addition to redirecting (which is already almost solved), is how to change wordpress menus depending on the language. I can not put a different menu for each page, but I believe that I will try to do changing the theme, but this plugin would do it?

Show 2 more comments

3 answers

6


This solution posed in the question does not go very well by the way in which the HTTP_ACCEPT_LANGUAGE works. It returns a string in this format:

en-US,en;q=0.8,pt-BR;q=0.6,pt;q=0.4

indicating the user’s preference order for the parameter q= (technically called quality factor), and as you may notice, you may have more than one language (general or regionalized) in the list.

The following is interpreted in the example line: "I accept US English, and if not, "general" English (weight 0.8). In the absence of these, it may be Brazilian Portuguese (weight 0.6), and finally "general Portuguese" (weight 0.4).

The problem is that there is no guarantee that this list will come in order of importance. I’ve never seen out of order, but the specification clearly states that the order is given by quality factor and not by textual position.

Also, it may happen that the first one on the list is a language that you don’t have available, but the second or third one might be. In this case, as the question code only takes the first one on the list, there is no way it will solve your problem.

That said, let’s get to the solution.


Function to do the parse string

Based on what I mentioned at the beginning of the answer, I have worked out a basic function that can serve as a starting point for what you need:

$acceptLanguage = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
$langs = array();
foreach( explode(',', $acceptLanguage) as $lang) {
    $lang = explode(';q=', $lang);
    $langs[$lang[0]] = count($lang)>1?floatval($lang[1]):1;
}
arsort($langs);

Basically what she does is break the string original by commas, using the explode, and keeping in a array in language=>weight format. Once this is done, the arsort orders our list starting at the highest weight and going down to the lowest.

Once the parse, we need to see what we have available to serve the user. For this part, here is a solution:

$ourLanguages = array('pt-BR'=>'pt','pt'=>'pt','es'=>'es');

$choice = 'pt'; //Caso nenhuma outra sirva
foreach($langs as $lang=>$q) {
   if(in_array($lang,array_flip($ourLanguages))) {
      $choice=$ourLanguages[$lang];
      break;
   }
}

header("Location: http://www.example.com/$choice/");

The working principle is simple, we test one by one of the client’s languages until we find one that fits. To completely solve the problem, we use the format linguagem do cliente => nosso mapeamento, so you can say that pt-BR should be understood simply as pt, which is the part you use in the URL.

You can see a functional example on IDEONE.


Just for the record, there’s a PECL extension that handles this, but I’d say it’s more of a cast than our solution: http://php.net/http_negotiate_language

  • thanks for the great response, but I failed to do the redirect, I tested with a echo and worked, however the header("Location: http://www.example.com/$choice/"); seems not to have worked. You know what can be?

  • My mistake, for case does not work redirecting to someone with same doubt, in Wordpress within the page.php you need to put the code inside the first PHP(Template Name) tag, because if there is some html tag or some "echo" or "print" before this function, it will not work.

  • @Giovannibernini we have some answers here at Sopt that explain this well, it’s not just about Location. Any and all header must be issued before the content of the page. It is a valid comment, more related to the nature of header() than the language problem itself. If I find one, link here. You could get around with ob_start(), but I find a dirty solution.

1

You can get this setting using the class Locale library lntl, which is available from php5.3.

<?php

echo 'Disponiveis: '. $_SERVER['HTTP_ACCEPT_LANGUAGE'] .'<br>';
$lang = substr(Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']), 0, 2);

if($lang === 'pt'){
    echo 'Olá amigo';
}else if($lang == 'es'){
    echo 'Hola amigo';  
}else if($lang == 'en'){
        echo 'Hello friend';
}else if($lang == 'de'){
    echo 'hallo Freund';
}

You can use firefox as a test to change your language preference. Go to the Tools>options> content tab menu. In languages change language leave at the top by Spanish exem and see how the code works.

Example - Phpfiddle

1

There is a very good translation plugin for Wordpress called Transposh.

With it is possible:

  • Dynamically translate any page of the site using Google, Bing, Yandex among others
  • use an existing page as a translation of another
  • Mark not to translate a particular excerpt or even the entire page, avoiding machine translation
  • Edit the translation directly into the site’s final HTML.
  • Display language flags allowing the user to view the site in any language
  • Generate links in the domain style/xx/page where xx stands for language as shown in HTTP_ACCEPT_LANGUAGE

More details on http://transposh.org/pt/faq/

I also recommend to make a donation if you like the plugin

  • Usar uma página já existente como tradução de outra That’s exactly what I need, I’m going to do a search here in the documentation to know how to do.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.