Если в созданном PDF не отображается кириллица, вместо русских букв обычно видны квадраты, знаки вопроса, пустые места или набор неправильных символов. Причина чаще находится не в тексте, а в шрифте и способе, которым генератор PDF преобразует Unicode в глифы.
Исправление нужно начинать с короткого воспроизводимого примера. Не меняйте одновременно кодировку базы, шаблон и библиотеку генерации: так легко скрыть симптом и получить новые ошибки в уже работающих документах.
Сначала определите вид ошибки
- Квадраты вместо букв — выбранный шрифт не содержит нужных кириллических глифов или не встроен.
- Знаки вопроса — текст мог быть поврежден до передачи в PDF-генератор.
- Набор символов вроде «РџСЂ» — UTF-8 был ошибочно прочитан как другая кодировка.
- Пропадают только жирные буквы — подключено обычное начертание, но отсутствует bold-файл.
- Кириллица видна на сервере, но не у клиента — шрифт не встроен, и просмотрщик подставляет локальную замену.
- Текст виден, но поиск и копирование не работают — генератор сохранил буквы как контуры или неверно построил таблицу соответствия.
Отдельно проверьте, проблема возникает во всем документе или только в таблице, header, footer, SVG, форме либо отдельном компоненте. У разных частей шаблона могут быть свои стили и шрифты.
Проверьте текст до генерации
Сохраните исходные данные непосредственно перед вызовом библиотеки в безопасный диагностический лог или тестовый файл. Если строка уже повреждена, подключение нового шрифта не поможет.
- Файлы шаблона сохранены в UTF-8 без случайного преобразования редактором.
- Соединение с базой использует utf8mb4, а не устаревшую или однобайтовую кодировку.
- JSON сформирован и разобран штатными функциями, без ручной замены байтов.
- CSV и внешние API явно преобразуются из их исходной кодировки в UTF-8.
- HTML содержит корректный charset, если библиотека сначала рендерит разметку.
- Строки не проходят повторный utf8_encode, iconv или похожее преобразование без необходимости.
Сделайте минимальный тестовый документ
Создайте одну страницу без рабочего дизайна и выведите несколько строк: русский алфавит, цифры, кавычки, тире, знак рубля, смешанный русский и английский текст. Добавьте обычное, жирное и курсивное начертания. Такой тест отделяет проблему шрифта от таблиц, шаблонизатора и бизнес-данных.
- АБВГД абвгд 0123456789.
- Счет № 125 — итого 15 900 ₽.
- ООО «Пример»: доставка, оплата и возврат.
- Обычный, жирный и курсивный текст.
- Смешанная строка: order_id, Москва, API.
Если минимальный файл отображается правильно, постепенно возвращайте CSS и компоненты исходного документа. Момент появления ошибки покажет, какой стиль или блок меняет шрифт.
Выберите шрифт с поддержкой кириллицы
Название шрифта не гарантирует наличие русских букв в конкретном файле. Нужен TTF или OTF с кириллическим набором. Проверьте также лицензию: она должна разрешать использование и встраивание шрифта в документы.
- Обычное начертание подключается отдельным файлом.
- Bold, italic и bold italic подключаются как самостоятельные файлы.
- Файл действительно содержит кириллицу, знак рубля и нужные специальные символы.
- Версия шрифта одинакова в разработке и на сервере.
- Шрифт хранится в контролируемом каталоге проекта или образа, а не зависит от компьютера разработчика.
Системные Arial, Times New Roman или Calibri могут быть доступны на одном компьютере и отсутствовать на Linux-сервере. Для повторяемой генерации лучше поставлять разрешенный шрифт вместе с приложением или устанавливать его при развертывании.
Подключите все начертания явно
Распространенный случай: обычный русский текст работает, а заголовок превращается в квадраты. CSS запрашивает font-weight 700, генератор ищет bold-версию и подставляет встроенный шрифт без кириллицы.
- Свяжите font-weight 400 с regular-файлом.
- Свяжите font-weight 700 с bold-файлом.
- Для italic укажите соответствующее наклонное начертание.
- Не имитируйте начертание, если PDF-библиотека делает это некорректно.
- Проверьте стили таблиц, header и footer: там часто задан другой font-family.
Убедитесь, что шрифт доступен процессу
Относительный путь может работать из консоли и ломаться при запуске через PHP-FPM, очередь или cron. Стройте путь от известного каталога приложения и проверяйте существование файла перед генерацией.
- Путь не зависит от текущей рабочей директории.
- Пользователь веб-сервера имеет право читать файл и проходить по каталогам.
- В имени файла нет ошибки регистра, незаметной на Windows и критичной на Linux.
- Контейнер или сервер действительно получил шрифты при развертывании.
- Ограничения open_basedir и sandbox разрешают доступ к каталогу.
- Файл не поврежден и не подменен HTML-страницей при скачивании.
Встройте шрифт в PDF
Если PDF ссылается на шрифт, которого нет у получателя, результат зависит от просмотрщика и операционной системы. Для счетов, актов, сертификатов и документов, отправляемых клиентам, шрифт следует встраивать.
Некоторые генераторы автоматически встраивают зарегистрированный TTF, другие требуют отдельной настройки. Проверьте свойства готового PDF или используйте утилиту анализа шрифтов: в списке должно быть видно, что нужное семейство embedded или embedded subset.
Полное встраивание или subset
Полный шрифт увеличивает размер каждого документа. Subset содержит только использованные символы и обычно подходит для обычного текста. Но динамические поля, объединение нескольких PDF и последующее редактирование могут требовать дополнительных проверок.
- Проверьте, что subset включает все символы итогового документа.
- Не кешируйте набор глифов между документами с разным текстом неправильным способом.
- При объединении файлов убедитесь, что библиотеки не теряют таблицы шрифтов.
- Оценивайте размер на реальном многостраничном документе, а не только на тесте.
Особенности HTML-to-PDF
Dompdf, mPDF, wkhtmltopdf и браузерный рендеринг по-разному поддерживают CSS, web fonts и пути к ресурсам. Рабочая страница в браузере не гарантирует такой же результат в PDF.
- Используйте формат шрифта, поддерживаемый выбранным движком.
- Проверьте разрешение локальных и удаленных ресурсов.
- Укажите абсолютный путь или корректный file URL по правилам библиотеки.
- Задайте единый font-family на корневом контейнере документа.
- Не рассчитывайте на автоматический fallback к системному шрифту.
- Проверьте отдельные стили для печати и media print.
- После изменения шрифта очистите кеш библиотеки.
Очистите кеш шрифтов безопасно
PDF-библиотека может хранить метрики, карту символов и зарегистрированные семейства. После замены файла старый кеш продолжает использовать прежние данные. Очищайте только документированный каталог кеша конкретного проекта и затем регистрируйте шрифт заново.
Перед удалением проверьте абсолютный путь. Не применяйте рекурсивную очистку к общему системному каталогу и не делайте кеш доступным на запись всем пользователям сервера.
Проверьте fallback-шрифты
В документе могут встречаться символы, отсутствующие даже в хорошем кириллическом шрифте: редкие знаки, emoji, математические обозначения или иероглифы. Настройте контролируемую цепочку fallback либо заменяйте неподдерживаемые символы по бизнес-правилам.
- Основной шрифт покрывает русский и латиницу.
- Дополнительный шрифт используется только для отсутствующих диапазонов.
- Emoji проверяются отдельно: цветные шрифты поддерживаются не всеми генераторами.
- Замена символа фиксируется, чтобы важные данные не исчезали молча.
Отдельно проверьте SVG и изображения
Текст внутри SVG может рендериться другим движком и не использовать шрифт основного документа. Если надпись является частью диаграммы, встройте подходящий шрифт по поддерживаемому механизму или заранее преобразуйте контролируемую графику в формат, который стабильно понимает генератор.
Не превращайте весь документ в изображение ради кириллицы. Это ухудшит поиск, копирование текста, доступность, качество печати и размер файла.
Если проблема только на сервере
- Сравните версии PDF-библиотеки и ее системных зависимостей.
- Проверьте наличие шрифтов внутри контейнера или chroot.
- Сравните права, пути и регистр имен файлов.
- Проверьте локаль процесса, но не пытайтесь лечить отсутствие глифов сменой locale.
- Убедитесь, что production использует тот же шаблон и CSS.
- Очистите только кеш шрифтов приложения и перезапустите нужный worker.
Как проверить результат
- Сгенерируйте минимальный тест со всеми нужными символами и начертаниями.
- Откройте PDF в двух разных просмотрщиках.
- Проверьте поиск по русскому слову и копирование текста.
- Посмотрите свойства шрифтов и убедитесь, что они встроены.
- Распечатайте тестовую страницу или проверьте печатный preview.
- Сгенерируйте рабочий документ с таблицей, header и footer.
- Запустите тот же сценарий через веб, очередь и cron, если используются все способы.
- Сравните размер файла и время генерации до и после исправления.
Типичные неправильные решения
- Несколько раз менять кодировку уже корректной UTF-8 строки.
- Установить шрифт только на компьютер разработчика.
- Подключить regular и ожидать, что bold появится автоматически.
- Использовать шрифт без кириллицы из-за совпадающего названия семейства.
- Заменить все русские буквы изображением.
- Игнорировать лицензию на встраивание коммерческого шрифта.
- Очищать системные каталоги кеша без проверки пути.
- Проверять файл только в одном просмотрщике.
Профилактика
Добавьте в проект эталонный PDF и автоматический тест с кириллицей, цифрами, валютами и всеми используемыми начертаниями. При обновлении библиотеки генерируйте документ заново и проверяйте, что текст извлекается, а шрифты остаются встроенными.
- Версионируйте разрешенные файлы шрифтов вместе с приложением или образом.
- Проверяйте их наличие и читаемость при запуске сервиса.
- Не допускайте молчаливый fallback к случайному системному шрифту.
- Фиксируйте версии генератора и зависимостей.
- Тестируйте реальные счета, акты и сертификаты после изменения шаблонов.
Итог
Когда в PDF не отображается кириллица, нужно проверить целостность UTF-8 текста, наличие глифов в файле шрифта, подключение каждого начертания, доступность пути на сервере и встраивание шрифта в итоговый документ. Минимальный тест помогает быстро отделить эти причины от ошибок шаблона.
Если нужно исправить генерацию PDF, я могу проверить данные и шаблон, подключить кириллические шрифты, настроить их встраивание и кеш, исправить таблицы и печатные стили, а затем протестировать счета, акты или сертификаты в серверном сценарии.