Если в созданном 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.

Как проверить результат

  1. Сгенерируйте минимальный тест со всеми нужными символами и начертаниями.
  2. Откройте PDF в двух разных просмотрщиках.
  3. Проверьте поиск по русскому слову и копирование текста.
  4. Посмотрите свойства шрифтов и убедитесь, что они встроены.
  5. Распечатайте тестовую страницу или проверьте печатный preview.
  6. Сгенерируйте рабочий документ с таблицей, header и footer.
  7. Запустите тот же сценарий через веб, очередь и cron, если используются все способы.
  8. Сравните размер файла и время генерации до и после исправления.

Типичные неправильные решения

  • Несколько раз менять кодировку уже корректной UTF-8 строки.
  • Установить шрифт только на компьютер разработчика.
  • Подключить regular и ожидать, что bold появится автоматически.
  • Использовать шрифт без кириллицы из-за совпадающего названия семейства.
  • Заменить все русские буквы изображением.
  • Игнорировать лицензию на встраивание коммерческого шрифта.
  • Очищать системные каталоги кеша без проверки пути.
  • Проверять файл только в одном просмотрщике.

Профилактика

Добавьте в проект эталонный PDF и автоматический тест с кириллицей, цифрами, валютами и всеми используемыми начертаниями. При обновлении библиотеки генерируйте документ заново и проверяйте, что текст извлекается, а шрифты остаются встроенными.

  • Версионируйте разрешенные файлы шрифтов вместе с приложением или образом.
  • Проверяйте их наличие и читаемость при запуске сервиса.
  • Не допускайте молчаливый fallback к случайному системному шрифту.
  • Фиксируйте версии генератора и зависимостей.
  • Тестируйте реальные счета, акты и сертификаты после изменения шаблонов.

Итог

Когда в PDF не отображается кириллица, нужно проверить целостность UTF-8 текста, наличие глифов в файле шрифта, подключение каждого начертания, доступность пути на сервере и встраивание шрифта в итоговый документ. Минимальный тест помогает быстро отделить эти причины от ошибок шаблона.

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