# @comvi/core/rich-text

API reference for @comvi/core/rich-text and @comvi/core/tags: prepareTranslation, registerTagSyntax, tagSyntaxExtension and the VirtualNode constructors.

Canonical: https://comvi.io/docs/i18n/api/core-rich-text

The rich-text toolbox every framework's `<T>` runs on. `/rich-text` is pure. `/tags` re-exports
all of it and registers ambient `<tag>` syntax for plain `t()` as an import side effect.

## Exports

- `@comvi/core/rich-text`: `prepareTranslation`, `getPendingHandlerName`, `childrenToArray`,
`registerTagSyntax`, `createElement`, `createTextNode`, `createFragment`, `isVirtualNode`;
types `PrepareTranslationProps`, `PrepareTranslationSource`, `PreparedTranslation`,
`PendingHandler`, `TagComponentsMap`, `TagComponentConfig`, `VirtualNode`, `ElementNode`,
`TextNode`, `FragmentNode`, `TranslationResult`.
- `@comvi/core/tags`: everything above, plus `tagSyntaxExtension`; type `SyntaxExtension`.

## `prepareTranslation(i18n, props)`

```ts
function prepareTranslation(i18n: PrepareTranslationSource, props: PrepareTranslationProps): PreparedTranslation

interface PrepareTranslationSource {
tRaw(key: string, params?: TranslationParams): TranslationResult;
hasTranslation(key: string, locale?: string, namespace?: string, checkFallbacks?: boolean): boolean;
}
```

| Prop | Type | Meaning |
| --- | --- | --- |
| `i18nKey` | `string` | The key |
| `params` | `TranslationParams` | Interpolation params |
| `ns` | `string` | Overrides a same-named `params` key unless `undefined` |
| `locale` | `string` | Same |
| `fallback` | `string` | Same |
| `markers` | `boolean` | Same |
| `components` | `TagComponentsMap` | Tag name to handler; strings and string-target configs render directly, anything else is opaque |

| Returned | Type | Meaning |
| --- | --- | --- |
| `content` | `TranslationResult` | Marker element nodes stand in for opaque handlers |
| `pendingHandlers` | `PendingHandler[]` | `{ name, marker, handler, props? }` per opaque handler; `[]` when none |
| `isMissing` | `boolean` | The result is the key itself; a set `fallback` or an `onMissingKey` value makes it `false` |

`TagComponentConfig` is `{ tag?, component?, props? }`; `tag` and `component` are aliases.

`src/prepare-demo.ts`

```ts

const i18n = createI18n({
locale: 'en',
messages: { en: { tos: 'Read our <link>terms</link>' } },
});

const { content, pendingHandlers, isMissing } = prepareTranslation(i18n, {
i18nKey: 'tos',
components: { link: { tag: 'a', props: { href: '/terms' } } },
});
```

## `registerTagSyntax()`

```ts
function registerTagSyntax(): () => void
const tagSyntaxExtension: SyntaxExtension
```

Registers `<tag>` parsing for plain `t()` process-wide; idempotent, and the return value
unregisters. `import '@comvi/core/tags'` calls it at module scope. `tagSyntaxExtension` is the
grammar itself, which `prepareTranslation` passes per call through `tagInterpolation.extensions`.
Ambient registration is per bundle, so a server graph needs its own import.

## Helpers

```ts
function childrenToArray(children: TranslationResult): (string | VirtualNode)[]
function getPendingHandlerName(tag: string): string | undefined
function createElement(tag: string, props?: Record<string, unknown>, children?: Array<VirtualNode | string>): ElementNode
function createTextNode(text: string): TextNode
function createFragment(children: Array<VirtualNode | string>, key?: string | number): FragmentNode
function isVirtualNode(value: unknown): value is VirtualNode
```

| Helper | Meaning |
| --- | --- |
| `childrenToArray(children)` | `''` becomes `[]` |
| `getPendingHandlerName(tag)` | The handler name a marker tag carries, else `undefined` |
| `createElement(tag, props?, children?)` | `children` is one array argument. Also on the `@comvi/core` root |
| `createTextNode(text)` | Not on the root |
| `createFragment(children, key?)` | Not on the root |
| `isVirtualNode(value)` | True only for a node built by `createElement`, `createTextNode` or `createFragment`; an object literal of the same shape, a Vue VNode or a React element is not one. Also on the root |

## Read next

- [`@comvi/core`](/docs/i18n/api/core): the i18n instance and the `t` / `tRaw` pair these helpers read from.
- [Insert values and markup](/docs/i18n/tag-interpolation): tag interpolation per framework, and `<T>` versus plain `t()`.
