Skip to content
Comvi

Connect to Comvi

View .md

With the i18n instance from the Quick start rendering an inline catalog, the next move is to take the catalog out of your source and let the Comvi platform serve it over its CDN, so a translator’s edit reaches users without a build. You need a Comvi project with at least the greeting key in it; Your first project gets you one. The switcher in the header picks the framework, and every tab follows it.

Terminal
npm install @comvi/plugin-fetch-loader

The loader is one package for every binding. pnpm, yarn and bun take the same name.

src/main.tsx
import { createRoot } from 'react-dom/client';
import { createI18n, I18nProvider } from '@comvi/react';
import { cdnLoader } from '@comvi/plugin-fetch-loader';
import App from './App';
const i18n = createI18n({
locale: 'en',
fallbackLocale: 'en',
}).use(cdnLoader({ cdnUrl: 'https://cdn.comvi.io/<project-token>' }));
createRoot(document.getElementById('root')!).render(
<I18nProvider i18n={i18n} fallback={<div className="spinner" />}>
<App />
</I18nProvider>,
);

Two things changed against the Quick start: messages is gone, and .use(cdnLoader()) is composed onto the instance in the same expression that creates it. The loader fetches {cdnUrl}/{locale}.json for the active locale when init() runs, and again for each locale you switch to. Compose it inside the createI18n expression because the binding calls init() as soon as it has the instance, and .use() belongs before init(); only plain @comvi/core awaits init() itself.

The catalog arrives over the network, so there is a moment when t() has nothing to read. React and Solid paint the fallback prop for that moment, Vue and Svelte read isInitializing. Next.js and Nuxt fetch on the server, so the HTML already carries the text and no gate is visible. The components are unchanged and keep asking for greeting with a {name} placeholder, so the project needs that key with that placeholder. Until a translator adds it, the heading reads greeting.

If your keys use ICU ({count, plural, …}), add compiler: icuCompiler as on Pluralize with ICU. The platform and the compiler are independent: either works without the other.

flowchart LR
  App["Components<br/>t('greeting')"]
  Loader["cdnLoader"]
  CDN["Comvi CDN<br/>cdnUrl/locale.json"]
  Catalog["Catalog in the instance"]
  Bundled["Bundled fallback<br/>import map"]
  Chain["fallbackLocale chain"]
  Key["The key itself"]

  App --> Loader --> CDN --> Catalog
  CDN -- "fetch fails" --> Bundled --> Catalog
  Catalog -- "key missing" --> Chain -- "still missing" --> Key
One request per locale and namespace. A failed fetch tries the bundled fallback import map; a key missing from the loaded catalog walks the fallbackLocale chain; what is left renders as the key.

The loader makes one request per locale:namespace pair and does not retry it. When the fetch fails, or returns something that is not a catalog, the loader looks for a fallback entry under locale:namespace, then under the bare locale for the default namespace, and merges whatever that import returns; a fallback that works reports through onLoadSuccess, not onLoadError. A miss is reported through onLoadError and onError first. When at least one requested namespace landed, init() resolves and the app mounts with the catalog it has; when every one failed and no fallback covered it, init() rejects with E_ALL_NAMESPACES_FAILED after the report, which is what the try/catch in the Vanilla tab is for. From there the per-key rules take over. A key missing or empty in the current locale is looked up along the fallbackLocale chain, and a key missing everywhere renders as itself. fallbackLocale: 'en' in the snippets makes init() fetch en.json next to the active locale’s file, one request per fallback locale and namespace, so the chain has a catalog to read; a fallback file that fails to load is reported and does not fail init(). Important defaults has the full account.

The CDN endpoint URL is under Settings → Content Deploy in your Comvi project, once Content Deploy is enabled and saved; pass it as cdnUrl. The URL format is on CDN Deployment.

The endpoint appears once you enable Content Deploy, tick the Locales and Namespaces to publish, and save. With every locale and namespace ticked, a locale or namespace added later deploys too. The endpoint is public and needs no key, so it can sit in a browser bundle. A write to the project schedules a deploy about five seconds after the last write, and at most a minute into a continuous stream of writes; Deploy Now pushes the current state at once.

Edit the greeting value in the dashboard, wait for the deploy to land, and reload the app. The new wording is on screen, and nothing in your repository changed.