gettext — 다국어 국제화 서비스
gettext — 다국어 국제화 서비스
gettext 모듈은 파이썬 모듈과 애플리케이션을 위한 국제화(I18N) 및 지역화(L10N) 서비스를 제공해요. GNU gettext 메시지 카탈로그 API와, 파이썬 파일에 더 적합할 수 있는 더 높은 수준의 클래스 기반 API를 모두 지원해요. 아래에 설명된 인터페이스를 사용하면 모듈과 애플리케이션 메시지를 하나의 자연 언어로 작성하고, 다른 자연 언어로 실행하기 위한 번역된 메시지 카탈로그를 제공할 수 있어요.
본문
GNU gettext API
gettext 모듈은 GNU gettext API와 매우 유사한 다음 API를 정의해요. 이 API를 사용하면 전체 애플리케이션의 번역에 전역적으로 영향을 줘요. 애플리케이션이 단일 언어이고 사용자의 로케일에 따라 언어가 결정되는 경우 종종 원하는 동작이에요. 파이썬 모듈을 지역화하거나 애플리케이션이 즉시 언어를 전환해야 하는 경우에는 클래스 기반 API를 사용하는 것이 좋아요.
gettext.bindtextdomain(domain, localedir=None) — 도메인을 로케일 디렉터리 localedir에 바인딩해요. 구체적으로 gettext는 주어진 도메인에 대해 경로 localedir/language/LC_MESSAGES/domain.mo(Unix 기준)를 사용해 바이너리 .mo 파일을 찾으며, 언어는 환경 변수 LANGUAGE, LC_ALL, LC_MESSAGES, LANG에서 순서대로 검색해요. localedir이 생략되거나 None이면 domain에 대한 현재 바인딩이 반환돼요.
gettext.textdomain(domain=None) — 현재 전역 도메인을 변경하거나 조회해요. domain이 None이면 현재 전역 도메인이 반환되고, 그렇지 않으면 전역 도메인이 domain으로 설정되어 반환돼요.
gettext.gettext(message, /) — 현재 전역 도메인, 언어, 로케일 디렉터리를 기반으로 message의 지역화된 번역을 반환해요. 이 함수는 보통 로컬 네임스페이스에서 _()로 별칭 처리돼요.
gettext.dgettext(domain, message, /) — gettext()와 같지만 메시지를 지정된 도메인에서 찾아요.
gettext.ngettext(singular, plural, n, /) — gettext()와 같지만 복수 형태를 고려해요. 번역이 발견되면 복수 공식을 n에 적용해 결과 메시지를 반환해요(일부 언어는 두 개 이상의 복수 형태를 가짐). 번역이 없으면 n이 1이면 singular를, 그렇지 않으면 plural을 반환해요.
복수 공식은 카탈로그 헤더에서 가져와요. 이는 자유 변수 n을 가진 C 또는 파이썬 표현식으로, 카탈로그에서 복수의 인덱스로 평가돼요.
gettext.dngettext(domain, singular, plural, n, /) — ngettext()와 같지만 메시지를 지정된 도메인에서 찾아요.
gettext.pgettext(context, message, /), gettext.dpgettext(domain, context, message, /), gettext.npgettext(context, singular, plural, n, /), gettext.dnpgettext(domain, context, singular, plural, n, /) — 접두사에 p가 없는 대응 함수(gettext(), dgettext(), ngettext(), dngettext())와 비슷하지만 번역이 주어진 메시지 컨텍스트로 제한돼요. 버전 3.8에서 추가됨.
GNU gettext는 dcgettext() 메서드도 정의하지만, 유용하지 않다고 판단되어 현재 구현되지 않았어요.
이 API의 일반적인 사용 예시:
import gettext
gettext.bindtextdomain('myapplication', '/path/to/my/language/directory')
gettext.textdomain('myapplication')
_ = gettext.gettext
print(_('This is a translatable string.'))
클래스 기반 API
gettext 모듈의 클래스 기반 API는 GNU gettext API보다 더 많은 유연성과 편의성을 제공하며, 파이썬 애플리케이션과 모듈을 지역화하는 권장 방법이에요. gettext는 GNU .mo 형식 파일의 파싱을 구현하고 문자열을 반환하는 메서드를 가진 GNUTranslations 클래스를 정의하며, 이 클래스의 인스턴스는 내장 네임스페이스에 함수 _()로 설치될 수도 있어요.
gettext.find(domain, localedir=None, languages=None, all=False) — 표준 .mo 파일 검색 알고리즘을 구현해요. textdomain()이 받는 것과 동일한 domain을 받아요. Languages는 언어 코드 문자열의 리스트예요. localedir이 주어지지 않으면 기본 시스템 로케일 디렉터리가 사용되고, languages가 주어지지 않으면 환경 변수 LANGUAGE, LC_ALL, LC_MESSAGES, LANG을 검색해요. find()는 localedir/language/LC_MESSAGES/domain.mo 구성의 존재하는 첫 번째 파일을 반환하고, 없으면 None을 반환해요. all이 주어지면 모든 파일 이름의 리스트를 반환해요.
gettext.translation(domain, localedir=None, languages=None, class_=None, fallback=False) — domain, localedir, languages를 기반으로 *Translations 인스턴스를 반환해요. 이들은 먼저 find()에 전달되어 관련 .mo 파일 경로 리스트를 얻어요. .mo 파일이 없으면 fallback이 false(기본값)일 때 OSError를 발생시키고, fallback이 true일 때 NullTranslations 인스턴스를 반환해요.
gettext.install(domain, localedir=None, *, names=None) — domain과 localedir을 기반으로 파이썬의 내장 네임스페이스에 함수 _()를 설치해요. 일반적으로 애플리케이션의 번역 대상 문자열을 _() 호출로 감싸서 표시해요.
NullTranslations 클래스
class gettext.NullTranslations(fp=None) — 모든 번역 클래스가 사용하는 기본 클래스로, 직접 특수화된 번역 클래스를 작성할 수 있는 기본 인터페이스를 제공해요. _parse() 메서드는 기본 클래스에서 no-op이며, 지원되지 않는 메시지 카탈로그 파일 형식이 있으면 이 메서드를 오버라이드해 형식을 파싱할 수 있어요.
add_fallback(fallback) — 현재 번역 객체의 폴백 객체로 fallback을 추가해요. 번역 객체는 주어진 메시지에 대한 번역을 제공할 수 없으면 폴백을 참조해야 해요.
gettext(message, /), ngettext(singular, plural, n, /), pgettext(context, message, /), npgettext(context, singular, plural, n, /) — 폴백이 설정되어 있으면 폴백으로 전달하고, 그렇지 않으면 메시지를 반환해요. 파생 클래스에서 오버라이드돼요.
info() — 메시지 카탈로그 파일에서 찾은 메타데이터를 포함하는 딕셔너리를 반환해요.
charset() — 메시지 카탈로그 파일의 인코딩을 반환해요.
install(names=None) — gettext()를 내장 네임스페이스에 설치해 _에 바인딩해요. names 파라미터가 주어지면 _() 외에 설치할 함수 이름의 시퀀스여야 하며, 지원되는 이름은 'gettext', 'ngettext', 'pgettext', 'npgettext'예요.
지역화된 모듈은 전역적으로 내장 네임스페이스에 영향을 주므로 _()를 설치하면 안 돼요. 대신:
import gettext
t = gettext.translation('mymodule', ...)
_ = t.gettext
GNUTranslations 클래스
class gettext.GNUTranslations — NullTranslations에서 파생된 추가 클래스로, GNU gettext 형식의 .mo 파일을 빅엔디언과 리틀엔디언 형식 모두에서 읽을 수 있도록 _parse()를 오버라이드해요. .mo 파일의 매직 넘버가 유효하지 않거나, 메이저 버전 번호가 예상과 다르거나, 파일을 읽는 중 다른 문제가 발생하면 GNUTranslations 클래스를 인스턴스화할 때 OSError가 발생할 수 있어요.
n = len(os.listdir('.'))
cat = GNUTranslations(somefile)
message = cat.ngettext(
'There is %(num)d file in this directory',
'There are %(num)d files in this directory',
n) % {'num': n}
프로그램과 모듈 국제화
국제화(I18N)는 프로그램이 여러 언어를 인식하게 되는 작업을 뜻하고, 지역화(L10N)는 국제화된 프로그램을 로컬 언어와 문화적 관습에 맞게 적응시키는 것을 뜻해요. 다국어 메시지를 제공하려면 다음 단계를 수행해야 해요:
- 번역 가능한 문자열을 특별히 표시해 프로그램이나 모듈을 준비한다.
- 표시된 파일에 도구 모음을 실행해 원시 메시지 카탈로그를 생성한다.
- 메시지 카탈로그의 언어별 번역을 만든다.
- 메시지 문자열이 제대로 번역되도록
gettext모듈을 사용한다.
xgettext, pygettext 등은 마크된 각 문자열과 그 번역본의 자리 표시자를 포함하는 .po 파일을 생성해요. 이 파일들은 번역가에게 넘겨져 <language-name>.po 파일로 완성되고, msgfmt 프로그램으로 기계 판독 가능한 .mo 바이너리 카탈로그로 컴파일돼요. .mo 파일은 런타임에 gettext 모듈이 실제 번역 처리에 사용해요.
모듈 지역화 — 모듈을 지역화할 때는 내장 네임스페이스 같은 전역 변경을 하지 않도록 주의해야 해요. GNU gettext API 대신 클래스 기반 API를 사용해야 해요:
import gettext
t = gettext.translation('spam', '/usr/share/locale')
_ = t.gettext
애플리케이션 지역화 — 애플리케이션을 지역화할 때는 보통 메인 드라이버 파일에서 _() 함수를 전역적으로 내장 네임스페이스에 설치할 수 있어요:
import gettext
gettext.install('myapplication')
즉석 언어 변경 — 프로그램이 동시에 많은 언어를 지원해야 한다면 여러 번역 인스턴스를 만들고 명시적으로 전환할 수 있어요:
lang1 = gettext.translation('myapplication', languages=['en'])
lang2 = gettext.translation('myapplication', languages=['fr'])
lang1.install()
lang2.install()
지연 번역(Deferred translations) — 보통 문자열은 코딩된 곳에서 번역되지만, 가끔은 번역을 위해 문자열을 표시하면서 실제 번역은 나중으로 미뤄야 할 때가 있어요. 더미 정의 def _(message): return message를 사용하면 문자열을 변경 없이 그대로 유지하면서 나중에 번역할 수 있어요.