Hurtigstart
React + i18next
Installer SDK-en, pakk appen din i <SonentaProvider /> og kall useTranslation(). Manglende nøkler havner automatisk i dashbordet, ingen ekstra kobling.
1. Installer
Én avhengighet. Ingen peer-dep-akrobatikk, SDK-en har med alt på React-siden.
terminal 1npm i @sonenta/react-i18next 2. Pakk inn appen
SonentaProvider tar en projectUuid og en defaultLocale; API-nøkkelen sendes i propen token. Det finnes ingen automatisk locale-gjenkjenning, defaultLocale er påkrevd. Namespaces hentes ved behov fra CDN, og manglende nøkler sendes i partier, hvert 5. sekund eller hvert 50. hendelse, avhengig av hva som skjer først.
main.tsx 1// src/main.tsx2import { SonentaProvider } from "@sonenta/react-i18next";3import { createRoot } from "react-dom/client";4import { App } from "./App"; 6createRoot(document.getElementById("root")!).render(7 <SonentaProvider8 projectUuid="proj_xxx"9 token={import.meta.env.VITE_SONENTA_TOKEN}10 defaultLocale="en"11 namespaces={["common"]}12 >13 <App />14 </SonentaProvider>15); Alle SonentaProvider-props
| Prop | Type | Default |
|---|---|---|
| projectUuid | string | påkrevd |
| defaultLocale | Locale | påkrevd |
| children | ReactNode | påkrevd |
| token | string | req. unless transport |
| namespaces | Namespace[] | ["common"] |
| defaultNS | Namespace | - |
| keySeparator | string | false | "." (auto-detected) |
| nsSeparator | string | false | ":" |
| apiBase | string | https://api.sonenta.dev |
| cdnBase | string | https://cdn.sonenta.com |
| fetchImpl | typeof fetch | global fetch |
| env | "prod" | "dev" | "prod" |
| version | string | "main" |
| versionSlug (deprecated) | string | - |
| missingHandler | "send" | "log" | "off" | "send" |
| transport | (batch: MissingKeyEvent[]) => … | built-in POST |
| flushIntervalMs | number | 5000 |
| flushBatchSize | number | 50 |
| missingEventsBufferSize | number | 200 |
| initialBundles | Record<Locale, Record<...>> | - |
| languageCatalog | LanguageMeta[] | - |
| disableLanguageCatalog | boolean | false |
| disableLanguageManifest | boolean | false |
| fallbackLng | Locale | Locale[] | - |
| surface | Surface | - |
| surfaceBreakpoints | SurfaceBreakpoints | boolean | - |
| a11ySurfaces | A11ySurface[] | [] |
| plainLanguage | boolean | false |
| plugins | SonentaPlugin[] | - |
| interpolation | { format?: (…) => string } | - |
-
tokenis required unless you supply your owntransport. Passing neither throws at mount. It authenticates only the missing-key POST, the key-style probe, and the runtime fetch inenv: "dev". - Only
formatis configurable underinterpolation.escapeValueis alwaysfalse, because React escapes already. - Regional variants already fall back to their base (
fr-CAtofr) with no configuration.fallbackLngis appended after that chain, it does not replace it.
3. Bruk hooken
useTranslation() returnerer { t, i18n }. Kjent form hvis du har brukt react-i18next. i18n.ready sier når initielle namespaces er hydrert; i18n.changeLanguage() bytter locale i runtime.
Checkout.tsx 1// src/Checkout.tsx2import { useTranslation } from "@sonenta/react-i18next"; 4export function Checkout() {5 const { t, i18n } = useTranslation("common"); 7 if (!i18n.ready) return null; // first paint after hydration 9 return (10 <button onClick={() => i18n.changeLanguage("fr")}>11 {t("checkout.review.confirm")}12 </button>13 );14} Det du får gratis
- Fangst av manglende nøkler. Hver nøkkel du kaller som ikke finnes i ordboken køes, debounces (5s default) og POSTes til dashbordets missing-kø. Produksjonssikkert, fallbacken din rendres fortsatt.
- Namespaces via CDN. Oversettelsesbunter hentes fra
cdn.sonenta.commed HTTP-caching og stale-while-revalidate. Ingen build-time-bundling kreves. - Auto-detektert locale. Hvis du ikke sender
defaultLocale, leser SDK-ennavigator.languageog faller tilbake på prosjektets default. - Åpne eksporter. Alt du pusher til Sonenta kan du eksportere tilbake til JSON i18next, XLIFF eller PO. Bytt verktøy i morgen uten å skrive om koden.
Three failures that stay silent
Each of these leaves your page looking perfectly fine. None of them raises an error you will notice.
- A broken token barely warns, and never throws. Passing no
tokenand notransportthrows at mount. A token that is present but shaped like an unset environment variable ("undefined","null") produces aconsole.warn. Both guards exist only from@sonenta/react-i18next2.6.1 (@sonenta/i18n-core1.1.3); below that, nothing is reported at all. And an empty string, the?? ""you write to satisfy TypeScript, is covered by no warning at any version. In every case the server returns 401, the SDK degrades gracefully, the CDN keeps serving, and your app stays unauthenticated. Do not grep your logs forApiKey undefined: with?? ""that is a guaranteed false negative. Read theAuthorizationheader of the network request in your deployed build instead. - A missing namespace looks like an empty one. Namespace bundles are fetched from the CDN only when
envis"prod"; in"dev"they come from the authenticated runtime API instead. And a 404 resolves to an empty bundle, with no error and no retry, so a namespace you have not published yet is indistinguishable from one that is genuinely empty. - Undeclared a11y surfaces fall back quietly. The accessibility accessors only read surfaces you asked for at load time, via
a11ySurfaces. Without it the overlay is never downloaded andt.aria(key)simply returns the visible text, with no error and no warning. The symptom is not a crash, it is anaria-labelthat duplicates the label next to it.
Egen transport (avansert)
Må du logge manglende nøkler til din egen observability-stack, gate dem bak din auth, eller stubbe dem ut i tester? Send inn en transport-funksjon. SDK-en debouncer og batcher fortsatt; du bestemmer hva som skjer med batchen.
main.tsx 1// custom transport, useful for tests, edge cases, or auditing2<SonentaProvider3 projectUuid="proj_xxx"4 token={import.meta.env.VITE_SONENTA_TOKEN}5 flushIntervalMs={2000}6 transport={(batch) => fetch("/internal/i18n-misses", {7 method: "POST",8 body: JSON.stringify(batch),9 })}10/>