계정: 로그인
AA

(!) English version of this document also exists.

  • 마지막 마이너 버전 업그레이드: 2005-09-22e-1.0.2

  • DRAFT: 이 문서는 아직 작업중이며, 계속 변경되고 있습니다.

  • 이 문서는 도쿠위키 2005-09-22e 판을 대상으로 합니다. 다른 버전에서는 이 문서에서 설명하는 방법이 작동하지 않을 수 있습니다.

  • 이 문서에서 말하는 다국어지원 (NLS) 기능이란 '한국어를 기본 언어로 사용하며 영어를 추가로 지원하기 위한 제한적이고 부분적인 다국어지원'을 뜻합니다. 물론 같은 아이디어를 기반으로 조금만 수정하면 한국어 이외의 다른 언어를 기본 언어로 사용하거나 몇 가지 더 많은 수의 언어들을 지원하도록 확장할 수 있습니다만, 이는 어디까지나 이 기법을 가져가서 쓰시는 분들의 역할일 뿐입니다.1

요구 조건에 대한 가정

이 문서에서 설명하는 기법은 다음과 같은 요구조건이 주어진 경우에 쓰일 수 있습니다:

  • 웹 사이트의 도메인명과 호스트명이 고정되어있으며 임의로 추가하거나 바꿀 수 없습니다. 즉, 위키 백과사전처럼 언어에 따라서 en.wikipedia.orgko.wikipedia.org를 사용할 수 없는 경우입니다.

  • 사용자 관리 등의 여러가지 편의를 위해 오직 한 개의 도쿠위키 설치본만을 운영하고 싶습니다. 즉, 언어에 따라서 서로 다른 별도의 위키 설치본을 운영하고싶지는 않습니다.
  • 표현하고자 하는 언어의 종류가 미리 확정되어있습니다. 즉, 관리자가 미처 예상하지 못했던 신기한 언어 사용자가 접속할 경우 (비록 도쿠위키 자체적으로는 그 언어에 대한 UI 번역 등이 마련되어있다고 해도) 그 사용자 특유의 언어까지 지원해줄 생각은 없으며, 이런 사용자는 미리 확정되어있는 언어들 중에서 가장 타당한 다른 언어를 보게될 것입니다.2

  • 사용자의 브라우저 언어 설정에 따라 유연하게 동작하게끔 만들고싶지만, 그 와중에도 사용자가 명시적으로 자신의 브라우저 언어 설정과는 다른 언어를 자유롭게 선택해서 볼 수 있는 여지도 남기고 싶습니다.
  • 모든 문서들을 (미리 확정된) 모든 언어들로 전부 번역할 생각은 없습니다. 어떤 문서는 여러가지 언어로 번역되고 사용자의 브라우저 언어 설정이나 선택에 따라 각종 번역본을 제공하겠지만, 또 어떤 문서는 그 중 일부 언어들로만 (심지어 오직 하나의 언어로만) 제공될지도 모릅니다.
  • A 언어로 번역된 문서를 보고있는 상태에서는 UI도 A 언어로 보입니다.3

  • 검색 엔진에 모든 언어의 문서들이 제대로 등록되기 위해서
    • 서로 다른 언어로 작성된 문서는 서로 다른 URL을 가져야하며,
    • form submit이 아닌 단순 링크에 의해 각 언어 사이를 넘나들 수 있어야합니다.

기본 아이디어

기본 아이디어는 무척 단순합니다만, 설명의 편의를 위해 지금부터 한 가지 가정을 하겠습니다: 관리자는 자신의 위키 사이트에 한국어(ko)와 영어(en) 번역본을 넣을 생각입니다.

  • 모든 문서들의 ID를 *.ko(한글판)이나 *.en(영문판)으로 재조정합니다. 그렇지 않은 문서가 존재하더라도 오류를 유발하지는 않지만, 존재할 필요가 없는 문서일 뿐만 아니라 어차피 그 내용을 읽을 수도 없습니다.

  • 사용자가 요청한 문서가 한글판이냐 영문판이냐에 따라서 NLS_LANG이라는 상수를 정의해둡니다.
  • 만일 사용자가 요청한 문서가 한글판도 영문판도 아니라면, 사용자 브라우저의 언어 설정에 따라 간단히 content negotiation을 수행합니다. 그 결과에 따라:
    • NLS_LANG 상수의 값을 koen 중 하나로 결정합니다.

    • NLS_REDIRECT라는 상수를 설정합니다. 요청한 문서 ID 뒤에 마침표와 NLS_LANG을 붙이면 됩니다.
    • HTTP header나 HTML meta 태그를 통해 NLS_REDIRECT 문서로 자동 이동합니다.
  • $conf['lang'] 변수의 값을 NLS_LANG으로 재조정해둡니다. 주의: $conf 배열은 도쿠위키 스크립트의 무척 초기에 세팅됩니다. 몇 가지 이유로 NLS_LANG 상수의 값을 이보다 빨리 결정해두기가 어려우므로, NLS_LANG이 결정된 후 기존에 세팅되어있는 $conf['lang']을 변경하고 그 효과가 확실히 나타나도록 조치하는게 중요합니다.4

  • 언어 파일 (inc/lang/$conf['lang']/lang.php)을 재등록합니다.

  • locale을 ko_KR.UTF-8이나 en_US.UTF-8로 적절히 재설정합니다.

  • 자신의 템플릿 파일(예: lib/tpl/foo/mail.php)에서 NLS_LANG, NLS_REDIRECT 등을 적극 활용합니다.

이상입니다. 간단하죠? :-)

코드

inc/NLS.php 파일을 생성합니다. 아래 코드는 제가 작성한 inc/NLS.php의 내용이지만, 언어 종류나 content negotiation 정책은 조금씩 바꿔쓰실 수 있습니다. 중요한 점은, 이 코드에서 정의하고있는 2~3가지 상수들이 반드시 올바르게 정의되어야 한다는 점 뿐입니다. (리다이렉션 주소는 알맞게 고치셔야합니다.)

   1 <?php
   2 /**
   3  * NLS features
   4  */
   5 
   6 $tmp_NLS_pageID = getID();
   7 
   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 }
  39 
  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 ?>

이제 doku.php 파일의 초판부에 다음과 같이 NLS 기능을 하는 스크립트를 추가합니다. 이 줄의 위치가 무척 중요합니다. NLS 스크립트는 가능한 한 일찍 로딩되는 것이 좋은데, inc/pageutils.php 파일에 들어있는 기능 하나를 꼭 써야하므로 이보다는 뒤에 들어와야합니다. 따라서 inc/pageutils.php 바로 아래에 추가하십시오: (이 코드는 아랫부분이 생략되어있습니다.)

   1 /**
   2  * DokuWiki mainscript
   3  *
   4  * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
   5  * @author     Andreas Gohr <andi@splitbrain.org>
   6  */
   7 
   8 //  xdebug_start_profiling();
   9 
  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 ...

이상의 내용만으로도 일단

  • 언어별 문서 번역본에 따른 UI 언어와 로켈 재설정
  • 언어별 문서가 아닐 경우 적절한 언어별 문서로 자동 이동

기능은 구현되었습니다. 이제, 예를 들어 사용자(방문객)가 이 문서의 영문 번역판 보기 등의 링크를 누를 수 있게 해보겠습니다. 아래 코드는 제 자작 템플릿에 들어있는 main.php 파일의 일부입니다:

   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 } ?>

여기서 resolve_pageid나 getNS 등의 함수는 도쿠위키에 내장된 함수입니다.

이 외에도 많은 부분에 NLS_LANG 등의 상수들을 활용할 수 있습니다.

할 일

문서 내용에 대한 NLS와 UI에 대한 NLS를 분리하고 싶습니다. 작업량은 그다지 많을 것 같지 않은데, 귀찮군요. :-( 분리 목표는:

  • 언어가 명시되지 않은 가상 문서 요청시 적절한 언어별 문서로 redirection하는 과정은 현행 방식대로 유지합니다. (브라우저 설정에만 의존)
  • 언어별 문서를 보다가 그 문서의 다른 언어판으로 이동하는 링크도 현행대로 유지합니다.
  • 다만, 도쿠위키 UI에 쓰이는 언어는 결정 방식이 바뀝니다. 상기 번역판 링크와는 별도로, UI 언어를 결정하는 select 박스와 설정 버튼을 만들고 그 선택 내용을 쿠키로 저장합니다. 선택 항목은:

    • 브라우저 언어 설정에 맞춤 (향후 이것을 기본 값으로 할 예정입니다.)

    • 읽고있는 문서의 내용 언어에 맞춤 (즉, 현행 방식)

    • 무조건 한국어 UI로 고정

    • 무조건 영어 UI로 고정

입니다. 시급한 문제는 아니라서 귀차니즘이 발동중인데, 언젠가는 하겠죠 뭐.... :-?

마지막 방식은 아무래도 별로 좋은 방법이 아닌 것 같아서 무기한 보류합니다.


  1. 더 완전한 다국어지원 기능을 원하시면 Multilingual sites with DokuWikiBrowser Language Detection을 참조하시기 바랍니다. (1)

  2. 단, 문서 내용이 아닌 UI에 관해서 만큼은 이 조항이 바뀔 수도 있습니다. 추후 문서 내용에 대한 다국어지원 기능과 UI에 대한 다국어지원 기능이 분리되면 모드 사용자들은 자신이 원하는 언어로 UI를 쓸 수 있게됩니다. (2)

  3. 이 부분도 추후 개선될 예정입니다. 쿠키 등을 통해 UI 언어만큼은 문서 내용 언어에 상관 없이 한 언어로 고정시키거나 브라우저 설정을 따르도록 선택할 수 있게될 것입니다. (3)

  4. 이 부분이 의외로 간단치 않습니다만, 모든 일이 그렇듯이 방법은 있습니다. :-) (4)