React + i18next
Install the SDK, wrap your app in <SonentaProvider />, and call useTranslation(). Missing keys flow to your dashboard automatically, no extra wiring.
1. Install
Section titled “1. Install”Single dependency. No peer-dep gymnastics, the SDK includes everything React-side.
npm i @sonenta/react-i18next2. Wrap your app
Section titled “2. Wrap your app”SonentaProvider takes a projectId and an apiKey. Everything else has sane defaults: locale auto-detect from the browser, namespaces lazy-loaded from your CDN, missing-key handler debounced and POSTed automatically.
import { SonentaProvider } from "@sonenta/react-i18next";import { createRoot } from "react-dom/client";import { App } from "./App";
createRoot(document.getElementById("root")!).render( <SonentaProvider projectUuid="proj_xxx" token={import.meta.env.VITE_SONENTA_TOKEN} defaultLocale="en" namespaces={["common"]} > <App /> </SonentaProvider>);All SonentaProvider props
| Prop | Type | Default |
|---|---|---|
projectUuid | string | required |
token | string | required |
defaultLocale | string | browser |
defaultNS | string | "common" |
namespaces | string[] | ["common"] |
cdnUrl | string | cdn.sonenta.com |
baseUrl | string | api.sonenta.com |
missingHandlerEndpoint | string | /v1/missing |
debounceMs | number | 5000 |
transport | (batch) => void | Promise<void> | internal |
3. Use the hook
Section titled “3. Use the hook”useTranslation() returns { t, i18n }. Familiar shape if you've used react-i18next. i18n.ready tells you when initial namespaces have hydrated; i18n.changeLanguage() swaps locale at runtime.
import { useTranslation } from "@sonenta/react-i18next";
export function Checkout() { const { t, i18n } = useTranslation("common");
if (!i18n.ready) return null; // first paint after hydration
return ( <button onClick={() => i18n.changeLanguage("fr")}> {t("checkout.review.confirm")} </button> );}What you get for free
Section titled “What you get for free”- Missing-key capture. Any key you call that isn't in the dictionary is queued, debounced (default 5s), and POSTed to your dashboard's missing queue. Production-safe, your fallback still renders.
- CDN-served namespaces. Translation bundles are pulled from
cdn.sonenta.comwith HTTP caching and stale-while-revalidate. No build-time bundling required. - Locale auto-detect. If you don't pass
defaultLocale, the SDK readsnavigator.languageand falls back to your project's default. - Open exports. Whatever you push to Sonenta, you can export back to JSON i18next, XLIFF, or PO. Switch tools tomorrow without rewriting your code.
Custom transport (advanced)
Section titled “Custom transport (advanced)”Need to log missing keys to your own observability stack, gate them behind your auth, or stub them out in tests? Pass a transport function. The SDK still debounces and batches; you decide what happens to the batch.
// custom transport: useful for tests, edge cases, or auditing<SonentaProvider projectUuid="proj_xxx" token={import.meta.env.VITE_SONENTA_TOKEN} debounceMs={2000} transport={(batch) => fetch("/internal/i18n-misses", { method: "POST", body: JSON.stringify(batch), })}/>- All docs (Reference): CLI, MCP server, API reference (in progress).
- Plans & limits (Pricing): Free 500 keys; Hobby $9; Pro $29; Team $79.