UseModWiki 의 wiki.pl 프로그램을 들여다보면, 거의 모든 메세지 또는 메뉴 링크 들이 다음과 같이 T() 또는 Ts() 함수로 만들어져 있다.
$fullHtml .= '<b>' . Ts('Revision %s not available', $revision)
. ' (' . T('showing current revision instead')
. ')</b><br>';
T와 Ts의 정의는 각각 다음과 같다.
sub T {
my ($text) = @_;
if (1) {
if (defined($Translate{$text}) && ($Translate{$text} ne '')) {
return $Translate{$text};
}
}
return $text;
}
sub Ts {
my ($text, $string) = @_;
$text = T($text);
$text =~ s/\%s/$string/;
return $text;
}
T() 는 인자로 문자열을 받는다. 그리고 $Translate{$text} 가 정의되어 있다면 (형태에서 보면 알겠지만 Translate 는 해쉬변수이고, T() 가 인자로 받은 문자열은 $text 에 담겨서 해쉬변수의 키로 들어간다) 그 값을 반환하고, 정의되어 있지 않다면 인자인 $text 를 그대로 반환한다.
Ts() 는 T() 의 확장으로, 문자열 안에 "%s" 가 있으면 그 자리를 두번째 인자의 값으로 치환한다. c 의 printf("%s", string) 문을 연상하면 되겠다.
따라서, UseModWiki 의 각종 출력 메세지를 번역하고 싶다면, 프로그램 소스는 건드릴 필요 없이, %Translate 해쉬 변수에다가 해당하는 메세지를 키로 하고 번역된 메세지를 값으로 갖는 엔트리를 추가해 주면 된다.
%Translate = ("원문1", "번역문1", "원문2", "번역문2", ... );
그런데 메세지가 한두개도 아니고 (3~400여 개 쯤 된다), 이런 엔트리들을 wiki.pl 안에 넣는 것은 너무 복잡하다. 따라서 이 Translate 의 정의만 별도의 화일(translation file)에 보관한다. 예를 들어, 위키가 설치된 디렉토리 아래 translations 이라는 디렉토리를 만들고, 그 안에 korean.pl 화일을 생성한 후 화일 안에서 다음과 같이 Translate 엔트리를 정의한다.
# korean.pl
%Translate = split('\n',<<END_OF_TRANSLATION);
Could not create %s <-- 원문
%s 를 생성할 수 없습니다 <-- 번역문 이렇게 한 쌍씩 정의해 나간다.
Showing revision %s
%s 번째 수정본 <-- Ts() 에 들어가는 형태는 %s 를 어순에 맞춰 적절한 위치에 둔다.
showing current revision instead
최종본을 대신 보여드립니다 <-- T() 에 들어가는 형태는 그냥 번역하면 된다.
for %s only
<-- 번역하기 애매한 경우는 번역문이 들어갈 자리에 그냥 빈 줄을 넣는다.
Displaying Wiki Version
위키 버전 정보
END_OF_TRANSLATION <-- 마지막 줄은 첫 줄에서 명시한 limit string 으로 끝낸다.
이렇게 번역화일을 작성했으면, wiki.pl 이 이 화일을 읽어들이도록 한다. config.pl 화일 제일 마지막에 다음 라인을 추가한다.
do "./translations/korean.pl";
또는, wiki.pl 화일에 직접 명시해 줄 수도 있다. (그다지 권장하지는 않는다)
sub DoWikiRequest {
if ($UseConfig && (-f "config.pl")) {
do "config.pl";
}
do "./translations/korean.pl";
&InitLinkPatterns();
if (!&DoCacheBrowse()) {
...
}
이제는, 자기가 원하는 부분만 얼마든지 한글 또는 다른 언어로 출력되게 할 수 있다. 영어로 나오는 메세지가 있다면, wiki.pl 소스 내에서 그 메세지를 검색하여, 메세지가 T() 또는 Ts() 안에 들어가 있는 형태인지 확인한다. 만약에 이 함수들 안에 들어 있지 않고 바로 출력되는 문자열이라면 (일부 메세지들은 이렇게 되어 있다) 수정한다.
print 'Original Message'; 이렇게 되어 있다면
print T('Original Message'); 이렇게 바꾼다
그 다음은 자신이 사용할 번역화일에다가 엔트리를 추가해 주면 된다.
이 홈페이지에서 사용하는 번역화일은 wiki/korean.txt 이다. 여기에는 오리지널 UseModWiki 소스에 나오는 메세지들 2백여개와, 이 홈페이지에서 사용되는 소스에 추가된 메세지 수십개가 엔트리로 들어가 있다. 그 중 몇 개는 번역이 되어 있지 않은 채로 빈 줄로 남겨져 있다. 이 화일을 다운받아 확장자를 pl 로 바꾼 후 사용하면 된다.
프랑스어 등 다른 언어의 번역화일을 사용하고 싶다면 UseModWiki/Translations 에 몇 가지가 올라와 있다.
Behind Story...
UseModWiki 의 메뉴 링크라던가 환경설정 항목에 대한 설명, 기타 이런 저런 메세지들 중 일부는 Luke 님 소스에서 한글로 번역이 되어 있고, 나머지는 그대로 영문으로 출력되고 있었다.
이 영문메세지들을 한글로 마저 번역하려고 손을 대었는데, 코드 내에 하드코딩된 메세지들을 직접 수정하면 유연성이 너무 떨어질 것 같아서, 일종의 언어팩을 도입하려고 했다. 즉 모든 메시지 문자열들을 변수로 바꾸고, 메세지 변수들의 정의는 별도의 화일에서 처리한 후, config 화일의 설정에 따라서 원하는 화일을 선택하여 읽어 들이도록 하는 것이다. resouce 화일이랄까...
그런데 메세지 몇 개를 그렇게 바꾸는 과정에서 특이한 것을 발견했는데, 메시지들이 단순한 문자열이 아니라, 특정한 함수의 리턴값으로 되어 있는 것이다. T("메세지") 또는 Ts("메세지 %s", 변수) 등의 형태로 되어 있는 것을 보고 이 T 와 Ts 함수가 무엇인지 확인해 보았더니 이런 훌륭한 구조가 이미 마련되어 있었다. :-)
관련 링크:
위키위키분류