Интернационализация локального проекта django

в 14:30, , рубрики: django, i18n, python, разработка, метки: , ,

Хорошо, когда при разработке проекта под django, разработчики проекта изначально озаботились его интернационализацией.

Минимальными усилиями, проект адаптируется под различные языки. Django имеет богатый набор инструментов, достаточный для почти автоматического добавления новых языков, исправления и добавления переводов отдельных участков текста и так далее.

Ситуация выглядит совсем иначе, если проект изначально не предназначался для интернационализации. Огромный массив файлов, в которых разбросаны локальные строки в совершеннейшем беспорядке, при этом многие из них дублируются в разных файлах. Собирать все эти строчки в один файл, сортировать, заменять их содержимое в исходных файлах на идентификаторы сообщений — огромная и неблагодарная работа.

Встретившись с этой задачей, я понял, что выполняя ее вручную, я умру от скуки, если прежде того меня не стошнит. При этом я с удивлением обнаружил, что инструментов, которые бы облегчали мне жизнь хотя бы наполовину, до сих пор нет. Четыре дня работы — и на свет появился проект django-make-i18n, который я вам и представляю.

Всю работу выполняет один достаточно объемный скрипт на python. Дополнительно к питону (у меня 2.7), сам скрипт зависит только от polib и не требует наличия окружения django.

Запуская скрипт в первый раз и напуская его на каталог проекта, вы получаете заготовку файла django.po, в которой собраны все обнаруженные строки на локальном (по умолчанию — русском) языке. Пойманные строки размещены в разделах msgstr, а msgid заполнены начальным значением «NEEDS TO BE EDITED [nnn]».

Исходные файлы не изменяются, вместо этого рядом с исходным проектом создается параллельный, с добавлением к имени каталога расширения .i18n.

Далее вам предстоит пройтись по файлу django.po и произвести «обратный перевод», то есть заменить начальные значения msgid каким-нибудь внятным эквивалентом на английском языке. Надо только следить, чтобы у всех строк msgid значения при этом оставались уникальными.

Второй запуск скрипта анализирует файл django.po и производит подстановку обращений к подсистеме перевода вместо исходных локальных строк. Например, допустим Вы имеете файл views.py, в котором размещен следующий код:

    if request.method == 'POST': # If the form has been submitted...
        post = True
        logging.info('POST запрос обнаружен')
        request_form = RequestVideoForm(request.POST)
        if request_form.is_valid(): # All validation rules pass
            logging.info('Форма верна')
            ok = True
            send_request(request,request_form,request.region.urlname,'feedback@doroga.tv')
            message = u'Ваша заявка была отправлена'
            request_form = None
            # clean form
        else:
            message = u'Исправьте данные в форме'

После первого запуска скрипта, в django.po обнаружатся строки примерно следующего содержания:

msgid "NEEDS TO BE EDITED [333]"
msgstr "POST запрос обнаружен"

msgid "NEEDS TO BE EDITED [334]"
msgstr "Форма верна"   

msgid "NEEDS TO BE EDITED [335]"
msgstr "Ваша заявка была отправлена"

msgid "NEEDS TO BE EDITED [336]"
msgstr "Исправьте данные в форме"

Если вы ничего не измените в файле django.po, то после второго запуска скрипта, будет создана копия файла views.py, содержащая примерно следующие строки:

    if request.method == 'POST': # If the form has been submitted...
        post = True
        logging.info(_('NEEDS TO BE EDITED [333]'))
        request_form = RequestVideoForm(request.POST)
        if request_form.is_valid(): # All validation rules pass
            logging.info(_('NEEDS TO BE EDITED [334]'))
            ok = True
            send_request(request,request_form,request.region.urlname,'feedback@doroga.tv')
            message = _('NEEDS TO BE EDITED [335]')
            request_form = None
            # clean form
        else:
            message = _('NEEDS TO BE EDITED [336]')
        
    else:
        logging.info(_('NEEDS TO BE EDITED [337]'))
        request_form = RequestVideoForm(auto_id=True)

Попробуем заполнить строки в django.po следующим образом:

msgid "POST request has been found"
msgstr "POST запрос обнаружен"

msgid "Form is valid"   
msgstr "Форма верна"

msgid "Your request has just been sent"
msgstr "Ваша заявка была отправлена"

msgid "Fix form data"   
msgstr "Исправьте данные в форме"

Запускаем скрипт еще раз — и получаем вполне сносный код следующего вида:

    if request.method == 'POST': # If the form has been submitted...
        post = True
        logging.info(_('POST request has been found'))
        request_form = RequestVideoForm(request.POST)
        if request_form.is_valid(): # All validation rules pass
            logging.info(_('Form is valid'))
            ok = True
            send_request(request,request_form,request.region.urlname,'feedback@doroga.tv')
            message = _('Your request has just been sent')
            request_form = None
            # clean form
        else:
            message = _('Fix form data')

Дополнительно, скрипт добавляет в начало файла код импорта пакета интернационализации:

from django.utils.translation import ugettext as _

на случай, если вы случайно забыли сделать это.

Те же операции, с учетом специфики языка и использования django, выполняются на файлах html и js. При этом для JavaScript создается файл djangojs.po.

Осталось скомпилировать сообщения:

python manage.py compilemessages --all

Вуаля — ваш проект подготовлен к интернализации. Конечно, еще остается много всяких деталей самой интернационализации под django, но они выходят за рамки данной статьи.

Автор: nnseva

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js