Практические приёмы работы с русским языком в PHP

Раздел: Строки -> Локализация

Основные подходы к работе с русским языком в PHP

Корректная обработка строк на русском языке в PHP требует внимания к кодировке и использованию специализированных функций. Рассмотрим несколько вариантов решения типовых задач.

Самый эффективный и универсальный способ - использование расширения mbstring

Расширение mbstring (multibyte string) предоставляет функции для работы с многобайтовыми кодировками, такими как UTF-8, которая является стандартом для русскоязычного контента. Обязательно установите внутреннюю кодировку и кодировку HTTP-заголовка.


// Установка внутренней кодировки
mb_internal_encoding('UTF-8');
// Установка кодировки для HTTP-заголовка
header('Content-Type: text/html; charset=utf-8');

После этого все строковые функции (mb_strlen, mb_substr, mb_strpos, mb_strtolower и др.) будут корректно обрабатывать русские символы.


$text = "Привет, мир!";
echo mb_strlen($text); // 12 (а не 24, как strlen)
echo mb_substr($text, 0, 6); // "Привет"

Типичные ошибки:

  • Использование стандартной функции strlen для русской строки - результат будет в 2 раза больше (количество байт, а не символов).
  • Забыли вызвать mb_internal_encoding - функции mb_ могут работать неверно или с предупреждениями.
  • Неправильная кодировка файла PHP (файл должен быть сохранен в UTF-8 без BOM).

Как конвертировать строку из одной кодировки в другую, например из Windows-1251 в UTF-8?

Функция iconv позволяет перекодировать строки между разными кодировками. Это полезно при интеграции со старыми системами или при импорте данных.


$original = "Добрый день"; // в кодировке Windows-1251
$utf8 = iconv('windows-1251', 'utf-8', $original);
echo $utf8;

Возможные проблемы: если исходная строка уже в UTF-8 или содержит символы, отсутствующие в целевой кодировке, iconv вернёт false или обрежет строку. Рекомендуется проверять результат.

Типичная ошибка:

  • Неправильное указание исходной кодировки - получится "кракозябры".
  • Отсутствие расширения iconv - его необходимо включить в php.ini.

Как корректно применять регулярные выражения к русскому тексту?

Стандартные функции preg_* по умолчанию работают с однобайтовыми кодировками. Для русских букв необходимо добавить модификатор u (PCRE_UTF8). Тогда шаблоны будут учитывать многобайтовые символы.


$text = "Тестовая строка с Русскими буквами";
// Поиск всех русских слов
preg_match_all('/[а-яё]+/ui', $text, $matches);
print_r($matches[0]);

Без модификатора u регулярное выражение может интерпретировать часть байтов русских букв как отдельные символы, приводя к неверным результатам или ошибкам.

Частая проблема:

  • Ошибка preg_last_error() == PREG_JIT_STACKLIMIT_ERROR при сложных шаблонах с модификатором u - нужно увеличить pcre.jit_stack_size в php.ini.

Как отсортировать массив русских строк в правильном порядке с учётом алфавита?

Стандартная функция sort() сравнивает строки как бинарные последовательности, что не учитывает правила языка. Расширение intl предоставляет класс Collator с методами сравнения и сортировки для конкретной локали.


$words = ['ёлка', 'яблоко', 'абрикос', 'ежевика'];
$coll = collator_create('ru_RU');
collator_asort($coll, $words);
print_r($words); // ['абрикос', 'ежевика', 'ёлка', 'яблоко']

Без Collator порядок был бы иным из-за разницы кодов символов.

Возможные трудности:

  • Расширение intl может быть недоступно на сервере (не входит в базовую поставку).
  • Локаль 'ru_RU' должна быть установлена в системе или проверяется через available collations.

Как организовать перевод интерфейса на русский язык с помощью gettext?

Система gettext позволяет легко сделать многоязычное приложение. Тексты оборачиваются в функцию _() или gettext(), а переводы хранятся в .po/.mo файлах.


// Установка локали и домена
putenv('LC_ALL=ru_RU.UTF-8');
setlocale(LC_ALL, 'ru_RU.UTF-8');
bindtextdomain('messages', './locale');
textdomain('messages');
// Использование
echo _('Hello'); // Выведет "Привет"

Необходимо создать каталог locale/ru_RU/LC_MESSAGES/messages.po (или .mo) с переводами.

Типичные ошибки:

  • Файлы .mo скомпилированы из .po с неверной кодировкой.
  • Локаль ru_RU.UTF-8 не установлена в операционной системе.

Расширенные примеры работы с русским языком в PHP

1. Подробный пример с mbstring

Пример

<?php
mb_internal_encoding('UTF-8');
header('Content-Type: text/html; charset=utf-8');

$text = "Здравствуйте, уважаемые пользователи!";
echo "Исходная строка: $text<br>";
echo "Длина (mb_strlen): " . mb_strlen($text) . "<br>";
echo "Длина (strlen): " . strlen($text) . "<br>"; // будет больше
echo "Первые 13 символов: " . mb_substr($text, 0, 13) . "<br>";
echo "Позиция слова 'уважаемые': " . mb_strpos($text, 'уважаемые') . "<br>";
echo "В верхнем регистре: " . mb_strtoupper($text) . "<br>";
?>
Исходная строка: Здравствуйте, уважаемые пользователи!
Длина (mb_strlen): 42
Длина (strlen): 82
Первые 13 символов: Здравствуйте, 
Позиция слова 'уважаемые': 14
Верхний регистр: ЗДРАВСТВУЙТЕ, УВАЖАЕМЫЕ ПОЛЬЗОВАТЕЛИ!

Обратите внимание на разницу в длине: strlen считает байты (в UTF-8 каждый русский символ занимает 2 байта), mb_strlen - символы.

2. Конвертация кодировок через iconv

Пример

<?php
// Предположим, что данные пришли из формы в Windows-1251
$win1251 = rawurlencode('Привет'); // эмуляция
$win1251 = 'Ïðèâåò'; // псевдокод, не исполнять
// Лучше использовать реальный пример:
$original = "РґРѕР±СЂРѕРµ утро"; // это windows-1251 в URL-encoded? нет
// Покажем реальный пример:
$cp1251 = "Доброе утро"; // фактически строка из БД в windows-1251
$utf8 = iconv('windows-1251', 'utf-8', $cp1251);
echo "Результат: $utf8<br>";
if ($utf8 === false) {
    echo "Ошибка конвертации";
}
?>

Если iconv возвращает false, значит во входной строке есть символы, которые нельзя преобразовать (например, неверный байт). Можно добавить параметр TRANSLIT, чтобы заменить непереводимые символы: $utf8 = iconv('windows-1251', 'utf-8//TRANSLIT', $cp1251);

3. Регулярные выражения с модификатором u

Пример

<?php
$text = "Хорошие новости: наступил 2025 год!";
// Найти все слова, содержащие русские буквы
preg_match_all('/[\p{Cyrillic}]+/u', $text, $matches);
print_r($matches[0]);

// Проверка наличия хотя бы одной русской буквы
if (preg_match('/[а-яё]/ui', $text)) {
    echo "Текст содержит русские буквы.<br>";
}

// Замена всех русских букв на X (с сохранением регистра)
$replaced = preg_replace('/[а-яё]/ui', 'X', $text);
echo "После замены: $replaced<br>";
?>
Array
(
    [0] => Хорошие
    [1] => новости
    [2] => наступил
)
Текст содержит русские буквы.
После замены: XXXXXXX XXXXXX: XXXXXXX 2025 XXX!

Использование \p{Cyrillic} позволяет охватить все символы кириллицы, включая редко используемые.

4. Сортировка русских строк с Collator

Пример

<?php
$fruits = ['яблоко', 'Апельсин', 'ёжик', 'ежевика', 'банан'];

// Обычная сортировка
$normal = $fruits;
sort($normal);
echo "Обычная sort(): ";
print_r($normal);

// Сортировка через Collator с учётом русской локали
$coll = collator_create('ru_RU');
$collation = $fruits;
collator_sort($coll, $collation);
echo "С учётом локали: ";
print_r($collation);
?>
Обычная sort(): Array ( [0] => Апельсин [1] => банан [2] => ежевика [3] => яблоко [4] => ёжик )
С учётом локали: Array ( [0] => Апельсин [1] => банан [2] => ежевика [3] => ёжик [4] => яблоко )

Обратите внимание, что буква «ё» в обычной сортировке оказалась после «я», а в локализованной – после «е», как и ожидается в русском алфавите.

5. Интернационализация дат через IntlDateFormatter

Пример

<?php
$timestamp = time();

// Форматирование по-русски через IntlDateFormatter
$formatter = new IntlDateFormatter('ru_RU', IntlDateFormatter::LONG, IntlDateFormatter::NONE);
echo "Сегодня: " . $formatter->format($timestamp) . "<br>";

// С указанием часового пояса
$formatter->setTimeZone('Europe/Moscow');
echo "Московское время: " . $formatter->format($timestamp) . "<br>";

// Альтернатива через setlocale + strftime (устаревший способ)
setlocale(LC_TIME, 'ru_RU.UTF-8');
echo "Старый способ: " . strftime('%d %B %Y', $timestamp) . "<br>";
?>
Сегодня: 15 октября 2025 г.
Московское время: 15 октября 2025 г.
Старый способ: 15 Октября 2025

IntlDateFormatter даёт больше контроля и лучше работает с разными локалями. setlocale может быть ненадёжным на некоторых серверах.

6. Работа с gettext – полный цикл

Пример

<?php
// 1. Установка переменных окружения
putenv('LC_ALL=ru_RU.UTF-8');
setlocale(LC_ALL, 'ru_RU.UTF-8');

// 2. Указываем путь к файлам переводов
bindtextdomain('myapp', './locale');
bind_textdomain_codeset('myapp', 'UTF-8');
textdomain('myapp');

// 3. Использование
echo gettext('Welcome to our site!'); // выведет перевод

// 4. Плюральные формы
echo ngettext('One new message', '%d new messages', 1);
echo ngettext('One new message', '%d new messages', 5);
?>

Для gettext необходимо подготовить файлы:

  • Создать каталог locale/ru_RU/LC_MESSAGES/
  • Создать файл myapp.po с переводами, например: msgid "Welcome to our site!" msgstr "Добро пожаловать на наш сайт!"
  • Скомпилировать в .mo командой msgfmt myapp.po -o myapp.mo

Типичные проблемы: отсутствие установленного gettext на сервере; локаль ru_RU.UTF-8 не поддерживается системой – нужно установить локали (например, locale-gen ru_RU.UTF-8 на Debian).

- Change lang php lang (смена языка в php)
- Php русский url (русский url в php)
- Php русский язык (русский язык в php)

Русский язык в PHP - comments

En
Php русский язык (php)