Многоязычный сайт на django без редиректов
Начиная с django 1.4, можно задать префикс для url для каждого включенного языка. К примеру, мы хотим сайт, который будет иметь русскую и английскую версию.
Для этого добавляем в settings.py
:
# default language, it will be used, if django can't recognize user's language
LANGUAGE_CODE = 'ru'
# list of activated languages
LANGUAGES = (
('ru', 'Russian'),
('en', 'English'),
)
# enable django’s translation system
USE_I18N = True
# specify path for translation files
LOCALE_PATHS = (
os.path.join(PROJECT_DIR, 'locale'),
)
# add LocaleMiddleware
MIDDLEWARE_CLASSES = (
# ...
'django.middleware.locale.LocaleMiddleware',
# ...
)
И в urls.py
используем i18n_patterns вместо patterns:
from django.conf.urls import url
from django.conf.urls.i18n import i18n_patterns
urlpatterns = i18n_patterns('',
url(r'^about/$', 'about.view', name='about'),
)
В этом случае, когда мы обратимся по адресу /about/, django попытается определить предпочитаемый нами язык и сделает редирект на страницу с префиксом языка. Допустим django определил, что наш язык - русский, тогда произойдет редирект на /ru/about/. При этом, если мы сами пройдем по адресу /en/about/, то уже никаких редиректов не будет, а отобразится английская версия сайта, т.к. в url уже присутствует префикс /en/.
При такой схеме могут возникнуть проблемы с индексированием сайта некоторыми поисковыми системами. Например yandex.ru очень долго отказывался индексировать сайт, т.к. не получал http кода 200 с корневого url. C Google’ом таких проблем не было, но все же и он не рекомендует использовать редиректы. Из http://support.google.com/webmasters/bin/answer.py?hl=ru&answer=182192:
Избегайте автоматического перенаправления по языку пользователя. Это может привести к тому, что пользователи и поисковые системы не смогут просмотреть все версии вашего сайта.
Поэтому я решил создать пакет, который позволял бы работать без редиректов.
Схема работы будет такая:
- Если в url нет языкового префикса, то используется язык по умолчанию (
settings.LANGUAGE_CODE
) - Если префикс есть, то используется язык, соответствующий префиксу (/en/ = англ), но при этом префикса для языка по умолчанию нет.
Благо для этого нужно совсем немного кода, нужно лишь изменить LocaleMiddleware и i18n_patterns, что я и сделал в репозитории https://github.com/st4lk/django-solid-i18n-urls.
Установка:
-
Устанавливаем django-solid-i18n-urls, например с помощью pip:
pip install solid_i18n
-
Изменяем LocaleMiddleware на SolidLocaleMiddleware:
MIDDLEWARE_CLASSES = ( # ... # remove 'django.middleware.locale.LocaleMiddleware', 'solid_i18n.middleware.SolidLocaleMiddleware', # ... )
-
Вместо i18n_patterns используем solid_i18n_patterns:
from django.conf.urls import url from solid_i18n.urls import solid_i18n_patterns urlpatterns = solid_i18n_patterns('', url(r'^about/$', 'about.view', name='about'), )
Репозиторий на github: https://github.com/st4lk/django-solid-i18n-urls.
UPDATED
Добавлена опция settings.SOLID_I18N_USE_REDIRECTS
(по умолчанию False). Если она равна True, то будут использованы редиректы по следующим правилам:
- При обращении по url без языкового префикса, например
'/'
, язык будет определен из предпочтений пользователя. Если этот язык не равен языку по умолчанию (settings.LANGUAGE_CODE
), то будет перенаправление на url с соответствующем префиксом. Если равен, то отображается url без префикса (который и был запрошен). - При обращении по url с языковым префиксом поведение не меняется, т.е. всегда используется язык из префикса.
Привет:
# settings.py:
LANGUAGE_CODE = 'ru'
SOLID_I18N_USE_REDIRECTS = True
Допустим предпочитаемый язык пользователя - английский.
Тогда при обращении к '/'
будет редирект на '/en/'
.
А если предпочитаемый язык - русский, то редиректа не будет, т.е. при обращении к '/'
оторбразиться '/'
.
Замечание
При таком подходе возможна следующая ситуация. Предпочитаемый язык браузера - английский. Но пользователь хочет увидеть русскую версию, которая отображается без префикса. Если для переключения языков использовать простые ссылки, т.е. <a href="{{ specific language url}}">
, то пользователь будет постоянно перенаправляться на английскую версию. Поэтому при переключении языков надо записывать в cookie пользователя выбранный им язык. Это можно делать с помощью специального встроенного в django set_language view.