장고 - 번역 기능 학습

  • 장고에서 번역 기능을 사용하는 것을 I18N(Internationalization)을 사용한다고 한다.
  • 이번 포스트에서는 I18N 기능 사용법에 대해 알아볼 것이다.

장고 프로젝트에 번역 기능 추가

ex) python-api 프로젝트

1. 기본 언어 설정

  • 경로 : config(프로젝트) > settings.py
    1
    2
    LANGUAGE_CODE = 'ko-KR'
    TIME_ZONE = 'Asia/Seoul'

2. 다국어 지원을 하기 위해 LocaleMiddleware 추가

  • LocalMiddleware는 세션 데이터를 사용하고,
  • CommonMiddleware가 언어를 활성화하는 작업을 수행하므로,
  • Session과 Commen 사이에 위치시켜야 한다.
  • 경로 : config(프로젝트) > settings.py
    1
    2
    3
    4
    5
    6
    7
    MIDDLEWARE = [
    ...
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.middleware.common.CommonMiddleware',
    ...
    ]

3. 지원하고 싶은 언어 설정

  • 경로 : config > settings.py
    1
    2
    3
    4
    5
    6
    from django.utils.translation import ugettext_lazy as_

    LANGUAGES = [
    ('ko', _('Korean')),
    ('en', _('English')),
    ]

4. 번역 파일이 저장될 폴더 생성

  • 경로 : config > settings.py
    1
    2
    3
    LOCALE_PATHS = (
    os.path.join(BASE_DIR, 'locale'),
    )

5. 번역할 텍스트를 입력할 샘플 뷰 작성

  • 경로 : sample > views.py
    1
    2
    3
    4
    5
    6
    7
    # 한글 메시지를 영어로 번역되도록 설정
    from django.http import HttpResponse
    from django.utils.translation import ugettext_lazy as _
    from django.utils import translation
    def index(request):
    msg = _("안녕하세요 조누스") # _(message) --> message를 번역하겠다.
    return HttpResponse(msg)

6. 번역할 텍스트 목록 파일 생성

  • 경로 : python_api > 터미널
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $ python manage.py makemessages -a
    # 최초 실행 시, 언어별 별도 실행
    # -i venv : venv 파일 무시하고 실행
    $ python manage.py makemessages -l ko -i venv
    $ python manage.py makemessages -l en -i venv

    # 만약 gettext가 없다는 오류 발생 시,
    Mac)
    $ brew install gettext
    $ brew link gettext --force

    ubuntu)
    $ sudo apt-get install gettext

7. locale 디렉토리에 생성된 django.po 파일을 열어서, ‘#, fuzzy’ 줄 제거

  • 경로 : locale > en 혹은 ko > LC_MESSAGES > django.po

8. django.po 파일에서 msgid를 참고하여 msgstr 설정

  • id를 보고 str에 번역 내용 입력
  • 경로 : locale > en > LC_MESSAGES > django.po
    1
    2
    3
    #: sample/templates/sample/index.html:11
    msgid "안녕하세요 조누스"
    msgstr "Hi Jonus"

9. 번역 내용을 장고에서 읽어 처리할 수 있도록 mo 파일 생성

  • 경로 : python_api > 터미널
    1
    2
    3
    $ python manage.py compilemessages
    # 만약 언어 파일별로 컴파일 하고 싶다면,
    $ python manage.py compilemessage -l ko

10. 번역 파일 정상 작동하는지 확인 위해 강제로 언어설정 변경

  • 경로 : sample > views.py

    1
    2
    3
    4
    5
    6
    # 기존 LANGUAGE_SESSION_KEY 삭제하고, 'en'으로 활성화
    if translation.LANGUAGE_SESSION_KEY in request.session:
    del(request.session[translation.LANGUAGE_SESSION_KEY])
    translation.activate('en')

    request.session[translation.LANGUAGE_SESSION_KEY] = 'en'
  • 브라우저로 해당 뷰 접속해 보면 ‘안녕하세요 조누스’ 대신 ‘Hi Jonus’ 표시

11. 언어 설정을 사용자가 선택해서 변경할 수 있도록 뷰 생성

  • 경로 : sample > views.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    from django.shortcuts import render
    from django.http import HttpResponse
    from django.utils import translation
    from django.conf import settings
    # 1) url named group 을 통해 language code 받기
    def change_language(request, code):
    # 지원하는 언어 코드 목록을 만듦
    languages = [language[0] for language in settings.LANGUAGES]
    # 기본 언어 설정 가져오기
    default_language = settings.LANGUAGE_CODE[:2] # LANGUAGE_CODE = 'ko-KR'

    if translation.LANGUAGE_SESSION_KEY in request.session:
    del(request.session[translation.LANGUAGE_SESSION_KEY])
    # code가 지원하는 언어코드이고 기본 언어 설정이 아닌 경우, 원하는 언어로 번역 실행
    if code in languages and code != default_language:
    translation.activate(code)
    request.session[translation.LANGUAGE_SESSION_KEY] = code
    else:
    request.session[translation.LANGUAGE_SESSION_KEY] = default_language
    code = default_language

    return HttpResponse("Language Change to "+code)

    # 2) 쿼리 스트링으로 language code 받기
    def change_language2(request):
    code = request.GET.get('code')
    if translation.LANGUAGE_SESSION_KEY in request.session:
    del(request.session[translation.LANGUAGE_SESSION_KEY])
    translation.activate(code)

    request.session[translation.LANGUAGE_SESSION_KEY] = code

    return HttpResponse("Language Change to "+code)

12. 템플릿 번역 기능 사용

  • 템플릿에서 번역 기능 사용하려면, ‘load i18n’ 사용하고 trans 태그 사용해야 한다.
  • 경로 : sample > templates > sample > index.html
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <!DOCTYPE html>
    <html lang="{{LANGUAGE_CODE}}">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body>
    {% load i18n %}
    {% trans '안녕하세요' %}
    <!-- 여러 줄이 들어가있는 번역 블록 설정 -->
    {% blocktrans %}
    블록 번역
    테스트하는 중입니다.
    {% endblocktrans %}
    <!-- context가 있는 번역을 템플릿에서 사용-->
    {% blocktrans context '구어' %}안녕 조누스{% endblocktrans %}
    </body>
    </html>

13. 뷰에서 context를 가진 번역 진행

  • 경로 : sample > views.py
    1
    2
    3
    4
    from django.utils.translation import pgettext_lazy as __
    def index(request):
    msg = __("구어", "안녕하세요")
    return HttpResponse(msg)

14. 언어 선택창 생성하여 해당 언어로 번역 표시되도록 진행

  • 경로 : sample > forms.py

    1
    2
    3
    4
    5
    from django import forms
    from django.conf import settings
    # 언어 선택 폼 생성
    class LanguageForm(forms.Form):
    code = forms.ChoiceField(choices=settings.LANGUAGES)
  • 경로 : sample > context_processors.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    from .forms import LanguageForm
    from django.utils import translation
    # code를 context_processors 로 설정
    def language(request):
    language_form = LanguageForm()
    if translation.LANGUAGE_SESSION_KEY in request.session:
    current_language = request.session[translation.LANGUAGE_SESSION_KEY]
    language_form = LanguageForm(initial={'code':current_language})

    return {'language_form':language_form}
  • 경로 : config > settings.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 설정에서 sample 앱의 context_processors 추가
    TEMPLATES = [
    {
    ...
    'OPTIONS': {
    'context_processors': [
    ...
    'sample.context_processors.language',
    ],
    },
    },
    ]
  • 경로 : sample > templates > sample > index.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <!DOCTYPE html>
    <html lang="{{LANGUAGE_CODE}}">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body>
    <!-- 언어 선택창 생성 -->
    <!-- 폼 전송 시, 이동할 경로 설정 -->
    <form action="{% url 'change_language' %}" method="post">
    {% csrf_token %}
    {{language_form.as_p}}
    <input type="submit" value="Change">
    </form>
    {% load i18n %}
    {% trans '안녕하세요 조누스' %}
    {% blocktrans context '구어' %}안녕 조누스{% endblocktrans %}
    </body>
    </html>
  • 경로 : sample > views.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    from django.shortcuts import redirect
    from .forms import LanguageForm
    def change_language(request):
    language_form = LanguageForm(request.POST)
    if language_form.is_valid():
    language = language_form.cleaned_data['code']
    languages = [language[0] for language in settings.LANGUAGES]
    if translation.LANGUAGE_SESSION_KEY in request.session:
    if language in languages:
    del (request.session[translation.LANGUAGE_SESSION_KEY])
    translation.activate(language)
    request.session[translation.LANGUAGE_SESSION_KEY] = language
    url = request.META['HTTP_REFERER']
    return redirect(url)
  • 경로 : sample > urls.py

    1
    2
    3
    4
    5
    6
    7
    # 폼 전송 후, 이동할 경로 설정
    from django.urls import path
    from .views import *

    urlpatterns = [
    path('changelanguage/', change_language, name='change_language'),
    ]