DokuWiki

It's better when it's simple

User Tools

Site Tools


tips:browserlanguagedetection

Browser Language Detection

:!: OBSOLETE

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, doku.php and media.php /this file is obsolete now/ in the same way, 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 conf/dokuwiki.php again, and comment $conf['lang'] line:

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

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



The Here is another one approach worked for me. Filenames have changed and you have to edit them this way:

  • instead of in /conf/local.conf.protected put the code in /conf/local.protected.php , this will prevent modifications by the configuration manager. Create the file if it doesn't exist.
  • :!: problem 1 [solved] :!: the default language option is removed from the local.php after saving configuration. \\my workaround was to put the default language in the lang.protected.php file. Here's my /conf/local.protected.php:
<?php
//added for language support
$conf['lang'] = 'it';
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"];
}
  • :!: problem 2 [solved] :!: conflicts with multilingual plugin browser language preference option; if you want to choose the language and you're using the plugin you have to disable the option, then everything works fine.

Comment: this solution doesn't work if the browser doesn't accept cookies.

– posted 2009-07-31 by bjaast


A Improved Using of the top Tip

I use Release 2013-05-10a “Weatherwax” and Translation Plugin to set a multi-language wiki. User should visit different home page according to his browser's accepted language priority. I found some shortage of the top tip below:

  • Can't be used in current DokuWiki;
  • Can't match language code correctly sometime, e.g., browser accepted languages “zh-tw,zh,en-us,en” will match pattern string “zh” in the available languages “zh,zh-tw,en”, so the highest priority browser accepted language “zh-tw” is missed;
  • Should according to the browser's accepted language priority to search the website's available language page, not vice versa.

And, I use nice URLs of .htaccess file, the two lines must be commented as below:

#RewriteRule ^$                        doku.php  [L]
#RewriteRule ^index.php$               doku.php

I only edit one file “index.php” to redirect to the related home page. The entire “index.php” as below, welcome comment it:

<?php
/**
 * Forwarder to doku.php
 *
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Andreas Gohr <andi@splitbrain.org>
 */
 
$conf['lang_default'] = 'en'; // default language
$conf['lang_enabled'] = array('zh', 'zh-tw', 'en');
// 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'));
    $languages = strtolower($languages);
//    print($languages.'<br>');
    $bol_language_detected = false;
 
    $browser_langsarray = preg_split("/[^\-a-z]/", $languages);
//    print_r($browser_langsarray);
//    print('<br>');
 
    foreach ($browser_langsarray as $tmp_browser_lang) {
      if ($tmp_browser_lang == 'zh-cn' || $tmp_browser_lang == 'zh-sg') {
        $tmp_browser_lang = 'zh';
      }
 
      if ($tmp_browser_lang == 'zh-hk') {
        $tmp_browser_lang = 'zh-tw';
      }
 
      if (substr($tmp_browser_lang,0,3) == 'en-') {
        $tmp_browser_lang = 'en';
      }
 
//      print('tmp_browser:'.$tmp_browser_lang.'<br>');
      foreach ($conf['lang_enabled'] as $tmp_arr_language) {
//        print('tmp_enabled:'.$tmp_arr_language.'<br>');
        if ($tmp_browser_lang == $tmp_arr_language) {
          $tmp_str_language_detected = $tmp_browser_lang;
          $bol_language_detected = true;
          break 2;
        }
      } // ForEach pre-defined content language.
    }// ForEach browser accept 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.
 
$browser_lang = detect_browser_language();
//print($browser_lang.'<br>');
 
if ($browser_lang == 'zh') {
  header("Location: /mobilemate/zh/");
}
 
if ($browser_lang == 'zh-tw') {
  header("Location: /mobilemate/zh-tw/");
}
 
if ($browser_lang == 'en') {
  header("Location: /mobilemate/about");
}

– posted 2013-09-25 MobileMate created by littlebat

Discussion

Please post your comment about “A Improved Using of the top Tip” below.

I think there are two goals with the above - one appears to be allow for translation and the other is simply to provide a per-user localised interface for the users of dokuwiki.

I want the latter function and I achieved it by using the detect_browser_language() function above. I placed it in inc/init.php I then hacked init_lang (in init.php). I haven't really used dokuwiki before so please can someone let me know a better place to “hack” this browser language override.

function init_lang($langCode) {
    //prepare language array
    global $lang, $config_cascade;
    $lang = array();
    $langCode = detect_browser_language();   // HACK this line in to override language setting with browser language

    //load the language files
    require(DOKU_INC.'inc/lang/en/lang.php');
    foreach ($config_cascade['lang']['core'] as $config_file) {
        if (@file_exists($config_file . 'en/lang.php')) {
            include($config_file . 'en/lang.php');
        }
    }

    if ($langCode && $langCode != 'en') {
        if (file_exists(DOKU_INC."inc/lang/$langCode/lang.php")) {
            require(DOKU_INC."inc/lang/$langCode/lang.php");
        }
        foreach ($config_cascade['lang']['core'] as $config_file) {
            if (@file_exists($config_file . "$langCode/lang.php")) {
                include($config_file . "$langCode/lang.php");
            }
        }
    }
}

(dylan 2016/05/19)

tips/browserlanguagedetection.txt · Last modified: 2018-04-24 01:41 by Dr-Yukon

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