Утром 21 сентября в репозитории libprisma — им Telegram раскрашивает блоки кода в сообщениях — за три часа прошла дюжина правок. В таблицу языков добавили Tolk, основной язык смарт-контрактов TON, обновили определения Tact и FunC и впервые с 20 ноября 2023 года пересобрали сам файл, который читают приложения.
В приложениях этого пока не видно. Каждый клиент несёт свою копию таблицы, и все три копии — из 2023 года.

Как Telegram раскрашивает код
Блок кода в сообщении разбирает не сервер, а сам клиент. За разбор отвечает libprisma — перенос браузерной библиотеки Prism.js на C++, который Telegram выложил осенью 2023 года. Правила языков генератор собирает из двух мест — из пакета Prism.js и из нескольких файлов, написанных прямо в репозитории, откуда и берутся языки TON, — прогоняет через нормализацию и складывает в один бинарный файл grammars.dat. Клиент загружает этот файл при старте и дальше спрашивает у него токены для каждого блока кода — где ключевое слово, где строка, где комментарий.
Такой файл — это и есть весь список поддерживаемых языков. Языка нет в таблице — блок остаётся серым моноширинным текстом, даже если автор честно подписал его tolk после трёх обратных кавычек.
Android устроен иначе: движок Prism там переписан на Java, а таблица лежит своя, codelng.gzip, и приехала она с версией 10.2 в конце октября 2023 года. Разные движки регулярных выражений у одной и той же таблицы — Boost в C++ и java.util.regex в Java — дальше окажутся главной причиной, почему правок оказалось двенадцать, а не две.
Почему языки TON до сих пор серые
Серыми они остаются не потому, что правил для TON никто не написал. Определения четырёх языков — Tact, FunC, Fift и TL-B — легли в исходники libprisma в мае 2024 года. Через четыре месяца туда же принесли обновление: Tact с версии 1.2.0 до 1.6.0 и переписанный целиком FunC с 0.2.0 до 0.4.4.
До приложений не дошло ни то, ни другое, и причина не в приложениях. Правила языков живут в репозитории как обычные файлы, а клиенты читают бинарную таблицу, собранную из них, — и эту таблицу последний раз собирали 20 ноября 2023 года, за полгода до того, как в репозиторий попал первый язык TON. Всё, что добавляли после, лежало в исходниках и никуда не ехало.
Сборку делает workflow на GitHub Actions, и он не запускался с тех пор вовсе: GitHub вывел из эксплуатации actions/upload-artifact@v3, после чего задача помечалась упавшей до того, как выполнится первый её шаг. Обновление Tact и FunC так и провисело в очереди два года.
Tolk — отдельная история. Язык появился как развитие FunC и сейчас в документации TON назван рекомендованным, а сам FunC переведён в разряд устаревших. В libprisma его предложили в мае 2026 года и держали черновиком с пометкой, что нужно сначала понять, как это раскатывать по всем клиентам.
Что прошло 21 сентября
Сначала починили сборку. Версии действий подняты, Node 18 заменён на 22, и задача снова запускается — руками и сама, как только меняются правила языков, — после чего открывает pull request с пересобранной таблицей. После этого приняли Tolk и обновление Tact и FunC.
В обновлении по дороге нашлась ошибка, из-за которой FunC был раскрашен не полностью. Правило для операторов-функций (_+_, _<=>_ и остальные, где подчёркивания обозначают места аргументов) собиралось из другого правила, а то заканчивалось проверкой «дальше пробел». В собранном виде проверка требовала пробел ровно в той позиции, где обязано стоять закрывающее подчёркивание, — условие невыполнимое, так что правило не срабатывало никогда.
Остальные правки касаются не TON, но объясняют, почему одна таблица годится сразу для двух движков. Boost читает выражения байтами и не понимает записи вида \uXXXX: внутри символьного класса такая запись превращается в набор произвольных ASCII-символов. В языке Dhall из-за этого класс операторов съедал первую букву каждого имени типа, а квантор ∀ не подсвечивался ни в одном языке, где он вообще описан. Сериализация таблицы резала старший байт у символов за пределами первых двухсот пятидесяти шести, и записанный в грамматике BQN символ • приезжал в таблицу двойной кавычкой, ∞ — управляющим символом, π — буквой À.
Третья правка — про расхождение движков. \v компилируется в обоих и значит в них разное: в одном это один символ вертикальной табуляции, в другом — весь класс вертикальных пробелов вместе с переводом строки, из-за чего значения в ini убегали за конец своей строки. Проверка «компилируется ли» такое не ловит, поэтому теперь на каждый pull request таблица пересобирается заново и каждое из без малого четырёх тысяч выражений прогоняется через оба движка.
Когда это увидят в приложениях
Срок не назначен ни в одном из них. Таблицу клиенты не берут из репозитория на лету, а несут свою копию, и каждая копия старше самого первого языка TON в libprisma.
| Клиент | Откуда берёт таблицу | Дата копии |
|---|---|---|
| Telegram Desktop | форк libprisma, закреплённый подмодулем | апрель 2024, таблица внутри — ноябрь 2023 |
| Telegram для iOS | файл grammars.dat в самом репозитории клиента | 31 октября 2023 |
| Telegram для Android | файл codelng.gzip в ресурсах приложения | 28 октября 2023 |
Обновление копии — решение каждой команды клиента, и в черновике Tolk об этом сказано прямо: PR ждал ответа, как раскатывать новую таблицу по всем приложениям. Пока ответа нет, блок, подписанный tolk, tact или func, выглядит в переписке так же, как выглядел вчера.



