Consume Translations
Once you’ve published translations, any app can consume them. Comvi is deliberately unopinionated about how you load them — pick the shape that fits your runtime and deployment model.
This page covers the two production-grade approaches and when to choose each.
Two approaches
Section titled “Two approaches”| Approach | How it works | Best for |
|---|---|---|
| Runtime fetch (CDN) | Your app downloads a bundle from the CDN at startup or on demand | Web apps, apps that want translation updates without a redeploy |
| Build-time bundle (CLI / export) | You pull translations into your repo and ship them with your app | Mobile apps, embedded/offline apps, anywhere you want zero runtime dependency on Comvi |
You can also mix: bundle a fallback set at build time and fetch updates at runtime.
Bundle shape
Section titled “Bundle shape”Every published bundle is plain JSON — a flat map of keys to values for one (language, namespace) pair:
{ "greeting": "Hello, {name}!", "welcome_message": "Welcome to our application", "nav.home": "Home", "nav.settings": "Settings"}URLs follow a predictable shape:
https://cdn.comvi.io/<distribution-token>/<namespace>/<language>.json# the default namespace is served at the project root:https://cdn.comvi.io/<distribution-token>/<language>.jsonThe distribution token is project-scoped and lives under Settings → Content Deploy. See CDN Deployment for the full URL format.
Because the format is plain JSON, any i18n library that accepts a JSON resource can consume it. You can also load it by hand with fetch if you don’t want a library at all.
Option 1 — Runtime fetch from the CDN
Section titled “Option 1 — Runtime fetch from the CDN”With the Comvi i18n library
Section titled “With the Comvi i18n library”Our i18n library is the path of least resistance for web apps. Install the core package plus a framework binding, add the fetch loader plugin, and point it at your distribution URL.
The library handles:
- Loading bundles on demand (per namespace, per language)
- ICU MessageFormat rendering (plurals, selects, placeholders)
- Language switching at runtime
- Optional TypeScript types for autocompleted keys
- Server-side rendering for Next.js, Nuxt, and similar frameworks
See the i18n library quick start for framework-specific setup.
With any other i18n library
Section titled “With any other i18n library”Bundles are standard JSON, so any existing i18n stack can consume them. Point the library’s resource loader at your Comvi CDN URL — no adapter needed.
Typical shape:
- Configure your i18n library to load resources from a URL pattern (the library will have its own way to specify this)
- Plug in
https://cdn.comvi.io/<distribution-token>/<namespace>/<lang>.json(orhttps://cdn.comvi.io/<distribution-token>/<lang>.jsonfor the default namespace) as the URL - Keep your existing rendering / plural / interpolation behaviour
If you are migrating from another i18n library, start with the closest framework guide in the i18n library docs.
Without any library
Section titled “Without any library”For a small app, plain fetch is enough:
const bundle = await fetch( 'https://cdn.comvi.io/YOUR_DISTRIBUTION_TOKEN/en.json',).then((r) => r.json());
document.querySelector('h1')!.textContent = bundle.welcome_message;Caching, language switching, and interpolation become your responsibility — pick this only if your needs are genuinely that simple.
Option 2 — Bundle at build time
Section titled “Option 2 — Bundle at build time”When you want zero runtime dependency on Comvi — mobile apps, offline-first apps, static sites without client-side JS — pull translations into your repo at build time and ship them with the binary / bundle.
With the CLI
Section titled “With the CLI”The Comvi CLI has a pull command that fetches translations from the platform and writes them to your filesystem.
npx @comvi/cli pullTypical setup:
- Create a project-scoped API key
- Add a
.comvirc.jsonin your repo pointing at the project and output directory - Run
comvi pullin your build step (local dev, CI, release pipeline) - Commit the output or let CI fetch it on every build
See CLI pull for configuration options, output format choices, and typed output for TypeScript projects.
With an export
Section titled “With an export”If the CLI is overkill — for example, if your build pipeline isn’t Node.js — use the Import & Export UI to download a ZIP of all translations. Exports are served as JSON (default) or an i18next-v4 compatible shape. Any language can read JSON, so this works for backend services, desktop apps, static site generators, or any pipeline where Node.js tooling isn’t available.
Keeping translations fresh
Section titled “Keeping translations fresh”Translations change more often than code. How each approach handles updates:
- Runtime CDN fetch — updates appear on the next fetch after the editor clicks Publish. Typical propagation is a few seconds at the edge; your app sees them on next page load / i18n library refresh interval / user action.
- Build-time bundle — updates require a new build and deploy of your app. Subscribe to webhooks to trigger CI automatically. For content changes the relevant events are
translation.created,translation.updated, andtranslation.batch_updated(bulk operations like MT or TM apply). Addkey.*if you want rebuilds on source-key changes too. Debounce on the CI side — individual edits fan out one event per value, while a bulk operation emits a singletranslation.batch_updated.
For contributors who need to preview edits before publishing, see the In-Context Editor plugin — authorized editors see their drafts instantly in your live app without going through the publish cycle.