DokuWiki

It's better when it's simple

User Tools

Site Tools


tips:multilingual_content:local.php

Basic Multilanguage Support for local.php

With these lines of code, you can:

  • display the user interface in browsers favorite language
  • change the UI language depending on leading namespace
  • provide different start pages for every language
  • install it in 5 minutes and uninstall in 30 seconds.

Installation

To enable multilanguage support for your dokuwiki installation:

  1. open the file conf/local.php (or conf/dokuwiki.php if you dont have local.php)
  2. paste the following code at the end of the file and save
  3. press reload in your browser!
/* Multilanguage Support
 * Paste these lines at the end of your local.php and have a look if it works! 
 * DokuWiki shall detect your user agents favorite language and switch interface language depending on leading namespace
 * Your (international) start page will still be 'start' by default, unless you create a page like en:start or de:start
 */

// Configuration 
$conf['lang_enabled'] = array();	//allowed languages (leave this array blank or comment out for auto-detection)

// Autodetect all languages your dokuwiki installation supports
$supportedLanguages = array();
if ($handle = opendir(DOKU_INC.'inc/lang')) {
   while (false !== ($file = readdir($handle))) {
      if (is_dir(DOKU_INC.'inc/lang/'.$file)) array_push($supportedLanguages,$file);
   }
   closedir($handle);
}
if (!isset($conf['lang_enabled'])) $conf['lang_enabled'] = array();
if (count($conf['lang_enabled'])==0) $conf['lang_enabled'] = $supportedLanguages;

// Set default language to the user agents most favorite one
$languages = split(',', preg_replace('/(;q=\d+.\d+)/i', '', getenv('HTTP_ACCEPT_LANGUAGE'))); 
foreach ($languages as $lang) if (in_array($lang, $conf['lang_enabled'])) {
    $conf['lang'] = $lang;
    break;
}

// Check, if language is set by namespace and overwrite choosed language
$lang = preg_replace('/^(..+)[:\/].*/i','$1',$_REQUEST['id']);
if (!in_array($lang, $conf['lang_enabled'])) $lang = preg_replace('/^(..+)[:\/].*/i','$1',$_REQUEST['ns']);
if (in_array($lang, $conf['lang_enabled'])) $conf['lang'] = $lang;

// prepend default start page with language namespace, if this page already exists.
if (file_exists($conf['savedir'].'/pages/'.str_replace(':','/',$conf['lang'].':'.$conf['start']).'.txt')) $conf['start'] = $conf['lang'].':'.$conf['start'];

Testing

Test your new multilanguage features:

  • lets say your dokuwiki is located at http://mydokuwiki.org/, and your default start page is 'start', ok?
  • open http://mydokuwiki.org/ → your start page appears and the user interface is in the language, your browser likes most.
  • open a page like de:test or fr:test → the user interface is in german or french
  • create a localized start page like de:start (try it with the tested browser language in 1.), open http://mydokuwiki.org/ again → your localized start page with localized UI appears
  • press the login button → localized UI appears as well.

Release Notes

The following lines of code are compatible to PHP4+ and any dokuwiki, that configures $conf['lang'], $conf['savedir'] and $conf['start'] and defines DOKU_INC. I think this is valid for at least 2006-03-09 and every later release. (give some feedback)

Seems to be Working for me on 2018 Greebo. — GHSRobert Ciang 2019-04-12 21:47
But not working with PHP 7.2.1… Needs PHP 5.6 to work. — GHSRobert Ciang 2019-04-20 01:32

Discussion

Please leave your comments here. Thank you for try out! — Johannes Vockeroth 2006-07-01 20:41

Your code does not work with the current revision of DokuWiki: « the prepend default start page with language » trick expands an internal link like

[[project:]]

to id=project2:fr:start (where fr is my preferred language in my browser). — Guy Brand 2006-08-27 23:40

Use

[[project:start]] or [[fr:project:start]]

and this work fine. — Patrick


Really nice, seems to work well. Just one question, you have on your webpage links to the same page in another language. How did you achieve this? — Dirk `el loco´ Haage


Hello,

I based my website http://www.pxxo.net on dokuwiki with your multilanguale patch but I extended it a bit in order to :

  1. add a lang switcher (clickable flags buttons)
  2. keep trace of the choosen language : adapte the menu links to the current choosed language

In my local.php :

// Configuration
$conf['lang_enabled'] = array();        //allowed languages (leave this array blank or comment out for auto-detection)
// Autodetect all languages your dokuwiki installation supports
$supportedLanguages = array();
if ($handle = opendir(DOKU_INC.'inc/lang')) {
   while (false !== ($file = readdir($handle))) {
      if (is_dir(DOKU_INC.'inc/lang/'.$file)) array_push($supportedLanguages,$file);
   }
   closedir($handle);
}
if (!isset($conf['lang_enabled'])) $conf['lang_enabled'] = array();
if (count($conf['lang_enabled'])==0) $conf['lang_enabled'] = $supportedLanguages;
// Set default language to the user agents most favorite one
$languages = split(',', preg_replace('/(;q=\d+.\d+)/i', '', getenv('HTTP_ACCEPT_LANGUAGE')));
foreach ($languages as $lang) if (in_array($lang, $conf['lang_enabled'])) {
    $conf['lang'] = $lang;
    break;
}
// Check, if language is set by namespace and overwrite choosed language
$lang = preg_replace('/^(.[^:\/]+)[:\/].*/i','$1',$_REQUEST['id']);
if (!in_array($lang, $conf['lang_enabled'])) $lang = preg_replace('/^(.[^:\/]+)[:\/].*/i','$1',$_REQUEST['ns']);
if (in_array($lang, $conf['lang_enabled'])) $conf['lang'] = $lang;
// prepend default start page with language namespace, if this page already exists.
if (file_exists($conf['savedir'].'/pages/'.str_replace(':','/',$conf['lang'].'.txt'))) $conf['start'] = $conf['lang'];
 
function tpl_youarehere2()
{
  ob_start();
  tpl_youarehere();
  $data = ob_get_contents();
  ob_end_clean();
  $data = str_replace('href="/en"','href="/"',$data);
  echo $data;
}

in main.php template file I replaced the tpl_youarehere() by tpl_youarehere2() and I added the langswitcher.php section which allows to dynamicaly change the language by clicking on the flags :

[...]
        <div id="menu">
            <ul>
                <?php include('menu.php'); ?>
            </ul>
        </div>
[...]
              <div id="langswitcher">
                <ul>
                  <?php include('langswitcher.php'); ?>
                </ul>
              </div>
[...]
              <p><?php tpl_youarehere2(); ?></p>
[...]

in langswitcher.php :

<?php $pagesuffix = substr($ID,2); ?>
<li>
<?php
$LANG2 = 'en';
$ID2 = $LANG2 . $pagesuffix;
if (realpath(wikiFN($ID2,$REV)) != '')
{
  tpl_link(wl($ID2),'<img src="'.DOKU_TPL.'images/lang/'.$LANG2.'.png" alt="'.hsc($LANG2).'"/>');
}
?>
</li>
<li>
<?php
$LANG2 = 'fr';
$ID2 = $LANG2 . $pagesuffix;
if (realpath(wikiFN($ID2,$REV)) != '')
{
  tpl_link(wl($ID2),'<img src="'.DOKU_TPL.'images/lang/'.$LANG2.'.png" alt="'.hsc($LANG2).'"/>');
}
?>
</li>

in menu.php :

<li><?php tpl_link(wl($conf['lang']."/about"),"About"); ?></li>
<li><?php tpl_link(wl($conf['lang']."/news"),"News"); ?></li>
<li><?php tpl_link(wl($conf['lang']."/download"),"Download"); ?></li>
<li><?php tpl_link(wl($conf['lang']."/support"),"Support"); ?></li>
<li><?php tpl_link(wl($conf['lang']."/tutorials"),"Tutorials"); ?></li>
<li><?php tpl_link(wl($conf['lang']."/faq"),"FAQ"); ?></li>

in my images/lang/ directory I added these two images :

Hope this will help someone.

best regards,

Stéphane Gully


I think the regular expression in the original script should be '/^(..+?)[:\/].*/i (with question sign after the plus) in order to match ungreedy. This is important for deep namespace hierarchies. — Esther Brunner 2006-11-21 19:17


:?: Is there any possibility Stéphane Gully's excellent work could be merged with Cha ReeSeo's work on nls? I asked this in the dokuwiki forum.

Tito Vergara 2006-12-01 15:50FIXME


Great !!!

:!: local.php get wiped every time changes are made via the admin control panel.:?:Is that normal? –jack

Yes, but you should find a @include(DOKU_CONF.'local.protected.php'); line in local.php, so you can put handmade changes in your local.protected.php file. Don't know if this would work here though.— Grahack 2008/04/25 13:54

The local.protected.php works fine. Mine looks like this (I combined several tips from this page):

<?php
/* Multilanguage Support
 * Paste these lines at the end of your local.php and have a look if it works!
 * DokuWiki shall detect your user agents favorite language and switch interface language depending on leading namespace
 * Your (international) start page will still be 'start' by default, unless you create a page like en:start or de:start
 */
 
// Configuration
//allowed languages (leave this array blank or comment out for auto-detection)
$conf['lang_default'] = 'en';
$conf['lang_enabled'] = array('en', 'de');
 
// Autodetect all languages your dokuwiki installation supports
$supportedLanguages = glob(DOKU_INC . 'inc/lang/*', GLOB_ONLYDIR);
foreach ($supportedLanguages as $idx=>$lang) $supportedLanguages[$idx] = basename($lang);
 
if (!isset($conf['lang_enabled']) || count($conf['lang_enabled'])==0) $conf['lang_enabled'] = $supportedLanguages;
if (!in_array($conf['lang_default'], $conf['lang_enabled'])) $conf['lang_default'] = reset($conf['lang_enabled']);  // make sure, default lang is valid
 
// Set default language to the user agent's most favorite one
$languages = split(',', preg_replace('/(;q=\d+.\d+)/i', '', getenv('HTTP_ACCEPT_LANGUAGE')));
foreach ($languages as $lang) if (in_array($lang, $conf['lang_enabled'])) {
    $conf['lang'] = $lang;
    break;
}
 
// Check, if language is set by namespace and overwrite chosen language
$lang = preg_replace('/^(..+?)[:\/].*/i','$1',$_REQUEST['id']);
if (!in_array($lang, $conf['lang_enabled'])) $lang = preg_replace('/^(..+?)[:\/].*/i','$1',$_REQUEST['ns']);
if (in_array($lang, $conf['lang_enabled'])) $conf['lang'] = $lang;
 
// prepend default start page with language namespace, if this page already exists.
// if (file_exists($conf['savedir'].'/pages/'.str_replace(':','/',$conf['lang'].':'.$conf['start']).'.txt')) $conf['start'] = $conf['lang'].':'.$conf['start'];
 
function tpl_youarehere2() {
    global $conf;
    ob_start();
    tpl_youarehere();
    $data = ob_get_contents();
    ob_end_clean();
    $data = str_replace('href="' . DOKU_BASE . $conf['lang_default'] . '/', 'href="' . DOKU_BASE, $data);
    $data = str_replace('title="' . $conf['lang_default'] . ':', 'title="', $data);
    $prefixpos = strpos($data, '>'.$conf['lang'].'</a>');
    if ($prefixpos !== false) {
        // find start of anchor (strrpos() only works for single characters, not strings)
        $prefixstart = -1;
        do {
            $prefixstart = strpos($data, '<a ', $prefixstart+1);
            $prefixpre   = strpos($data, '<a ', $prefixstart+1);
        } while ($prefixpre !== false && $prefixpre<$prefixpos);
        // find start of next anchor
        $prefixend   = strpos($data, '<a ', $prefixpos);
        if ($prefixstart > 0 && $prefixend > 0) $data = substr($data, 0, $prefixstart) . substr($data, $prefixend);
    }
    echo $data;
}
 
function tpl_flagimg($lang) {
    // translate language-code to country-code (where the lang is mostly spoken/written)
    switch ($lang) {
        case 'da': $lang = 'dk'; break;  // Danish -> Denmark
        case 'el': $lang = 'gr'; break;  // Greek -> Greece
        case 'en': $lang = 'en-all'; break; // English -> combined GB/US flag
        case 'he': $lang = 'il'; break;  // Hebrew -> Israel
        case 'ja': $lang = 'jp'; break;  // Japanese -> Japan
        case 'ko': $lang = 'kr'; break;  // Korean -> Korea
        case 'ku': $lang = 'iq'; break;  // Kurdish -> Iraq
        case 'pt-br': $lang = 'br'; break;  // Braz. Portuguese -> Brazil
        case 'uk': $lang = 'ua'; break;  // Ukrainian -> Ukraine
        case 'zh': $lang = 'cn'; break;  // Simpl. Chinese -> China
        case 'zh-tw': $lang = 'tw'; break;  // Trad. Chinese -> Taiwan
        default: break;
    }
    $img = DOKU_BASE . 'lib/images/flags/' . $lang . '.gif';
    return $img;
}
 
// assumes Flag icons (.gif) from http://www.famfamfam.com/lab/icons/flags/ in /lib/images/flags (rename us.gif or gb.gif to en-all.gif)
function tpl_langswitcher() {
    global $ID, $conf;
    echo PHP_EOL . '<div id="langswitcher" class="no">';
    echo '<style type="text/css">#langswitcher LI.lang:hover { border: 1px solid #8cacbb; background-color: white; } #langswitcher LI.lang IMG { opacity: 0.3; } #langswitcher LI.lang:hover IMG { opacity: 1; }</style>';
    echo '<ul style="list-style: none; display: inline;">';
    foreach ($conf['lang_enabled'] as $lang) {
        $thislang = ($conf['lang']==$lang);
        $newID    = (($lang!=$conf['lang_default'])?$lang.':':'') . (($ID{2}==':')?substr($ID, 3):$ID);
        // TODO: check existance of file
        $img      = '<img src="' . tpl_flagimg($lang) . '" alt="' . hsc($lang) . '" title="' . hsc($lang) . '" />';
        echo '<li style="display: inline; padding: 2px;"' . ((!$thislang)?' class="lang"':'') . '>';
        if (!$thislang) tpl_link(wl($newID), $img); else echo $img;
        echo '</li>';
    }
    echo '</ul>';
    echo '</div>' . PHP_EOL;
}
 
?>

The flags are from FamFamFam. To show the flags, add to main.php: <?php tpl_langswitcher()?> where you want it to be (right after the Old revisions-button is a perfectly place!). Also change tpl_youarehere() to tpl_youarehere2(). Clicking a flag shows the page in the clicked language. You can easily make it only show flags for languages where there are translations.

I had to comment out the $conf['start'] override because it borked something in cache so that indexmenu was unsure which start-item to show. But using the sidebar-layout with indexmenu in the sidebar, you can easily add a specific sidebar for each language which only shows the localized tree (i.e. everything below that namespace).

Would be nice if there were hooks to make such things as a real plugin, though.

Markus Birth 2008-07-16 20:05

I've made change in orginal script by removing regex and using explode since it's safe and less CPU hungry and because it catch pl:something:somethin:something right :)

<?php
/* Multilanguage Support
 * Paste these lines at the end of your local.php and have a look if it works!
 * DokuWiki shall detect your user agents favorite language and switch interface language depending on leading namespace
 * Your (international) start page will still be 'start' by default, unless you create a page like en:start or de:start
 */
 
// Configuration
$conf['lang_enabled'] = array();        //allowed languages (leave this array blank or comment out for auto-detection)
 
// Autodetect all languages your dokuwiki installation supports
$supportedLanguages = array();
if ($handle = opendir(DOKU_INC.'inc/lang')) {
   while (false !== ($file = readdir($handle))) {
      if (is_dir(DOKU_INC.'inc/lang/'.$file)) array_push($supportedLanguages,$file);
   }
   closedir($handle);
}
if (!isset($conf['lang_enabled'])) $conf['lang_enabled'] = array();
if (count($conf['lang_enabled'])==0) $conf['lang_enabled'] = $supportedLanguages;
 
// Set default language to the user agents most favorite one
$languages = split(',', preg_replace('/(;q=\d+.\d+)/i', '', getenv('HTTP_ACCEPT_LANGUAGE')));
foreach ($languages as $lang) if (in_array($lang, $conf['lang_enabled'])) {
    $conf['lang'] = $lang;
    break;
}
 
// Check, if language is set by namespace and overwrite choosed language
//$lang = preg_replace('/^(..+)[:\/].*/i','$1',$_REQUEST['id']);
$wiki_path = explode(':',$_REQUEST['id']);
$lang = $wiki_path[0];
if (!in_array($lang, $conf['lang_enabled'])) {
    //$lang = preg_replace('/^(..+)[:\/].*/i','$1',$_REQUEST['ns']);
    $wiki_path = explode(':',$_REQUEST['ns']);
    $lang = $wiki_path[0];
}
if (in_array($lang, $conf['lang_enabled'])) $conf['lang'] = $lang;
 
// prepend default start page with language namespace, if this page already exists.
if (file_exists($conf['savedir'].'/pages/'.str_replace(':','/',$conf['lang'].':'.$conf['start']).'.txt')) $conf['start'] = $conf['lang'].':'.$conf['start'];
?>

Trick with:

@include(DOKU_CONF.'local.protected.php');

doesn't work anymore. I just saved code as lang.php in /conf, added include in local.php and made it read only… This solution has one problem. I't disables admin settings pannel, but auth and rest are fine. If i need to modify something I do it manually or by backing up local.php

dr4cul4 2009-05-07 00:25

In order for local.protected.php to work again you can edit the lib/plugins/config/settings/config.class.php file: Add the line

$out .= "\n@include(DOKU_CONF.'local.protected.php');\n";

just before the line

$out .= "\n// end auto-generated content\n";

of function _out_footer()

Now, every time you change your configuration via the admin panel, the include line will be automatically added to local.php

tips/multilingual_content/local.php.txt · Last modified: 2019-04-20 01:33 by MilchFlasche

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