다국어 지원을 할 때, gettext를 많이 써먹게 됩니다. 이 글에서는 mo와 po 파일에 대해서 간단하게 알아봅니다. gettext가 설치하시고 진행해 주세요. 이 글에서는 xgettext, msgmerge, msgfmt 명령어의 상세한 것을 다루지 않습니다. 이 글에서는, 다국어 지원하기 위해 어떻게 해야 하는지에 대한 process를 다루게 됩니다.
gettext mo po 파일
먼저, mo와 po 파일에 대해서 그림으로 간단하게 알아보도록 합시다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/10/gett17.png)
먼저, xgettext로 source로부터, gettext string을 모두 추출합니다. 이들이 번역 재료가 됩니다. 어? 무슨 이야기인가?
- Hello
- My name is cho
라는 것을 번역하고 싶어요. 그러면, py 파일이던, c++ 파일 안에 gettext 처리를 하겠지요? 이들이 번역 재료가 되는 것입니다. 다음, msgmerge가 있어요. 이건 무엇을 하는 건가? merge. 합치는 것입니다. merge sort는 합치는 방식으로 sort를 하는 것이고요. merge branch는 두 브랜치의 변경 사항을 병합하는 것입니다.
마찬가지입니다. 여러 .po나 .pot 파일에 있는 내용들을 병합할 때 msgmerge 명령어를 쓰게 됩니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/10/gett18.png)
그러면, 두 파일들을 merge 해서 새로운 결과를 만들어 낼 수 있습니다. 이것이 msgmerge의 역할입니다. 그런데, c++이나, c 소스 파일만 있다고 실행되지는 않아요. 컴파일 해서 obj를 만들고, 실행 파일을 만들어야 합니다. 마찬가지. 이 po 파일을 컴파일 해서 mo 파일로 만드는 것이, msgfmt입니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/10/gett19.png)
이 mo 파일을 python 프로그램이나, 다른 파일이 불러오면, 번역이 되는 것입니다. 여기까지 po와 mo 파일이 어떤 식으로 다국어에서 동작하는지 이해가 가시나요?
- po는 소스 파일. 그러니까 msg를 어떻게 번역할 것인지 정보를 저장합니다.
- mo는 po를 컴파일한 파일. 프로그램이 mo를 바탕으로 해석해요.
여기까지 따라 오셨다면, 실습을 하나 해 보겠습니다.
번역해 보기
자. 그러면, 실습 하나 해 보겠습니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/10/gett1.png)
프로젝트 구조는 위와 같아요. locale/ko/LC_MESSAGES 밑에 po와 mo 파일이 들어갈 거에요. 그리고, locale 밑에 base.po가 하나 들어갈 겁니다. 이는, base.po는 gettext로 추출한 문구만 남기기 위함입니다.
locale/{lang}/LC_MESSAGES가 중요해요. gettext가 인식하는 폴더 구조이니, 잘 익혀두세요.
![](https://codingdog.pe.kr/wp-content/uploads/2023/10/gett6.png)
먼저, main.py 입니다. 1번째 인자는 body.po를 읽겠다는 것을 의미합니다. 2번째는 locale 밑에 있는 폴더에 language 번역 정보가 들어있다는 것을 의미해요. 다음 _를 t.gettext로 하였는데, 이렇게 하면 _를 호출했을 때, 문자열을 제가 특정한 언어로 번역하게 됩니다. 더 정확히 말하면
- gettext의 추출 대상이 됩니다.
- mo가 있다면, 이를 기반으로 해석하게 됩니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/10/gett2.png)
자. 이제, xgettext 명령어를 사용할 건데요. locale 밑에 base.po라는 이름으로 현재 디렉토리에 있는 모든 py 파일에 대해 source로부터 gettext를 추출한 결과를 생성할 거에요.
![](https://codingdog.pe.kr/wp-content/uploads/2023/10/gett3-1.png)
그러면, 요런 내용이 들어가 있음을 볼 수 있어요. 여기서, 아무것도 건드리지 말고, Content-type 부분에서 charset만 UTF-8로 바꾸어 줍시다. 저는 이 base.po를 그대로 쓰지 않습니다. locale 밑에 각각의 언어 폴더가 있고, 그 밑에 LC_MESSAGES 라는 폴더를 만들어서 관리할 것이기 때문이에요.
![](https://codingdog.pe.kr/wp-content/uploads/2023/10/gett4.png)
자. locale/base.po의 내용을 그대로 locale/ko/LC_MESSAGES 밑에 있는 body.po에 복사합시다. 그러면, 이제 프로젝트 구조가 위 그림과 같이 됩니다. 여기까지 한 것이 뭔가?
- 소스로부터 gettext string을 추출한 결과를 base.po에 저장해 놓았습니다.
- 각 언어별로 body.po를 저장해 놓았습니다.
여기까지 정리 되시나요? 이제, locale/ko/LC_MESSAGES에 들어가서, body.po를 보도록 하겠습니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/10/gett5-1.png)
그러면, msgstr에 아무것도 없을 겁니다. 그냥 “”만 있겠지요. msgid는 키 값, 그리고 msgstr은 키 값에 대해 어떻게 번역할 것인지를 의미합니다. “hello”는 “안녕하세요”로 번역되면 되고, 문장 “new game is started”는 “새로운 게임이 시작되다” 정도로 번역하면 됩니다. 그러니 위와 같이 작성해 주겠습니다.
그 다음에 어떻게 해야 겠나요? 소스 파일은 있는데 컴파일 결과가 없네요.
![](https://codingdog.pe.kr/wp-content/uploads/2023/10/gett7.png)
그러면 컴파일을 해야 겠지요? msgfmt로 컴파일 합시다. 그러면, body.po 파일에 대해, 컴파일 결과인 body.mo가 나오게 됩니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/10/gett8.png)
실행 결과는 위와 같습니다. 저는 ko 언어로 번역했기 때문에, 안녕하세요와, 새로운 게임이 시작되다로 번역되었습니다.
번역할 구문 추가하기
그런데, 번역 구문이 추가되면 어떻게 해야 할까요? gettext mo po 파일 둘 다 업데이트 되어야 겠지요. 그러면, 업데이트 되어야 할 것이 3군데입니다.
- base.po
- 각 언어별로 body.po
- 각 언어별로 컴파일 결과인 body.mo
하나씩 진행해 볼게요.
![](https://codingdog.pe.kr/wp-content/uploads/2023/10/gett9.png)
hey!가 번역되어야 할 것에 추가되었습니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/10/gett10.png)
base.po는 새로 생성합니다. base.po는 번역본이 지워져도 되기 때문에 새로 생성해도 무난합니다. 그런데 중요한 것은, msgmerge를 사용해서, 각 언어별로 body.po를 locale/base.po를 참조해서 업데이트 했다는 점입니다.
이제, locale/ko/LC_MESSAGES/body.po와 locale/base.po를 보겠습니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/10/gett12.png)
먼저 base.po는 msgid만 들어가 있습니다. msgstr에는 아무 것도 없다는 것을 주목해 보세요.
![](https://codingdog.pe.kr/wp-content/uploads/2023/10/gett14.png)
body.po에는 “hey!” 라는 내용만 추가되었습니다. msgstr에 제가 번역할 내용을 적어줍니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/10/gett15.png)
내용이 바뀌었다면, mo 파일에 반영하기 위해 다시 컴파일을 합니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/10/gett16.png)
이제, main.py를 실행해 봅시다. 그러면, hey!가 어이!로 번역되었다는 것을 볼 수 있습니다.