Каждый вебмастер хотя бы раз видел страницу, где вместо текста набор вопросительных знаков, ромбиков или странных сочетаний вроде «Рџ ривет». Эти «кракозябры» появляются, когда данные записаны в одной кодировке, а прочитаны в другой. Проблема кажется мистической, но на деле у неё всегда есть логичное объяснение. Давайте разберёмся, как устроены кодировки и где в цепочке сайта может случиться сбой.
Что такое кодировка
Компьютер хранит не буквы, а числа. Кодировка — это таблица соответствия между символами и числами. В первые годы существовало много национальных таблиц: для русского языка использовались сразу несколько, и они несовместимы между собой. Один и тот же байт мог означать разные буквы в зависимости от таблицы.
Сегодня общепринятый стандарт — Юникод, а наиболее распространённый способ его записи в вебе — UTF-8. Он умеет представлять символы всех языков, включая кириллицу, иероглифы и эмодзи, и является стандартом по умолчанию для современных браузеров и серверных технологий. Если вы начинаете проект, выбор очевиден: везде используйте UTF-8.
Откуда берутся «кракозябры»
Данные проходят несколько этапов, и на каждом можно ошибиться:
- Автор набирает текст в редакторе и сохраняет файл в определённой кодировке.
- Файл лежит на сервере, и сервер отдаёт его браузеру вместе с заголовком, где указана кодировка.
- Браузер выбирает, как декодировать байты: по заголовку, по метатегу в документе или по собственным догадкам.
- Если в игре участвует база данных, добавляется ещё три точки: кодировка таблиц, кодировка соединения и кодировка данных от клиента.
Если на любом шаге кодировка не совпадает с предыдущим, получается мусор. Типичный пример: файл сохранён в UTF-8, а браузер читает его как однобайтную кириллическую кодировку. Каждая русская буква, занимающая два байта, превращается в два странных символа.
Как задать кодировку страницы
Первое, что нужно сделать — явно указать кодировку документа. В HTML это делается метатегом в самом начале раздела head:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Заголовок</title>
</head>
Метатег должен находиться как можно выше, в пределах первых килобайтов документа, до любых русских символов. Иначе браузер может начать разбирать страницу с неверной кодировкой и перезапустить разбор, когда доберётся до тега.
Но метатег — лишь один из источников. Приоритет выше у HTTP-заголовка, который отправляет сервер. Если заголовок говорит одно, а метатег другое, браузер послушает заголовок. Поэтому настройка сервера критична.
Заголовок сервера
В заголовке ответа поле Content-Type обычно содержит параметр с названием кодировки. Проверить его можно в инструментах разработчика браузера, на вкладке сети, либо консольной утилитой. Если там указана устаревшая кодировка, а файлы лежат в UTF-8, проблема найдена.
Во многих серверах кодировку по умолчанию задают директивой конфигурации. В Apache это можно сделать через файл .htaccess одной строкой, назначающей кодировку по умолчанию. Для PHP стоит проверить параметр, отвечающий за кодировку по умолчанию в конфигурации. Если сервер добавляет собственную кодировку, скорректируйте её, а не пытайтесь перебить метатегом.
Файлы и редакторы
Частая причина — разные редакторы сохраняют файлы по-разному. Блокнот в старых версиях Windows по умолчанию использовал локальную однобайтную кодировку. Если вы правите файлы в таком редакторе и сохраняете «как есть», шаблон может сломаться.
- Используйте нормальный редактор кода и выбирайте UTF-8 для всех проектов.
- Сохраняйте файлы без метки порядка байтов (BOM). Эта невидимая метка в начале файла, отправляемая сервером перед заголовками, приводит к ошибкам вроде «headers already sent» в PHP и лишним пробелам в верхней части страницы.
- Проверьте, что все подключаемые файлы — шаблоны, языковые пакеты, скрипты — имеют одинаковую кодировку.
- Настройте систему контроля версий и редактор так, чтобы кодировка не менялась случайно.
База данных
Если сайт использует MySQL, проблемы бывают на уровне хранилища. Нужно согласовать три настройки: кодировку самой базы, таблиц и столбцов, кодировку соединения. Типичная ошибка — таблицы в UTF-8, а соединение открыто в старой однобайтной кодировке. Тогда русский текст записывается в таблицу уже искажённым.
После подключения к базе в приложении отправьте команду установки кодировки соединения, соответствующую выбранной. Современные драйверы позволяют задать её прямо в параметрах подключения. Для полной поддержки всех символов Юникода, включая эмодзи, выбирайте вариант кодировки с расширенной поддержкой четырёхбайтовых символов, иначе при вставке таких знаков запись обрежется.
Как восстановить испорченные данные
Если «кракозябры» уже попали в базу, действовать нужно осторожно. Сначала сделайте полную резервную копию. Затем определите, в чём искажение: возможно, текст был записан как однобайтная кодировка поверх байтов UTF-8. Такие случаи иногда исправляются двойным преобразованием: сначала данные трактуются как исходный набор байтов, затем читаются как правильная кодировка. Выполняйте это сначала на копии таблицы и проверяйте результат на небольшой выборке.
Если же в данных уже стоят вопросительные знаки вместо букв, информацию, к сожалению, не вернуть: символы потеряны при записи. Остаётся восстановление из резервной копии или ручное исправление.
Диагностика по шагам
- Откройте страницу и принудительно смените кодировку в браузере. Если текст стал читаемым, проблема в объявленной кодировке.
- Посмотрите заголовок ответа сервера и метатег: совпадают ли они.
- Откройте исходный файл в редакторе и определите его реальную кодировку.
- Если данные берутся из базы, проверьте кодировку соединения и таблиц.
- Проверьте сторонние данные: внешние скрипты, RSS-ленты, ответы интерфейсов, формы, отправляемые на страницу.
- Убедитесь, что формы отправляются в нужной кодировке и серверная часть корректно её принимает.
Профилактика
Простейшее правило: везде UTF-8. Редактор, файлы, метатег, заголовок сервера, база данных, соединение, обработка форм, письма. Не смешивайте кодировки в рамках одного проекта, даже если «так исторически сложилось». Миграция на единый стандарт один раз сэкономит бесконечные часы поисков по ночам.
Если вы вынуждены работать со старыми файлами, храните их в исходной кодировке только на границе системы, а внутри проекта конвертируйте сразу на входе. Для данных, приходящих из внешних источников, всегда проверяйте заявленную кодировку и не доверяйте ей слепо.
Кодировка в письмах, адресах и экспорте
Проблемы не ограничиваются страницами. Письма с сайта часто уходят с неверной кодировкой темы и тела: убедитесь, что почтовая библиотека явно задаёт UTF-8 и кодирует заголовки. Русские символы в адресах страниц передаются в закодированном виде с процентами, и серверная часть должна корректно их декодировать. Экспорт данных в таблицы тоже коварен: программа для работы с таблицами может открыть файл в локальной кодировке, и тогда придётся использовать импорт с выбором кодировки.
Если пользователи жалуются на странные символы в формах, проверьте атрибут кодировки у самой формы и убедитесь, что скрипт, принимающий данные, не пытается перекодировать уже правильный текст второй раз. Двойное преобразование — одна из самых частых причин путаницы.
Заключение
«Кракозябры» — не магия, а несоответствие кодировок на одном из этапов пути данных. Выберите UTF-8, укажите её явно в документе, сервере, базе и соединении, сохраняйте файлы без метки порядка байтов, а при сбое проверяйте цепочку шаг за шагом. С такой системой вы быстро найдёте виновника и больше не будете бояться нечитаемых страниц.