@comvi/svelte
The Svelte 5 binding (peer svelte ^5.3.0). Context is set with setI18nContext(); reactive
members are readable stores.
Exports
Section titled “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/coretype.
I18n is a type only; @comvi/core/tags is not re-exported.
import { createI18n, loader, plugins } from '@comvi/svelte';
export const i18n = createI18n({ locale: 'en', fallbackLocale: 'en' }) .use(loader({ en: () => import('./locales/en.json') })) .use(plugins());setI18nContext(i18n, options?)
Section titled “setI18nContext(i18n, options?)”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.
<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()
Section titled “useI18nInstance()”function useI18nInstance(): WrapperI18nInstanceThe i18n instance itself, not a store, callable during component initialization only. Throws
with no setI18nContext ancestor.
useI18n(ns?)
Section titled “useI18n(ns?)”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 |
<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()
Section titled “useI18nLoader(), useI18nPlugins()”function useI18nLoader(): UseI18nLoaderReturn // AcquiredLoaderApifunction useI18nPlugins(): UseI18nPluginsReturn // AcquiredPluginsApiContext 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.
<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>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 exportedtype 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.
| 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.
<script lang="ts"> import { T } from '@comvi/svelte'; import Highlight from './Highlight.svelte';</script>
<T i18nKey="rich.message" components={{ bold: 'strong', highlight: Highlight, link: { tag: 'a', props: { href: '/about' } }, }}/><T i18nKey="optional.feature">Default content</T>When a tag handler throws
Section titled “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
Section titled “Store creators”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
Section titled “Read next”- Svelte: setup, loading, plurals, tags and typing for a Svelte app.
- Insert values and markup: the
<T>boundary and when to reach for@comvi/core/tags. @comvi/core: the i18n instance, the capabilities and every type.