Многоязычный сайт на django без редиректов

Начиная с django 1.4, можно задать префикс для url для каждого включенного языка. К примеру, мы хотим сайт, который будет иметь русскую и английскую версию.

Для этого добавляем в settings.py:

    # язык сайта по умолчанию, если не удалось определить язык другими способами
    LANGUAGE_CODE = 'ru'

    # список доступных языков
    LANGUAGES = (
        ('ru', 'Russian'),
        ('en', 'English'),
    )

    # включаем систему перевода django
    USE_I18N = True

    # указываем, где лежат файлы перевода
    LOCALE_PATHS = (
        os.path.join(PROJECT_DIR, 'locale'),
    )

    # Добавляем 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:

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

Поэтому я решил создать пакет, который позволял бы работать без редиректов.

Схема работы будет такая:

  1. Если в url нет языкового префикса, то используется язык по умолчанию (settings.LANGUAGE_CODE)

  2. Если префикс есть, то используется язык, соответствующий префиксу (/en/ = англ), но при этом префикса для языка по умолчанию нет.

Благо для этого нужно совсем немного кода, нужно лишь изменить LocaleMiddleware и i18n_patterns, что я и сделал в репозитории https://github.com/st4lk/django-solid-i18n-urls.

Установка:

  1. Устанавливаем django-solid-i18n-urls, например с помощью pip:

    pip install solid_i18n
    
  2. Изменяем LocaleMiddleware на SolidLocaleMiddleware:

    MIDDLEWARE_CLASSES = (
       # ...
       # удаляем 'django.middleware.locale.LocaleMiddleware',
       'solid_i18n.middleware.SolidLocaleMiddleware', 
       # ...
    )
    
  3. Вместо 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, то будут использованы редиректы по следующим правилам:

  1. При обращении по url без языкового префикса, например '/', язык будет определен из предпочтений пользователя. Если этот язык не равен языку по умолчанию (settings.LANGUAGE_CODE), то будет перенаправление на url с соответствующем префиксом. Если равен, то отображается url без префикса (который и был запрошен).

  2. При обращении по url с языковым префиксом поведение не меняется, т.е. всегда используется язык из префикса.

Пример:

# settings.py: 
LANGUAGE_CODE = 'ru'
SOLID_I18N_USE_REDIRECTS = True

Допустим предпочитаемый язык пользователя - английский.

Тогда при обращении к '/' будет редирект на '/en/'.

А если предпочитаемый язык - русский, то редиректа не будет, т.е. при обращении к '/' оторбразиться '/'.

Замечание

При таком подходе возможна следующая ситуация. Предпочитаемый язык браузера - английский. Но пользователь хочет увидеть русскую версию, которая отображается без префикса. Если для переключения языков использовать простые ссылки, т.е. <a href="{{ specific language url}}">, то пользователь будет постоянно перенаправляться на английскую версию. Поэтому при переключении языков надо записывать в cookie пользователя выбранный им язык. Это можно делать с помощью специального встроенного в django set_language view.

Comments powered by Disqus