Skip to content

@comvi/svelte API Reference

@comvi/svelte provides Svelte store-based reactivity, context functions for setup, and a <T> component for safe rich-text interpolation. It supports both Svelte 4 and Svelte 5. It builds on top of @comvi/core and re-exports all core APIs.

Unlike React or SolidJS providers, Svelte uses its built-in setContext/getContext API. Call setI18nContext() in your root component.

Sets the i18n instance in Svelte context. Must be called in the root component (e.g., App.svelte or +layout.svelte).

interface SetI18nContextOptions {
autoInit?: boolean; // default true
}
<script>
import { setI18nContext } from '@comvi/svelte';
import { i18n } from './lib/i18n';
setI18nContext(i18n); // auto-inits in microtask
// setI18nContext(i18n, { autoInit: false }); // to disable
</script>
<slot />

Auto-init is a microtask (occurs before renders but not immediately). Pass { autoInit: false } to disable.

Gets the i18n instance from Svelte context. Throws if called outside of a component with context set.

<script>
import { getI18nContext } from '@comvi/svelte';
const i18n = getI18nContext();
// Direct access to the i18n instance
const unsub = i18n.on('localeChanged', ({ to }) => {
console.log('Language changed to:', to);
});
</script>

The primary function for translating strings and reading i18n state. Returns an object with Svelte readable stores and i18n methods.

<script>
import { useI18n } from '@comvi/svelte';
const { t, locale, setLocale, isLoading } = useI18n();
</script>
{#if $isLoading}
<p>Loading...</p>
{:else}
<h1>{$t('hello.world')}</h1>
<p>{$t('greeting', { name: 'Alice' })}</p>
<p>Current locale: {$locale}</p>
{/if}
useI18n(ns?: string): UseI18nReturn

Pass an optional namespace string to scope all $t() calls to that namespace.

interface UseI18nReturn {
t: Readable<(key: string, params?: TranslationParams) => string>;
tRaw: Readable<(key: string, params?: TranslationParams) => TranslationResult>;
locale: Readable<string>;
isLoading: Readable<boolean>;
isInitializing: Readable<boolean>;
isInitialized: Readable<boolean>;
cacheRevision: Readable<number>;
// methods (direct refs):
setLocale, addTranslations, addActiveNamespace, setFallbackLocale,
onMissingKey, onLoadError, clearTranslations, reloadTranslations,
hasLocale, hasTranslation, getLoadedLocales, getActiveNamespaces,
getDefaultNamespace, getTranslationCache, on, reportError,
formatNumber, formatDate, formatCurrency, formatRelativeTime,
dir: Readable<"ltr" | "rtl">
}

Use as $t('key'), $locale, $dir. Stores are memoized per i18n + namespace.

<script>
const { t } = useI18n('dashboard');
</script>
<!-- Keys are scoped — no need for { ns: 'dashboard' } -->
<h1>{$t('page.title')}</h1>

In Svelte 5, use $derived for computed translations:

<script>
import { useI18n } from '@comvi/svelte';
const { t, locale } = useI18n();
let name = $state('Alice');
// Derived state updates when language or name changes
const greeting = $derived($t('greeting', { name }));
</script>
<p>{greeting}</p>

The <T> component renders translations containing rich content (HTML tags, styled elements) safely.

<script>
import { T } from '@comvi/svelte';
</script>

The <T> component accepts these props:

PropTypeNotes
i18nKeystringrequired
paramsTranslationParamsinterpolation params
nsstringnamespace
localestringoverride locale
fallbackstringfallback text
rawbooleanforwards raw: true to post-processors that support it, such as the in-context editor marker injector
componentsComponentMaptag map (HTML tags only)
<!-- Translation: "Hello, {name}!" -->
<T i18nKey="greeting" params={{ name: 'Alice' }} />
<!-- Translation: "Read our <link>terms of service</link> and <bold>privacy policy</bold>" -->
<T
i18nKey="legal.tos"
components={{
link: { tag: 'a', props: { href: '/terms', class: 'text-blue-600' } },
bold: 'strong',
}}
/>

Svelte’s ComponentMap supports two kinds of mappings:

<T
i18nKey="rich.message"
components={{
// 1. HTML tag name
bold: 'strong',
// 2. Tag with props
link: { tag: 'a', props: { href: '/about', class: 'underline' } },
icon: { tag: 'span', props: { class: 'icon icon-info' } },
}}
/>

For advanced use cases, @comvi/svelte exports low-level store creators that bridge the i18n event system to Svelte readable stores. All stores are memoized per i18n instance.

Store CreatorReturnsTracks
createLanguageStore(i18n)Readable<string>localeChanged events
createLoadingStore(i18n)Readable<boolean>loadingStateChanged events
createInitializingStore(i18n)Readable<boolean>loadingStateChanged events
createInitializedStore(i18n)Readable<boolean>initialized / destroyed events
createCacheRevisionStore(i18n)Readable<number>namespaceLoaded / translationsCleared events
<script>
import { createLanguageStore, createLoadingStore } from '@comvi/svelte';
import { getI18nContext } from '@comvi/svelte';
const i18n = getI18nContext();
const locale = createLanguageStore(i18n);
const isLoading = createLoadingStore(i18n);
</script>
<p>Locale: {$locale}, Loading: {$isLoading}</p>

@comvi/svelte re-exports createI18n, I18n, and all types from @comvi/core. Import other core value exports from @comvi/core directly.

See the @comvi/core API Reference for the full list.