Autodetect browser language & redirect

General questions about CMSimple
Post Reply
Nicky
Posts: 164
Joined: Sun Feb 08, 2009 9:50 am
Location: Antwerp, Belgium

Autodetect browser language & redirect

Post by Nicky » Mon Mar 11, 2013 9:02 pm

I use 3 languages on my website, so it would be nice to use the following javascript to autodetect user's browser language and redirect him to the right language.

Default language is Dutch (nl), and I also have an English and French version which are located in the usual /en and /fr folders.
German is also mentioned, but this should go to the English version, as I tried to specify in the script.
---------------------------------------------------------------------------------------
Here's the script:

<script>
/*
Browser Language Redirect script- By JavaScript Kit
For this and over 400+ free scripts, visit http://www.javascriptkit.com
This notice must stay intact
*/

//Enter ISO 639-2 letter Language codes to detect (see: http://www.w3.org/WAI/ER/IG/ert/iso639.htm):
var langcodes=new Array("nl", "en", "fr", "de", "default")

//Enter corresponding redirect URLs (last one is for default URL):
var langredirects=new Array("index.php", "/en/", "/fr/", "/en/", "index.php")

var languageinfo=navigator.language? navigator.language : navigator.userLanguage
var gotodefault=1

function redirectpage(dest){
if (window.location.replace)
window.location.replace(dest)
else
window.location=dest
}

for (i=0;i<langcodes.length-1;i++){
if (languageinfo.substr(0,2)==langcodes){
redirectpage(langredirects)
gotodefault=0
break
}
}

if (gotodefault)
redirectpage(langredirects[langcodes.length-1])

</script>
---------------------------------------------------------------------------------------

This seems to work, except for the 'Default' language.. I have tested the script by setting my browser to first English and then French language. The script reacts as it should, when it's approached with my browser in English, it redirects to http://www.mywebsite.com/en and the English version appears. Same done for French, also successful.

However, when I open the website with my browser set to Dutch, the url switches to http://www.mywebsite.com/index.php and loops infinite without loading anything.

It probably has something to do with the way I have configured the script, where I defined "index.php" as the default. Could there be a solution or is this script only possible if all 3 languages are in separate folders, and not structured as usual in cmsimple (default language directly on the root and extra languages in separate folders).

Hope someone is interested in the script and can help my out.
Thanks in advance.

cmb
Posts: 14225
Joined: Tue Jun 21, 2011 11:04 am
Location: Bingen, RLP, DE
Contact:

Re: Autodetect browser language & redirect

Post by cmb » Mon Mar 11, 2013 9:56 pm

Hi Nicky,

just try the following changes:

Code: Select all

var langcodes=new Array("en", "fr", "de", "nl")

var langredirects=new Array("/", "/en/", "/fr/", "/en/", "/")
Basically it's sufficient to handle "nl" as the default, and index.php is not necessary (results in nicer URLs). But this results in the redirect loop also. It would be possible to modify the script to not recurse, but please note the following remark.

I see several problems with this approach:
  • If JavaScript is disabled or not available in the browser, nothing happens. Amongs others this is a problem with bots, which usually do not evalutate JavaScript.
  • If JavaScript is enabled, the redirect takes place after the requested page was delivered. This is a bit wasteful.
  • It's not possible to manually override the language redirection. That's okay, if the site is fully localized (i.e. all pages are translated to all languages, and are up-to-date); otherwise the visitor should be able to switch the language manually.
  • Deep links from outside are lost; the visitor always lands on the start page of his language.
  • To detect the client's language only the first to letters of navigator.language resp. navigator.userLanguage are taken into account. navigator.language may take the value of the Accept-Language HTTP Header (this is at least so for recent Chrome and Firefox). But this value is actually more complex than just specifying the desired language. There can be several languages given, each with a weight, which to prefer, and it's even possible, that the preferred language is not the first in the list. Consider e.g. this Accept-Language header: "de;1.0,fr:0.9" (could be someone from the Saarland; a native German speaker, who speaks French very good). He will be redirected to "en" even if he would be happy to read the site in French.
  • The user can't navigate the site. If he browses to /?Second_page, he'll be redirected to / (i.e. the start page) ;)
On Friday I've experimented a bit with a small add-on, that should do this language dependent redirect server side. It offers a variant of languagemenu() which will force the chosen language. It should cater for the Accept-Language header (currently it does the same as the given JS script ;)). And it takes into account which page was selected, so it could redirect the visitor directly to this page. And that's were I stopped: usually that doesn't work, as the page might be "Welcome" in English and "Bienvenue" in French. To make this possible, there is Multilang_XH, but it is abandoned, and the author didn't respond to my mail. So quite I while ago I developed an alternative: Polyglott_XH, which still runs as ALPHA version on my webspace: http://3-magi.net/. Actually I consider to add the language dependent redirect to Polyglott_XH, but until I can publicly release a BETA may take some time.

So you can try it as it is. Just put the following code to userfuncs.php:

Code: Select all

<?php

function Autolang_languages()
{
    global $pth, $cf;

    $languages = array();
    $dn = $pth['folder']['base'];
    $dh = opendir($dn);
    while (($fn = readdir($dh)) !== false) {
        if (is_dir($dn . $fn) && preg_match('/^[A-z]{2}$/', $fn)) {
            $languages[] = $fn;
        }
    }
    if ($dh) {
        closedir($dh);
    }
    sort($languages);
    array_unshift($languages, $cf['language']['default']);
    return $languages;
}

function user_language()
{
    if (isset($_COOKIE['autolang_choice'])) {
        $language = $_COOKIE['autolang_choice'];
    } else {
        $language = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2); // TODO
    }
    return $language;
}

function Autolang_menu()
{
    global $pth, $sl;

    $items = array();
    $languages = Autolang_languages();
    foreach ($languages as $i => $language) {
        $fn = $pth['folder']['flags'] . $language . '.gif';
        $label = is_readable($fn)
            ? tag('img src="' . $fn . '" alt="' . $language . '"')
            : "[$language]";
        $items []= '<a href="' . CMSIMPLE_ROOT . ($i > 0 ? "$language/" : '')
            . '?autolang_force=' . $language . '">' . $label . '</a>';
    }
    return implode(' ', $items);
}


function Autolang()
{
    global $sn, $sl;

    if (isset($_GET['autolang_force'])) {
        setcookie('autolang_choice', $_GET['autolang_force'], 0, CMSIMPLE_ROOT);
        header("Location: $sn", true, 301);
        exit();
    }

    $languages = Autolang_languages();
    $userLang = user_language();

    if (!$userLang) {
        return;
    }

    if (!in_array($userLang, $languages)) {
        $userLang = $languages[0];
    }
    if ($userLang != $sl) {
        header("Location: $sn$userLang/", true, 303);
        exit;
    }
}

Autolang(); 
That may be a working replacement for the JavaScript script.

Christoph
Christoph M. Becker – Plugins for CMSimple_XH

Post Reply