앱을 망치지 않고 PO 파일 번역하는 방법
TABLE OF CONTENTS
PO 파일은 단순한 텍스트 파일처럼 보이지만, 번역된 %s, 누락된 복수형, 또는 수정된 msgid가 앱을 망가뜨릴 수 있습니다. 이 워크플로우를 사용하면 gettext 구조를 그대로 유지하면서 사용자에게 보여지는 문자열만 번역할 수 있습니다.
전체 파일을 일반 번역기에 붙여넣지 마세요. PO 파일은 소스 코드와 밀접한 파일입니다: 단어는 번역할 수 있지만, 파일 구조, 플레이스홀더, 주석, 복수형 인덱스는 변경 없이 그대로 유지되어야 합니다.
방법 1: PO 파일 번역기 사용하기
빠르고 안전한 초안이 필요하고 msgid / msgstr 쌍을 직접 수정하고 싶지 않을 때 이 방법을 선택하세요.
-
원본
.po파일을 백업하세요. 번역을 맡기기 전에 저장소에 깨끗한 복사본을 보관하세요. 번역된 파일이 문제가 생기면 비교할 수 있는 정상 파일이 필요합니다. -
PO 인식 번역기를 엽니다. gettext 파일을 위해 만들어진 도구를 사용하세요. 예를 들어 OpenL PO Translator는 유료 문서 번역 도구입니다. PO 인식 도구는 소스 문자열, 주석, 플레이스홀더, 파일 구조를 그대로 유지하면서 대상 문자열만 번역해야 합니다. 아직 도구를 선택 중이라면 최고의 PO 번역기 가이드에서 옵션을 비교해보세요.
-
.po파일을 업로드하세요.msgid와msgstr항목이 포함된 언어 파일을 사용하세요..pot템플릿만 있다면 먼저 대상 언어의.po파일을 생성한 후, 그.po파일을 업로드하세요. -
소스 언어와 대상 언어를 선택하세요. 소스 언어는 관리자 인터페이스의 언어가 아니라
msgid에 들어있는 텍스트의 언어와 일치해야 합니다. 예를 들어 파일에 영어msgid문자열이 있고 스페인어로 번역해야 한다면, 영어에서 스페인어로 선택하세요. -
번역된 파일을 다운로드하세요. 프레임워크에서 기대하는 로케일 명명 규칙에 맞게 저장하세요. WordPress 플러그인은 보통 텍스트 도메인과 로케일 패턴을 사용하고, Django는 일반적으로
locale/<language>/LC_MESSAGES/경로 아래에 파일을 저장합니다. -
먼저 위험한 문자열을 검토하세요. 번역된 파일에서
%,{,},<,>,msgid_plural,msgctxt, 그리고#, fuzzy를 검색하세요. 이 항목들은 런타임 동작에 영향을 줄 가능성이 가장 높습니다. -
앱에서 번역 파일을 테스트하세요. 언어를 로컬로 로드하고 번역된 문자열이 사용되는 화면을 클릭해 확인하세요. PO 파일은 번역이 끝났다고 해서 완성된 것이 아닙니다. 앱이 정상적으로 렌더링되는지 확인해야 완성된 것입니다.
방법 2: Poedit에서 PO 파일 번역하기
사람의 검토가 필요하거나, WordPress 호환성, 또는 꼼꼼한 항목별 워크플로우가 필요할 때 이 방법을 선택하세요.
-
Poedit에서 파일을 엽니다. Poedit는 PO 및 기타 로컬라이제이션 포맷을 위한 전용 번역 에디터입니다. 기본 에디터는 무료이며, 더 복잡한 작업을 위한 유료 Pro 기능도 있습니다. WordPress의 경우, 공식 Polyglots 핸드북에 따르면 Poedit는 POT 파일에서
.po와.mo파일을 생성할 수 있으며, 복수형과 UTF-8을 지원합니다. -
소스가 변경되었다면 POT 템플릿으로 업데이트하세요. 개발자가 앱 텍스트를 변경했다면, 번역 전에 최신
.pot파일로.po파일을 업데이트하세요. 이렇게 하면 새로운, 삭제된, 그리고 fuzzy 문자열이 눈에 띄게 표시되어 오래된 UI 텍스트가 조용히 배포되는 것을 막을 수 있습니다. -
msgstr필드만 번역하세요.msgid는 앱이 번역을 찾을 때 사용하는 원본 문자열입니다. 일반적인 gettext 워크플로우에서는 번역자가msgstr만 수정해야 하며,msgid는 건드리지 않습니다. -
플레이스홀더는 정확히 그대로 유지하세요.
%s,%d,%1$s,{name},%(count)s,:name, 또는 HTML 태그와 같은 변수는 번역하거나 띄어쓰기를 변경하지 마세요. 단어 순서가 바뀌어야 한다면 플레이스홀더를 하나의 단위로 이동하세요. -
복수형은 별도의 번역으로 처리하세요. 복수형 항목에는
msgid,msgid_plural, 그리고 여러 개의msgstr[n]값이 포함될 수 있습니다. 대상 언어에 필요한 모든 복수형 슬롯을 채우고, 같은 문장을 반복해서 복사하지 마세요. -
앱에서
.mo파일이 필요하다면 저장하고 컴파일하세요. 일부 개발 환경에서는 개발 중에.po파일을 직접 읽지만, WordPress와 많은 gettext 기반 시스템은 런타임에 컴파일된.mo파일을 사용합니다. Poedit는 저장 시 자동으로.mo파일을 컴파일할 수 있고, Django에서는django-admin compilemessages명령어로 메시지를 컴파일할 수 있습니다. -
업로드 전에 경고를 해결하세요. Poedit에서 경고 아이콘은 깨진 플레이스홀더, 누락된 변수, 복수형 불일치 등을 나타냅니다. WordPress, Django, Drupal 또는 릴리즈 브랜치에 번역을 가져오기 전에 반드시 수정하세요.
방법 3: 로컬라이제이션 플랫폼 사용하기
여러 번역가, 리뷰어, 릴리즈 매니저가 동일한 PO 파일을 작업해야 할 때 이 방법을 선택하세요.
-
gettext를 지원하는 플랫폼에 PO 파일을 가져오기하세요. Weblate와 같은 로컬라이제이션 플랫폼은 PO 워크플로우를 지원합니다. 팀용 로컬라이제이션 플랫폼은 대부분 유료이지만, Weblate는 오픈소스 셀프호스팅 옵션도 제공합니다. 각 플랫폼마다 댓글, 헤더, fuzzy 문자열, 플레이스홀더 처리 방식이 다르므로, 실제 파일을 업로드하기 전에 포맷 설정을 반드시 확인하세요.
-
플레이스홀더 및 태그 검사를 설정하세요. printf 스타일 플레이스홀더, 명명된 변수, HTML/XML 태그, 복수형에 대한 QA 규칙을 활성화하세요. 이런 검사는 일반 맞춤법 검사기로는 잡아낼 수 없는 실수를 발견해줍니다.
-
개발자 댓글을 항상 볼 수 있도록 하세요. PO 댓글에는 소스 참조, 개발자 노트, 플래그, 이전 소스 문자열 등 맥락 정보가 담겨 있습니다. “Open”처럼 짧은 UI 라벨이 동사, 형용사, 메뉴 명령 등 여러 의미를 가질 수 있으므로 번역가에게 이런 노트가 꼭 필요합니다.
-
번역 메모리 사용 시 리뷰를 병행하세요. 번역 메모리는 반복되는 UI 문자열에 유용하지만, 이전 번역이 새로운 맥락에 그대로 복사될 수 있습니다.
msgctxt, 소스 참조, 주변 UI가 변경된 경우에는 재사용된 문자열을 반드시 검토하세요. -
PO 파일을 내보내고 로컬 검사를 실행하세요. 내보낸 파일을 무조건 신뢰하지 마세요. 번역된 파일을 앱에 다시 넣고, 필요하다면 컴파일한 뒤, 화면을 테스트한 후에 병합하세요.
절대 어기면 안 되는 PO 파일 규칙
| PO 항목 | 번역해야 하나요? | 안전한 예시 | 중요한 이유 |
|---|---|---|---|
msgid | 아니오 | msgid "Save changes" | 앱이 이 소스 문자열을 여러 gettext 워크플로에서 조회 키로 사용합니다. |
msgstr | 예 | msgstr "Guardar cambios" | 사용자가 실제로 보는 대상 언어 텍스트입니다. |
msgctxt | 아니오 | msgctxt "button" | 동일한 소스 문자열을 구분하기 위해 컨텍스트가 필요합니다. |
%s, %d, %1$s | 아니오 | Hello, %s -> Hola, %s | 런타임 코드가 이 자리표시자를 실제 값으로 대체합니다. |
{name}, %(count)s, :name | 아니오 | Welcome, {name} | 변수 이름은 앱 코드와 반드시 일치해야 합니다. |
| HTML 태그 | 보통 아니오 | <strong>Warning</strong> | 텍스트만 번역하고 태그 문법은 그대로 둡니다. |
msgid_plural | 아니오 | msgid_plural "%d files" | 소스 복수형은 원래 코드 경로에 속합니다. |
msgstr[0], msgstr[1] | 예, 신중하게 | msgstr[0] "%d file" | 각 대상 언어마다 고유한 복수 규칙이 있습니다. |
#, fuzzy | 먼저 검토 | #, fuzzy | fuzzy는 번역이 오래되었거나 미확인 상태임을 의미합니다. |
#. 개발자 코멘트 | 보통 아니오 | #. Button label | 번역자가 컨텍스트를 이해하는 데 도움이 되는 참고 사항입니다. |
빠른 예시: 안전한 PO 번역 vs. 깨진 번역
다음은 일반적인 gettext 항목입니다:
#. %s is the user's display name.
#, c-format
msgid "Welcome back, %s"
msgstr ""
안전한 스페인어 번역은 %s를 그대로 유지합니다:
#. %s is the user's display name.
#, c-format
msgid "Welcome back, %s"
msgstr "Bienvenido de nuevo, %s"
깨진 번역은 자리표시자를 변경합니다:
msgid "Welcome back, %s"
msgstr "Bienvenido de nuevo, % s"
작은 공백 하나도 중요할 수 있습니다. GNU msgfmt --check-format는 잘못된 % 자리표시자처럼 포맷 문자열 불일치를 잡아내도록 설계되어 있으며, Poedit도 흔한 자리표시자 문제에 대해 경고합니다. 번역하지 말아야 할 문자열의 더 폭넓은 목록은 번역하지 말아야 할 것 가이드에서 확인할 수 있습니다.
번역된 PO 파일을 확인하는 방법
- gettext가 설치되어 있다면 gettext 검증을 실행하세요.
msgfmt --check --check-format -o /tmp/messages.mo path/to/messages.po
이 명령은 구문, 헤더, 형식 문자열을 검사한 후, 파일이 유효하면 임시로 컴파일된 카탈로그를 작성합니다.
- 프레임워크에서 기대하는 방식으로 파일을 컴파일하세요.
django-admin compilemessages
Django 프로젝트의 경우, compilemessages는 makemessages로 생성된 .po 파일을 gettext 지원을 위한 .mo 파일로 컴파일합니다.
- 빈 번역을 검색하세요.
grep -n 'msgstr ""' path/to/messages.po
빈 msgstr 필드는 번역되지 않은 항목에 대해 의도적으로 남겨둘 수 있지만, 릴리스 시 예상치 못한 상황이 발생하지 않도록 확인해야 합니다.
- fuzzy 문자열을 검색하세요.
grep -n '#, fuzzy' path/to/messages.po
fuzzy 문자열은 릴리스 전에 반드시 사람이 검토해야 합니다. 기본적으로 msgfmt는 fuzzy 번역을 사용하지 않으며, --use-fuzzy 옵션으로 컴파일할 때만 사용됩니다. 따라서 fuzzy 항목은 최종 카탈로그에서 번역되지 않은 문자열처럼 동작할 수 있습니다.
- 실제 UI를 테스트하세요. 폼, 복수형 카운트, 오류 메시지, 계정 메뉴, 결제 흐름이 포함된 화면을 직접 열어보세요. PO 파일 검증은 파일 문제를 잡아내지만, UI 테스트만이 어색한 표현, 오버플로우, 누락된 맥락을 발견할 수 있습니다.
어떤 방법을 사용해야 할까요?
| 상황 | 최적의 방법 | 이유 |
|---|---|---|
| PO 파일 하나에 대해 빠른 초안이 필요할 때 | PO 파일 번역기 | 구조를 유지하면서 가장 빠르게 번역 가능 |
| WordPress 플러그인이나 테마를 관리할 때 | Poedit | .mo 컴파일과 함께 익숙한 WordPress 워크플로우 제공 |
| Django 앱을 관리할 때 | PO 번역기 또는 Poedit, 그리고 compilemessages | 번역은 빠르지만 프레임워크 컴파일은 여전히 필요 |
| 여러 언어와 리뷰어가 있을 때 | 로컬라이제이션 플랫폼 | 할당, 이력, QA, 리뷰 관리가 더 효율적 |
| 개발자용 문자열을 번역할 때 | 기계 번역 후 인간 검토 | 코드 용어, 플레이스홀더, 맥락이 더 중요함 |
| JSON이나 프론트엔드 i18n 파일도 현지화할 때 | 형식별 워크플로우 사용 | PO 규칙이 JSON, YAML, ICU 메시지에는 항상 적용되지 않음 |
프로젝트에서 gettext PO 파일과 JSON 로케일 파일을 혼합해서 사용하는 경우, 각 형식의 구조를 이해하는 도구로 번역하세요. PO 파일은 msgid와 msgstr 중심이고, JSON 현지화는 키와 값 중심입니다. 이 워크플로우에 대해서는 2026년 최고의 JSON 번역기 가이드를 참고하세요.
FAQ
Google Translate로 PO 파일을 번역할 수 있나요?
개별 msgstr 값을 일반 번역기에 복사하는 것은 가능하지만, 전체 PO 파일을 일반 텍스트 번역기에 업로드하거나 붙여넣는 것은 위험합니다. 일반 번역기는 msgid, 주석, 따옴표 이스케이프, 복수 인덱스, 플레이스홀더 등을 변경할 수 있습니다. PO 구조를 인식하는 번역기, Poedit, 또는 로컬라이제이션 플랫폼을 사용하세요.
.po, .pot, .mo의 차이점은 무엇인가요?
.pot는 소스 코드에서 추출된 템플릿 파일로, 보통 원본 문자열만 있고 번역은 없습니다. .po는 특정 언어에 대한 편집 가능한 번역 파일입니다. .mo는 많은 gettext 기반 앱이 런타임에 로드하는 컴파일된 바이너리 카탈로그입니다.
msgid를 번역해야 하나요?
아니요, 일반적인 작업 흐름에서는 그렇지 않습니다. msgstr를 번역하세요. GNU gettext 매뉴얼에 따르면 msgid는 원본 미번역 문자열이고, msgstr는 번역된 문자열입니다. msgid 문자열은 gettext 도구에 의해 생성되고 관리됩니다.
PO 파일이 유효한지 어떻게 확인하나요?
gettext가 설치되어 있다면 msgfmt --check --check-format 명령을 실행하세요. 또는 Poedit에서 파일을 열거나, 사용하는 로컬라이제이션 플랫폼의 QA 검사를 활용할 수 있습니다. 이후 앱 내에서 파일을 컴파일하고 테스트하세요. 검증은 필수이지만, UI 테스트를 대체할 수는 없습니다.
플레이스홀더를 잘못 다루면 어떻게 되나요?
최선의 경우, 앱에서 이상한 문자열이 표시됩니다. 최악의 경우, 런타임 포매터가 오류를 발생시키며, 번역된 문자열이 코드에서 전달하는 변수와 더 이상 일치하지 않게 됩니다. 플레이스홀더는 항상 완전한 토큰 단위로만 이동해야 하며, 번역하거나 부분적으로 수정해서는 안 됩니다.
OpenL로 PO 파일을 번역할 수 있나요?
네, OpenL PO Translator는 gettext .po 파일을 위해 설계되었으며, 100개 이상의 언어로 번역하면서 플레이스홀더와 변수를 그대로 유지한다고 안내하고 있습니다. 문서 번역은 사용량 기반 결제 방식으로 제공되므로, PO 구조를 수동으로 모두 관리하는 것보다 빠른 초안이 필요할 때 활용할 수 있습니다. 만약 .pot 템플릿만 있다면, OpenL을 사용하기 전에 대상 언어의 .po 파일을 먼저 생성해야 합니다.
출처
- GNU gettext manual: PO Files — 공식 gettext의 PO 파일 형식 설명.
- GNU gettext manual: PO File Entries —
msgid,msgstr, 주석, 플래그, 항목 구조에 대한 공식 자료. - GNU gettext manual: Entries with Plural Forms — 복수형 항목 구조에 대한 공식 자료.
- GNU gettext manual: msgfmt Invocation —
msgfmt --check및 형식 문자열 검증에 대한 공식 자료. - OpenL PO Translator —
.po파일의 자리 표시자와 변수를 유지하며 번역하는 OpenL 제품 페이지. - Poedit — PO 번역 에디터 및 Pro 버전 공식 Poedit 사이트.
- WordPress Polyglots Handbook: Poedit — Poedit 사용법, POT 파일, PO 파일, MO 컴파일, 자리 표시자 경고에 대한 WordPress 안내서.
- Django documentation: Translation — 메시지 파일 및 번역을 위한 Django 워크플로우.
- Django documentation: compilemessages —
.po파일을.mo파일로 컴파일하는 Django 명령어 참고. - Drupal documentation: PO and POT files —
.po,.pot, 컨텍스트, 복수형, 주석, 변수에 대한 Drupal 설명. - Weblate documentation: GNU gettext PO — PO 헤더, 이전 소스 문자열, 폐기된 문자열, 생성된 MO 파일에 대한 로컬라이제이션 플랫폼 안내.