This solution put in the question does not work very well for how 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
that indicates the order of preference of the user by the parameter q=
(technically called quality factor ), and as you can see, you can have more than one language (general or regionalized) in the list .
The following line is interpreted in the example line: "I accept US English, and if not," general "English (weight 0.8). last, "general" Portuguese (weight 0.4).
The problem is that nothing guarantees that this list will come in the order of importance. I've never seen out of order, but the specification clearly states that the order is given by the quality factor and not by the textual position.
In addition, the first one on the list may be a language you do not have available, but the second or third language may be. In this case, as the question code takes only the first one from the list, it does not really have how to solve your problem.
That said, let's get to the solution.
Function to parse string
Based on what I mentioned at the beginning of the answer, I've developed 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 it does is break the original string with the commas, using explode
, and saving in array in the format 'language => weight'. Once this is done, arsort
sorts our list starting with the largest weight and going to the lowest.
Once parse is done, 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 principle of operation is simple, we will test one of one of the customer's languages until we find one that works. To fully resolve the problem, we use the linguagem do cliente => nosso mapeamento
format, 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 working example in IDEONE .
Just to be noted, it has a PECL extension that deals with this, but I'd say it's more ingrained than our solution: link