Согласовывайте язык только для /, а явные URL, такие как /en/ и /fr/, всегда должны отдавать указанную в них языковую версию. В этом руководстве издателю, работающему на Mac, показано, как задать такое поведение, сохранить доступность ссылок на документы и проверить результат.

В качестве рабочего примера используется условная общедоступная коллекция документов с английской и французской версиями краткого руководства по расположению фигур. Корневая страница служит для выбора языка, а её вступительный текст может адаптироваться к запросу. Все примеры адресов описывают предполагаемую структуру; они не означают, что по этим адресам сейчас размещены страницы.

Определите поведение URL до изменения языковых настроек

Начните с краткого описания правил маршрутизации. В этом примере корневая страница помогает читателям выбрать язык, а два явных пути содержат полный перевод документа. Google рекомендует использовать отдельные URL для языковых версий и не перенаправлять читателей между ними автоматически на основании предполагаемого языка. Видимые ссылки позволяют читателям сделать собственный выбор. Управление многоязычными и мультирегиональными сайтами.

Запрошенный путь Предполагаемый ответ Влияние языковых предпочтений
/ Выбор языка с кратким вступлением Может меняться вступление и предлагаемая ссылка
/en/ Полный документ на английском Язык документа не меняется
/fr/ Полный документ на французском Язык документа не меняется
Неопубликованный путь Ответ об отсутствии страницы Нельзя незаметно подменять его другим документом

Используйте эту таблицу как техническое задание. Выбирайте язык только после проверки, что запрос направлен к корневой странице. Общее правило, которое выполняется до обработки каждого запроса страницы, может переопределить явный выбор и нарушить заданный контракт.

Например, пользователь, перешедший по /fr/, должен получить французский документ, даже если в его запросе указан предпочтительный английский язык. Предпочтение английского полезно в начальной точке, когда выбор ещё не сделан; явный путь в других случаях уже задаёт этот выбор. На этом принципе приоритета основаны рекомендации в статье.

Оставляйте обе языковые ссылки видимыми на каждой странице. На корневой странице предложенный язык может упростить первый выбор, не скрывая другой вариант. На страницах полных документов переключатель должен вести прямо к соответствующему документу.

Выберите предсказуемую политику выбора языка корневой страницы

Заголовок Accept-Language содержит предпочтительные языки ответа с весовыми коэффициентами, например fr;q=0.9,en;q=0.5. Он не обязывает сервер предоставлять все запрошенные языки. Нулевой вес означает, что язык неприемлем. Заголовок Content-Language описывает предполагаемую аудиторию возвращаемого представления, но не выбирает маршрут. RFC 9110: Семантика HTTP, разделы 8.5, 12.4.2 и 12.5.4.

До настройки чего-либо запишите список поддерживаемых языков и резервный вариант. В этом примере используются вступления на английском и французском. Если в запросе нет подходящего языка, показывается английское вступление и оба варианта языка. Это пример издательского решения, а не требование HTTP.

Используйте механизм сопоставления языков с явно заданной политикой. В RFC 4647 различаются фильтрация и поиск по языку: поиск выбирает один результат, обрабатывает запрошенные диапазоны в порядке приоритета и постепенно удаляет подметки, чтобы найти соответствие. Также приложения, использующие поиск, должны определить поведение по умолчанию. Поэтому запрос fr-CA при поиске может привести к вступлению на поддерживаемом обобщённом языке fr. RFC 4647: Сопоставление языковых меток, разделы 3.4–3.4.1.

Не выбирайте язык, просто находя в заголовке первое вхождение fr или en. Такой упрощённый подход не учитывает веса и исключения. Механизм сопоставления должен разбирать предпочтения, учитывать исключения с нулевым весом и затем применять задокументированный резервный вариант.

Предпочтение в запросе корневой страницы Ожидаемый результат в этом примере
Заголовок отсутствует Английское вступление и оба варианта
fr Французское вступление и оба варианта
fr-CA,fr;q=0.9,en;q=0.5 Французское вступление
en;q=0.9,fr;q=0.2 Английское вступление
de Резервная страница выбора
fr;q=0,en;q=1 Английское вступление; французский не выбирается
*;q=0 Явно определённая обработка неподдерживаемого языка

Для последней строки нужно принять осознанное решение. В рамках этой схемы выбора укажите, что при запросе, исключающем все языки, показывается резервная страница выбора, поскольку приложение не выполняет это предпочтение, а не потому, что запросу соответствует английский. Если требуется строгое согласование, определите и проверьте соответствующее поведение для неприемлемого ответа. В любом случае не допускайте, чтобы ноль случайно трактовался как обычное низкое предпочтение.

Согласуйте язык документа, ссылки и поисковые аннотации

Для каждого HTML-документа задайте атрибут lang в соответствии с его основным языком: en для английской страницы и fr для французской. В WHATWG lang определён как основной язык содержимого элемента и текстовых атрибутов; если он не задан, язык наследуется от родительского элемента. Один лишь языковой префикс этого не обеспечивает. Стандарт HTML: атрибуты lang и xml:lang.

Проверьте навигационные ссылки наряду с текстом страницы. Относительные URL разрешаются относительно базового URL согласно стандарту WHATWG URL. Например, если у документа нет другого базового URL, fr/ относительно https://example.com/en/ разрешается в https://example.com/en/fr/; /fr/ ведёт к французскому пути на этом же источнике. Для видимого переключателя используйте предполагаемый абсолютный путь. Стандарт URL: запись и разбор URL.

Поисковые аннотации выполняют отдельную задачу. Google поддерживает аннотации эквивалентных языковых версий через HTML, заголовки HTTP или карту сайта. Выберите один удобный способ. Для каждой версии укажите её саму и соответствующие версии, используя полные URL; версии должны ссылаться друг на друга через эти аннотации. Целевой страницей x-default может быть корневая страница выбора. Как сообщить Google о локализованных версиях страницы.

Для условной коллекции соответствия аннотаций таковы:

Аннотация Условный адрес
en https://example.com/en/
fr https://example.com/fr/
x-default https://example.com/

Добавьте эти связи с помощью поддерживаемого издательской системой механизма аннотаций. Это описание структуры, а не исполняемая разметка. x-default не настраивает согласование на сервере и не предоставляет перевод. Google также указывает, что определяет язык страницы алгоритмически, а не использует hreflang или HTML lang для его распознавания. Как сообщить Google о локализованных версиях страницы.

Полные переводы должны быть доступны независимо от адаптации корневой страницы. Google сообщает, что его поисковый робот отправляет запросы без Accept-Language, и предупреждает: адаптивные к локали страницы могут остаться не обнаруженными. Надёжный резервный вариант и прямые URL языковых версий решают эту проблему доступности, не требуя от поискового робота запрашивать разные варианты вступления на корневой странице. Как Google сканирует страницы, адаптивные к локали.

Настройте кэширование корневых ответов с учётом выбора языка

Если выбор языка на корневой странице зависит от Accept-Language, добавьте Vary: Accept-Language к ответам этой страницы, включая резервный вариант. Сохраните все существующие поля вариации. В приведённом ниже примере французского ответа корневой страницы показана часть заголовка, а не полное HTTP-сообщение: RFC 9110: Семантика HTTP, раздел 12.5.5.

Content-Type: text/html; charset=utf-8
Content-Language: fr
Vary: Accept-Language

RFC 9111 требует от кэша сверять поля запроса, указанные в Vary, прежде чем повторно использовать сохранённый ответ без повторной проверки. Это важно, поскольку URL корневой страницы остаётся прежним, а её вступление меняется. Vary описывает входные данные для выбора, но не реализует механизм сопоставления языков. RFC 9111: Кэширование HTTP, раздел 4.1.

В рамках этой схемы документы /en/ и /fr/ не зависят от Accept-Language. Проверьте весь путь доставки, включая любой общий кэш, на соответствие правилам маршрутизации. В качестве практической диагностики поочерёдно отправьте запросы к корневой странице с предпочтением английского и французского, а затем поменяйте их порядок. Если корневая страница снова и снова возвращает язык из предыдущего запроса, проверьте совместно поведение кэша и маршрутизацию.

Проверьте правила с Mac

Сначала подготовьте три условные страницы на общедоступном демонстрационном источнике. Приведённая ниже проверка предполагает, что на этом источнике находятся только страницы демонстрационной коллекции по адресам /, /en/ и /fr/. Она не создаёт страницы и не настраивает хост. Указанные выше условные адреса example.com не являются работающей тестовой установкой.

Откройте приложение Mac Terminal и выполните curl --version, чтобы убедиться, что curl доступен. Затем вставьте следующий полный диагностический скрипт оболочки. По запросу введите адрес демонстрационного источника вместе с https://, без пути и завершающей косой черты.

printf 'Public demo origin, without a trailing slash: '
IFS= read -r demo_origin
case "$demo_origin" in
  https://*) ;;
  *) printf 'Enter an HTTPS origin.\n' >&2; exit 1 ;;
esac

for demo_path in / /en/ /fr/; do
  for demo_language in '' 'en' 'fr' 'fr-CA,fr;q=0.9,en;q=0.5' 'en;q=0.9,fr;q=0.2' 'de' 'fr;q=0,en;q=1'; do
    printf '\nPath: %s | Accept-Language: %s\n' \
      "$demo_path" "${demo_language:-absent}"
    curl --silent --show-error --connect-timeout 5 --max-time 15 \
      --dump-header - --header "Accept-Language: $demo_language" \
      "$demo_origin$demo_path" || exit 1
  done
done

Диагностика выводит заголовки ответов и тела сообщений. Параметр curl --header задаёт предпочтение; пустое значение удаляет этот заголовок. --dump-header - выводит заголовки в стандартный поток вывода, а ограничения по времени ограничивают длительность каждой передачи. Перенаправления намеренно не отслеживаются, чтобы неожиданный редирект оставался заметным. curl — руководство по использованию.

Синтаксис скрипта оболочки проверен; здесь не утверждается, что демонстрационная версия развёрнута или что работа маршрутизации языков проверена в реальном времени. При ошибке передачи curl скрипт останавливается, однако HTTP-ответ с ошибкой всё равно может появиться в выводе — его нужно проверить.

Сравните ответы корневой страницы с таблицей предпочтений. Затем проверьте, что каждый ответ /en/ содержит английский текст, а каждый ответ /fr/ — французский, независимо от указанного предпочтения. Проверьте коды состояния, неожиданные поля Location, указанное возвращённое значение языка и фактический текст документа. Если заголовок верен, а тело нет, проверка всё равно не пройдена.

Наконец, откройте оба явных URL в браузере. Перейдите по переключателю языка, перезагрузите целевую страницу и проверьте адресную строку. Так можно обнаружить ошибки навигации, которые не выявляет успешный прямой запрос. Отдельно проверьте неопубликованный путь и убедитесь, что на нём незаметно не отображается один из полных документов.

Используйте стабильную страницу выбора, если согласование недоступно

Для этой схемы требуется уровень обслуживания, способный читать заголовок запроса и выбирать ответ. Механизмы языка документа и URL в WHATWG описывают документы и адреса; добавление атрибута lang или изменение текста ссылки само по себе не создаёт согласование HTTP. Выбор в зависимости от запроса должен быть настроен на уровне доставки HTTP. Стандарт HTML, RFC 9110: Семантика HTTP.

Если издательская система не предоставляет такой возможности обслуживания, используйте фиксированную корневую страницу выбора с прямыми ссылками на полные языковые версии. Это сохраняет за читателем право выбора и соответствует рекомендации Google использовать отдельные URL языковых версий и видимые ссылки переключения. Здесь не предполагается использование функции согласования какого-либо конкретного издательского продукта. Управление многоязычными и мультирегиональными сайтами.

Практический критерий приёмки прост: предпочтения могут помочь на корневой странице, а явные ссылки на языковые версии должны оставаться надёжными адресами. В завершение задокументируйте резервный вариант, укажите соответствующие языки документов и взаимные аннотации языковых версий, а также соберите свидетельства по отдельным запросам, подтверждающие соблюдение правил маршрутизации.

Источники