I use the following PHP script as index for my website.
This script should include a specific page depending on the browser's language (automatically detected).
This script does not work well with all browsers, so it always includes index_en.php
for any detected language (the cause of the problem is most probably an issue with some Accept-Language header not being considered).
Could you please suggest me a more robust solution?
<?php // Open session var session_start(); // views: 1 = first visit; >1 = second visit // Detect language from user agent browser function lixlpixel_get_env_var($Var) { if(empty($GLOBALS[$Var])) { $GLOBALS[$Var]=(!empty($GLOBALS['_SERVER'][$Var]))? $GLOBALS['_SERVER'][$Var] : (!empty($GLOBALS['HTTP_SERVER_VARS'][$Var])) ? $GLOBALS['HTTP_SERVER_VARS'][$Var]:''; } } function lixlpixel_detect_lang() { // Detect HTTP_ACCEPT_LANGUAGE & HTTP_USER_AGENT. lixlpixel_get_env_var('HTTP_ACCEPT_LANGUAGE'); lixlpixel_get_env_var('HTTP_USER_AGENT'); $_AL=strtolower($GLOBALS['HTTP_ACCEPT_LANGUAGE']); $_UA=strtolower($GLOBALS['HTTP_USER_AGENT']); // Try to detect Primary language if several languages are accepted. foreach($GLOBALS['_LANG'] as $K) { if(strpos($_AL, $K)===0) return $K; } // Try to detect any language if not yet detected. foreach($GLOBALS['_LANG'] as $K) { if(strpos($_AL, $K)!==false) return $K; } foreach($GLOBALS['_LANG'] as $K) { //if(preg_match("/[[( ]{$K}[;,_-)]/",$_UA)) // matching other letters (create an error for seo spyder) return $K; } // Return default language if language is not yet detected. return $GLOBALS['_DLANG']; } // Define default language. $GLOBALS['_DLANG']='en'; // Define all available languages. // WARNING: uncomment all available languages $GLOBALS['_LANG'] = array( 'af', // afrikaans. 'ar', // arabic. 'bg', // bulgarian. 'ca', // catalan. 'cs', // czech. 'da', // danish. 'de', // german. 'el', // greek. 'en', // english. 'es', // spanish. 'et', // estonian. 'fi', // finnish. 'fr', // french. 'gl', // galician. 'he', // hebrew. 'hi', // hindi. 'hr', // croatian. 'hu', // hungarian. 'id', // indonesian. 'it', // italian. 'ja', // japanese. 'ko', // korean. 'ka', // georgian. 'lt', // lithuanian. 'lv', // latvian. 'ms', // malay. 'nl', // dutch. 'no', // norwegian. 'pl', // polish. 'pt', // portuguese. 'ro', // romanian. 'ru', // russian. 'sk', // slovak. 'sl', // slovenian. 'sq', // albanian. 'sr', // serbian. 'sv', // swedish. 'th', // thai. 'tr', // turkish. 'uk', // ukrainian. 'zh' // chinese. ); // Redirect to the correct location. // Example Implementation aff var lang to name file /* echo 'The Language detected is: '.lixlpixel_detect_lang(); // For Demonstration echo "<br />"; */ $lang_var = lixlpixel_detect_lang(); //insert lang var system in a new var for conditional statement /* echo "<br />"; echo $lang_var; // print var for trace echo "<br />"; */ // Insert the right page iacoording with the language in the browser switch ($lang_var){ case "fr": //echo "PAGE DE"; include("index_fr.php");//include check session DE break; case "it": //echo "PAGE IT"; include("index_it.php"); break; case "en": //echo "PAGE EN"; include("index_en.php"); break; default: //echo "PAGE EN - Setting Default"; include("index_en.php");//include EN in all other cases of different lang detection break; } ?>
We can detect requesting browser's language using PHP's super global variable $_SERVER . It is a superglobal variable which holds information about headers, paths, and script locations. It is basically an associative array in PHP which has keys like SERVER_NAME, SERVER_ADDR, REQUEST_METHOD , etc.
First you set $availableLangs the array of the available languages in your app, you may use config\app. php instead of initializing the array in the middleware as I did. If the first language is available in the request language data, it sets the locale, if not, it will search the next one, and so on.
why dont you keep it simple and clean
<?php $lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2); $acceptLang = ['fr', 'it', 'en']; $lang = in_array($lang, $acceptLang) ? $lang : 'en'; require_once "index_{$lang}.php"; ?>
Accept-Language is a list of weighted values (see q parameter). That means just looking at the first language does not mean it’s also the most preferred; in fact, a q value of 0 means not acceptable at all.
So instead of just looking at the first language, parse the list of accepted languages and available languages and find the best match:
// parse list of comma separated language tags and sort it by the quality value function parseLanguageList($languageList) { if (is_null($languageList)) { if (!isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { return array(); } $languageList = $_SERVER['HTTP_ACCEPT_LANGUAGE']; } $languages = array(); $languageRanges = explode(',', trim($languageList)); foreach ($languageRanges as $languageRange) { if (preg_match('/(\*|[a-zA-Z0-9]{1,8}(?:-[a-zA-Z0-9]{1,8})*)(?:\s*;\s*q\s*=\s*(0(?:\.\d{0,3})|1(?:\.0{0,3})))?/', trim($languageRange), $match)) { if (!isset($match[2])) { $match[2] = '1.0'; } else { $match[2] = (string) floatval($match[2]); } if (!isset($languages[$match[2]])) { $languages[$match[2]] = array(); } $languages[$match[2]][] = strtolower($match[1]); } } krsort($languages); return $languages; } // compare two parsed arrays of language tags and find the matches function findMatches($accepted, $available) { $matches = array(); $any = false; foreach ($accepted as $acceptedQuality => $acceptedValues) { $acceptedQuality = floatval($acceptedQuality); if ($acceptedQuality === 0.0) continue; foreach ($available as $availableQuality => $availableValues) { $availableQuality = floatval($availableQuality); if ($availableQuality === 0.0) continue; foreach ($acceptedValues as $acceptedValue) { if ($acceptedValue === '*') { $any = true; } foreach ($availableValues as $availableValue) { $matchingGrade = matchLanguage($acceptedValue, $availableValue); if ($matchingGrade > 0) { $q = (string) ($acceptedQuality * $availableQuality * $matchingGrade); if (!isset($matches[$q])) { $matches[$q] = array(); } if (!in_array($availableValue, $matches[$q])) { $matches[$q][] = $availableValue; } } } } } } if (count($matches) === 0 && $any) { $matches = $available; } krsort($matches); return $matches; } // compare two language tags and distinguish the degree of matching function matchLanguage($a, $b) { $a = explode('-', $a); $b = explode('-', $b); for ($i=0, $n=min(count($a), count($b)); $i<$n; $i++) { if ($a[$i] !== $b[$i]) break; } return $i === 0 ? 0 : (float) $i / count($a); } $accepted = parseLanguageList($_SERVER['HTTP_ACCEPT_LANGUAGE']); var_dump($accepted); $available = parseLanguageList('en, fr, it'); var_dump($available); $matches = findMatches($accepted, $available); var_dump($matches);
If findMatches
returns an empty array, no match was found and you can fall back on the default language.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With