Многоязычный сайт ломается не там, где его проверяют. Переводы могут быть отличными, вёрстка одинаковой, а в поиске версии начинают конкурировать друг с другом или просто не появляются. Ниже — по порядку, включая ошибки, которые видно только в логах сервера.
1. Одна страница — один URL, один язык
Языковая версия должна жить по собственному адресу. Подойдёт и папка (/uz/), и поддомен — важно, чтобы адрес был стабильным и различался.
Чего делать нельзя: показывать разный язык по одному и тому же адресу в зависимости от заголовка браузера. Поисковый робот приходит с одним набором заголовков и увидит ровно одну версию — остальные для него не существуют.
2. hreflang должен быть двусторонним
Каждая версия перечисляет все остальные, включая саму себя. Если русская страница ссылается на узбекскую, а узбекская на русскую — нет, связка не засчитывается и страницы остаются сами по себе.
Проверять это надо на всех языках, а не на одном. Односторонняя связка — самая частая ошибка в реализации.
3. x-default — это не «английский по умолчанию»
x-default указывает страницу для тех, чей язык не подошёл ни под одну из перечисленных. Это не синоним английской версии и не «главная». Логичнее всего вести туда, где посетитель сможет выбрать язык сам, либо на самую полную версию.
Без x-default сайт не сломается, но у поисковика не будет ответа на вопрос «а что показывать всем остальным».
4. Коды языков различаются по слоям — и это источник битых ссылок
Здесь легко потерять полдня. Один и тот же язык может называться по-разному в трёх местах:
-
в адресе страницы — так, как вы решили:
/kz/,/zh-CN/; -
в hreflang — по стандарту BCP 47:
kkдля казахского,zh-Hansдля упрощённого китайского; -
в базе или API — так, как назвал разработчик.
Само по себе это нормально, пока преобразование между ними лежит в одном месте. Проблема появляется, когда кто-то собирает ссылку из кода, взятого не из того слоя, — и получает адрес, которого не существует.
5. Регистр в адресе: тихая потеря ссылок
Если хоть один языковой сегмент содержит заглавные буквы — а zh-CN содержит, — рано или поздно он приедет к вам в нижнем регистре. URL приводят к нижнему регистру почтовые клиенты, редакторы, часть прокси и просто люди, набирающие вручную.
Проверьте, что происходит с /zh-cn/. Плохой сценарий: сервер не узнаёт сегмент, считает его частью пути, приписывает язык по умолчанию спереди и выдаёт редирект на адрес, которого нет. Формально это 301, фактически — 404 в конце цепочки. Посетитель ушёл, а внешняя ссылка, которая на вас вела, пропала впустую.
Лечится сравнением без учёта регистра и таблицей синонимов, которая приводит любое написание к каноническому сегменту одним редиректом.
6. Что ставить в canonical, если перевода нет
Ситуация обычная: статья есть на русском и узбекском, а корейская версия страницы показывает русский текст, потому что так настроен откат.
Если такая страница объявляет каноническим саму себя, вы просите проиндексировать русский текст под корейским адресом. Правильнее указать канонический адрес той версии, чей текст на самом деле показан. Тогда сигналы собираются на одной странице вместо того, чтобы размазываться по семи её копиям.
И обратное правило: не перечисляйте в hreflang языки, переводов на которые нет. Список альтернатив должен совпадать с тем, что действительно существует.
7. Карта сайта — это тоже часть hreflang
Альтернативы можно объявлять не только в <head>, но и в sitemap.xml через xhtml:link. Это удобнее в сопровождении: связка описана один раз в файле, который генерируется программой, а не размазана по шаблонам.
Два условия: в карту попадают только адреса, которые отдают 200 без редиректа, и набор языков в карте совпадает с набором в разметке. Карта из редиректов частично отбрасывается.
8. Переводить ли адреса страниц
Переведённый слаг (/uz/xizmatlar/sayt-yaratish вместо /uz/services/website-development) читается лучше и совпадает с тем, как люди формулируют запрос.
Цена решения — обратной дороги нет. Как только адрес проиндексирован, менять его можно только с редиректом со старого на новый, и историю этих редиректов придётся хранить. Если переводите слаги — сразу закладывайте механизм хранения прежних адресов, а не дописывайте его через год.
9. Переключатель языка не должен терять страницу
Переключение с любой страницы должно вести на её же аналог на другом языке, а не на главную. Возврат на главную — это потеря контекста для посетителя и разрыв связки для поисковика.
Отдельно: переключение должно менять адрес, а не только надписи. Если после смены языка URL остался прежним, при перезагрузке или отправке ссылки другу язык вернётся обратно.
10. Перевод — это не только видимый текст
Забывают обычно об одном и том же:
-
<title>и описание страницы; -
атрибут
langу<html>; -
altу картинок; -
тексты в структурированной разметке;
-
сообщения об ошибках в формах и страница 404.
Чек-лист перед запуском
-
У каждой версии свой стабильный адрес.
-
hreflang двусторонний — проверен со всех языков, а не с одного.
-
x-defaultуказан осознанно. -
Языковой сегмент в нижнем регистре не приводит к 404.
-
Страница без перевода канонизируется на ту версию, чей текст показан.
-
В карте сайта только адреса, отдающие 200.
-
Переключатель языка сохраняет страницу и меняет адрес.
-
Переведены title, description,
lang,altи 404.
Если многоязычная версия уже запущена и вы не уверены, что связки настроены верно — можем проверить и показать, где именно рвётся.
