Интернационализация Django - ЧАСТЬ 1
Фреймворк 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 е., ил.
Похожие посты:
- Вывод текста с отступом (0)
- Изменение фонового цвета строки при наведении на нее указателя мыши (0)
- Введение в Django (0)
- Шаблон проектирования MVC (0)
- Второе представление: динамическое содержимое (0)
- Справочник по API доступа к базе данных Django - ЧАСТЬ 3 (0)
- Справочник по обобщенным представлениям Django (0)