Встроенные токены (Inline tokens)
Вставляйте ссылки, URL ресурсов и непереводимые строки в MDX-тексты с помощью токенов, которые обновляются во всех локалях без необходимости перевода.
View as MarkdownЧасто в MDX-файлах требуются значения, которые Scribe уже известны: ссылка на другую запись, публичный URL файла, константа, не подлежащая переводу, или короткая строка, повторяющаяся в документе. Если «зашивать» их прямо в текст, он становится хрупким (изменился слаг или переместился файл — ссылка сломалась), а процесс локализации усложняется (ведь URL не нужно «переводить»).
Встроенные токены решают эту проблему. Вы один раз прописываете токен в английском тексте. Во время чтения он раскрывается с учётом локали, а при локализации воспринимается как неизменяемая метка-заглушка.
Синтаксис
Формат токена — ${{<kind>:<args>}}. Доступно четыре типа:
| Токен | Во что преобразуется |
|---|---|
${{static:"text"}} | Точная строка text (JSON-строка со всеми правилами экранирования и кавычек). Не переводится, остаётся одинаковой во всех языках. |
${{relation:<typeId>:<enSlug>:href}} | Путь-ссылка на целевую запись (см. режимы связей). Суффикс режима обязателен. |
${{relation:<typeId>:<enSlug>:slug}} | Английский слаг целевой записи — надёжный идентификатор для MDX-компонентов, которые сами загружают контент из Scribe. |
${{asset:/web/path.webp}} | Публичный URL ресурса (результат склейки assets.publicPath и пути). Подробнее в разделе Ресурсы. |
${{var:key}} | Значение frontmatter.vars[key] текущего документа. |
Поскольку в слаге не может быть двоеточий, парсинг связей (relation) работает однозначно. Токен ${{relation:<typeId>:<enSlug>}} без указания режима вызовет ошибку валидации.
Режимы связей (relation)
Любой токен типа relation должен заканчиваться на :href или :slug.
| Режим | Назначение |
|---|---|
:href | Навигационная ссылка. Итоговый вид зависит от потребителя (см. ниже). |
:slug | Идентификация: всегда возвращает английский слаг целевого документа. |
Результат работы :href зависит от того, кто читает документ:
| Потребитель | Результат :href |
|---|---|
createScribe() (во время работы приложения) | Путь с локализованным слагом, но без префикса локали (например, /for/vestidos). Идеально для компонента Link вашего роутера. |
Статический экспорт .md | Полный локализованный публичный путь с расширением (например, /es/for/vestidos.md), повторяющий структуру экспортированных файлов. |
Экранирование
Конструкция ${{ (с обратным слешем) выводит буквально ${{ и не считается токеном. Это удобно для написания документации по токенам (как на этой странице).
Ключ frontmatter vars
vars — это опциональный объект Record<string, string>, который можно объявить в любом документе без добавления в схему типа:
---
title: Весенняя распродажа
vars:
cta: За покупками
---
Готовы? ${{var:cta}}. Время акции ограничено.
Свойство vars зарезервировано: оно извлекается до проверки схемы (строгая схема его пропустит), никогда не отправляется на перевод и живёт только в исходном английском документе. При чтении переведённые документы берут значения ${{var:key}} из vars своего родительского английского файла. В итоге у вас единый источник правды.
Хеширование и перевод
Токены извлекаются из текста до вычисления хеша. На месте каждого токена остаётся пронумерованный маркер-заглушка (%%1%%, %%2%% и т.д. по порядку). Именно этот текст с плейсхолдерами хешируется и уходит к переводчику. Что это значит на практике:
- Изменение значения токена (статичного текста, цели ссылки, пути к картинке или значения
var) не меняет хеш английского оригинала, поэтому переводы не помечаются как устаревшие из-за правки ссылок. - Добавление, удаление или изменение порядка токенов меняет хеш, и переводы логично уходят на обновление.
- Текст без токенов хешируется ровно так же, как и раньше, так что внедрение токенов не спровоцирует массового сброса статуса переводов.
Переводчик получает инструкцию: маркеры %%n%% неизменяемы, каждый нужно вставить ровно один раз, не переводить и не менять нумерацию. Маркер можно переместить в рамках предложения, если того требует синтаксис языка. После получения перевода система проверяет наличие всех маркеров; при расхождении строка получает статус ошибки и уходит на повтор. В базе переводы хранятся с этими маркерами, а реальные значения подставляются уже в момент чтения.
Подстановка во время чтения
Замена токенов происходит на этапе чтения аналогично путям к ресурсам. Функция createScribe() включает подстановку для среды приложения, а статический экспорт — для раскладки .md. При этом CLI-команды, scribe validate и студия оперируют сырыми токенами, чтобы анализировать связи и корректно пересчитывать хеши.
- В английских документах токены просто раскрываются для дефолтной локали.
- В переведённых документах маркеры
%%n%%заполняются на основе актуального списка токенов из текущего английского документа с учётом локали. Поэтому ссылка на другую запись всегда будет использовать её свежий локализованный слаг, даже если сам текст перевода давно не обновлялся.
Есть два краевых случая, когда токен превратится в пустую строку при выполнении (на них укажет scribe validate): это relation в режиме :href к типу без свойства path и отсутствие ключа var.
Валидация
scribe validate находит следующие проблемы на уровне документа:
- Сломанный синтаксис токена (некорректная JSON-строка, неверное количество аргументов, неизвестный тип): ошибка.
relation: неизвестныйtypeId, неизвестныйenSlug, нет режима, либо режим:hrefуказывает на тип, для которого не предусмотрен роутинг: ошибка.asset: файл физически отсутствует на диске: ошибка.var: ключ не найден в словареvarsдокумента илиvarsне является объектом «строка-строка»: ошибка.
Перед валидацией самого MDX-тела сырые токены маскируются, поэтому правильный токен никогда не спровоцирует ложную ошибку парсинга MDX.
Упоминания в тексте и удаление
Панель «Used by» в студии и браузер ресурсов сканируют тексты: токены ${{relation:...}} отображаются как обратные ссылки (с меткой поля body), а ${{asset:...}} фиксируются как использования файлов. Если запись упомянута только в тексте (body) другой записи, её удаление не вызовет каскадных действий, отсоединений и не будет заблокировано. Подробнее см. Удаление записей. При планировании удаления такие связи попадут в раздел предупреждений «body references»: после удаления они превратятся в «висячие» ссылки и станут ошибками валидации.