수색…


통사론

  • gettext (메시지)
  • ngettext (단수, 복수, 숫자)
  • ugettext (메시지)
  • ungettext (단수, 복수, 숫자)
  • pgettext (컨텍스트, 메시지)
  • npgettext (컨텍스트, 단수, 복수, 숫자)
  • gettext_lazy (메시지)
  • ngettext_lazy (단수, 복수, 숫자 = 없음)
  • ugettext_lazy (메시지)
  • ungettext_lazy (단수, 복수, 숫자 = 없음)
  • pgettext_lazy (컨텍스트, 메시지)
  • npgettext_lazy (컨텍스트, 단수, 복수, 숫자 = 없음)
  • gettext_noop (메시지)
  • ugettext_noop (메시지)

국제화 소개

설정

settings.py

from django.utils.translation import ugettext_lazy as _

USE_I18N = True  # Enable Internationalization
LANGUAGE_CODE = 'en'  # Language in which original texts are written
LANGUAGES = [  # Available languages
    ('en', _("English")),
    ('de', _("German")),
    ('fr', _("French")),
]

# Make sure the LocaleMiddleware is included, AFTER SessionMiddleware
# and BEFORE middlewares using internationalization (such as CommonMiddleware)
MIDDLEWARE_CLASSES = [
   'django.contrib.sessions.middleware.SessionMiddleware',
   'django.middleware.locale.LocaleMiddleware',
   'django.middleware.common.CommonMiddleware',
]

문자열을 번역 가능한 것으로 표시하기

번역의 첫 번째 단계는 문자열을 번역 가능 으로 표시하는 것 입니다. 이것은 gettext 함수 중 하나를 통해 전달합니다 ( 구문 섹션 참조 ). 예를 들어, 다음은 모델 정의의 예입니다.

from django.utils.translation import ugettext_lazy as _
# It is common to import gettext as the shortcut `_` as it is often used
# several times in the same file.

class Child(models.Model):

    class Meta:
        verbose_name = _("child")
        verbose_name_plural = _("children")

    first_name = models.CharField(max_length=30, verbose_name=_("first name"))
    last_name = models.CharField(max_length=30, verbose_name=_("last name"))
    age = models.PositiveSmallIntegerField(verbose_name=_("age"))

_() 캡슐화 된 모든 문자열은 이제 변환 가능한 것으로 표시됩니다. 인쇄 될 때, 선택된 언어에 상관없이 항상 캡슐화 된 문자열로 표시됩니다 (아직 번역을 사용할 수 없기 때문에).

문자열 변환

이 예제는 번역을 시작하기에 충분합니다. 대부분의 경우 문자열을 번역 가능한 것으로 표시하여 프로젝트의 국제화예상 할 수 있습니다. 따라서이 내용은 다른 예에서 다룹니다.

게으른 vs 비 게으른 번역

non-lazy translation을 사용할 때 문자열은 즉시 변환됩니다.

>>> from django.utils.translation import activate, ugettext as _
>>> month = _("June")
>>> month
'June'
>>> activate('fr')
>>> _("June")
'juin'
>>> activate('de')
>>> _("June")
'Juni'
>>> month
'June'

게으름을 사용할 때 번역은 실제로 사용될 때만 발생합니다.

>>> from django.utils.translation import activate, ugettext_lazy as _
>>> month = _("June")
>>> month
<django.utils.functional.lazy.<locals>.__proxy__ object at 0x7f61cb805780>
>>> str(month)
'June'
>>> activate('fr')
>>> month
<django.utils.functional.lazy.<locals>.__proxy__ object at 0x7f61cb805780>
>>> "month: {}".format(month)
'month: juin'
>>> "month: %s" % month
'month: Juni'

다음 경우에 게으른 번역을 사용해야합니다.

  • _("some string") 이 평가 될 때 번역이 활성화되지 않을 수 있습니다 (언어가 선택되지 않았습니다).
  • 일부 문자열은 시작시에만 평가 될 수 있습니다 (예 : 모델 및 양식 필드 정의와 같은 클래스 속성)

템플릿 번역

템플릿에서 번역을 사용하려면 i18n 라이브러리를로드해야합니다.

{% load i18n %}

기본 번역은 trans 템플릿 태그로 이루어집니다.

{% trans "Some translatable text" %}
{# equivalent to python `ugettext("Some translatable text")` #}

trans 템플릿 태그는 컨텍스트를 지원합니다.

{% trans "May" context "month" %}
{# equivalent to python `pgettext("May", "month")` #}

번역 문자열에 자리 표시자를 포함하려면 다음과 같이하십시오.

_("My name is {first_name} {last_name}").format(first_name="John", last_name="Doe")

blocktrans 템플릿 태그를 사용해야합니다 :

{% blocktrans with first_name="John" last_name="Doe" %}
  My name is {{ first_name }} {{ last_name }}
{% endblocktrans %}

물론 "John""Doe" 대신 변수 및 필터를 사용할 수 있습니다.

{% blocktrans with first_name=user.first_name last_name=user.last_name|title %}
  My name is {{ first_name }} {{ last_name }}
{% endblocktrans %}

first_namelast_name 이 이미 컨텍스트에있는 경우 with 절을 생략 할 수도 있습니다.

{% blocktrans %}My name is {{ first_name }} {{ last_name }}{% endblocktrans %}

그러나 "최상위"컨텍스트 변수 만 사용할 수 있습니다. 이 작동하지 않습니다 :

{% blocktrans %}
    My name is {{ user.first_name }} {{ user.last_name }}
{% endblocktrans %}

변수 이름이 번역 파일의 자리 표시 자로 사용되기 때문입니다.

blocktrans 템플릿 태그는 복수형도 허용합니다.

{% blocktrans count nb=users|length }}
    There is {{ nb }} user.
{% plural %}
    There are {{ nb }} users.
{% endblocktrans %}

마지막으로, i18n 라이브러리에 관계없이 _("") 구문을 사용하여 변환 가능한 문자열을 템플리트 태그에 전달할 수 있습니다.

{{ site_name|default:_("It works!") }}
{% firstof var1 var2 _("translatable fallback") %}

이것은 함수 호출 문법을 모방하는 magic built-in django 템플릿 시스템이지만 이것은 함수 호출이 아닙니다. _("It works!")default 템플릿 태그에 문자열 '_("It works!")' _("It works!") 전달되며,이 문자열은 name 이 변수로 구문 분석되고 "name" 이 될 것처럼 번역 가능한 문자열로 구문 분석됩니다 문자열로 구문 분석됩니다.

문자열 변환

문자열을 번역하려면 번역 파일을 만들어야합니다. 이렇게하기 위해 django는 makemessages 라는 관리 명령을 makemessages 합니다.

$ django-admin makemessages -l fr
processing locale fr

위의 명령은 설치된 앱에서 translatable로 표시된 모든 문자열을 검색하고 각 언어 번역을위한 하나의 언어 파일을 만듭니다. 예를 들어 번역 가능한 문자열이 포함 된 app myapp 가 하나 뿐인 경우 myapp/locale/fr/LC_MESSAGES/django.po 파일이 만들어 myapp/locale/fr/LC_MESSAGES/django.po . 이 파일은 다음과 같을 수 있습니다.

# 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: 2016-07-24 14:01+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#: myapp/models.py:22
msgid "user"
msgstr ""

#: myapp/models.py:39
msgid "A user already exists with this email address."
msgstr ""

#: myapp/templates/myapp/register.html:155
#, python-format
msgid ""
"By signing up, you accept our <a href=\"%(terms_url)s\" "
"target=_blank>Terms of services</a>."
msgstr ""

먼저 자리 표시자를 채워야합니다 (대문자로 강조). 그런 다음 문자열을 번역하십시오. msgid 는 코드에서 translatable로 표시된 문자열입니다. msgstr 바로 위 문자열의 번역을 작성해야합니다.

문자열에 자리 표시자가 포함되어 있으면 번역에도 포함시켜야합니다. 예를 들어 최신 메시지를 다음과 같이 번역합니다.

#: myapp/templates/myapp/register.html:155
#, python-format
msgid ""
"By signing up, you accept our <a href=\"%(terms_url)s\" "
"target=_blank>Terms of services</a>."
msgstr ""
"En vous inscrivant, vous acceptez nos <a href=\"%(terms_url)s\" "
"target=_blank>Conditions d'utilisation</a>"

번역 파일이 완성되면 .po 파일을 .mo 파일로 컴파일해야합니다. 이것은 compilemessages 관리 명령을 호출하여 수행됩니다.

$ django-admin compilemessages

이제 번역이 가능합니다.

코드를 변경할 때 번역 파일을 업데이트하려면 django-admin makemessages -l fr 다시 실행하십시오. 이렇게하면 .po 파일이 업데이트되어 기존 번역이 유지되고 새 번역본이 추가됩니다. 삭제 된 문자열은 여전히 ​​댓글에서 사용할 수 있습니다. 모든 언어에 대한 .po 파일을 업데이트하려면 django-admin makemessages -a 실행하십시오. .po 파일이 업데이트되면 django-admin compilemessages 다시 실행하여 .mo 파일을 생성하는 것을 잊지 마십시오.

Noop 유스 케이스

(u)gettext_noop 는 실제로 번역하지 않고 문자열을 번역 가능으로 표시하도록합니다.

일반적인 사용 사례는 개발자를위한 메시지를 영어로 기록하고 클라이언트에 요청한 언어로 메시지를 표시하려는 경우입니다. gettext 변수를 전달할 수는 있지만 정의에 따라 변수가 있기 때문에 내용이 변환 가능한 문자열로 발견되지 않습니다. .

# THIS WILL NOT WORK AS EXPECTED
import logging 
from django.contrib import messages

logger = logging.getLogger(__name__)

error_message = "Oops, something went wrong!"
logger.error(error_message)
messages.error(request, _(error_message))

오류 메시지는 .po 파일에 나타나지 않으므로 수동으로 추가하려면 존재 함을 기억해야합니다. 이 문제를 해결하려면 gettext_noop 을 사용할 수 있습니다.

error_message = ugettext_noop("Oops, something went wrong!")
logger.error(error_message)
messages.error(request, _(error_message))

이제 문자열 "Oops, something went wrong!" 생성 될 때 .po 파일에서 발견되어 사용 가능합니다. 오류는 개발자를 위해 영어로 계속 기록됩니다.

일반적인 함정

퍼지 번역

때때로 makemessages 는 번역을 위해 찾은 문자열이 기존 번역과 다소 유사하다고 생각할 수도 있습니다. 이것은 .po 파일에 다음과 같이 특별한 fuzzy 주석을 달아 표시합니다.

#: templates/randa/map.html:91
#, fuzzy
msgid "Country"
msgstr "Länderinfo"

번역이 정확하거나 수정하기 위해 수정 한 경우에도 fuzzy 주석 행을 제거하지 않으면 프로젝트를 번역하는 데 사용되지 않습니다.

여러 줄

makemessages 는 일반 텍스트에서부터 파이썬 코드에 이르는 다양한 형식의 파일을 구문 분석하며 여러 형식의 다중 행 문자열을 갖는 모든 가능한 규칙을 따르도록 설계되지 않았습니다. 대부분의 경우 단 한 줄의 문자열로도 잘 작동하지만 다음과 같은 구조를 가지고 있다면 :

translation = _("firstline"
"secondline"
"thirdline")

번역을위한 firstline 선택합니다. 이를 해결하려면 가능한 경우 여러 줄 문자열을 사용하지 않는 것이 좋습니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow