Интернационализация Django - ЧАСТЬ 1

Опубликовал: Saturday, February 18, 2024 в категории Django | Пока нет комментариев

Фреймворк Django изначально разрабатывался буквально в центре Соединенных Штатов, ведь расстояние от города Лоуренс в штате Канзас до географического центра континентальной части США составляет меньше 55 км. Но, как и большинство проектов с открытым исходным кодом, сообщество Django разрослось и теперь включает людей со всего мира. По мере роста сообщества все большую значимость приобретают вопросы интернационализации и локализации. Поскольку многие разработчики имеют расплывчатое представление об этих терминах, дадим их краткие определения.

Интернационализация - это методика проектирования программ, рассчитанных на работу с любыми языками и культурными особенностями. Сюда относится реализация возможности перевода текста в элементах пользовательского интерфейса и сообщений об ошибках, абстрагирование отображения даты и времени, чтобы можно было адаптироваться к местным стандартам, поддержка часовых поясов и вообще такая организация кода, чтобы в нем не было никаких допущений о местонахождении пользователя. Слово интернационализация (iinternationalization) часто сокращают до I18N (здесь 18 - количество пропущенных букв между начальной I и конечной N).

Локализация - это процедура фактического перевода интернациональной программы на конкретный язык с учетом конкретных культурных особенностей (все вместе называется локалъю). Иногда слово локализация (localization) сокращают до L10N.

Сам фреймворк Django полностью интернационализирован; для всех строк предусмотрена возможность перевода, а порядок отображения величин, зависящих от локали (например, даты и времени), контролируется параметрами настройки. В дистрибутив Django входит свыше 50 файлов локализации. Если ваш родной язык не английский, то с большой вероятностью Django уже включает соответствующий перевод.

Для локализации своего кода и шаблонов вы можете использовать эту же подсистему интернационализации.

Для этого необходимо расставить в коде и шаблонах совсем немного дополнительных элементов, которые называются переводимыми строками и сообщают Django: «Этот текст следует перевести на язык конечного пользователя, если перевод на этот язык существует».

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

При этом Django решает двойную задачу:

•      Позволяет разработчикам и авторам шаблонов определить, какие части приложения подлежат переводу.

•      Использует полученную информацию, чтобы перевести приложения Django на язык пользователя в соответствии с его языковыми настройками.

Примечание —————————————————————————

Механизм перевода в Django основан на библиотеке GNU gettext (http://www. gnu.org/software/gettext/), интерфейс с которой реализован в стандартном модуле Python gettext.

Для интернационализации приложения Django следует выполнить следующие действия:

1.     Вставить переводимые строки в Python-код и в шаблоны.

2.     Выполнить перевод этих строк на поддерживаемые языки.

3.     Активировать дополнительный процессор локали в файле параметров.

Ниже мы подробно рассмотрим эти шаги.

Если вам не нужна интернационализация

По умолчанию поддержка интернационализации в Django включена, что приводит к небольшим накладным расходам. Если вы не собираетесь пользоваться механизмом интернационализации, то можете включить в файл параметров строку USE_I18N = False. В этом случае Django обойдет загрузку механизма интернационализации.

Возможно также желательно будет удалить строку ‘django.core. context_processors.i18n’ из параметра TEMPLATE_CONTEXT_PROCESSORS.

Как определять переводимые строки

Переводимая строка означает, что «данный текст должен быть переведен». Такие строки могут встречаться как в коде, так и в шаблонах. Пометить строки как переводимые вы должны сами; система может перевести лишь строки, о которых знает.

В коде на языке Python Стандартный перевод

Определите переводимую строку с помощью функции ugettext(). По соглашению ее принято импортировать в виде короткого синонима _.

В следующем примере текст "Welcome to my site" помечен как переводимая строка:

from django.utils.translation import ugettext as

def my_view(request):

output = _("Welcome to my site.") return HttpResponse(output)

Понятно, что можно было бы обойтись и без синонима:

from django.utils.translation import ugettext

def my_view(request):

output = ugettext("Welcome to my site.") return HttpResponse(output)

Переводиться могут также вычисляемые значения, поэтому оба примера выше эквивалентны следующему:

def my_view(request):

words = [‘Welcome’, ‘to’, ‘my’, ‘site.’] output = _(‘ ‘.join(words)) return HttpResponse(output)

Перевод применяется и к переменным. Вот еще одна эквивалентная форма:

def my_view(request):

sentence = ‘Welcome to my site.’ output = _(sentence) return HttpResponse(output)

Предупреждение ———————————————————————-

Предусматривая перевод переменных или вычисляемых значений, имейте

в виду, что входящая в дистрибутив Django утилита извлечения переводимых

строк, django-admin.ру makemessages, не распознает такие строки. Мы еще

вернемся к этой утилите ниже.

В строках, передаваемых _() или ugettextQ, допускается использовать именованные маркеры, определяемые с помощью стандартного синтаксиса интерполяции строк. Например:

def my_view(request, m, d):

output = _(‘Today is %(month)s %(day)s.’) % {‘month’: m, ‘day’: d} return HttpResponse(output)

Этот прием позволяет изменять порядок следования маркеров при переводе. Так, английский текст "Today is November 26м по-русски выглядит так: "Сегодня 26 ноября". Изменилось только взаимное расположение маркеров (месяца и дня).

По этой причине всегда следует пользоваться интерполяцией именованных строк (например, %(day)s), а не позиционной интерполяцией (например, %s или %d), если количество параметров больше 1. При использовании позиционной интерполяции переводчик не сможет переставить маркеры местами.

Пометка строк без перевода

Функция django.utils.translation.ugettext_noop() помечает строку как переводимую, но не требующую перевода. Позже перевод такой строки будет взят из переменной.

Этот прием используется при наличии строк-констант, которые при передаче между системами или пользователями должны содержать текст на оригинальном языке, как, например, строки в базе данных, и должны переводиться лишь в самый последний момент, непосредственно перед отображением пользователю.

Отложенный перевод

Функция django.utils.translation.ugettext_lazy() позволяет переводить строки не в момент вызова самой функции, а в момент доступа к значению.

Например, чтобы перевести значение атрибута help_text модели, можно поступить следующим образом:

from django.utils.translation import ugettext_lazy

class MyThing(models.Model):

name - models.CharField(help_text=ugettext_lazy(‘This is the help text’))

В данном случае ugettext_lazy() сохранит ссылку на объект отложенного перевода1, а не на сам перевод. Перевод будет выполнен, когда строка встретится в строковом контексте, например, при отображении шаблона в административном интерфейсе Django.

Точнее, ссылку на вызываемый объект (функцию ugettext) с параметром, содержащим строку, предназначенную для перевода. - Прим. науч. ред.

Результат ugettext_lazy() можно использовать всюду, где в Python допустима строка Unicode (объект типа Unicode). Попытка использовать его там, где ожидается байтовая строка (объект типа str) закончится неудачно, потому что ugettext_lazy() не знает, как преобразовать свой результат в байтовую строку. Но поскольку использовать строку Unicode внутри байтовой строки также не разрешается, то это ограничение согласуется с обычным поведением Python. Например:

tt Правильно: прокси-обьект Unicode1 вставляется в строку Unicode. u"Hello %s" % ugettext_lazy("peopleM)

tt He работает, так как нельзя вставить объект Unicode в байтовую tt строку (как нельзя вставить и прокси-обьект Unicode) "Hello %s" % ugettext_lazy("people")

Если вы когда-нибудь увидите нечто вроде "hello <django.utils. functional…>", знайте, что это результат попытки вставить в байтовую строку значение, возвращаемое ugettext_lazy(). Это ошибка в вашем коде.

Если вам не нравится длинное имя ugettext_lazy, можете воспользоваться синонимом _ (знак подчеркивания):

from django.utils.translation import ugettext_lazy as

class MyThing(models.Model):

name = models.CharField(help_text=_(‘This is the help text’))

В моделях Django всегда пользуйтесь только отложенным переводом. Имена полей и таблиц должны помечаться для перевода (иначе они останутся непереведенными в административном интерфейсе). Это означает, что в классе Meta следует определить атрибуты verbose_name и verbose_name_plural явно , а не полагаться на алгоритм их образования из имени класса модели, принятый в Django по умолчанию:

from django.utils.translation import ugettext_lazy as

class MyThing(models.Model):

name = models.CharField(_(‘name’), help_text=_(‘This is the help text’)) class Meta:

verbose_name = _(‘my thing’) verbose_name_plural = _(‘mythings’)

Образование множественного числа

Для определения текста сообщений, которые выглядят по-разному в единственном и множественном числе, служит функция django.utils. translation.ungettext(). Например:

from django.utils.translation import ungettext

Имеется в виду вызываемый объект, возвращающий значение типа Unicode. - Прим. науч. ред.

def hello_world(request, count):

page = ungettext(‘there is %(count)d object’, ‘there are %(count)d objects’, count) % { ‘count’: count,

}

return HttpResponse(page)

Функция ungettext принимает три аргумента: переводимую строку в единственном числе, переводимую строку во множественном числе и количество объектов (которое передается в виде переменной count)1.

В шаблонах

Для перевода текста в шаблонах Django применяются два шаблонных тега и синтаксис, несколько отличающийся от используемого в коде на Python. Чтобы получить доступ к этим тегам, поместите в начало файла шаблона директиву {% load i18n %}.

Тег {% trans %} переводит как литералы строк (заключенные в одиночные или двойные кавычки), так и содержимое переменных:

<title>{% trans "This is the title." %}</title> <title>{% trans myvar %}</title>

Если задан параметр noop, то поиск переменной производится, но перевод пропускается. Это полезно, когда требуется поставить заглушку для содержимого, которое понадобится перевести позже:

<title>{% trans "myvar" noop %}</title>

В теге {% trans %} не допускается помещать шаблонную переменную внутрь строки. Если необходимо перевести строки, содержащие переменные, пользуйтесь тегом {% blocktrans %}:

{% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %}

Чтобы перевести результат шаблонного выражения (например, включающего фильтр), необходимо связать это выражение с локальной переменной перед входом в блок {% blocktrans %}:

{% blocktrans with value|filter as myvar %} This will have {{ myvar }} inside. {% endblocktrans %}

Несколько связываемых в блоке выражений разделяются связкой and:

{% blocktrans with book|title as book_t and author|title as author_t %} This is {{ book_t }} by {{ author_t }}

Хотя функция ungettext принимает всего две строки на оригинальном языке (в единственном числе и во множественном), тем не менее в файле перевода можно указать более двух форм склонений по числам (как это принято в русском языке) и получать корректный перевод. Эта особенность русского языка уже учтена в стандартном файле перевода Django. - Прим. науч. ред.

Источник: Головатый А., Каплан-Мосс Дж. Django. Подробное руководство, 2-е издание. - Пер. с англ. - СПб.: Символ- Плюс, 2010. - 560 е., ил.

Похожие посты:

Комментировать

Your email address will not be published. Required fields are marked *