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: 14227
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

Michael_G
Posts: 203
Joined: Thu Feb 18, 2016 11:01 pm
Contact:

Re: Autodetect browser language & redirect

Post by Michael_G » Wed Sep 11, 2024 10:59 pm

Hello Christoph,

I dug up this thread and tried your workaround.
Conclusion:
Your PHP snippet is not quite complete:

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(); 
Something is still missing to intercept an infinite loop.
Could you please take another look and add it?
Thank you very much!
Ciao
Michael

Let's Encrypt!

lck
Posts: 3108
Joined: Wed Mar 23, 2011 11:43 am
Contact:

Re: Autodetect browser language & redirect

Post by lck » Thu Sep 12, 2024 5:16 pm

Ich habe den Code von Christoph für die userfuncs.php mal getestet, lokal unter Xampp mit PHP 8.2.12 und einem jungfräulichen XH 1.7.6.
Bei mir funktioniert es. Standardsprache en, Zusatzsprachen de, fr und it.
Rufe ich die Seite https://www.example.com/ auf und die Browsersprache ist de wird auf https://www.example.com/de weitergeleitet, dementsprechend auch bei den anderen Browsersprachen.
„Bevor du den Pfeil der Wahrheit abschießt, tauche die Spitze in Honig!“   👉 Ludwig's XH-Templates for MultiPage & OnePage

Michael_G
Posts: 203
Joined: Thu Feb 18, 2016 11:01 pm
Contact:

Re: Autodetect browser language & redirect

Post by Michael_G » Thu Sep 12, 2024 8:35 pm

lck wrote:
Thu Sep 12, 2024 5:16 pm
Ich habe den Code von Christoph für die userfuncs.php mal getestet, lokal unter Xampp mit PHP 8.2.12 und einem jungfräulichen XH 1.7.6.
Bei mir funktioniert es. Standardsprache en, Zusatzsprachen de, fr und it.
Rufe ich die Seite https://www.example.com/ auf und die Browsersprache ist de wird auf https://www.example.com/de weitergeleitet, dementsprechend auch bei den anderen Browsersprachen.
Danke fürs Testen, Ludwig,
habe es jetzt auf meiner kleinen Website online getestet, da dient wie auf der großen Website „at” als Standardsprache, damit ich „de” und „en” mit Sprachordner quasi als Zweitsprachen nutzen kann (wird Besuchern nicht als „at”/Österreich präsentiert, da es nur als Introseite (de|en) dient, von der zu /de/ oder /en/ gewechselt werden kann).

Sobald ich auf https://example.com/en/ wechseln möchte, erscheint vom Browser der Hinweis auf die Endlosschleife und in der Adresszeile steht hinter der Domain /en/de/de/de/de/de/de/de/de/de/de/de/de/de/de/de/de/de/de/de/de/ (ginge endlos weiter, aber Safari bemerkt die Endlosschleife und beendet das Trauerspiel mit der Fehlermeldung).

Inzwischen auch noch mit Googles Chrome getestet, hier von Root (Introseite https://example.com) gewechselt auf de:
Resultat: https://example.com/de/at/at/at/at/at/a ... /at/at/at/
Chrome bemerkt die Endlosschleife und beendet das Trauerspiel mit der Fehlermeldung.

In Chrome habe ich als einzige Browsersprache „Dänisch” hinterlegt, damit ich überhaupt die Introseite geladen bekomme, denn ansonsten wird entweder durch das PHP-Script aus userfuncs.php /de/ oder /en/ geladen.
Oder oder ein Apache-Script in der .htaccess-Datei erledigt das (fehlerfrei, aber ich wollte jetzt mal eine .htaccess-unabhängige Lösung probieren, daher meine Frage hier jetzt im Forum).

Mein Anliegen hier ist nicht dringend, aber für XH-Nutzer, die sich mit der .htaccess-Datei nicht auskennen, gar keinen Apache–Webserver nutzen oder einfach alles innerhalb von XH steuern wollen, ist eine solche Lösung sicher interessant.

Nachtrag: habe nochmal getestet und mir war noch eingefallen, dass ich ins Sprachordnerverzeichnis meiner Websites immer eine kleine .htaccess-Datei einfüge, um die sprachlich angepassten Fehlerseiten zu nutzen:

Code: Select all

DefaultLanguage de
ErrorDocument 403 /de/?403
ErrorDocument 404 /de/?404
ErrorDocument 410 /de/?410
– Das war wohl der Grund, warum es eine Endlosschleife gibt, aber wenn ich diese .htaccess-Datei weglasse, funktioniert es trotzdem nicht fehlerfrei, denn dann wird nach Anklicken der Flagge zum Sprachwechsel nicht korrekt umgeleitet:
Von Homepage (Standardsprache: Englisch) zu Deutsch: Umleitung auf example.com/de/en/ anstatt auf example.com/en/.

Und wenn Browsersprachen hinterlegt sind (Deutsch als Standard), dann lädt er nur example.com/de/ und Mausklick auf die englische Flagge (verlinkt mit root = EN) bewirkt … nichts.
Last edited by Michael_G on Sun Sep 15, 2024 9:20 pm, edited 2 times in total.
Ciao
Michael

Let's Encrypt!

olape
Posts: 2948
Joined: Fri Mar 13, 2015 8:47 am
Contact:

Re: Autodetect browser language & redirect

Post by olape » Fri Sep 13, 2024 5:40 pm

Michael_G wrote:
Thu Sep 12, 2024 8:35 pm
Sobald ich auf https://example.com/en/ wechseln möchte, erscheint vom Browser der Hinweis auf die Endlosschleife und in der Adresszeile steht hinter der Domain /en/de/de/de/de/de/de/de/de/de/de/de/de/de/de/de/de/de/de/de/de/ (ginge endlos weiter, aber Safari bemerkt die Endlosschleife und beendet das Trauerspiel mit der Fehlermeldung).
Nun weiß ich ja, das du in dieser Richtung sehr viel experimentierst.
Bist du sicher, dass da nicht noch irgendwas anderes reinspielt?
Hast du mal mit einer wirklich sauberen Installation getestet?
Gruß Olaf, Plugins for CMSimple_XH

Ich habe schon lange den Verdacht, dass so viele so eifrig auf Gender, Trans und Queer machen:
Weil sie für das Fachliche ganz einfach zu doof sind.

Michael_G
Posts: 203
Joined: Thu Feb 18, 2016 11:01 pm
Contact:

Re: Autodetect browser language & redirect

Post by Michael_G » Sat Sep 14, 2024 8:03 pm

Ja, gleiches Ergebnis, wenn ich unverändertes XH v1.7.6 verwende.

Achte beim Testen mal darauf, keine (!) der Sprachen im Browser zu hinterlegen, welche Du verwendest.
Default-Sprache in XH, da nichts verändert: Englisch

Habe lediglich den 2lang-Ordner in „de” umbenannt, im content-Ordner einen Unterordner „de” angelegt und da hinein den content-Ordner aus 2lang verschoben (wie man das eben so macht, wenn man XH zweisprachig einrichtet/beginnt).

Nachtrag: habe nochmal getestet und mir war noch eingefallen, dass ich ins Sprachordnerverzeichnis meiner Websites immer eine kleine .htaccess-Datei einfüge, um die sprachlich angepassten Fehlerseiten zu nutzen (hier Beispiel für DE-Version):

Code: Select all

DefaultLanguage de
ErrorDocument 403 /de/?403
ErrorDocument 404 /de/?404
ErrorDocument 410 /de/?410
– Das war der Grund für die Endlosschleife, denn eigentlich wird nach Anklicken der Flagge zum Sprachwechsel nicht korrekt umgeleitet:
Von Homepage (Standardsprache: Englisch) zu Deutsch: Umleitung auf example.com/de/en/ anstatt auf example.com/en/.
Homepage zeigt mit Default-Template oben rechts die deutsche Flagge.
Last edited by Michael_G on Sun Sep 15, 2024 9:24 pm, edited 1 time in total.
Ciao
Michael

Let's Encrypt!

olape
Posts: 2948
Joined: Fri Mar 13, 2015 8:47 am
Contact:

Re: Autodetect browser language & redirect

Post by olape » Sat Sep 14, 2024 8:22 pm

Michael_G wrote:
Sat Sep 14, 2024 8:03 pm
Achte beim Testen mal darauf, keine (!) der Sprachen im Browser zu hinterlegen, welche Du verwendest.
Default-Sprache in XH, da nichts verändert: Englisch
Ich selber habe das gar nicht getestet.
Der Hinweis war nur so eine Idee, weil du ja oft in der Richtung unterwegs warst / bist.

Mal schauen, wenn ich Zeit, Lust und Laune habe.
Allerdings stehe ich dem autom. Weiterleiten eh sehr skeptisch gegenüber.
Gruß Olaf, Plugins for CMSimple_XH

Ich habe schon lange den Verdacht, dass so viele so eifrig auf Gender, Trans und Queer machen:
Weil sie für das Fachliche ganz einfach zu doof sind.

Michael_G
Posts: 203
Joined: Thu Feb 18, 2016 11:01 pm
Contact:

Re: Autodetect browser language & redirect

Post by Michael_G » Sat Sep 14, 2024 8:58 pm

Hallo Olaf, hallo Ludwig,

bei mir wird nur auf die „Zweitsprache”/Sprachordner /de/ bzw. /en/ weitergeleitet, wenn der Besucher bei sich die Browsersprache entsprechend hinterlegt hat.
Sonst empfängt meine Besucher die Introseite (root).

Ich dachte früher, dass Google selbst (weil Englisch) Seiten nur aus der englischsprachigen Perspektive prüft oder sich eher davon leiten lässt. Das ist aber nicht der Fall.

Googles Bots haben keine Browsersprache hinterlegt, werden nicht von sprachbedingten Weiterleitungen verwirrt und diese werden auch nicht bestraft – im Gegenteil! Wenn hreflang + canonical korrekt implementiert sind, freut das Google.

Bisher habe ich zur Spracherkennung diese .htaccess-Lösung implementiert, die hervorragend funktioniert:

Code: Select all

#Browsersprache seit 28.03.2022 | perfekt: 11.08.2024
	RewriteCond %{HTTP:Accept-Language} ^((?!en).)*de
	RewriteCond %{QUERY_STRING}	!(403|404|410|edit|file(browser)?|login|news(01|02|03)|normal|sysinfo)	[NC]
	RewriteRule ^$ de/	[R=301,L]
	RewriteCond %{HTTP:Accept-Language} ^((?!de).)*en
	RewriteCond %{QUERY_STRING}	!(403|404|410|edit|file(browser)?|login|news(01|02|03)|normal|sysinfo)	[NC]
	RewriteRule ^$ en/	[R=301,L]
Dieses Script stammt von einem Übersetzungsbüro, welches einen Artikel zu dem Thema veröffentlicht hatte.

Ich hatte das nur um die beiden Zeilen mit „RewriteCond %{QUERY_STRING} !…” ergänzt, damit ich als Admin weiterhin bei Bedarf auch die Introseite editieren kann (würde sonst immer auf Browsersprache umschalten).
Und am 11.08.2022 nur noch 403|404|410 hinzugefügt, damit Weiterleitungen von Fehlerseiten im root auf /de/ oder /en/ unterbunden werden (gäbe sonst nach z. B. ?404 noch eine WL auf /de/?404).

Ich habe meine Testversion gezippt und kann sie bei Interesse gern zur Verfügung stellen.
Dann kann das jeder selbst sehen, dass es eine unveränderte XH-Version aus dem XH-Repository ist.

Wie bereits erwähnt: für mich persönlich ist es nicht wichtig, ob die PHP-Version funktioniert oder nicht, aber da alle XH-Entwickler so darauf Wert legen, dass XH auch ganz ohne .htaccess-Lösungen alles kann und das für Anfänger auch sehr gut ist, hatte ich diese eben auch mal ausprobiert …
Für den Test habe ich auch keine .htaccess-Datei im Root verwendet. ;-)
Ciao
Michael

Let's Encrypt!

Post Reply