Дата подготовки материала: 18:45:05 ().
В современных веб‑приложениях часто возникает необходимость корректно хранить, извлекать и искать данные на русском языке. Неправильная обработка кириллических символов приводит к появлению вопросительных знаков вместо букв, к сбоям в поиске и к нежелательному попаданию русскоязычного контента в результаты поиска. В данной статье рассматриваются типичные проблемы и проверенные способы их решения, основанные на информации из открытых источников (Stack Overflow, LexisNexis, Google Search Community и др.).
Проблемы с кодировкой Cyrillic в MySQL
Одной из самых частых трудностей является вывод русского текста в виде «???» при использовании mysql_query и echo. Основные причины:
- Несоответствие кодировки соединения и кодировки таблиц/полей.
- Отсутствие явного указания набора символов при подключении.
- Использование устаревших функций
mysql_вместоmysqli_или PDO.
Пример проблемного кода
if (!link = mysql_connect('localhost','user','pass')) die('Could not connect: ' . mysql_error); if (!db = mysql_select_db('my_db', link)) die('Can't use DB: ' . mysql_error); $result = mysql_query('SELECT * FROM book', link); while ($row = mysql_fetch_assoc($result)) { echo ''; print_r($row); echo '';
}
mysql_close($link);
Решение: установка правильного charset
Необходимо явно указать кодировку UTF‑8 сразу после установления соединения:
$link = mysqli_connect('localhost','user','pass','my_db'); if (!$link) { die('Connect error: ' . mysqli_connect_error); } mysqli_set_charset($link, 'utf8'); // Важно! $result = mysqli_query($link, "SELECT * FROM book"); while ($row = mysqli_fetch_assoc($result)) { echo ''; print_r($row); echo '';
}
mysqli_close($link);
Если вы всё ещё используете расширение
mysql_*, замените вызов на:mysql_set_charset('UTF8', $link);
Поиск с учётом регистра в PostgreSQL
В PostgreSQL функция
LOWERработает корректно только если база и клиент используют одинаковую кодировку (обычно UTF‑8). Пример запроса, который не возвращает результатов:SELECT name FROM users WHERE LOWER(name) LIKE LOWER('после');Причина – различие в регистре символов при приведении к нижнему регистру из‑за неверной локали.
Как исправить
- Убедитесь, что база создана с кодировкой
UTF8и localeru_RU.UTF-8:
CREATE DATABASE mydb WITH ENCODING='UTF8' LC_COLLATE='ru_RU.UTF-8' LC_CTYPE='ru_RU.UTF-8' TEMPLATE=template0;
- При выполнении запроса используйте оператор
ILIKE(регистронезависимый LIKE) – он уже учитывает locale:
SELECT name FROM users WHERE name ILIKE 'после';
Если нужен явный LOWER, задайте locale в сессии:
SET lc_messages = 'ru_RU.UTF-8';
SELECT name FROM users WHERE LOWER(name) LIKE LOWER('после');
Исключение русскоязычных результатов в поисковых системах
Иногда требуется ограничить выдачу только контентом на определённом языке (например, исключить русскоязычные страницы при поиске в Украине). Ниже перечислены практические подходы:
В Google Search
- Используйте оператор
-lang:ru(не поддерживается напрямую, но можно комбинировать сsite:и-inurl:для известных русскоязычных доменов). - Применяйте параметр
hl=enи добавляйте&lr=lang_enв URL для принудительной локализации на английский. - Используйте расширения браузера или пользовательские скрипты, которые фильтруют результаты по атрибуту
hreflangили по мета‑тегуContent-Language.
В Яндекс и других поисковиках
- Яндекс поддерживает оператор
lang:– например,query lang:enпокажет только англоязычные страницы. - Для исключения русского можно добавить
-lang:ru.
На уровне собственного поискового движка
Если вы разрабатываете собственный поиск (например, на базе Elasticsearch или Sphinx), добавьте фильтр по языку:
{
"query": {
"bool": {
"must": [
{ "match": { "content": "ваш запрос" } }
],
"must_not": [
{ "term": { "language": "ru" } }
]
}
}
}
Обработка специальных символов и токенизация в полнотекстовом поиске
Современные поисковые системы не работают с «сырыми» строками. Перед индексацией выполняется токенизация – разбиение текста на лексемы с учётом языка, пунктуации и специальных символов;
Пример: Medium‑статья о токенизации
Согласно статье Khánh Phạm Đức (2026‑01‑29), перед индексацией текст проходит следующие этапы:
- Нормализация Юникода (NFKC).
- Разделение на токены по пробелам и пунктуации.
- Приведение к нижнему регистру (с учётом locale).
- Удаление стоп‑слов и стемминг/лемматизация.
Для корректной работы с кириллицей необходимо указать анализатор, поддерживающий русский язык, например:
PUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"ru_analyzer": {
"tokenizer": "standard",
"filter": ["lowercase", "russian_stop", "russian_stemmer"]
}
}
}
}
}
Регулярные выражения для исключения фраз
Если нужно выбрать все тексты, не содержащие определённую фразу на русском, можно использовать негативный просмотр вперёд:
(?!.фразу).Пример в MySQL (REGEXP):
SELECT * FROM articles WHERE content NOT REGEXP '(?i)frazа';Обратите внимание, что поддержка look‑ahead в MySQL ограничена; в таких случаях удобнее выполнять фильтрацию на уровне приложения (PHP, Python).
Лучшие практики и чек‑лист
- Кодировка соединения: всегда задавайте
utf8mb4(MySQL) илиUTF8(PostgreSQL) сразу после подключения. - Кодировка базы и таблиц: проверьте, что они созданы с
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci. - Клиентские библиотеки: используйте современные расширения (
mysqli,PDO,psycopg2) вместо устаревшихmysql_*. - Локаль и колляция: для корректной работы функций
LOWER,UPPER,LIKEзадавайте locale, соответствующий языку данных. - Полнотекстовый поиск: выбирайте анализатор, поддерживающий морфологию русского языка (например,
russiananalyzer в Elasticsearch). - Тестирование: после изменений выполните запрос с кириллическим текстом и убедитесь, что вывод не содержит «?».
- Логирование: фиксируйте случаи несовпадения кодировок – это поможет быстро локализовать проблемы в продакшене.
Корректная работа с кириллицей в веб‑приложениях требует внимания к деталям на всех уровнях: от соединения с базой данных до настройки поисковых движков и фильтрации результатов в внешних поисковиках. Следуя приведённым рекомендациям и используя проверенные решения, вы сможете избежать типичных проблем с вопросительными знаками, неправильным поиском и нежелательным попаданием русскоязычного контента в выдачу.
Материал подготовлен на основе информации из открытых источников (Stack Overflow, LexisNexis, Google Search Community, Medium) и актуален на .