Aller au contenu
Sonenta

Démarrage rapide

React + i18next

Installez le SDK, enveloppez votre app dans <SonentaProvider />, et appelez useTranslation(). Les clés manquantes remontent à votre tableau de bord automatiquement, aucun branchement supplémentaire.

1. Installer

Une seule dépendance. Pas d'acrobaties peer-dep, le SDK contient tout côté React.

terminal
1npm i @sonenta/react-i18next

2. Envelopper votre app

SonentaProvider prend un projectUuid et une defaultLocale ; votre clé d’API se passe dans la prop token. Il n’y a pas de détection automatique de la locale, defaultLocale est requis. Les namespaces sont chargés à la demande depuis le CDN, et les clés manquantes sont envoyées par lots, toutes les 5 secondes ou tous les 50 événements, au premier des deux.

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);
Toutes les props de SonentaProvider
Prop Type Défaut
projectUuid string obligatoire
defaultLocale Locale obligatoire
children ReactNode obligatoire
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 } -
  • token est requis sauf si vous fournissez votre propre transport. N’en passer aucun des deux lève une erreur au montage. Il n’authentifie que le POST des clés manquantes, la sonde de style de clé, et le fetch runtime en env: "dev".
  • Sous interpolation, seul format est configurable. escapeValue vaut toujours false, React échappe déjà.
  • Les variantes régionales retombent déjà sur leur base (fr-CA vers fr) sans configuration. fallbackLng s’ajoute après cette chaîne, il ne la remplace pas.

3. Utiliser le hook

useTranslation() retourne { t, i18n }. Forme familière si vous avez utilisé react-i18next. i18n.ready indique quand les namespaces initiaux sont hydratés ; i18n.changeLanguage() change la locale à l'exécution.

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}

Ce que vous obtenez gratuitement

Trois pannes qui ne disent rien

Chacune laisse votre page parfaitement normale. Aucune ne lève d’erreur que vous remarquerez.

  • Un token cassé n’avertit presque pas, et ne plante jamais. Ne passer ni token ni transport lève une erreur au montage. Un token présent mais ayant la forme d’une variable d’environnement non définie ("undefined", "null") produit un console.warn. Ces deux gardes n’existent qu’à partir de @sonenta/react-i18next 2.6.1 (@sonenta/i18n-core 1.1.3) ; en dessous, rien n’est signalé. Et une chaîne vide, le ?? "" qu’on écrit pour satisfaire TypeScript, n’est couverte par aucun avertissement, à aucune version. Dans tous les cas le serveur répond 401, le SDK dégrade en douceur, le CDN continue de servir, et votre application reste non authentifiée. Ne cherchez pas ApiKey undefined dans vos logs : avec un ?? "" c’est un faux négatif garanti. Regardez plutôt l’en-tête Authorization de la requête réseau dans votre build déployé.
  • Un namespace absent ressemble à un namespace vide. Les bundles de namespace viennent du CDN uniquement quand env vaut "prod" ; en "dev" ils viennent de l’API runtime authentifiée. Et un 404 se résout en bundle vide, sans erreur ni nouvelle tentative : un namespace que vous n’avez pas encore publié est donc indiscernable d’un namespace réellement vide.
  • Des surfaces a11y non déclarées retombent en silence. Les accesseurs d’accessibilité ne lisent que les surfaces demandées au chargement, via a11ySurfaces. Sans elle, l’overlay n’est jamais téléchargé et t.aria(key) renvoie simplement le texte visible, sans erreur ni avertissement. Le symptôme n’est pas un plantage, c’est un aria-label qui duplique le libellé d’à côté.

Transport custom (avancé)

Besoin de logger les clés manquantes dans votre propre stack d'observabilité, de les protéger derrière votre auth, ou de les stubber dans les tests ? Passez une fonction transport. Le SDK debounce et batche toujours ; vous décidez ce qu'on fait du batch.

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/>

Ensuite