# @comvi/svelte

API reference for @comvi/svelte: setI18nContext, useI18nInstance, useI18n and its stores, useI18nLoader and useI18nPlugins, the seven store creators, and <T>.

Canonical: https://comvi.io/docs/i18n/api/svelte

The Svelte 5 binding (peer `svelte ^5.3.0`). Context is set with `setI18nContext()`; reactive
members are readable stores.

## Exports

- Values: `T`, `setI18nContext`, `useI18nInstance`, `useI18n`, `useI18nLoader`,
`useI18nPlugins`, `createLocaleStore`, `createLoadingStore`, `createInitializingStore`,
`createInitializedStore`, `createCacheRevisionStore`, `createDefaultParamsStore`,
`createDefaultNamespaceStore`, `createI18n`, `loader`, `attachLoader`, `plugins`,
`definePlugin`, `icuCompiler`, `devtools`.
- Types: `SetI18nContextOptions`, `UseI18nReturn`, `UseI18nLoaderReturn`,
`UseI18nPluginsReturn`, `SvelteTextTranslationFunction`, `SvelteRawTranslationFunction`,
`TProps`, `ComponentMap`, `DevtoolsOptions`, `I18n`, every `@comvi/core` type.

`I18n` is a type only; `@comvi/core/tags` is not re-exported.

`src/lib/i18n.ts`

```ts

export const i18n = createI18n({ locale: 'en', fallbackLocale: 'en' })
.use(loader({ en: () => import('./locales/en.json') }))
.use(plugins());
```

## `setI18nContext(i18n, options?)`

```ts
function setI18nContext(i18n: AnyI18nInstance, options?: SetI18nContextOptions): void
```

| Option | Type | Default | Meaning |
| --- | --- | --- | --- |
| `autoInit` | `boolean` | `true` | Schedule `init()` in a microtask when the instance is neither initialized nor initializing; `isInitializing` reads `true` from the call on, so the first render is already inside the gate |
| `onError` | `(error: Error) => void` | none | Called after the instance's own `onError` when that `init()` rejects; with neither, the rejection is swallowed |

Call it in the root component.

`src/routes/+layout.svelte`

```svelte
<script lang="ts">
import { setI18nContext } from '@comvi/svelte';
import { i18n } from '$lib/i18n';

let { children } = $props();

setI18nContext(i18n, { onError: (error) => console.error(error) });
</script>

{@render children?.()}
```

## `useI18nInstance()`

```ts
function useI18nInstance(): WrapperI18nInstance
```

The i18n instance itself, not a store, callable during component initialization only. Throws
with no `setI18nContext` ancestor.

## `useI18n(ns?)`

```ts
function useI18n<D extends DefaultTranslationParams = {}, NS extends string | undefined = undefined>(ns?: NS): UseI18nReturn<D, NS>
```

Stores take `$`: `$t('key')`, `$locale`. The translation stores are memoized per instance and
namespace; `dir` is rebuilt per call.

| Returned | Type | Meaning |
| --- | --- | --- |
| `t` | `Readable<NamespaceBoundTranslateFn<NS, D, string>>` | A store of the translate function |
| `tRaw` | `Readable<NamespaceBoundTranslateFn<NS, D, TranslationResult>>` | Rich-text half |
| `locale` | `Readable<string>` | Current locale |
| `isLoading`, `isInitializing`, `isInitialized` | `Readable<boolean>` | Loading flags |
| `cacheRevision` | `Readable<number>` | Cache and config revision |
| `defaultParams` | `Readable<DefaultParamsSnapshot<D>>` | Shallow snapshot |
| `dir` | `Readable<'ltr' \| 'rtl'>` | Text direction |
| `setLocale` | `(locale: string) => Promise<void>` | `setLocale` |
| `addMessages`, `setFallbackLocale`, `setDefaultParams`, `clearMessages`, `hasLocale`, `hasTranslation`, `on`, `reportError` | as on the instance | Bound functions |
| `getLoadedLocales`, `getActiveNamespaces`, `getDefaultNamespace`, `getMessagesCache` | `() => …` | Snapshots |
| `formatNumber`, `formatDate`, `formatCurrency`, `formatRelativeTime` | bound, trailing `locale?` | Follow the locale in markup and `$derived`; a trailing `locale` overrides it |

`src/lib/Greeting.svelte`

```svelte
<script lang="ts">
import { useI18n } from '@comvi/svelte';

const { t, locale, setLocale } = useI18n();
</script>

<button onclick={() => setLocale($locale === 'en' ? 'de' : 'en')}>
{$t('greeting', { name: 'Alice' })}
</button>
```

## `useI18nLoader()`, `useI18nPlugins()`

```ts
function useI18nLoader(): UseI18nLoaderReturn // AcquiredLoaderApi
function useI18nPlugins(): UseI18nPluginsReturn // AcquiredPluginsApi
```

Context readers, not stores: callable during component initialization, returning plain bound
functions. `useI18nLoader()` gives `addActiveNamespace`, `addActiveNamespaces`,
`removeActiveNamespace`, `removeActiveNamespaces`, `reloadMessages`, `onLoadError`;
`useI18nPlugins()` gives `onMissingKey`. Each throws, in development and production, when the
instance lacks the capability. Cached per instance.

`src/lib/Dashboard.svelte`

```svelte
<script lang="ts">
import { onDestroy, onMount } from 'svelte';
import { useI18n, useI18nLoader } from '@comvi/svelte';

const { t } = useI18n('dashboard');
const { addActiveNamespace, onLoadError } = useI18nLoader();

onMount(() => void addActiveNamespace('dashboard'));
onDestroy(onLoadError((locale, ns, error) => console.error(locale, ns, error)));
</script>

<h1>{$t('page.title')}</h1>
```

## `<T>`

```ts
const T: Component<TProps>

type TProps = TBaseProps & Record<string, unknown>
type ComponentMap = Record<string, ComponentHandler>
// ComponentHandler and ComponentTarget are the shape of one ComponentMap entry; neither is exported
type ComponentHandler =
| string
| Component<any>
| ({ props?: Record<string, any> } & (
      | { tag: ComponentTarget; component?: ComponentTarget }
      | { component: ComponentTarget; tag?: ComponentTarget }
    ))
type ComponentTarget = string | Component<any>
```

Renders `<tag>` markup as real Svelte nodes through `<svelte:element>`; no HTML string is built.

### Props

| Prop | Type | Meaning |
| --- | --- | --- |
| `i18nKey` | `keyof TranslationKeys \| PermissiveKey` | Required |
| `params` | `TranslationParams` | Interpolation params; any other prop is a param too and wins a collision |
| `ns`, `locale`, `fallback` | `string` | Overrides; with `locale` set the component ignores locale changes |
| `markers` | `boolean` | `false` turns the in-context editor's markers off for this element when they cause a problem; it is then not editable in context |
| `components` | `ComponentMap` | Tag name to a tag name, a component (content arrives as its `children` snippet), or a `{ tag \| component, props }` config |
| `children` | `Snippet` | Rendered when the key is missing, no `fallback` was given and `onMissingKey` returned nothing |

In a config whose target is a tag name, a `props` value of `false` omits the attribute.

`src/lib/Rich.svelte`

```svelte
<script lang="ts">
import { T } from '@comvi/svelte';
import Highlight from './Highlight.svelte';
</script>

<T i18nKey="optional.feature">Default content</T>
```

### When a tag handler throws

The error is reported as `reportError(error, { source: 'translation', tagName })` and the tag
renders its own children.

| Binding | Guard | Degrades to | On the server |
| --- | --- | --- | --- |
| Svelte | `<svelte:boundary>`, stays failed until remount | the tag's children | throws |
| React | error boundary on the render, client only | the tag's children | throws |
| Vue | `try`/`catch` on slot handlers | `<span>` with the children | caught |
| Solid | `try`/`catch` on the call | the children | caught |

## Store creators

```ts
function createLocaleStore(i18n: WrapperI18nInstance): Readable<string>
function createLoadingStore(i18n: WrapperI18nInstance): Readable<boolean>
function createInitializingStore(i18n: WrapperI18nInstance): Readable<boolean>
function createInitializedStore(i18n: WrapperI18nInstance): Readable<boolean>
function createCacheRevisionStore(i18n: WrapperI18nInstance): Readable<number>
function createDefaultParamsStore<D>(i18n: WrapperI18nInstance<D>): Writable<DefaultParamsSnapshot<D>>
function createDefaultNamespaceStore(i18n: WrapperI18nInstance): Writable<string>
```

| Store | Tracks |
| --- | --- |
| `createLocaleStore` | `localeChanged` |
| `createLoadingStore` | `loadingStateChanged` (`isLoading`) |
| `createInitializingStore` | `loadingStateChanged` (`isInitializing`); also `true` while a scheduled auto-init is pending |
| `createInitializedStore` | `initialized` and `destroyed` |
| `createCacheRevisionStore` | every revision event except `localeChanged` and `loadingStateChanged` |
| `createDefaultParamsStore` | `configChanged`; `set` and `update` call `setDefaultParams`, `undefined` clears |
| `createDefaultNamespaceStore` | `defaultNamespaceChanged`; assigning calls `setDefaultNamespace` |

All are memoized per instance. `useI18n()` builds and returns them.

## Read next

- [Svelte](/docs/i18n/svelte): setup, loading, plurals, tags and typing for a Svelte app.
- [Insert values and markup](/docs/i18n/tag-interpolation): the `<T>` boundary and when to reach for `@comvi/core/tags`.
- [`@comvi/core`](/docs/i18n/api/core): the i18n instance, the capabilities and every type.
