Форматированный текст
Ссылка внутри переведённого предложения — классическая головная боль в i18n: разбей строку на три ключа, и переводчик потеряет порядок слов. В MF2 для этого есть разметка, а компонент Rich рендерит её через snippet-ы — имя разметки в сообщении решает, какой snippet обернёт текст.
Попробуйте #
И ссылка, и её адрес живут в переводе, а не в компоненте:
Прочитайте документацию, прежде чем публиковать
{ "cta": "Read {#link to=|/docs|}the docs{/link} before you ship" }<script lang="ts">
import { Rich } from 'svelte-dialect';
import { formatParts } from '#lib/i18n.js';
// options come from the translation: let only a path on this site through
const internal = (to: unknown) => (/^\/(?![/\\])/.test(String(to)) ? String(to) : undefined);
</script>
<Rich parts={formatParts('home:cta')}>
{#snippet link(children, options)}<a href={internal(options.to)}>{@render children()}</a>{/snippet}
</Rich>Опции и вложенность #
Snippet получает snippet для содержимого разметки и её MF2-опции — {#link to=|/x|} превращается в { to: '/x' } — так что перевод может нести атрибуты, специфичные для локали. Это такие же входные данные, как любые другие, поэтому проверяйте их, прежде чем отдавать в атрибут: snippet'ы на этой странице пропускают только путь на этом сайте. Вложенность работает на любую глубину, каждый уровень проходит через свой snippet:
жирный текст с ссылкой внутри
Отсутствующий snippet не ломает страницу #
Разметка без подходящего snippet-а всё равно рендерит своё содержимое — так устаревший перевод или перевод, написанный до появления snippet-а, деградирует мягко, а не исчезает:
В этом предложении есть неподключённая разметка посередине
Под капотом Rich #
formatParts(key, params) — примитив, лежащий в основе: он возвращает части text / open / close / standalone. Используйте его напрямую, если хотите рендерить разметку собственной механикой.
Имена разметки #
Имена разметки становятся именами snippet-ов, так что держите их валидными идентификаторами — для {#my-link} нет подходящего snippet-а.