Account: please sign in

(!) 이 문서는 한국어판도 있습니다.

  • The most recent minor version upgrade: 2005-09-22e-1.0.2

  • DRAFT: This document is under construction, and is being changed continuously.

  • This document is for the DokuWiki version 2005-09-22e. The techniques described in this document may not work for the other versions.

  • The Native Language Support (NLS) feature mentioned in this document means 'a restricted and partial NLS to provide additional English, where the default language is Korean.' Of course, you can use more languages other then English and can select another language as the default language if you modify this technique, but it is still up to you. 1

Assumptions for the Requirements

The techniques described in this document can be used when there are requirements as follows:

  • The domain name and host name for the web site is fixed and cannot be added or changed arbitrarilly. That is, you cannot use, for example, or according to the languages as in the Wikipedia.

  • You want to operate only one installation of DokuWiki for various conveniences such as user management. That is, you don't want to separate installations of DokuWiki according to the languages.

  • The list of languages you want to use is already fixed. That is, you don't have any intention that you support some esoteric languages when some visitors of your site use them, even though DokuWiki itself supports those languages for its UI. Such visitors using esoteric languages will be redirected to the documents in some appropriate language among the pre-fixed list of languages.2

  • Basically you want to let DokuWiki act according to the language settings of the user agents, but still you also want to let users freely select languages other than their language settings in their browsers.

  • You don't have any intention of translating every documents in every (pre-fixed) languages you selected. You want some documents are translated in various languages, but still want the other documents are written in fewer (or, even only one) language(s).
  • When a visitor reads a document in language A, the UI is also shown to her/him in the language A.3

  • In order for the web crowlers to retrieve and save all the languages correctly:
    • any two documents in two different languages should have different URLs, and
    • the crowlers should be able to navigate between languages not by form-submitting but by simple links.

Basic Ideas

Basic idea is very simple. I'll assume one thing for the convenience: administrator wants to manage only two languages, Korean (ko) and English (en).

  • I'll add a postfix *.ko (for Korean docs) or *.en (for English docs) to the ID's of every documents. No errors are raised at all if there remain some documents without such postfix, but those documents are not needed and are unreadable.

  • I'll define a constant NLS_LANG according to the language requested by the users.

  • If the language requested by the user is neither Korean nor English, than a simple content negotiation will be done according to the browser setting. Then:
    • The value of the constant NLS_LANG will be set to either ko or en.

    • The constant NLS_REDIRECT will be defined. It will add a dot (.) and the value of NLS_LANG after the document ID requested.

    • Visitor will be automatically redirected to the NLS_REDIRECT document using HTTP header or HTML meta tags.

  • The value of the variable $conf['lang'] will be changed to the value of NLS_LANG. Caution: the array $conf is set in the very early stage of the DokuWiki script. In some reason, it is difficult to decide the value of NLS_LANG earlier than this $conf array. So, it is important that we should reset $conf['lang'] after NLS_LANG is set, and that we should carefully let this resetting has the effect appropriately.4

  • The language file (inc/lang/$conf['lang']/lang.php) will be re-registered.

  • The locale will be reconfigured appropriately, in either ko_KR.UTF-8 or en_US.UTF-8.

  • Administrators now can utilize NLS_LANG and NLS_REDIRECT in their template file (for example, lib/tpl/foo/mail.php.)

Simple, huh? :-)


Create a file named inc/NLS.php. The code below is a inc/NLS.php I wrote, but you can change the list of languages and rules for the content negotiation. The most important point is that the two or three constants in this code should be defined correctly. (You should modify the address for the redirection appropriately.)

   1 <?php
   2 /**
   3  * NLS features
   4  */
   6 $tmp_NLS_pageID = getID();
   8 // parsing page ID for language detection
   9 if (substr($tmp_NLS_pageID, -3) == '.ko') {
  10         define('NLS_LANG', 'ko');
  11         define('NLS_ALT', 'en');
  12 } elseif (substr($tmp_NLS_pageID, -3) == '.en') {
  13         define('NLS_LANG', 'en');
  14         define('NLS_ALT', 'ko');
  15 } else {
  16         $tmp_lang = 'en';       // This (English) is the default!
  17         // parsing 'Accept-Language' header from UA
  18         $acclang_arr = split(" *, *", trim($_SERVER['HTTP_ACCEPT_LANGUAGE']));
  19         foreach ($acclang_arr as $acclang) {
  20                 if (ereg("^(.+) *;.+= *(.+)$", $acclang, $acclang_parts))
  21                         $acclang_sorted[$acclang_parts[1]] = (double)($acclang_parts[2]);
  22                 else
  23                         $acclang_sorted[$acclang] = 1.0;
  24         }
  25         asort($acclang_sorted, SORT_NUMERIC);
  26         reset($acclang_sorted);
  27         foreach ($acclang_sorted as $lang_str => $priority) {
  28                 if (ereg("ko.*", $lang_str))
  29                         $tmp_lang = 'ko';
  30                 elseif (ereg("en.*", $lang_str))
  31                         $tmp_lang = 'en';
  32         }
  33         define('NLS_LANG', $tmp_lang);
  34         define('NLS_ALT', ($tmp_lang == 'ko') ? 'en' : 'ko');
  35         define('NLS_REDIRECT', $tmp_NLS_pageID.".".NLS_LANG);
  36         if (! array_key_exists("idx", $_GET))  // No redirection when indexing
  37                 header('Location: /' . str_replace(":", "/", NLS_REDIRECT));
  38 }
  40 // a quick hack for UI  -- testing version
  41 global $conf;
  42 $conf['lang'] = NLS_LANG;
  43 require_once(DOKU_INC.'inc/lang/'.$conf['lang'].'/lang.php');
  44 setlocale(LC_ALL, (NLS_LANG == 'ko' ? 'ko_KR' : 'en_US'). ".UTF-8");
  45 ?>

Then, add a line for this NLS feature at the front part of doku.php file. The position of this line is very important. NLS should be loaded as early as possible, but should be loaded after the inc/pageutils.php file because NLS utilizes a feature in this file. So, load NLS just after the inc/pageutils.php. (The last part of this code is omitted.)

   1 /**
   2  * DokuWiki mainscript
   3  *
   4  * @license    GPL 2 (
   5  * @author     Andreas Gohr <>
   6  */
   8 //  xdebug_start_profiling();
  10 if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__)).'/');
  11 require_once(DOKU_INC.'inc/init.php');
  12 require_once(DOKU_INC.'inc/common.php');
  13 require_once(DOKU_INC.'inc/pageutils.php');
  14 require_once(DOKU_INC.'inc/NLS.php');  // 이 줄을 추가합니다.
  15 require_once(DOKU_INC.'inc/html.php');
  16 require_once(DOKU_INC.'inc/auth.php');
  17 require_once(DOKU_INC.'inc/actions.php');
  18 ...

By the works done until now, two features are implemeted:

  • resetting UI language and locale along the translations of contents
  • automatically redirecting to the page in appropriate language, if it is inappropriate.

Now, let's implement a feature which let a visitor click a link saying "English version of this document", for example. The code below is a part of main.php in my own template:

   1 <?php if ($ACT == 'show' && ! defined('NLS_REDIRECT')) { ?>
   2         <?php
   3         $NLS_altp_ID = substr($ID, 0, -2) . NLS_ALT;
   4         $NLS_altp_URL = str_replace(':', '/', $NLS_altp_ID);
   5         $NLS_altp_exists = false;
   6         resolve_pageid(getNS($NLS_altp_ID), $NLS_altp_ID, $NLS_altp_exists);
   7         ?>
   8         <a href="/<?php echo $NLS_altp_URL; ?>"><img
   9             src="<?php echo DOKU_TPL ?>images/gnome-24/config-language.png"
  10             width="24" height="24" alt="NLS feature"/>
  11         <?php if ($NLS_altp_exists && NLS_ALT == 'ko') { ?>
  12         이 문서의 한국어판
  13         <?php } elseif ($NLS_altp_exists) { ?>
  14         English version of this document
  15         <?php } elseif ((! $NLS_altp_exists) && NLS_ALT == 'ko') { ?>
  16         이 문서에는 아직 한국어판이 없습니다.
  17         <?php } else { ?>
  18         No English version for this document yet
  19         <?php } ?></a>
  20 <?php } ?>

The functions resolve_pageid and getNS here are built-in functions of DokuWiki.

You can use the constant NLS_LANG in many other places.

To Do

I want to separate the content NLS from the UI NLS. The work for this seems not heavy, but still tedious. :-( The goal for separations are:

  • The links to other translations will remain still.
  • Decision rule for the UI language will be changed. Aside from the links for the translations described above, I'll make a new selection box and a button for the UI language and I'll let them saved as a cookie. Selectable options will be:

    • According to the language configured in the user agent (this will be the 'default' oneday.)

    • According to the content language of current document

    • Fixed Korean UI

    • Fixed English UI

I'm procrastinating because it seems not so urgent. Maybe I'll do it oneday. :-?

The last methods seems not so good. I'll postpone it indefinitely.

  1. For more complete NLS features, see Multilingual sites with DokuWiki and Browser Language Detection. (1)

  2. For the UI, however, this requirement can be changed. After the content NLS is separated from the UI NLS oneday, almost every visitors will be able to see the UI in their own language. (2)

  3. This will be changed. The language for UI will be selected and saved as a cookie, or will be automatically changed according to the browser setting. (3)

  4. This is not so simple, but still possible. :-) (4)