@comvi/solid
The SolidJS binding (peer solid-js ^1.8): a provider, a useI18n() hook whose reactive
members are accessors, low-level primitives and a <T> component.
Exports
Section titled “Exports”- Values:
I18nProvider,T,useI18n,useI18nInstance,useI18nLoader,useI18nPlugins,createLocaleSignal,createDefaultNamespaceSignal,createDefaultNamespaceState,createDefaultParamsSignal,createDefaultParamsState,createLoadingSignal,createInitializingSignal,createInitializedSignal,createCacheRevisionSignal,createI18n,loader,attachLoader,plugins,definePlugin,icuCompiler,devtools. - Types:
I18nProviderProps,UseI18nReturn,UseI18nLoaderReturn,UseI18nPluginsReturn,TProps,ComponentMap,DevtoolsOptions,I18n, every@comvi/coretype.
I18n is a type only; @comvi/core/tags is not re-exported. TagComponentConfig comes from
@comvi/core/rich-text.
import { createI18n, loader, plugins } from '@comvi/solid';
export const i18n = createI18n({ locale: 'en', fallbackLocale: 'en' }) .use(loader({ en: () => import('./locales/en.json') })) .use(plugins());<I18nProvider>
Section titled “<I18nProvider>”const I18nProvider: ParentComponent<I18nProviderProps>| Prop | Type | Default | Meaning |
|---|---|---|---|
i18n |
AnyI18nInstance |
required | The i18n instance; any default-params type |
children |
JSX.Element |
required | The subtree |
autoInit |
boolean |
true |
Call init() on mount |
fallback |
JSX.Element |
none | Rendered instead of children until isInitialized; also what renderToString paints. undefined does not gate; false or null gates blank |
ssrLocale |
string |
none | Written onto the instance in the render phase, so SSR needs a per-request instance. It paints on the first render when that locale’s catalogs are already available; otherwise the switch lands when they load |
onError |
(error: Error) => void |
none | Called when auto-initialization fails, after the instance’s own onError |
import { I18nProvider } from '@comvi/solid';import { i18n } from './i18n';
export function App() { return ( <I18nProvider i18n={i18n} fallback={<p>Loading</p>}> <h1>Hello</h1> </I18nProvider> );}useI18n(ns?)
Section titled “useI18n(ns?)”function useI18n<DefaultNS extends string | undefined = undefined, D extends DefaultTranslationParams = {}>(ns?: DefaultNS): UseI18nReturn<DefaultNS, D>Reactive members are accessors: locale(), isLoading(). t() in JSX tracks the locale and
the cache revision. A bound namespace adds its bare keys to t’s key union.
| Returned | Type | Meaning |
|---|---|---|
t |
NamespaceBoundTranslateFn<DefaultNS, D, string> |
Translate, reactive |
tRaw |
NamespaceBoundTranslateFn<DefaultNS, D, TranslationResult> |
Rich-text half |
locale |
Accessor<string> |
Current locale |
isLoading, isInitializing, isInitialized |
Accessor<boolean> |
Loading flags |
cacheRevision |
Accessor<number> |
Cache and config revision |
defaultParams |
Accessor<DefaultParamsSnapshot<D>> |
Shallow snapshot |
dir |
() => '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? |
Reactive: read the locale signal at call time, like t(); a trailing locale overrides it |
import { useI18n } from '@comvi/solid';
export function Greeting() { const { t, locale, setLocale } = useI18n(); return ( <button onClick={() => void setLocale(locale() === 'en' ? 'de' : 'en')}> {t('greeting', { name: 'Alice' })} </button> );}useI18nLoader(), useI18nPlugins()
Section titled “useI18nLoader(), useI18nPlugins()”function useI18nLoader(): UseI18nLoaderReturn // AcquiredLoaderApifunction useI18nPlugins(): UseI18nPluginsReturn // AcquiredPluginsApiuseI18nLoader() 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.
import { onMount } from 'solid-js';import { useI18n, useI18nLoader } from '@comvi/solid';
export function LazyNamespace() { const { t } = useI18n('dashboard'); const { addActiveNamespace } = useI18nLoader();
onMount(() => void addActiveNamespace('dashboard'));
return <h1>{t('page.title')}</h1>;}useI18nInstance()
Section titled “useI18nInstance()”function useI18nInstance(): WrapperI18nInstanceThe i18n instance itself, not a signal. Throws outside <I18nProvider>.
const T: Component<TProps>
type TProps = TBaseProps & Record<string, unknown>type ComponentMap = Record<string, ComponentHandler>// ComponentHandler and ComponentConfigTarget are the shape of one ComponentMap entry; neither is exportedtype ComponentHandler = | string | ((props: { children?: JSX.Element }) => JSX.Element) | (Omit<TagComponentConfig, 'props'> & { props?: Record<string, any> } & ( | { tag: ComponentConfigTarget; component?: ComponentConfigTarget } | { component: ComponentConfigTarget; tag?: ComponentConfigTarget } ))type ComponentConfigTarget = string | ((props: any) => JSX.Element)| Prop | Type | Meaning |
|---|---|---|
i18nKey |
keyof TranslationKeys | PermissiveKey |
Required |
params |
TranslationParams |
Interpolation params; any other prop is merged in |
ns, locale, fallback |
string |
Overrides; with locale set the component does not recompute on a locale change |
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, or a { tag | component, props } config |
children |
JSX.Element |
Rendered when the key is missing, no fallback was given and onMissingKey returned nothing |
A handler that throws is reported as reportError(error, { source: 'translation', tagName })
and the tag renders its children, on the server and the client alike. A non-callable opaque
handler renders its children silently.
import { T } from '@comvi/solid';
export function Rich() { return ( <> <T i18nKey="rich.message" components={{ bold: 'strong', highlight: ({ children }) => <mark>{children}</mark>, link: { tag: 'a', props: { href: '/about' } }, }} /> <T i18nKey="optional.feature">Default content</T> </> );}Reactive primitives
Section titled “Reactive primitives”Each takes an i18n instance and runs inside a reactive context. A Signal reads; a State
returns [accessor, setter] and the setter writes through to the instance.
function createLocaleSignal(i18n: WrapperI18nInstance): Accessor<string>function createDefaultNamespaceSignal(i18n: WrapperI18nInstance): Accessor<string>function createDefaultNamespaceState(i18n: WrapperI18nInstance): [Accessor<string>, (namespace: string) => void]function createDefaultParamsSignal<D>(i18n: WrapperI18nInstance<D>): Accessor<DefaultParamsSnapshot<D>>function createDefaultParamsState<D>(i18n: WrapperI18nInstance<D>): [Accessor<DefaultParamsSnapshot<D>>, (params: SetDefaultParamsArg<D>) => void]function createLoadingSignal(i18n: WrapperI18nInstance): Accessor<boolean>function createInitializingSignal(i18n: WrapperI18nInstance): Accessor<boolean>function createInitializedSignal(i18n: WrapperI18nInstance): Accessor<boolean>function createCacheRevisionSignal(i18n: WrapperI18nInstance): Accessor<number>| Primitive | Tracks |
|---|---|
createLocaleSignal |
localeChanged |
createDefaultNamespaceSignal, createDefaultNamespaceState |
defaultNamespaceChanged; the setter calls setDefaultNamespace |
createDefaultParamsSignal, createDefaultParamsState |
configChanged; the setter calls setDefaultParams |
createLoadingSignal |
loadingStateChanged (isLoading) |
createInitializingSignal |
loadingStateChanged (isInitializing) |
createInitializedSignal |
initialized and destroyed |
createCacheRevisionSignal |
every revision event except localeChanged and loadingStateChanged |
Read next
Section titled “Read next”- Solid: setup, loading, plurals, tags and typing for a Solid app.
- Type-check translation keys: generated keys, autocomplete and compile-time checks.
@comvi/core: the i18n instance, the capabilities and every type.