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
Where did you put the method calls?
– Marcos Regis
In this code is as methods, but when I tested I took and left straight without the functions.
– Giovanni Bernini
Ever tried using a plugin? I use Transposh. Very good.
– Marcos Regis
@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.)
– Giovanni Bernini
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.
– Marcos Regis
@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?
– Giovanni Bernini
Let’s go continue this discussion in chat.
– Marcos Regis