クイックスタート
React + i18next
SDK をインストールし、アプリを <SonentaProvider /> でラップして useTranslation() を呼ぶだけです。欠落キーは自動でダッシュボードに送られます, 追加の配線は不要です。
1. インストール
依存はひとつだけ。peer-dep の取り回しも不要で、React 側に必要なものはすべて SDK に含まれています。
terminal 1npm i @sonenta/react-i18next 2. アプリをラップ
SonentaProvider は projectUuid と defaultLocale を受け取ります。API キーは token プロパティに渡します。ロケールの自動検出はなく、defaultLocale は必須です。namespace は CDN から必要に応じて読み込まれ、欠落キーは 5 秒ごと、または 50 件ごとの、いずれか早い方でまとめて送信されます。
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); SonentaProvider の全 props
| Prop | Type | デフォルト |
|---|---|---|
| projectUuid | string | 必須 |
| defaultLocale | Locale | 必須 |
| children | ReactNode | 必須 |
| 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. フックを使う
useTranslation() は { t, i18n } を返します。react-i18next 経験者には馴染みの形です。i18n.ready で初期 namespace のハイドレート完了を判定でき、i18n.changeLanguage() でランタイムにロケールを切り替えられます。
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} 標準で手に入るもの
- 欠落キーの取得。 辞書に存在しないキーを呼び出すと、キューに入り、debounce(デフォルト 5 秒)を経てダッシュボードの missing キューに POST されます。本番でも安全, フォールバックは描画され続けます。
- CDN 配信の namespace。 翻訳バンドルは
cdn.sonenta.comから HTTP キャッシュおよび stale-while-revalidate 付きで取得されます。ビルド時バンドルは不要です。 - ロケール自動検出。
defaultLocaleを渡さない場合、SDK はnavigator.languageを読み、プロジェクトのデフォルトにフォールバックします。 - オープンなエクスポート。 Sonenta に push したものは、JSON i18next、XLIFF、PO に書き戻せます。明日ツールを乗り換えてもコードを書き直す必要はありません。
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.
カスタムトランスポート(上級)
欠落キーを自前の可観測性スタックにログしたい、認証で守りたい、テストでスタブしたい? transport 関数を渡してください。SDK 側は引き続き debounce とバッチ化を行い、バッチの処理方法はあなたが決めます。
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/>