Unicode является фундаментом любой современной системы интернационализации, а в контексте FormatJS именно он определяет границы корректной работы сообщений, плейсхолдеров и форматирования. Ошибки, связанные с кодировкой, в таких системах редко проявляются сразу: они возникают на стыке сериализации данных, сборки, передачи через API и последующего рендеринга сообщений в браузере или Node.js-среде.
JavaScript использует UTF-16 для представления строк, что создаёт ряд системных особенностей при работе с международным текстом. Один символ Unicode может занимать один или два 16-битных кодовых слова. Это приводит к тому, что:
FormatJS, опираясь на ICU MessageFormat, не абстрагирует полностью эти особенности. При интерполяции значений в сообщения любая ошибка в разбиении строки может привести к повреждению финального текста.
Особенно критично это при работе с данными, которые проходят через несколько слоёв: backend → JSON → транспорт → фронтенд → форматирование сообщений.
Основные проблемы возникают не в самой библиотеке FormatJS, а на границах системы:
charset=utf-8)Особое значение имеет этап агрегации переводов. Message catalogs часто хранятся в JSON-файлах, где любое нарушение UTF-8 приводит к тому, что ICU-сообщения становятся невалидными и перестают компилироваться.
FormatJS использует синтаксис ICU MessageFormat, в котором фигурные скобки, кавычки и специальные управляющие конструкции имеют семантическое значение.
Ключевые источники проблем:
{ }Например, сообщение:
Hello {name}
является корректным только при условии, что name
существует в контексте. Если же текст приходит из внешнего источника и
содержит { или }, парсер ICU может
интерпретировать это как начало выражения.
В ICU MessageFormat одинарная кавычка используется как escape-символ. Это приводит к частым ошибкам при переводах:
Message catalogs FormatJS обычно представлены в JSON-формате. Несмотря на то, что JSON строго определяет UTF-8 как стандарт, на практике возникают отклонения:
\uXXXXПроблема усиливается при наличии многоуровневой сборки: перевод может быть создан в одном инструменте, преобразован другим, затем минифицирован и только после этого попадает в runtime.
Особенно критично поведение последовательностей:
"\uD83D\uDE00"
Это корректная суррогатная пара emoji, но при частичном разбиении или неправильной сериализации результатом становится «битый» символ.
FormatJS часто используется совместно с React, где сообщения могут попадать в DOM. В этом контексте возникает проблема двойного экранирования:
В результате текст:
Tom & Jerry
может последовательно превратиться в:
Tom & Jerry
а затем при неправильной обработке — в:
Tom & Jerry
Подобные эффекты особенно часто возникают при смешивании ICU-сообщений и HTML-сущностей внутри одного каталога переводов.
Unicode допускает несколько способов представления одного и того же символа. Например, символ может быть представлен:
FormatJS не выполняет автоматическую нормализацию строк, поэтому различия в форме представления приводят к:
Например, слово с диакритическим знаком может существовать в двух разных формах, которые визуально идентичны, но не равны при сравнении строк.
Emoji в Unicode часто состоят из нескольких кодовых точек. Проблемы возникают при:
Суррогатная пара может быть разорвана:
\uD83D + \uDE00
Если между ними происходит операция разбиения строки, результатом становится некорректный символ, отображающийся как «�».
В контексте FormatJS это особенно критично при форматировании сообщений с динамическими значениями, где эмодзи передаются как параметры.
При работе с языками RTL (арабский, иврит) возникают проблемы смешивания направлений текста. ICU поддерживает сложные структуры сообщений, но кодировка может искажать порядок отображения:
FormatJS корректно обрабатывает ICU-структуры, но любые ошибки кодировки приводят к потере управляющих символов, которые отвечают за направление текста.
Проблемы кодировки часто проявляются не напрямую, а через интерполяцию значений:
ICU MessageFormat ожидает строгие типы, и любое отклонение приводит к:
Особенно часто ошибки возникают при передаче данных через REST API, где отсутствует единый стандарт сериализации локализованных значений.
Сборка фронтенд-приложений добавляет дополнительный слой риска:
При неправильной конфигурации сборки возможны ситуации, когда:
Это особенно критично для больших проектов с множеством локалей.
При хранении message catalogs в базе данных возникают дополнительные проблемы:
Даже при корректной UTF-8 настройке возможны проблемы с сортировкой и сравнением строк, особенно для языков с расширенными алфавитами или сложными диакритическими системами.
Наиболее сложные проблемы кодировки возникают не локально, а на стыке всех слоёв:
В результате FormatJS может:
Такие эффекты особенно трудно диагностируются, поскольку каждый отдельный слой системы выглядит корректным.