Scribe

Встроенные токены (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»: после удаления они превратятся в «висячие» ссылки и станут ошибками валидации.

Встроенные токены (Inline tokens) · Scribe