تخطَّ إلى المحتوى
Sonenta

بداية سريعة

React + i18next

ثبّت SDK، ولفّ تطبيقك بـ <SonentaProvider />، ثم استدعِ useTranslation(). تنتقل المفاتيح الناقصة إلى لوحة التحكم تلقائياً, دون أي توصيلات إضافية.

1. التثبيت

تبعية واحدة فقط. لا حاجة لمعاناة peer-dep, يضم SDK كل ما يلزم على جانب React.

terminal
1npm i @sonenta/react-i18next

2. لفّ تطبيقك

SonentaProvider يأخذ projectUuid وdefaultLocale؛ ومفتاح الـ API يُمرَّر في الخاصية token. لا يوجد اكتشاف تلقائي للغة، وdefaultLocale مطلوب. تُحمَّل الـ namespaces عند الطلب من الـ 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);
كل props الخاصة بـ SonentaProvider
Prop النوع القيمة الافتراضية
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 } -
  • token is required unless you supply your own transport. Passing neither throws at mount. It authenticates only the missing-key POST, the key-style probe, and the runtime fetch in env: "dev".
  • Only format is configurable under interpolation. escapeValue is always false, because React escapes already.
  • Regional variants already fall back to their base (fr-CA to fr) with no configuration. fallbackLng is appended after that chain, it does not replace it.

3. استخدم الـ hook

يُعيد useTranslation() الكائن { t, i18n }. شكل مألوف لمن استخدم react-i18next. يخبرك i18n.ready متى اكتمل تحميل الـ namespaces الأولية، ويبدّل i18n.changeLanguage() اللغة في الـ 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}

ما تحصل عليه مجاناً

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 token and no transport throws at mount. A token that is present but shaped like an unset environment variable ("undefined", "null") produces a console.warn. Both guards exist only from @sonenta/react-i18next 2.6.1 (@sonenta/i18n-core 1.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 for ApiKey undefined: with ?? "" that is a guaranteed false negative. Read the Authorization header 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 env is "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 and t.aria(key) simply returns the visible text, with no error and no warning. The symptom is not a crash, it is an aria-label that 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/>

التالي