2014-06-03
echo "Hello" 라는 구문은 화면상에 "Hello" 라는 문구를 출력해 준다. 그런데 해당 언어가 영어가 아닌 한글이나 다른 언어로 표시 되어야 한다면, 우리는 소스상에서 if문이나 switch문으로 "Hello"가 아닌 "안녕하세요" 라는 구분도 넣어주는게 보통의 방법일 것이다.
그런데 그렇게 안하고 소스 수정 없이 어딘가에 설정 파일만으로 해당 출력을 조절 하는 방법이 있지 않을까?

바로, gettext를 사용 하면 된다.

이글을 CentOS 기준으로 쓰여진 글임을 밝힌다.

1. xgettext와 msgfmt 명령어를 사용할 수 있는 gettext를 설치한다.
다운링크 : http://www.gnu.org/software/gettext/
해당 글의 The latest release is http://ftp.gnu.org/pub/gnu/gettext/gettext-0.19.tar.gz 이부분에서 다운을 받고,
# tar -xvzf gettext-0.19.tar.gz : 압축을 풀고 # cd gettext-0.19 : 해당 폴더로 들어간뒤에 # ./configure : configure를 실행시키고 # make : make 도 해주고 # make install : make install 도 해주면 설치 완료

2. php.ini에서 gettext를 사용할 수 있게 설정한다.
보통은 php.ini에 해당 모듈이 설치되어 있긴 한데, 주석처리가 되어 있을것이다. gettext.so 모듈 추가 부분을 찾아서 주석(;)을 풀어주고 아파치를 재시작 한다.

3. 예제로 쓰일 소스 파일(t1.php)이다.
$language = "ko_KR"; //LC_MESSAGES가 있는 디렉토리
putenv("LANG=" . $language); 
setlocale(LC_ALL, $language);
 
$domain = "messages"; //생성된 mo,po파일 이름
bindtextdomain($domain, "/var/html/locale"); // ko_KR이 있는 디렉토리
textdomain($domain);
 
echo _("Hello"); //gettext()는 _()이런식으로도 쓸수 있다.
echo "<br>";
echo gettext("b1ix");

4. po와 mo 파일이 생성될 디렉토리를 만든다.
디렉토리는 /var/html/locale/ko_KR/LC_MESSAGES/ 로 만든다.
여기서 중요한 부분은 "ko_KR" 과 "LC_MESSAGES" 라는 이름이다.
euc-kr을 캐릭터 셋으로 사용하려면 ko_KR을 사용해야 한다.
그리고 그 하위 디렉토리로 LC_MESSAGES라는 식으로 만들지 않으면 gettext에서 제대로 인식을 못한다. (이거때문에 반나절을 삽질했다.)
캐릭터셋과 줄임이름은 아래를 참조하길 바란다.
참조 : http://b1ix.net/141

5. xgettext를 실행 시켜 .po 파일을 만든다.
위 3번의 예제소스(t1.php)가 있는 위치로 가서, 아래와 같이 명령어를 쳐준다.
# ​xgettext -o ./locale/ko_KR/LC_MESSAGES/messages.po -n t1.php : *.php로도 해줄수 있다.

6. messages.po 파일을 수정한다.
# cd locale/ko_KR/LC_MESSAGES/ : .po파일이 있는 위치로 간뒤 # vim messages.po : vim 으로 열어보면 아래와 같은 파일이 생겼을 것이다.
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-06-03 17:58+0900\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=EUC-KR\n"
"Content-Transfer-Encoding: 8bit\n"

#: t1.php:10
msgid "Hello"
msgstr "안녕하세요"

#: t1.php:12
msgid "b1ix"
msgstr "블릭스"
그중에서 charset을 지정해 주고(필자는 한글이기에 euc-kr을 해준것), 3번의 소스에서 gettext로 만들어놓은 파일들에 대한 설정을 해주도록 설정들이 생겼을 것이다. msgstr 다음의 "" 부분에 바꿔서 표시해줄 텍스트들을 입력해준다.

7. msgfmt으로 mo파일을 만든다.
# msgfmt messages.po : messages.mo 파일이 생성된다.

8. 자 이제 준비가 끝났다. t1.php를 웹에서 실행해 보기 바란다.
Hello
b1ix
대신에
안녕하세요
블릭스
라는 문구가 나오면 제대로 된것이다.

참조
링크1 : http://www.pontikis.net/blog/php-javascript-internationalization-gettext-poedit
링크2 : http://www.sitepoint.com/localizing-php-applications-1/
링크3 : http://www.hanbit.co.kr/network/view.html?bi_id=447

//---------------------추가 2016.03.16

po파일을 만들고 난뒤 몇개의 gettext를 추가하고 다시 po파일을 만든다면, 기존의 po파일의 msgstr "ㅇㅇ" 부분은 남겨두고 새로 추가한 것만 추가 되도록 해야 할 것이다.

이럴때 필요한 옵션이 -j와 -M이다.

예제는 아래와 같다.
xgettext -o -M -j --no-location -Lphp [gettext가 포함된 파일] --output=[기존 .po 파일] --from-code=utf-8

위와 같이 써주면, 기존의 .po파일은 그대로 유지된채로 파일이 .po파일이 새로 생긴다.

그리고 파일의 캐릭터 셋이 맞지 않다는 오류가 생길 수 있는데, 그럴때는 [기존 .po파일]의 "Content-Type: text/plain; charset=UTF-8\n" 부분에 있는 캐릭터셋을 위 명령어로 새로 만들어질 .po파일의 캐릭터 셋과 일치 시켜야 한다.

참고로,
--no-location 옵션은 msgid "aa" 위에 생기는 주석을 생기지 않게 하는 옵션이며,
-Lphp 옵션은 php파일들을 변환 한다는 옵션이다.