Как сообщить Google о других языках на вашем сайте Django
Если у вас есть общедоступный сайт Django на нескольких языках, вы, вероятно, захотите сообщить об этом Google и другим поисковым системам.
Многоязычный сайт Django
Django имеет очень обширную структуру для обслуживания сайтов на нескольких языках. Ознакомимся с базовыми настройками, необходимыми для добавления дополнительных языков на сайт Django.
Активируйте фреймворк i18n в settings.py
:
# settings.py USE_I18N = True
Определите поддерживаемые языки:
# settings.py from django.utils.translation import gettext_lazy as _ LANGUAGES = [ ('en', _('English')), ('ru', _('Russian')), ]
Установите язык по умолчанию:
# settings.py LANGUAGE_CODE = 'en'
ДобавьтеLocaleMiddleware
:
# settings.py MIDDLEWARE = [ # ... 'django.middleware.locale.LocaleMiddleware', # ... ]
Используйте gettext
, чтобы пометить тексты для перевода:
# app/views.py from django.utils.translation import gettext_lazy as _ from django.http import HttpResponse def about(request) -> HttpResponse: return HttpResponse(_('Hello!'))
Создайте файлы перевода:
$ python manage.py makemessages
Переведите текст:
msgid "Hello!" msgstr "Привет!"
Скомпилируйте файлы перевода:
$ python manage.py compilemessages
Настройте представления на нескольких языках с помощью i18n_patterns
:
# urls.py from django.conf.urls.i18n import i18n_patterns from django.conf.urls import url from . import views urlpatterns = i18n_patterns( url(r'^about$', views.about, name='about'), )
Убедитесь, что это работает:
$ curl http://localhost:8000/en/about Hello! $ curl http://localhost:8000/ru/about Привет!
Это всё!
Есть несколько дополнительных шагов, таких как добавление представления для переключения языка, но в целом ваш многоязычный сайт Django готов к работе!
Ссылка на другие языки с помощью hreflang
Чтобы поисковые системы знали, что страница доступна на другом языке, вы можете использовать специальный тег ссылки:
<link rel="alternate" hreflang="en" href="https://example.com/en" />
Тег имеет следующие атрибуты:
hreflang
: Код языка связанной страницы.href
: Ссылка на страницу на указанном языке.
Согласно рекомендациям Google и информации в Википедии, мы должны соблюдать следующие правила:
- Используйте абсолютные URL-адреса, включая схему.
- Ссылка должна быть действительной, а связанная страница должна быть на указанном языке.
- Перечислить все языки, включая текущий.
- Если язык X ссылается на язык Y, язык Y должен ссылаться обратно на язык X.
Чтобы реализовать следующее в Django, начните с перечисления доступных языков в шаблоне и установите код языка в атрибуте hreflang
:
{% load i18n %} {% get_available_languages as LANGUAGES %} {% for language_code, language_name in LANGUAGES %} <link rel="alternate" hreflang="{{ language_code }}" href="TODO" /> {% endfor %}
Следующим шагом будет добавление локализованных ссылок для каждого языка. Потребовалось немного покопаться, но оказалось, что в Django уже есть функция translate_url
, которую мы можем использовать:
>>> from django import urls >>> from django.utils import translation >>> translation.activate('en') >>> reverse('about') '/en/about' >>> urls.translate_url('/en/about', 'ru') '/ru/about'
Функция translate_url
принимает URL-адрес и язык и возвращает URL-адрес на этом языке. В приведенном выше примере мы активировали английский язык и получили URL-адрес с префиксом /en
.
В правилах требуются абсолютные URL-адреса.
Убедитесь, что translate_url
может обрабатывать и абсолютные URL:
>>> urls.translate_url('https://example.com/en/about', 'ru') 'https://example.com/ru/about'
Отлично! translate_url
может «переводить» абсолютные URL-адреса.
Как насчет URL-адресов с параметрами запроса или хешем?
>>> urls.translate_url('https://example.com/en/about?utm_source=search#top', 'ru') 'https://example.com/ru/about?utm_source=search#top'
Круто, тоже заработало!
ПРИМЕЧАНИЕ. Не имеет особого смысла иметь URL-адрес страницы с параметрами запроса и хешами в таком месте, как тег ссылки (или канонический в этом отношении). Причина, по которой я упоминаю об этом, заключается в том, что это может быть полезно для ссылок на другие страницы.
Это практически все, что нам нужно. Но у translate_url
есть некоторые ограничения, о которых стоит знать.
Перевести нелокализованный URL:
>>> urls.translate_url('/about', 'en') '/about'
Если вы используете встроенный LocaleMiddleware
и попытаетесь перейти к /about
, Django перенаправит вас на страницу на текущем языке. translate_url
не может сделать то же самое.
Как насчет перевода URL-адреса на язык, который не является текущим языком?
>>> translation.activate('en') >>> urls.translate_url('/ru/about', 'en') '/ru/about'
Нет, этого тоже нельзя.
Если вы посмотрите на реализацию translate_url
, это ограничение станет понятным:
# django/urls/base.py def translate_url(url, lang_code): """ Given a URL (absolute or relative), try to get its translated version in the `lang_code` language (either by i18n_patterns or by translated regex). Return the original URL if no translated version is found. """ parsed = urlsplit(url) try: match = resolve(parsed.path) except Resolver404: pass else: to_be_reversed = "%s:%s" % (match.namespace, match.url_name) if match.namespace else match.url_name with override(lang_code): try: url = reverse(to_be_reversed, args=match.args, kwargs=match.kwargs) except NoReverseMatch: pass else: url = urlunsplit((parsed.scheme, parsed.netloc, url, parsed.query, parsed.fragment)) return url
Django сначала пытается разрешить URL-путь. Это способ Django проверить правильность URL-адреса. Только если URL-адрес действителен, он разбивается на части и переворачивается на желаемом языке.
Шаблонный тэг translate_url
Теперь, когда мы знаем, как «переводить» URL-адреса на разные языки, нам нужно иметь возможность использовать это в шаблоне. Django предоставляет нам возможность определять собственные теги и фильтры шаблонов.
Давайте добавим собственный тег шаблона для translate_url
:
# app/templatetags/urls.py from typing import Optional, Any from django import urls register = template.Library() @register.simple_tag(takes_context=True) def translate_url(context: Dict[str, Any], language: Optional[str]) -> str: """Get the absolute URL of the current page for the specified language. Usage: {% translate_url 'en' %} """ url = context['request'].build_absolute_uri() return urls.translate_url(url, language)
Наш тег шаблона translate_url
принимает контекст. Это необходимо, если мы хотим предоставить абсолютный URL. Мы используем build_absolute_uri для получения абсолютного URL из запроса.
Тег также принимает код целевого языка для перевода URL-адреса и использует translate_url
для создания переведенного URL-адреса.
С помощью нашего нового тега шаблона мы можем заполнить пробелы в предыдущей реализации:
{% load i18n urls %} {% get_available_languages as LANGUAGES %} {% for language_code, language_name in LANGUAGES %} <link rel="alternate" hreflang="{{ language_code }}" href="{% translate_url language_code %}" /> {% endfor %}
Использование x-default
для языка по умолчанию
В руководстве есть еще одна рекомендация:
Зарезервированное значение hreflang = "x-default" используется, когда никакой другой язык/регион не соответствует настройке браузера пользователя. Это значение не является обязательным, но рекомендуется, чтобы вы могли управлять страницей, когда языки не совпадают. Хорошее использование - настроить таргетинг на домашнюю страницу вашего сайта, где есть интерактивная карта, позволяющая пользователю выбрать свою страну.
Так что также неплохо добавить ссылку на какой-нибудь язык по умолчанию. Если, например, мы хотим сделать нашим языком по умолчанию английский, мы можем добавить следующее в приведенный выше фрагмент:
{% load i18n urls %} {% get_available_languages as LANGUAGES %} {% for language_code, language_name in LANGUAGES %} <link rel="alternate" hreflang="{{ language_code }}" href="{% translate_url language_code %}" /> {% endfor %} <link rel="alternate" hreflang="x-default" href="{% translate_url en %}" />
Когда мы настраиваем наш проект Django, мы уже определили язык по умолчанию. Вместо жесткого кодирования английского (или любого другого языка в этом отношении) мы хотим использовать LANGUAGE_CODE
, определенный в settings.py
.
Чтобы использовать значения из settings.py
в шаблонах, мы можем использовать старый прием, который мы использовали в прошлом, чтобы визуально различать среды в админке Django. Это простой обработчик контекста, который предоставляет определенные значения из settings.py
шаблонам через контекст запроса:
# app/context_processor.py from typing import Dict, Any from django.conf import settings def from_settings(request) -> Dict[str, Any]: return { attr: getattr(settings, attr, None) for attr in ( 'LANGUAGE_CODE', ) }
Чтобы зарегистрировать обработчик контекста, добавьте в settings.py
следующее:
# settings.py TEMPLATES = [{ # ... 'OPTIONS': { 'context_processors': [ #... 'app.context_processors.from_settings', ], #... } ]}
Теперь, когда у нас есть доступ к LANGUAGE_CODE
в шаблоне, мы действительно можем завершить наш фрагмент:
{% load i18n urls %} {% get_available_languages as LANGUAGES %} {% for language_code, language_name in LANGUAGES %} <link rel="alternate" hreflang="{{ language_code }}" href="{% translate_url language_code %}" /> {% endfor %} <link rel="alternate" hreflang="x-default" href="{% translate_url LANGUAGE_CODE %}" />
Отрисованная разметка для страницы about выглядит так:
<link rel="alternate" hreflang="en" href="https://example.com/en/about" /> <link rel="alternate" hreflang="ru" href="https://example.com/ru/about" /> <link rel="alternate" hreflang="x-default" href="https://example.com/en/about" />
Заключительные слова
Надеюсь, эта короткая статья помогла вам лучше понять, как поисковые системы могут определять разные языки на вашем сайте Django. В процессе вы, возможно, также подобрали некоторые маленькие уловки для управления локализованными URL-адресами в Django.
Оригинал: https://hakibenita.com/django-multi-language-site-hreflang
Вернуться на верх