DokuWiki

It's better when it's simple

User Tools

Site Tools


tips:browserlanguagedetection

This is an old revision of the document!


Browser Language Detection

To have the Wiki language being select based on available languages set on user's browser, perform these actions:

Tip

Edit conf/dokuwiki.php, and replace

$conf['lang']        = 'en';              //your language

with

// $conf['lang']        = 'en';              //your language
$conf['lang_default'] = 'pt'; // default language
$conf['lang_enabled'] = array('pt', 'es', 'de', 'en');

Note: sort the array $conf['lang_enabled'] by first language to match first.


Edit inc/common.php, and add at the bottom, before the ?>

// DWD Modify -> Add: Set Language from Browser Language Settings.
  /*
  #=============================================================================#
  # Function: detect_browser_language()                                         #
  #-----------------------------------------------------------------------------#
  # Purpose: This function detects the user browser language.                   #
  #   If no valid language is found then it returns the default content language#
  # that is set on the configuration file                                       #
  #                                                                             #
  # Arguments:                                                                  #
  # Optionals:                                                                  #
  # Result: returns a string with the content language.                         #
  #                                                                             #
  #=============================================================================#
  */
  function detect_browser_language() {
    global $conf;
 
    $languages = preg_replace('/(;q=\d+.\d+)/i', '', getenv('HTTP_ACCEPT_LANGUAGE'));
 
    $bol_language_detected = false;
 
    // Check if browser language is compatible with pre-defined content languages.
    foreach ($conf['lang_enabled'] as $tmp_arr_language) {
      if (preg_match('/' . $tmp_arr_language . '/i', $languages)) {
        $tmp_str_language_detected = $tmp_arr_language;
        $bol_language_detected = true;
        break;
      }
    } // ForEach pre-defined content language.
 
    // If browser is set with compatible language return matching content path
    // Else return default content language path.
    if ($bol_language_detected) {
      return $tmp_str_language_detected;
    } else {
      return $conf['lang_default'];
    } // If browser set with compatible language.
  } // detect_browser_language
// DWD Modify End.

Edit inc/parser.php, and replace

require_once("lang/en/lang.php");
require_once("lang/".$conf['lang']."/lang.php");

with

require_once("lang/en/lang.php");
// DWD Modify -> Add: Set Language from Browser Language Settings.
$conf['lang'] = detect_browser_language();
// DWD Modify End.
require_once("lang/".$conf['lang']."/lang.php");

Edit doku.php, and replace

  require_once("lang/en/lang.php");
  require_once("lang/".$conf['lang']."/lang.php");

with

  require_once("lang/en/lang.php");
  // DWD Modify -> Add: Set Language from Browser Language Settings.
  $conf['lang'] = detect_browser_language();
  // DWD Modify End.
  require_once("lang/".$conf['lang']."/lang.php");

Edit media.php, and replace

require_once("lang/en/lang.php");
require_once("lang/".$conf['lang']."/lang.php");

with

require_once("lang/en/lang.php");
// DWD Modify -> Add: Set Language from Browser Language Settings.
$conf['lang'] = detect_browser_language();
// DWD Modify End.
require_once("lang/".$conf['lang']."/lang.php");

Discussion

I prefer this new function rather than the old one because it is more precise in parsing the browser acceptable languages and because it either returns a language found by match or the default language. Although it seems the former code was also fixed to return the same results. It also doesn't convert the HTTP_ACCEPT_LANGUAGE to lowercase, which I didn't see as necessary. – 2004.11.03.

:?: Has anyone been using this code, and if such with what results?

Some things to consider:

  1. All languages need to use the same language encoding or you will break things most certainly.
  2. The english language file should be included always before including any other language as this is the only file which is complete for sure
  3. store the selected language in the session perhaps …

I'll think about to include this idea in DokuWiki. Andi

If you add this in DokuWiki please make all UTF-8, that would save a lot of headache Clemens

It would be a wonderful idea! Joaquim

I think this way should be much better to choose language

fredrik
$languages = split(',', preg_replace('/(;q=\d+.\d+)/i', '', getenv('HTTP_ACCEPT_LANGUAGE')));
$bol_language_detected = false;
 
// Check if browser language is compatible with pre-defined content languages.
foreach ($languages as $tmp_arr_language) {
  if (in_array($tmp_arr_language, $conf['lang_enabled'])) {
    $tmp_str_language_detected = $tmp_arr_language;
    $bol_language_detected = true;
    break;
  }
} // ForEach pre-defined content language.
Fredrik, why the 3 changes you suggest make the code better, can you please elaborate on it?

* using split with preg_replace instead of just preg_replace.

  • loop for each $languages instead of $conf['lang_enabled'].
  • check if in_array instead of preg_match.

José Carlos Monteiro 03.12.2004 00:29

And what happens if the user has set 2 prefered languages for example us_uk and us with different weights, the first one being more preffered. We don't have translation for the first lang but have for the second. Will it stay on en or will pick the not so preffered translation? — Zeridon 28.06.2225


A quick hack (and a dirty one) for passing the language by URL to the session: In this way you can call eg http://localhost/dokuwiki/doku.php?plang=de

common.php

if (isset($_GET['plang'])){
    $_SESSION['plang']=$_GET['plang'];
} 

init.php

//comment the regular language setting
//require_once(DOKU_INC.'inc/lang/'.$conf['lang'].'/lang.php');
 
// and insert after the session_start line
require_once(DOKU_INC.'inc/lang/'.$_SESSION['plang'].'/lang.php');

Another quick hack … extending the previous one:

In file inc/init.php after:

  //load the language files
  require_once(DOKU_INC.'inc/lang/en/lang.php');
  /*   you have to comment these...
  if ( $conf['lang'] && $conf['lang'] != 'en' ) {
    require_once(DOKU_INC.'inc/lang/'.$conf['lang'].'/lang.php');
  } 
  */

put this:

  // HACK - Language Selection
  if(isset($_GET['lng'])){
    $_SESSION['lng']=$_GET['lng'];
  } 
  if(isset($_SESSION['lng']) and file_exists(DOKU_INC.'inc/lang/'.$_SESSION['lng'].'/lang.php')){
    require_once(DOKU_INC.'inc/lang/'.$_SESSION['lng'].'/lang.php');
    $conf['lang']=$_SESSION['lng'];
  } else {
    require_once(DOKU_INC.'inc/lang/'.$conf['lang'].'/lang.php');
  }

and move this block:

  // make session rewrites XHTML compliant
  @ini_set('arg_separator.output', '&');
 
  // init session
  session_name("DokuWiki");
  if (!headers_sent()) session_start();
 
  // kill magic quotes
  if (get_magic_quotes_gpc()) {
    if (!empty($_GET))    remove_magic_quotes($_GET);
    if (!empty($_POST))   remove_magic_quotes($_POST);
    if (!empty($_COOKIE)) remove_magic_quotes($_COOKIE);
    if (!empty($_REQUEST)) remove_magic_quotes($_REQUEST);
    if (!empty($_SESSION)) remove_magic_quotes($_SESSION);
    @ini_set('magic_quotes_gpc', 0);
  }
  @set_magic_quotes_runtime(0);
  @ini_set('magic_quotes_sybase',0);

…after this line:

  @include_once(DOKU_INC.'conf/local.php');

Then, you should be able to set the language with lng variable (eg. http://localhost/dokuwiki/doku.php?lng=cs). It is stored in a session and overrides messages defined not only in lang.php file, but also in other files in the language directory.

Bohumir Zamecnik 2005-07-11 Thanks Bohumir!


Here is another one:

without storing language in a session, but rather in a cookie and having people choose their own language for the interface instead of having browser-detection or namespace fiddling (since in reality imho nobody has the time to completely “copy and translate all content”): (tested with version 2007-06-27)

in /conf/local.conf.protected

if (isset($_GET['plang'])){
	$conf['lang']=$_GET['plang'];
	setcookie("plang",$_GET['plang']);
	$getrid="plang=".$_GET['plang']; 	//strip plang
	$script = str_replace( $getrid, "",$_SERVER['REQUEST_URI']);
	$loc="location:http://".getenv(HTTP_HOST).$script;
	header( $loc);
}
if (isset($_COOKIE["plang"])){
	$conf['lang']=$_COOKIE["plang"];
}

As far as I know the configuration manager overwrites all changes to local.conf, thats why you will have to put it in local.conf.protected.

Then create some language links somewhere in your template (/lib/tpl/../main.php), for example below your logo-div:

<div class="langselect">
  <?php 
    if((strpos($_SERVER['REQUEST_URI'],"?"))>0){
        $lref="<a href='".$_SERVER['REQUEST_URI']."&plang=";
        }else{
        $lref="<a href='".$_SERVER['REQUEST_URI']."?plang=";
        }
    echo $lref."en'>English</a>&nbsp;|&nbsp;\n";
    echo $lref."fr'>Francais</a>&nbsp;|&nbsp;\n";
    echo $lref."pt'>Portugues</a>&nbsp;|&nbsp;\n";
    echo $lref."es'>Espanol</a>&nbsp;|&nbsp;\n";
  ?>
</div>

and some displaying stuff in your css

div.dokuwiki .langselect {
  font-size: 90%;
  text-align:right;
  margin-top:3em;
}
 
div.dokuwiki .langselect a {
color:yellow !important;
}


Will any of these approaches work on the latest version of Dokuwiki? :

Many files are not in the same place and look very different. Is there a plugin to allow this or is this feature now built into Dokuwiki?

Any replies or links to recent updates would be most welcomed.

Thanks.

Posted : 2009/MAY/3



tips/browserlanguagedetection.1241336107.txt.gz · Last modified: 2009-07-31 11:42 (external edit)

Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 4.0 International
CC Attribution-Share Alike 4.0 International Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki