Table of Contents
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:
- open the file conf/local.php (or conf/dokuwiki.php if you dont have local.php)
- paste the following code at the end of the file and save
- 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:47But 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 :
- add a lang switcher (clickable flags buttons)
- 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,
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:50
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