Спросите свой вопрос и получите сводку документа, используя эту страницу и выбранного вами поставщика AI
Содержимое этой страницы было переведено с помощью ИИ.
Смотреть последнюю версию оригинального контента на английскомЕсли у вас есть идея по улучшению этой документации, не стесняйтесь внести свой вклад, подав запрос на вытягивание на GitHub.
Ссылка на документацию GitHubКопировать Markdown документа в буфер обмена
Hreflang: руководство по многоязычной SEO
Вы перевели свое приложение. Вы развернули /en, /fr, /es. И французские пользователи все еще попадают на английскую страницу.
Перевод — это простая половина. Сложная половина — это сообщение поисковым системам, что эти страницы — это одна и та же страница на другом языке, а не три документа, конкурирующих друг с другом. Это то, что делает hreflang, и это именно то место, где большинство многоязычных сайтов тихо теряют свой трафик.
Что такое hreflang на самом деле
Аннотация на странице, которая говорит: у этого URL есть эквивалентные версии там, для этих языков.
Копировать код в буфер обмена
Это дает вам две вещи: правильную версию, показываемую правильному пользователю, и ваши локали консолидированы в один кластер вместо того, чтобы каннибализировать друг друга как дубликаты.
Стоит быть ясным насчет того, чем это не является. Это не редирект — это подсказка, и Google может её переопределить. Это не бонус ранжирования — это меняет какая версия ранжируется, а не ранжируется ли вы вообще. А Bing полностью его игнорирует, полагаясь вместо этого на content-language и геотаргетинг.
Где его объявить
Три способа размещения, все действительные. Выберите один и оставайтесь там — один и тот же кластер, объявленный в двух местах, — это как наборы расходятся.
HTML <head> — обычный выбор. Одно предостережение: теги, внедренные после гидратации, ненадежны. Если ваш фреймворк добавляет их только на стороне клиента, краулер может их никогда не увидеть.
XML sitemap лучше масштабируется. Десять локалей на 5000 страницах означают 50000 элементов <link>, отправляемых браузерам впустую; в sitemap это стоит вашим страницам нулевые байты.
HTTP Link header — единственный вариант для файлов, не являющихся HTML, таких как PDF.
Правила
Самоссылка и взаимность
Набор на /fr/about должен включать hreflang="fr", указывающий на /fr/about. И если /about указывает на /fr/about, /fr/about должен указывать обратно. Google называет односторонний ref "no return tag" и удаляет его.
На практике это означает, что каждая страница в кластере отправляет одинаковый набор ссылок. Генерация их из одного общего списка локалей — это не удобство, это единственный способ оставаться корректным, когда у вас более двух локалей.
Абсолютные URL, всегда
Копировать код в буфер обмена
Причину стоит понять, а не просто запомнить. hreflang — это перекрёстная ссылка между документами: поисковые системы создают кластер с ключом по URL, который используется на каждой странице в нём. Относительный путь имеет смысл только относительно документа, в котором он находится, поэтому он не может выразить это. Кроме того, он не может пересекать хост — а альтернатива часто пересекает, когда локаль находится на example.fr или fr.example.com. В карте сайта или HTTP-заголовке вообще нет базового документа для разрешения.
Это имеет прямое следствие в коде. getLocalizedUrl("/about", "fr") возвращает /fr/about — относительный на входе, относительный на выходе. Для hreflang вы должны передать абсолютный URL:
Копировать код в буфер обмена
Единственное исключение — это framework, который разрешает относительные значения перед рендерингом: Next.js расширяет относительные alternates по отношению к metadataBase. Хорошо — но правило применяется к выданному HTML, поэтому проверяйте с помощью curl, а не инспектора DevTools.
Коды языков
ISO 639-1 для языка, ISO 3166-1 Alpha 2 для необязательного региона: fr, fr-CA, pt-BR.
Две ловушки ловят почти всех. Регион отдельно недействителен — hreflang="ca" это каталанский, а не Канада; вам нужен en-CA или fr-CA. И en-UK не существует: код страны для Соединённого Королевства это GB, так что это en-GB.
Добавляйте регион только тогда, когда вы действительно подаёте этому региону разный контент — разные цены, разные юридические уведомления. fr и fr-FR на идентичном контенте это шум.
x-default
Копировать код в буфер обмена
Одна концепция, которая чаще всего забывается и неправильно понимается, это x-default — менее 30% приложений реализуют это правильно.
Это резервный вариант для пользователей, язык которых не совпадает ни с одной записью в вашем наборе. Носитель нидерландского языка на сайте, предлагающем английский, французский и испанский языки, не совпадает ни с одной записью; без x-default Google выбирает за вас.
Люди ошибаются в том, что это означает. x-default не "версия на английском языке" и не "локаль по умолчанию", даже если обычно указывает туда. Это означает страница для пользователей, которых этот набор не охватывает. Именно поэтому вполне допустимо — и часто лучше — указать на селектор языка или страницу переадресации на основе геолокации, а не на /en. Если у вас нет такой страницы, ваш основной язык является разумным ответом.
Два момента, которые нужно держать в уме: x-default — это одна дополнительная запись в наборе, а не замена самоссылающейся, и, как и любая другая запись, она должна появляться одинаково на каждой странице в кластере.
Ловушка канонического URL
Каждая локализованная страница должна быть своим собственным каноническим URL:
Копировать код в буфер обмена
Указание канонического URL каждой локали на английскую версию:
Копировать код в буфер обмена
говорит, что французская страница является дубликатом, который не должен индексироваться, в то время как hreflang говорит, что это страница для обслуживания пользователей французского языка. Сигналы противоречат друг другу, canonical имеет приоритет, и ваши французские страницы выпадают из индекса.
Canonical является самореферентным для каждой локали. hreflang описывает кластер.
Выбор структуры URL
hreflang аннотирует URLs, поэтому структура идет в первую очередь.
Открыть таблицу в модальном окне для четкого просмотра всех данных
| Структура | Пример | Компромисс |
|---|---|---|
| Поддиректории | example.com/fr/ | Один домен, общий авторитет — более слабый геосигнал |
| Поддомены | fr.example.com | Легко добавить или убрать локаль — может читаться как отдельный сайт |
| ccTLDs | example.fr | Самый сильный сигнал страны — authority строится отдельно для каждого домена |
Подкаталоги — правильный выбор по умолчанию для большинства проектов. Обращайтесь к ccTLDs только если вы действительно работаете как отдельные страновые бизнесы.
Единственная структура, которой следует избегать: подача разных языков по одному и тому же URL на основе Accept-Language или IP. Краулеры видят одну версию и индексируют одну версию; всё остальное невидимо.
Intlayer охватывает все три варианта черезrouting.modeиrouting.domains. См. пользовательские домены и справочник конфигурации.
Реализация
Написание этих тегов вручную не переживает контакт со второй локалью. Вместо этого выводите их из вашего списка локалей.
Выдавайте кластер на каждой странице
Одинаковый набор везде, canonical для каждой локали, абсолютные URL,
x-defaultвключен.Metadata API предоставляет
alternates.languages, иgetMultilingualUrlsстроит всю запись из ваших настроенных локалей:src/app/[locale]/about/page.tsxКопировать кодКопировать код в буфер обмена
Полная настройка: Руководство i18n Next.js 16.
Функция
headмаршрута строит ссылки.localeMapперебирает ваши настроенные локали, поэтому добавление локали в конфиг добавляет её везде сразу:src/routes/{-$locale}/about.tsxКопировать кодКопировать код в буфер обмена
headвыполняется на сервере, поэтому теги попадают в исходный HTML. Полная настройка: TanStack Start i18n guide.Или переместите все это в sitemap
В большом масштабе держите аннотации полностью вне ваших страниц.
generateSitemapвыдаетxhtml:linkальтернативы для каждой записи, читая локали и режим маршрутизации из вашей конфигурации:src/routes/sitemap[.]xml.tsКопировать кодКопировать код в буфер обмена
Два варианта, на которые стоит обратить внимание:
xhtmlLinks(по умолчаниюtrue) — альтернативные версии выводятся только там, где URL-адреса локалей действительно отличаются. В режимеno-prefixкаждая локаль использует один URL, поэтому они пропускаются, если толькоrouting.domainsне предоставляет локалям свои имена хостов.entryPerLocale(defaultfalse) — по умолчанию одна запись<url>содержит все альтернативы. Обе формы валидны, но только URL, указанный как<loc>, считается отправленным в Search Console; локали только с альтернативами остаются обнаруживаемыми, но не атрибутируются никакой карте сайта. Включение этой опции дает каждому локализованному URL собственную запись с повторяющимся полным набором альтернатив. Это умножает количество записей на количество локалей, поэтому следите за лимитом в 50 000 URL / 50 МБ и разделите на индекс карты сайта при его превышении.
Проверьте, что получает краулер
hreflangможет молча не срабатывать, поэтому проверьте его вместо того, чтобы полагаться на предположения.Читайте источник, а не инспектор —
curl https://example.com/fr/about | grep hreflangпоказывает, что получает crawler; DevTools показывает DOM после выполнения JavaScript. Затем проверьте каждый alternate и подтвердите, что он указывает обратно с идентичным набором, и что ни один из них не перенаправляет. Отчет Search Console об International Targeting охватывает остальное по всему сайту.Для crawl, ориентированного на многоязычность, Intlayer SEO Scanner проверяет отсутствующие теги, сломанные alternates и конфликты canonical на ваших локализованных страницах.
Checklist
- Each locale has a distinct, crawlable URL
- Every page self-references, and every reference is reciprocal
- The same set ships on every page in the cluster
- Все значения
hrefявляются абсолютными в выданном HTML - Коды соответствуют ISO 639-1 + ISO 3166-1 Alpha 2 (
en-GB, а неen-UK) -
x-defaultприсутствует и указывает, куда должны перейти неопознанные пользователи - Canonical самореференциален для каждой локали
- Теги отрендерены на сервере, а не внедрены после гидрации
- Объявлены ровно в одном месте
- Нет перенаправлений между альтернатами
Завершение
hreflang прост и неумолим. Один пропущенный обратный тег, один относительный URL, один cross-locale canonical — и кластер отбрасывается без каких-либо ошибок. Каждый из этих случаев возникает из-за ручного написания тегов.
Выведите набор из одного списка локалей, отрендерьте его на сервере, сохраняйте canonical самоссылающимся и уделите x-default должное внимание. Сделайте это один раз, и правильность перестанет быть чем-то, что вы поддерживаете.
Дальнейшее изучение
- SEO и интернационализация — более широкая картина многоязычной оптимизации для поисковых систем
- SEO и i18n в Next.js —
next-intlvsnext-i18nextvs Intlayer - Руководство Next.js 16 i18n
- Руководство i18n TanStack Start
- Пользовательские домены для каждой локали
- Справочник конфигурации
Комментарии
Пока нет комментариев. Будьте первым, кто поделится своими мыслями.
