Мультиязычность сайта RU/UZ: кириллица и латиница без потери SEO
Две языковые версии на узбекистанском проекте — это норма, а не опция. Проблема в том, что у узбекского языка две графики, и большинство сайтов ломают на этом индексацию.
Три варианта структуры URL и какой выбрать
Подпапки (site.uz/ru/, site.uz/uz/) — рабочий вариант по умолчанию. Весь ссылочный вес копится на одном домене, настройка тривиальная, в Next.js это делается через сегмент [locale] в App Router и middleware, который редиректит корень на язык по умолчанию.
Поддомены (ru.site.uz) требуют отдельной настройки SSL и разводят авторитет домена по нескольким хостам. Отдельные ccTLD (site.uz и site.ru) оправданы только при разных юрлицах и разных прайсах — на локальном рынке это почти никогда не нужно.
Параметры вида ?lang=uz — худший вариант: поисковик видит один URL с меняющимся содержимым, и обе версии конкурируют за один адрес. Если такое досталось в наследство, переезд на подпапки с 301-редиректами делается в первую очередь.
Кириллица и латиница: не три языка, а два
Соблазн сделать три версии — ru, uz-latn, uz-cyrl — понятен: часть аудитории старше 40 лет читает по-кириллически. Но для поисковой системы это два почти идентичных документа, и вы получаете внутреннюю каннибализацию по всей семантике на узбекском.
Практичное решение: одна узбекская версия на латинице как каноническая (латиница — официальная графика и основа большинства поисковых запросов), а кириллица подключается опциональным клиентским транслитератором. Переключатель графики меняет отображение через JavaScript, но URL, canonical и hreflang остаются прежними.
Транслитерация ставится на уровне рендера текста: функция обходит текстовые узлы и подменяет символы по таблице соответствий, выбор сохраняется в localStorage. Индексируется по-прежнему один документ, а пользователь получает привычную графику.
Правильная разметка hreflang
На каждой странице нужен полный набор взаимных ссылок: <link rel="alternate" hreflang="ru" href="...">, hreflang="uz" и обязательный hreflang="x-default". Важное правило взаимности: если русская страница ссылается на узбекскую, узбекская обязана ссылаться обратно, иначе Google игнорирует всю группу.
Коды указываются по BCP 47. Для узбекского с явной графикой корректны uz-Latn и uz-Cyrl, но если у вас одна узбекская версия — используйте просто uz. Регион добавляют, когда версии различаются валютой или доставкой: ru-UZ и ru-RU.
В Next.js hreflang генерируется через поле alternates.languages в объекте metadata и должен быть частью серверного HTML. Ссылки, добавленные скриптом после загрузки, поисковик часто не учитывает.
Что ломается на практике
Самая частая ошибка — canonical, ведущий с узбекской версии на русскую. Так узбекская версия просто выпадает из индекса: canonical всегда должен указывать на себя, а связь языков описывает только hreflang.
Вторая ошибка — автоматический редирект по заголовку Accept-Language или по IP. Робот Googlebot ходит с американских адресов и видит одну версию из двух; вторая никогда не индексируется. Определение языка допустимо только как ненавязчивая подсказка-баннер.
Третья — частично переведённые страницы, где заголовки на узбекском, а карточки товаров подтянулись на русском. Такие страницы Google классифицирует как некачественные. Лучше не публиковать раздел, чем публиковать наполовину.
Технические мелочи, которые заметны
Атрибут lang на теге html должен меняться вместе с версией — от него зависит перенос слов, проверка орфографии и работа скринридеров. Апостроф в узбекской латинице (o‘, g‘) пишется как U+02BB, а не как обычная кавычка: иначе поиск по «gʻisht» и «g'isht» даёт разные результаты.
Слова в узбекском заметно длиннее русских: «Дополнительная информация» против «Qoʻshimcha maʼlumot» — и в кнопках вёрстка ползёт. Тестируйте узкие элементы интерфейса на самой длинной локали, а не на русской.
Sitemap стоит делать один, с блоками xhtml:link внутри каждого <url> — так Google получает языковые связи даже там, где HTML отдаётся из кэша.
Как организовать сами переводы
Тексты интерфейса храните в JSON-словарях по локалям, контент — в CMS с полем на каждый язык. Смешивать эти два потока не стоит: интерфейс меняется с релизом, контент — постоянно.
Заложите fallback: если перевода поля нет, показывается язык по умолчанию, но страница помечается для редактора. Тихо пустое поле хуже, чем непереведённое.
Бюджет на профессиональный перевод сайта на узбекский — ориентировочно от 300 000 до 800 000 сум за условную страницу текста в зависимости от тематики. Машинный перевод для юридических и медицинских разделов не подходит вовсе.