Сразу хочу сказать, ничего нового я не напишу. Более того, не претендую на всеобъемлющее и полное описание. Наконец, касаюсь только одной версии Django - 1.5.0. С другими не требовалось делать интернационализированные сайты. Ну и последнее замечание - статья больше для себя, даже не для новичков: все давно можно найти на просторах Интернет, но если кому-то пригодится будет здорово.
Сам являюсь довольно начинающим разработчиком, потому многие решения, возможно, покажутся странными и нелогичными: замечания приветствуются в комментариях!
Итак. Задача стоит следующим образом: необходимо сделать сайт на, например, двух языках: русском и английском. И сразу первый сюрприз: основной язык необходимо считать английским, а русский - локализацией. Этого требует американское происхождение Django. Итак. Основной язык en, локализация ru.
Теперь рассмотрим, что же необходимо сделать, чтобы сайт корректно работал с двумя (аналогично - и с большим числом) языками.
- Нужны переводы текста в Python-коде: всякого рода "Error!", "Page NOT found" надо корректно уметь переводить.
- Нужны переводы текста в HTML-шаблонах: "News" в заголовке при переключении на русский язык должно стать "Новости"
- Нужен и перевод текста, хранящегося в БД.
- URI уникальные для каждого языка.
Рассмотрим средства для решения трех последних - локализацию в коде пока не использовал, потому тонкости не смогу рассказать: по этим граблям ещё предстоит пройтись в будущем.
Когда сложная и непонятная задача разбивается на заведомо более простые и конкретные подзадачи, дальше становится проще.
- Перевод в шаблонах. Используется средство gettext. Файл проекта settings.py надо модифицировать так:
import os
LANGUAGE_CODE = 'ru'
LANGUAGES = (
('en', ('English')),
('ru', ('Russian')),
)
LOCALE_PATHS = (
os.path.join(os.path.dirname(__file__), 'locale'),
)
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)Из замечаний хочется сказать, что
django.middleware.locale.LocaleMiddleware
должна быть повыше и послеdjango.contrib.sessions.middleware.SessionMiddleware
. Так же, и главное, что этого нет в официальной доке, указываемLOCALE_PATHS
. Это ложь, конечно. Есть, но особого акцента на этом не ставится. В свое время пару дней потратил на борьбу с "мельницами" - лучше указать, ведь "Явное, лучше неявного.".Подготовка к переводам шаблонов (на самом деле и переводов в Python-коде, если этот перевод готовить) завершена. Как же процесс перевода этой части проходит? В шаблонах все фразы отмечаем шаблонными тэгами
{% trans "English" %}
и{% blocktrans %}"English"{% endblocktrans %}
, а в самом начале, после, если имеется, командыextend
каждого шаблона указываем, что данный шаблон подлежит переводу -{% load i18n %}
. Создаем каталог locale в месте, указанном вLOCALE_PATHS
, обычно - корень проекта. Запускаем командуdjango-admin.py makemessages -l ru -a
и Django создает локализацию: генерируется файл django.po. В нем много групп по три строки
#: abi/templates/base_event.html:13
msgid "Main"
msgstr ""где первая строка — места, в которых встретилась фраза, помеченная для перевода, вторая строка — фраза для перевода ("English"), а третья — перевод, который надо вписать ("Английский"). Специфику перевода, зависящего от числа рассматривать не буду. После того как будут заполнены строки переводов, выполняем команду по сборке интернационализации:
django-admin.py compilemessages
.При добавлении в будущем новых фраз для перевода - так же запускаем эти две команды: старые переводы никуда не пропадут, и придется лишь новые описывать.
Сейчас при переключении языков на сайте фразы на английском и русском должны так же соответственно языку меняться. Идем дальше.
- Перевод текста, хранящегося в БД. Это никак не описывается в официальной доке Django: так что интернационализировать данные в БД будем сторонним решением. Для начала могу сказать, что очень много решений для перевода БД устарели и не работают в версии Django 1.5.0, хотя в сети много инструкций и статей по их использованию. Соответственно выбираем работающий инструмент django-transmeta.
Каждый класс в моделях подготавливается для работы с django-transmeta отдельно. Допустим у нас есть такая модель:
class EventRecord(models.Model):
title = models.CharField(max_length = 160)
title_side = models.CharField(max_length = 160)
descript = models.CharField(max_length = 120, blank = True)
body = models.TextField()
report = models.BooleanField()
def __unicode__(self):
return self.title
class Meta:
ordering = ['id']Положим, мы хотим, чтобы поля
title
,title_side
,descript
иbody
имели перевод. Для этого модель надо изменить следующим образом:from transmeta import TransMeta
class EventRecord(models.Model):
__metaclass__ = TransMeta
title = models.CharField(max_length = 160)
title_side = models.CharField(max_length = 160)
descript = models.CharField(max_length = 120, blank = True)
body = models.TextField()
report = models.BooleanField()
def __unicode__(self):
return self.title
class Meta:
ordering = ['id']
translate = ('title', 'title_side', 'descript', 'body')Теперь необходимо выполнить команду
./manage.py sync_transmeta_db
[1] и transmeta изменит поля в БД. Конкретнее, вместо поляbody
, будут созданы поляbody_ru
и полеbody_en
. Еще конкретнее:body
будет переименовано вbody_ru
(основной язык). Эти поля необходимо, например, в админке, заполнить. Теперь в зависимости от языка[2] будут выбираться поля БД с соответствующим языковым префиксом. - URI. Тут довольно просто, чтобы URI зависел от языка, используйте
from django.conf.urls.i18n import i18n_patterns
иurlpatterns += i18n_patterns('event.views',
url(r'^event/(\d+)/$', 'event', name = 'event_anon'),
)вместо patterns.
Что ещё полезно, так это не конструировать URI вручную, а использовать шаблонный тэг {% url %} - он поддерживает интернационализацию и будет указывать на страницу с тем же языком.
- ↑При использовании sqlite3 команда не выполняется: из-за ограниченных возможностей ALTER таблицы не могут измениться так, как требуется для django-transmeta. Самый просто вариант - проделать указанные процедуры вручную. Для этого создаем дамп в формате SQL и модифицируем CREATE TABLES и INSERT для таблиц, модели которых должны иметь перевод. Сохраняем и пересоздаем sqlite из дампа - в админке все поля должны быть доступны для внесения перевода.
- ↑И в самой официальной документации, и во многих статьях по теме было много сказано об изменении переменной django-language. Например, в статье, внизу создается форма... В общем всё странно и непонятно (было мне). Много читал, думал. Решил сделать сам. (с) Идея такая: язык зависит от текущего урла, в котором всегда строго в данный момент прописан язык. Используется функция, модифицирующая, согласно этой идее, request:
def set_lang(request):
'''Set 'django_language' in request.session'''
url = request.META['PATH_INFO'].split('/')[1]
request.session['django_language'] = url
return requestДля меня решение подошло. Для ваших целей может не подойти. Но так понятнее, верно? ;)
Спасибо! Помогло)
ОтветитьУдалитьСпасибо, помогло, особенно про явное указание LOCALE_PATHS
ОтветитьУдалитьА я в свою очередь могу всем настоятельно рекомендовать html5 шаблон , улучшает и рационализирует разметку документов, и много прочего!
ОтветитьУдалить