Почему так происходит
Домен регистронезависим: SITE.RU и site.ru ведут на один сайт. А вот путь после домена обрабатывает файловая система сервера, и в Linux она различает регистр.
site.ru/catalog/divany/ → страница
site.ru/Catalog/divany/ → другая страница
site.ru/catalog/Divany/ → третья страница
Если все три варианта отдают код 200, поисковая система видит три страницы с одинаковым содержимым. Это классический источник дублей.
Откуда берутся заглавные буквы
Никто не создаёт такие адреса намеренно — они появляются побочным эффектом.
- Автоматическая транслитерация заголовка, если модуль не приводит результат к нижнему регистру. «Садовые Качели» дают
Sadovye-Kacheli. - Импорт из учётной системы, где артикулы записаны заглавными:
/product/ABC-123/. - Ручной ввод адреса в поле CMS с автозаменой первой буквы на заглавную.
- Внешние ссылки, где адрес набрали с ошибкой регистра.
- Ссылки из офлайн-материалов, напечатанные капслоком для читаемости.
Проверка за десять секунд. Возьмите любой внутренний адрес и сделайте первую букву пути заглавной. Страница открылась как обычная — есть дубль. Отдала 301 или 404 — всё в порядке.
Что делать: три уровня решения
Уровень первый — не создавать. Модуль транслитерации должен приводить адрес к нижнему регистру, причём до замены букв, а не после. Порядок операций разобран в статье про функцию транслита.
Уровень второй — перенаправлять. Адрес с заглавными буквами должен отдавать 301 на версию в нижнем регистре. На Apache это делается модулем mod_spelling или правилом с внешней картой соответствий; надёжнее реализовать проверку на уровне приложения.
Уровень третий — обозначить канонический адрес. Тег rel=canonical на всех страницах указывает вариант в нижнем регистре как основной.
Решение на уровне приложения
Самый предсказуемый способ: маршрутизатор сравнивает запрошенный путь с приведённым к нижнему регистру, и при расхождении отдаёт постоянное перенаправление.
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$lower = mb_strtolower($path, 'UTF-8');
if ($path !== $lower) {
header('Location: ' . $lower, true, 301);
exit;
}
Правило применяется до поиска страницы в базе, поэтому работает для всех адресов сразу, включая те, которых ещё не существует.
Где регистр менять нельзя
Приведение к нижнему регистру касается пути, но не всего адреса целиком.
| Часть адреса | Приводить к нижнему регистру |
|---|---|
| Домен | Можно, регистр не важен |
| Путь к странице | Да |
| Значения параметров | Нет — можно сломать токены и метки |
| Якорь после решётки | Нет — обрабатывается браузером |
Особенно осторожно с параметрами: ссылки подтверждения почты, токены авторизации и партнёрские метки чувствительны к регистру, и их изменение сломает переходы.
Как проверить весь сайт
- Выгрузите список адресов из карты сайта или отчёта панели вебмастера.
- Отфильтруйте строки, где путь содержит заглавные латинские буквы.
- Проверьте отчёт по внешним ссылкам: там могут быть адреса с неверным регистром.
- Посмотрите отчёт об ошибках обхода — адреса с регистром часто попадают туда как 404.
- Убедитесь, что внутренние ссылки в меню и текстах ведут на версию в нижнем регистре.
Если проиндексированы обе версии, оставьте в качестве основной ту, что собрала больше переходов, и настройте перенаправление на неё.
Особенность серверов на Windows
Файловая система Windows регистр не различает, поэтому на таком хостинге /Catalog/ и /catalog/ отдают одну и ту же страницу — обе с кодом 200.
Кажется, что проблемы нет, но она просто прячется: поисковая система по-прежнему считает адреса разными, а сервер их не разделяет. В индексе оказываются обе версии, и склеить их редиректом сложнее — сервер не видит разницы. Решение здесь только на уровне приложения: сравнить путь с приведённым к нижнему регистру и отдать перенаправление самостоятельно.
Регистр в именах файлов
То же правило действует для картинок, стилей и скриптов. Ссылка на /upload/Foto.JPG при реальном файле foto.jpg на Linux-сервере даст ошибку 404.
Классический сценарий: сайт разрабатывали локально на Windows, где всё работало, а после переноса на хостинг пропала часть изображений. Поэтому имена загружаемых файлов стоит приводить к нижнему регистру автоматически — при загрузке, а не потом вручную.
Короткий чек-лист
- Модуль транслитерации приводит адрес к нижнему регистру.
- Имена загружаемых файлов тоже приводятся к нижнему регистру.
- Адрес с заглавными буквами отдаёт 301, а не 200.
- Внутренние ссылки везде в нижнем регистре.
- Параметры адреса при этом не изменяются.
Частые вопросы
Почему домен регистронезависим, а путь нет?
Домен обрабатывается системой доменных имён, где регистр не учитывается. Путь после домена обрабатывает файловая система сервера, а в Linux она различает большие и маленькие буквы.
Можно ли просто поставить canonical и не делать редирект?
Можно, но менее надёжно: canonical — рекомендация. Версия адреса с заглавными буквами не нужна вообще, поэтому корректнее отдавать 301.
Нужно ли приводить к нижнему регистру параметры адреса?
Нет. В параметрах бывают токены и метки, чувствительные к регистру, и их изменение сломает ссылки подтверждения и рекламные переходы.
Готовый адрес можно собрать прямо сейчас: откройте генератор ЧПУ — он транслитерирует фразу по таблице Яндекса, уберёт служебные слова и покажет длину адреса.