本文へスキップ
Sonenta

Guide · Migration

Migrate from i18next

Already shipping with i18next? @sonenta/react-i18next is a drop-in replacement for react-i18next — same useTranslation() and t() API, you just swap the provider and your translations come live from the CDN. Bring your existing locales/ JSON into Sonenta with one command, then keep your code exactly as it is. The import creates the missing keys, upserts every translation, and is fully idempotent, so you can re-run it from CI without fear. This is the whole path: install, import, publish, verify, wire up the SDK.

Before you begin

Three things, then you're ready to import:

1. Install and initialise

Install the CLI globally, scaffold a config that points at your project, and export your key.

terminal
1# one global install — gives you the `sonenta` command (Node >= 18)2npm i -g @sonenta/cli 4# scaffold sonenta.config.json and point it at your project5sonenta init --project <project_uuid> 7# the CLI talks to the MCP surface — use an mcp:* scoped key8export SONENTA_TOKEN=vrb_live_<prefix>.<secret>

sonenta init writes a sonenta.config.json you can commit. In CI, skip init and pass --project plus the SONENTA_TOKEN environment variable. sonenta and SONENTA_* are canonical; the legacy verbumia command and VERBUMIA_* vars still work during the transition.

2. Preview, then import

The importer reads each file's path to infer its language and namespace, so a conventional locales/ tree needs no flags. Dry-run first to see the plan, then drop --dry-run to apply it.

your repo
1# the importer infers (language, namespace) from each path:2#   <lang>/<namespace>.json3locales/4├─ en/5│  ├─ common.json     → language en · namespace common6│  └─ checkout.json   → language en · namespace checkout7└─ fr/8   ├─ common.json     → language fr · namespace common9   └─ checkout.json   → language fr · namespace checkout
terminal
1# preview first — no writes, prints exactly what WOULD change2sonenta import "./locales/**/*.json" --dry-run 4# the real run — idempotent, safe to repeat5sonenta import "./locales/**/*.json" 7✓ common · checkout   (en, fr)8  keys           312 created · 0 reused9  translations   624 created · 0 updated · 0 unchanged10  errors 0 · glossary 0 violations 12# non-standard layout? override the inference per file:13sonenta import strings.fr.json --language fr --namespace common

Trees may be nested or flat — both import identically. --status sets the incoming status (draft or translated, default translated); --version targets a non-default version. Plurals expressed as a CLDR dict ({ one, other }) are stored as plural forms automatically.

3. Publish to the CDN

Importing fills the project; publishing makes it servable. Cut a release and the bundles propagate to the global CDN the SDK reads from.

terminal
1# cut a CDN release so the SDK and your build can fetch it2sonenta releases publish 4→ released "main" · propagating to cdn.sonenta.com

Releases are immutable snapshots of a version. Re-publish whenever you import new content — the SDK and your static build both fetch the latest release.

4. Verify the bundle

Confirm the content is live. A published bundle is a plain, public JSON file per language and namespace — fetch one directly, or open the project in the dashboard.

terminal
1# the published bundle is public — no auth needed2curl -s https://cdn.sonenta.com/p/<project_uuid>/main/latest/fr/common.json

404 on a locale? It isn't one of the project's languages yet, or the release hasn't propagated — give it a few seconds and retry.

5. Point your SDK at Sonenta

Swap your i18next backend for the Sonenta provider. Your t() calls, keys and namespaces stay the same — the translations now come from the CDN bundle you just published.

main.tsx
1// src/main.tsx — point @sonenta/react-i18next at the same project2import { SonentaProvider } from "@sonenta/react-i18next"; 4<SonentaProvider5  projectUuid="<project_uuid>"6  token={import.meta.env.VITE_SONENTA_TOKEN}7  defaultLocale="fr"8  namespaces={["common", "checkout"]}9>10  <App />11</SonentaProvider>

Keys that contain dots (a version, a price, a scripture reference)? Set keySeparator={false} and switch the project to flat — see the Flat vs nested keys guide. Otherwise the nested default just works.

Re-run anytime

sonenta import is idempotent: re-importing identical content changes nothing (0 created, 0 updated, N unchanged). Wire it into CI to keep Sonenta in sync with your repo — it only ever creates what's missing and updates what actually changed.

What the importer handles

Next