{"version":3,"sources":["../src/components/I18nProvider.tsx","../src/core/context.ts","../src/utils/languages.ts","../src/utils/plurals.ts","../src/core/client.ts","../src/utils/fonts.ts","../src/utils/formatting.ts","../src/components/LanguageSwitcher.tsx","../src/hooks/useTranslation.ts","../src/components/Trans.tsx","../src/hooks/useLangInfo.ts"],"sourcesContent":["// FILE: packages/sdk/src/components/I18nProvider.tsx\r\n//\r\n// THE MAIN COMPONENT — This is what developers add to their app:\r\n//\r\n//   <I18nProvider projectKey=\"bjs_...\" register=\"casual\">\r\n//     <App />\r\n//   </I18nProvider>\r\n//\r\n// What it does behind the scenes:\r\n//   1. Creates a TranslationClient instance\r\n//   2. Fetches the project info (to know which languages are supported)\r\n//   3. Fetches the (currentLang, currentRegister) bundle\r\n//   4. Provides t(), currentLang/setLang, register/setRegister, formatters to children\r\n//   5. When language or register changes, fetches the right bundle and updates the DOM\r\n//\r\n// HOW REGISTER WORKS:\r\n// `register` is the formality / style of the translation:\r\n//   - \"default\" (neutral)\r\n//   - \"formal\"  (legal, banking, government, insurance)\r\n//   - \"casual\"  (Gen-Z, code-mixing with English encouraged)\r\n// Set it once on the provider for the whole app, or call setRegister() at runtime\r\n// (e.g. switch to \"formal\" when the user enters a compliance/KYC flow).\r\n\r\nimport { useState, useEffect, useCallback, useRef, ReactNode } from \"react\";\r\nimport { BhashaConfig, NumberFormatOptions, CurrencyFormatOptions, DateFormatOptions, Register } from \"../types\";\r\nimport { I18nContext } from \"../core/context\";\r\nimport { TranslationClient } from \"../core/client\";\r\nimport { getLangInfo } from \"../utils/languages\";\r\nimport { loadFontForLang, preloadFonts } from \"../utils/fonts\";\r\nimport {\r\n  formatNumber as formatNumberUtil,\r\n  formatCurrency as formatCurrencyUtil,\r\n  formatDate as formatDateUtil,\r\n} from \"../utils/formatting\";\r\n\r\ninterface I18nProviderProps extends BhashaConfig {\r\n  children: ReactNode;\r\n}\r\n\r\n// Default API URL — points at the hosted BhashaJS service. The `/api` suffix\r\n// matches the server's mount point (sdk routes live at `/api/sdk/*`).\r\n// Override with `apiUrl` prop if you self-host (e.g. \"https://my.host/api\").\r\nconst DEFAULT_API_URL = \"https://api.bhashajs.com/api\";\r\n\r\nconst DEFAULT_REGISTER: Register = \"default\";\r\n\r\nexport function I18nProvider({\r\n  projectId = \"\",\r\n  projectKey = \"\",\r\n  defaultLang = \"en\",\r\n  apiUrl = DEFAULT_API_URL,\r\n  apiToken = \"\",\r\n  preloadedTranslations,\r\n  persistCache = true,\r\n  onLanguageChange,\r\n  region,\r\n  register: initialRegister = DEFAULT_REGISTER,\r\n  voice: voiceEnabled = false,\r\n  userSegment,\r\n  segmentRules,\r\n  children,\r\n}: I18nProviderProps) {\r\n  // ─── State ───────────────────────────────────────────────────\r\n\r\n  // Resolve initial register from the segment if a matching rule exists,\r\n  // otherwise fall back to the explicit `register` prop. This lets apps\r\n  // declare `userSegment=\"genz\"` and skip wiring `register=\"casual\"` separately.\r\n  const initialResolvedRegister = resolveRegisterFromSegment(\r\n    userSegment,\r\n    segmentRules,\r\n    initialRegister\r\n  );\r\n\r\n  const [currentLang, setCurrentLang] = useState(defaultLang);\r\n  const [currentRegister, setCurrentRegister] = useState<Register>(initialResolvedRegister);\r\n  const [currentSegment, setCurrentSegment] = useState<string | undefined>(userSegment);\r\n  const [supportedLangs, setSupportedLangs] = useState<string[]>([]);\r\n  const [isLoading, setIsLoading] = useState(true);\r\n  const [error, setError] = useState<string | null>(null);\r\n\r\n  // Force re-render when translations load (since they're in the client cache,\r\n  // not React state — we use a counter to trigger re-renders)\r\n  const [, setRenderTrigger] = useState(0);\r\n\r\n  // useRef to hold the client so it persists across renders\r\n  const clientRef = useRef<TranslationClient | null>(null);\r\n  // The config identity the current client was built for — so we recreate it\r\n  // when projectId/projectKey/apiUrl/apiToken change (the init effect re-runs on\r\n  // projectId, but without this it would keep using the OLD client).\r\n  const clientConfigRef = useRef<string>(\"\");\r\n\r\n  // A (lang, register) pair is ONE atomic locale target. Tracking the two\r\n  // dimensions with separate request counters let an interleaved\r\n  // setLang(\"hi\") + setRegister(\"formal\") commit the final \"hi/formal\" state\r\n  // while each call only fetched the pair it could *see* at call time\r\n  // (\"hi/default\" and \"en/formal\") — so the committed \"hi/formal\" bundle was\r\n  // never loaded. We keep a single shared counter plus a pending target that\r\n  // every switch writes BEFORE fetching; applyLocale() fetches the CURRENT\r\n  // pending pair and, if still the latest request, commits both dimensions\r\n  // together. Last-requested wins. Pending lives in refs (not state) so a\r\n  // switch reads the latest target synchronously, without a re-render.\r\n  const localeReqRef = useRef(0);\r\n  const pendingLangRef = useRef(defaultLang);\r\n  const pendingRegisterRef = useRef<Register>(initialResolvedRegister);\r\n\r\n  // A SEPARATE counter for the PROJECT-init guard. supportedLangs is project\r\n  // metadata that must ALWAYS load for the active project — a concurrent\r\n  // setLang/setRegister (a legitimate LOCALE change within the SAME project)\r\n  // must not cancel it. So the init effect guards its project-metadata commits\r\n  // (setSupportedLangs / setError / the finally setIsLoading(false)) on THIS\r\n  // counter, which only a genuine project switch bumps — never a plain\r\n  // setLang. The locale BUNDLE part of init still cooperates with\r\n  // `localeReqRef` so a concurrent setLang wins the visible language.\r\n  //\r\n  // Bumped ONLY when the init effect runs (a project-identity change — see the\r\n  // effect deps) and in resetLocaleForProjectSwitch (to invalidate an old\r\n  // in-flight init the instant a switch is observed). setLang/setRegister do\r\n  // NOT touch it.\r\n  const initReqRef = useRef(0);\r\n  const didSyncSegmentPropRef = useRef(false);\r\n  const lastSegmentRulesRef = useRef(segmentRules);\r\n  const lastUserSegmentPropRef = useRef(userSegment);\r\n\r\n  // Create the client on mount — and RECREATE it if the identifying config\r\n  // changes, so a changed projectId/projectKey doesn't keep serving the old\r\n  // project's data.\r\n  const clientConfig = `${projectId}|${projectKey}|${apiUrl}|${apiToken}|${persistCache}`;\r\n  if (!clientRef.current || clientConfigRef.current !== clientConfig) {\r\n    // Distinguish a genuine PROJECT SWITCH (the client already existed for a\r\n    // different config) from the FIRST mount. Only a switch needs the locale\r\n    // reset below — on first mount state already holds the right defaults.\r\n    const isProjectSwitch = clientRef.current !== null;\r\n\r\n    clientRef.current = new TranslationClient(projectId, apiUrl, apiToken, projectKey, { persistCache });\r\n    clientConfigRef.current = clientConfig;\r\n\r\n    // If preloaded translations were provided, load them into cache immediately\r\n    if (preloadedTranslations) {\r\n      clientRef.current.preload(preloadedTranslations);\r\n    }\r\n\r\n    if (isProjectSwitch) {\r\n      // ── PROJECT SWITCH: atomically reset locale state + invalidate in-flight ──\r\n      // This runs in the render phase, synchronously, the instant a new project\r\n      // identity is observed — strictly before the init effect (and before any\r\n      // commit from a still-pending applyLocale/setLang/init of the OLD project).\r\n      // The reset is factored into a pure helper so it can be unit-tested.\r\n      resetLocaleForProjectSwitch(\r\n        { localeReqRef, initReqRef, pendingLangRef, pendingRegisterRef },\r\n        { defaultLang, register: initialResolvedRegister },\r\n        {\r\n          setCurrentLang,\r\n          setCurrentRegister,\r\n          setError,\r\n          setIsLoading,\r\n          setSupportedLangs,\r\n        }\r\n      );\r\n    }\r\n  }\r\n\r\n  const client = clientRef.current;\r\n  client.setOnBundleUpdate(() => setRenderTrigger((p) => p + 1));\r\n\r\n  // ─── Initialization ──────────────────────────────────────────\r\n\r\n  useEffect(() => {\r\n    // TWO request claims, guarding two DIFFERENT concerns:\r\n    //\r\n    //  • initReqId (project-init guard) — claimed under `initReqRef`, which is\r\n    //    bumped ONLY here and in resetLocaleForProjectSwitch. It supersedes\r\n    //    only on a genuine PROJECT SWITCH (a new init runs, or a switch resets).\r\n    //    A concurrent setLang/setRegister does NOT bump it, so the init's\r\n    //    project-metadata commits (setSupportedLangs / setError / the finally\r\n    //    setIsLoading(false)) always settle for the active project. THIS is the\r\n    //    fix for the audit blocker: a setLang mid-init can no longer cancel\r\n    //    supportedLangs loading, which used to strand the LanguageSwitcher empty.\r\n    //\r\n    //  • localeReqId (locale guard) — claimed under the SHARED `localeReqRef`,\r\n    //    exactly like applyLocale. The user's concurrent setLang bumps this, so\r\n    //    init's *visible-locale* commit (default lang to the document + the\r\n    //    render trigger) defers to the user's selection: last-writer wins on the\r\n    //    locale, while supportedLangs/isLoading still settle from init above.\r\n    // The whole init body lives in an exported pure-ish helper so the\r\n    // load-bearing two-counter race-fix can be unit-tested without a DOM render\r\n    // harness (mirrors resetLocaleForProjectSwitch). The effect just wires the\r\n    // current refs/setters/client into it.\r\n    runProjectInit(\r\n      { localeReqRef, initReqRef, pendingRegisterRef },\r\n      { defaultLang, voiceEnabled, preloadedTranslations },\r\n      client,\r\n      { setIsLoading, setError, setSupportedLangs, bumpRenderTrigger: () => setRenderTrigger((p) => p + 1) }\r\n    );\r\n    // eslint-disable-next-line react-hooks/exhaustive-deps\r\n  }, [projectId, projectKey, apiUrl, apiToken, persistCache]); // Re-init when the project identity changes\r\n\r\n  // ─── Atomic locale switching ─────────────────────────────────\r\n  // (lang, register) is ONE locale target. Every switch updates the pending\r\n  // refs first, then applyLocale() snapshots the CURRENT pending pair, fetches\r\n  // THAT exact bundle (+ English / default-register fallbacks + voice), and —\r\n  // guarded by the single shared counter — commits BOTH dimensions together.\r\n  // Snapshotting the pending target (not currentLang/currentRegister) is what\r\n  // makes an interleaved setLang+setRegister fetch the real final pair instead\r\n  // of a stale half-state. Mirrors BhashaStore.applyLocale exactly.\r\n\r\n  const applyLocale = useCallback(async () => {\r\n    const reqId = ++localeReqRef.current;\r\n    const targetLang = pendingLangRef.current;\r\n    const targetRegister = pendingRegisterRef.current;\r\n\r\n    setIsLoading(true);\r\n    setError(null);\r\n    try {\r\n      await client.fetchTranslations(targetLang, targetRegister);\r\n      // English fallback (default register only — English has no formal/casual).\r\n      if (targetLang !== \"en\") {\r\n        await client.fetchTranslations(\"en\", DEFAULT_REGISTER);\r\n      }\r\n      // Pre-warm default register for register-fallback if needed.\r\n      if (targetRegister !== DEFAULT_REGISTER) {\r\n        await client.fetchTranslations(targetLang, DEFAULT_REGISTER);\r\n      }\r\n      // Voice mode: keep the IPA/SSML bundle in sync with the active locale.\r\n      // Without this, formatPhonetic/formatSSML return empty strings for every\r\n      // key after a switch until the next remount.\r\n      if (voiceEnabled) {\r\n        await client.fetchVoice(targetLang, targetRegister);\r\n        if (targetRegister !== DEFAULT_REGISTER) {\r\n          await client.fetchVoice(targetLang, DEFAULT_REGISTER);\r\n        }\r\n      }\r\n    } catch (e: any) {\r\n      // A failed switch must surface an error and clear loading rather than\r\n      // wedge isLoading:true forever. If a newer switch superseded us, let it\r\n      // own the final state.\r\n      if (reqId !== localeReqRef.current) return;\r\n      // Roll the pending target back to the committed locale so an identical\r\n      // retry isn't short-circuited by the equality guard in the setters.\r\n      pendingLangRef.current = currentLang;\r\n      pendingRegisterRef.current = currentRegister;\r\n      setIsLoading(false);\r\n      setError(e?.message || `Failed to load locale \"${targetLang}/${targetRegister}\"`);\r\n      console.error(\"[BhashaJS] setLocale error:\", e);\r\n      return;\r\n    }\r\n\r\n    // A newer switch superseded this one while we were fetching — let it own\r\n    // the loading state and the committed locale. Bailing here is what stops a\r\n    // slow earlier fetch from clobbering a newer selection.\r\n    if (reqId !== localeReqRef.current) return;\r\n\r\n    setIsLoading(false);\r\n\r\n    const langChanged = targetLang !== currentLang;\r\n    if (langChanged) {\r\n      loadFontForLang(targetLang);\r\n      applyLangToDocument(targetLang);\r\n    }\r\n    setCurrentLang(targetLang);\r\n    setCurrentRegister(targetRegister);\r\n\r\n    if (langChanged) onLanguageChange?.(targetLang);\r\n  }, [currentLang, currentRegister, client, voiceEnabled, onLanguageChange]);\r\n\r\n  // ─── Language Switching ──────────────────────────────────────\r\n\r\n  const setLang = useCallback(\r\n    async (newLang: string) => {\r\n      if (newLang === pendingLangRef.current) return;\r\n      pendingLangRef.current = newLang;\r\n      await applyLocale();\r\n    },\r\n    [applyLocale]\r\n  );\r\n\r\n  // ─── Register Switching ──────────────────────────────────────\r\n\r\n  const setRegister = useCallback(\r\n    async (newRegister: Register) => {\r\n      if (newRegister === pendingRegisterRef.current) return;\r\n      pendingRegisterRef.current = newRegister;\r\n      await applyLocale();\r\n    },\r\n    [applyLocale]\r\n  );\r\n\r\n  // ─── Segment Switching ───────────────────────────────────────\r\n  // Setting a segment that maps to a register (via segmentRules) flips both\r\n  // the segment and the register (through the same atomic locale path) and\r\n  // pre-fetches the new bundle. Setting a segment that ISN'T in the rules just\r\n  // records the segment label — the register stays as it was. This lets apps\r\n  // record analytics-only segments without forcing a register change.\r\n\r\n  const setSegment = useCallback(\r\n    async (newSegment: string) => {\r\n      setCurrentSegment(newSegment);\r\n      const mapped = segmentRules?.[newSegment];\r\n      if (mapped && mapped !== pendingRegisterRef.current) {\r\n        pendingRegisterRef.current = mapped;\r\n        await applyLocale();\r\n      }\r\n    },\r\n    [segmentRules, applyLocale]\r\n  );\r\n\r\n  useEffect(() => {\r\n    if (!didSyncSegmentPropRef.current) {\r\n      didSyncSegmentPropRef.current = true;\r\n      lastSegmentRulesRef.current = segmentRules;\r\n      lastUserSegmentPropRef.current = userSegment;\r\n      return;\r\n    }\r\n    // React ONLY to PROP changes (userSegment / segmentRules identity), never to\r\n    // currentSegment — otherwise a manual runtime setSegment() would be reverted\r\n    // back to the prop value the moment this effect re-fires.\r\n    const rulesChanged = lastSegmentRulesRef.current !== segmentRules;\r\n    const propChanged = lastUserSegmentPropRef.current !== userSegment;\r\n    lastSegmentRulesRef.current = segmentRules;\r\n    lastUserSegmentPropRef.current = userSegment;\r\n    if (userSegment !== undefined && (rulesChanged || propChanged)) {\r\n      void setSegment(userSegment);\r\n    }\r\n  }, [userSegment, segmentRules, setSegment]);\r\n\r\n  // ─── The t() function ────────────────────────────────────────\r\n\r\n  const t = useCallback(\r\n    (key: string, params?: Record<string, string | number>): string => {\r\n      return client.translate(key, currentLang, currentRegister, params);\r\n    },\r\n    [currentLang, currentRegister, client]\r\n  );\r\n\r\n  // ─── Formatting functions ────────────────────────────────────\r\n\r\n  const formatNumber = useCallback(\r\n    (value: number, options?: NumberFormatOptions): string => {\r\n      return formatNumberUtil(value, currentLang, region, options);\r\n    },\r\n    [currentLang, region]\r\n  );\r\n\r\n  const formatCurrency = useCallback(\r\n    (value: number, options?: CurrencyFormatOptions): string => {\r\n      return formatCurrencyUtil(value, currentLang, region, options);\r\n    },\r\n    [currentLang, region]\r\n  );\r\n\r\n  const formatDate = useCallback(\r\n    (date: Date | string | number, options?: DateFormatOptions): string => {\r\n      return formatDateUtil(date, currentLang, region, options);\r\n    },\r\n    [currentLang, region]\r\n  );\r\n\r\n  // ─── Voice helpers ───────────────────────────────────────────\r\n  // Walk the same fallback chain as t() — register-then-language. Return\r\n  // empty strings if the bundle hasn't been loaded; the developer can\r\n  // enable voice mode by passing `voice` on the provider.\r\n\r\n  const formatPhonetic = useCallback(\r\n    (key: string): string => {\r\n      return client.getVoice(key, currentLang, currentRegister)?.ipa || \"\";\r\n    },\r\n    [currentLang, currentRegister, client]\r\n  );\r\n\r\n  const formatSSML = useCallback(\r\n    (key: string): string => {\r\n      return client.getVoice(key, currentLang, currentRegister)?.ssml || \"\";\r\n    },\r\n    [currentLang, currentRegister, client]\r\n  );\r\n\r\n  // ─── Provide everything to children ──────────────────────────\r\n\r\n  const contextValue = {\r\n    currentLang,\r\n    setLang,\r\n    supportedLangs,\r\n    register: currentRegister,\r\n    setRegister,\r\n    currentSegment,\r\n    setSegment,\r\n    t,\r\n    isLoading,\r\n    error,\r\n    formatNumber,\r\n    formatCurrency,\r\n    formatDate,\r\n    formatPhonetic,\r\n    formatSSML,\r\n  };\r\n\r\n  return (\r\n    <I18nContext.Provider value={contextValue}>\r\n      {children}\r\n    </I18nContext.Provider>\r\n  );\r\n}\r\n\r\n/**\r\n * Pick the active register given a (possibly undefined) user segment, a\r\n * (possibly undefined) segment→register rule map, and a fallback register.\r\n *\r\n * Pulled out of the provider body so it's easy to unit-test without React.\r\n * Exported for the same reason — the test imports it directly.\r\n */\r\nexport function resolveRegisterFromSegment(\r\n  segment: string | undefined,\r\n  rules: Record<string, Register> | undefined,\r\n  fallback: Register\r\n): Register {\r\n  if (segment && rules && rules[segment]) return rules[segment];\r\n  return fallback;\r\n}\r\n\r\n/** Minimal shape of a React ref cell — `{ current }` — so the reset helper can\r\n *  be driven in a test without importing React's `MutableRefObject`. */\r\ninterface RefCell<T> {\r\n  current: T;\r\n}\r\n\r\n/** The slice of TranslationClient the init helper touches. Narrowed to an\r\n *  interface so a test can drive `runProjectInit` with a hand-rolled stub —\r\n *  no real network, no full client construction. */\r\ninterface InitClientSurface {\r\n  setSupportedLangs(langs: string[]): void;\r\n  getSupportedLangs(): string[];\r\n  fetchProjectInfo(): Promise<string[]>;\r\n  fetchTranslations(lang: string, register: Register): Promise<unknown>;\r\n  fetchVoice(lang: string, register: Register): Promise<unknown>;\r\n}\r\n\r\n/**\r\n * Run the provider's project initialization: load supportedLangs (project\r\n * metadata) and pre-warm the default (lang, register) bundle + fallbacks, then\r\n * commit the visible locale.\r\n *\r\n * Extracted from the init effect — like resetLocaleForProjectSwitch — so the\r\n * load-bearing TWO-COUNTER race-fix is unit-testable without a DOM render\r\n * harness (the SDK's vitest setup is node-environment, no jsdom).\r\n *\r\n * The two counters guard two DIFFERENT concerns:\r\n *\r\n *  • initReqRef (PROJECT-init guard) — bumped here at claim time and in\r\n *    resetLocaleForProjectSwitch; a plain setLang/setRegister does NOT touch it.\r\n *    The PROJECT-METADATA commits (setSupportedLangs / setError / the finally\r\n *    setIsLoading(false)) are guarded on it, so a concurrent setLang in flight\r\n *    during init can no longer cancel supportedLangs loading. Only a genuine\r\n *    project switch (new init / reset) supersedes them. THIS is the audit fix.\r\n *\r\n *  • localeReqRef (LOCALE guard) — the SHARED counter that setLang/setRegister/\r\n *    applyLocale also bump. The VISIBLE-LOCALE commit (apply default lang to the\r\n *    document + render trigger) is guarded on it, so a user's concurrent setLang\r\n *    wins the visible language: last-writer wins on the locale, while\r\n *    supportedLangs/isLoading still settle from init under initReqRef.\r\n *\r\n * Exported for tests.\r\n */\r\nexport async function runProjectInit(\r\n  refs: {\r\n    localeReqRef: RefCell<number>;\r\n    initReqRef: RefCell<number>;\r\n    pendingRegisterRef: RefCell<Register>;\r\n  },\r\n  config: {\r\n    defaultLang: string;\r\n    voiceEnabled: boolean;\r\n    preloadedTranslations?: Record<string, Record<string, string>>;\r\n  },\r\n  client: InitClientSurface,\r\n  setters: {\r\n    setIsLoading: (loading: boolean) => void;\r\n    setError: (error: string | null) => void;\r\n    setSupportedLangs: (langs: string[]) => void;\r\n    bumpRenderTrigger: () => void;\r\n  }\r\n): Promise<void> {\r\n  // Claim BOTH counters up front. initReqId guards the project-metadata commits;\r\n  // localeReqId guards only the visible-locale commit (and so defers to a\r\n  // concurrent setLang). A switch reset bumps both, invalidating this init.\r\n  const initReqId = ++refs.initReqRef.current;\r\n  const localeReqId = ++refs.localeReqRef.current;\r\n  const { defaultLang, voiceEnabled, preloadedTranslations } = config;\r\n\r\n  setters.setIsLoading(true);\r\n  setters.setError(null);\r\n\r\n  try {\r\n    const targetRegister = refs.pendingRegisterRef.current;\r\n\r\n    if (preloadedTranslations) {\r\n      const langs = Object.keys(preloadedTranslations);\r\n      client.setSupportedLangs(langs);\r\n      if (initReqId !== refs.initReqRef.current) return; // superseded by a project switch\r\n      setters.setSupportedLangs(langs);\r\n    } else {\r\n      const langs = await client.fetchProjectInfo();\r\n      if (initReqId !== refs.initReqRef.current) return; // superseded by a project switch\r\n      setters.setSupportedLangs(langs);\r\n    }\r\n\r\n    // Always fetch the requested register for the default language.\r\n    await client.fetchTranslations(defaultLang, targetRegister);\r\n\r\n    // Also fetch English as a fallback (default register only — English\r\n    // doesn't get formal/casual splits in this product).\r\n    if (defaultLang !== \"en\") {\r\n      await client.fetchTranslations(\"en\", DEFAULT_REGISTER);\r\n    }\r\n\r\n    // If the requested register isn't \"default\", also pre-warm \"default\"\r\n    // for the current lang so register-fallback is instant.\r\n    if (targetRegister !== DEFAULT_REGISTER) {\r\n      await client.fetchTranslations(defaultLang, DEFAULT_REGISTER);\r\n    }\r\n\r\n    // Voice mode: also fetch the IPA/SSML bundle so formatPhonetic and\r\n    // formatSSML can return non-empty strings synchronously.\r\n    if (voiceEnabled) {\r\n      await client.fetchVoice(defaultLang, targetRegister);\r\n      if (targetRegister !== DEFAULT_REGISTER) {\r\n        await client.fetchVoice(defaultLang, DEFAULT_REGISTER);\r\n      }\r\n    }\r\n\r\n    // The VISIBLE-LOCALE commit defers to the LOCALE guard: if a concurrent\r\n    // setLang (or a project switch) superseded us, don't apply the default lang\r\n    // to the document — the user's chosen lang (or the new project) owns the\r\n    // visible locale. supportedLangs/isLoading already settled under the init\r\n    // guard above, independently of this.\r\n    if (localeReqId !== refs.localeReqRef.current) return;\r\n\r\n    preloadFonts(client.getSupportedLangs());\r\n    applyLangToDocument(defaultLang);\r\n\r\n    setters.bumpRenderTrigger();\r\n  } catch (e: any) {\r\n    // Don't surface the old project's init error over the new project's load.\r\n    // Guarded on the PROJECT-init counter, not the locale one — a concurrent\r\n    // setLang must not swallow a genuine init failure for this project.\r\n    if (initReqId !== refs.initReqRef.current) return;\r\n    setters.setError(e?.message || \"Failed to initialize BhashaJS\");\r\n    console.error(\"[BhashaJS] Initialization error:\", e);\r\n  } finally {\r\n    // isLoading is project-load state: only a newer init (project switch) may\r\n    // keep the spinner up. A concurrent setLang has its OWN isLoading lifecycle\r\n    // in applyLocale, so init still settles the spinner here under the init\r\n    // guard — no stuck spinner after a mid-init setLang.\r\n    if (initReqId === refs.initReqRef.current) setters.setIsLoading(false);\r\n  }\r\n}\r\n\r\n/**\r\n * Atomically reset the locale machinery on a PROJECT SWITCH (projectId /\r\n * projectKey / apiUrl / apiToken changed, so the TranslationClient was\r\n * recreated). This is pulled out of the provider body so the load-bearing\r\n * race-fix can be unit-tested without a DOM render harness.\r\n *\r\n * It does two things, in this order, synchronously:\r\n *\r\n *  1. INVALIDATE IN-FLIGHT WORK from the previous project. `applyLocale` and the\r\n *     init effect's visible-locale commit capture `reqId = ++localeReq.current`\r\n *     up front and bail with `if (reqId !== localeReq.current) return` before\r\n *     committing lang/register/translations; the init effect's PROJECT-METADATA\r\n *     commits (supportedLangs/error/isLoading) capture `initReqRef` instead, so\r\n *     a plain setLang can't cancel them. Bumping BOTH counters here makes every\r\n *     reqId issued by the OLD project stale — neither a slow old locale fetch\r\n *     nor a slow old init can resolve and clobber the NEW client/state.\r\n *\r\n *  2. RESET both the pending locale target (refs) and the committed React state\r\n *     to the new project's defaults — clearing the old project's\r\n *     lang/register/error and emptying `supportedLangs` so the new project's\r\n *     languages reload. Resetting the pending refs keeps the atomic-locale\r\n *     setters diffing against the right baseline.\r\n *\r\n * Exported for tests.\r\n */\r\nexport function resetLocaleForProjectSwitch(\r\n  refs: {\r\n    localeReqRef: RefCell<number>;\r\n    initReqRef: RefCell<number>;\r\n    pendingLangRef: RefCell<string>;\r\n    pendingRegisterRef: RefCell<Register>;\r\n  },\r\n  defaults: { defaultLang: string; register: Register },\r\n  setters: {\r\n    setCurrentLang: (lang: string) => void;\r\n    setCurrentRegister: (register: Register) => void;\r\n    setError: (error: string | null) => void;\r\n    setIsLoading: (loading: boolean) => void;\r\n    setSupportedLangs: (langs: string[]) => void;\r\n  }\r\n): void {\r\n  // 1. Invalidate every reqId the previous project already issued — both the\r\n  //    locale counter (in-flight applyLocale / init visible-locale commit) and\r\n  //    the init counter (in-flight init's supportedLangs/error/isLoading commit).\r\n  refs.localeReqRef.current++;\r\n  refs.initReqRef.current++;\r\n\r\n  // 2a. Reset the pending locale target to the new project's defaults.\r\n  refs.pendingLangRef.current = defaults.defaultLang;\r\n  refs.pendingRegisterRef.current = defaults.register;\r\n\r\n  // 2b. Reset committed state: drop the old project's lang/register/error and\r\n  //     reload the new project's supported languages from scratch.\r\n  setters.setCurrentLang(defaults.defaultLang);\r\n  setters.setCurrentRegister(defaults.register);\r\n  setters.setError(null);\r\n  setters.setIsLoading(true);\r\n  setters.setSupportedLangs([]);\r\n}\r\n\r\n/**\r\n * Apply language settings to the HTML document.\r\n *\r\n * 1. Sets <html lang=\"hi\"> — important for SEO and screen readers\r\n * 2. Sets <html dir=\"rtl\"> — flips the entire layout for RTL languages\r\n * 3. Sets a CSS variable --bhasha-font — developers can use this in their CSS\r\n */\r\nfunction applyLangToDocument(lang: string) {\r\n  // No-op during SSR — there's no document. The provider re-applies on the\r\n  // client after hydration via the same call path.\r\n  if (typeof document === \"undefined\") return;\r\n\r\n  const langInfo = getLangInfo(lang);\r\n  const html = document.documentElement;\r\n\r\n  html.setAttribute(\"lang\", lang);\r\n  html.setAttribute(\"dir\", langInfo.dir);\r\n  html.style.setProperty(\"--bhasha-font\", langInfo.font);\r\n}\r\n","// FILE: packages/sdk/src/core/context.ts\n//\n// React Context for internationalization state.\n//\n// WHY A SEPARATE FILE:\n// The context is just the \"container\" — it holds the value shape\n// but doesn't have any logic. The actual logic lives in I18nProvider\n// (which fills this context) and useTranslation (which reads from it).\n//\n// This separation keeps things clean and avoids circular imports.\n\nimport { createContext } from \"react\";\nimport { I18nContextValue } from \"../types\";\n\n/**\n * The React Context that holds all i18n state.\n * \n * null means no provider was found — useTranslation will\n * throw a helpful error if someone forgets to add <I18nProvider>.\n */\nexport const I18nContext = createContext<I18nContextValue | null>(null);\n","// FILE: packages/sdk/src/utils/languages.ts\r\n//\r\n// This file is a KEY DIFFERENTIATOR of BhashaJS.\r\n//\r\n// Other i18n libraries like i18next treat every language the same —\r\n// they just swap strings. They don't know that Urdu is right-to-left,\r\n// that Hindi needs a specific font to render conjuncts properly, or\r\n// that Nepali should fall back to Hindi before falling back to English.\r\n//\r\n// BhashaJS ships with this knowledge built in. When a developer adds\r\n// Urdu support, we automatically handle RTL. When they add Bengali,\r\n// we know which font to load and which numbering system to use.\r\n//\r\n// This is what makes us purpose-built for South Asian languages.\r\n\r\nimport { LangInfo } from \"../types\";\r\n\r\n/**\r\n * Built-in language database — 14 entries covering 13 languages.\r\n * (Punjabi has two entries: Gurmukhi for India, Shahmukhi for Pakistan)\r\n *\r\n * Every South Asian language we support has:\r\n * - Its name in its own script (so the switcher shows हिन्दी not \"Hindi\")\r\n * - Text direction (RTL for Urdu/Shahmukhi Punjabi)\r\n * - A recommended Google Font that properly renders the script\r\n * - Default region, locale, currency, and numbering system for formatting\r\n */\r\nexport const LANGUAGES: Record<string, LangInfo> = {\r\n  en: {\r\n    code: \"en\",\r\n    name: \"English\",\r\n    englishName: \"English\",\r\n    dir: \"ltr\",\r\n    font: \"Inter, sans-serif\",\r\n    script: \"Latin\",\r\n    defaultRegion: \"IN\",\r\n    intlLocale: \"en-IN\",\r\n    numberingSystem: \"latn\",\r\n    defaultCurrency: \"INR\",\r\n  },\r\n  hi: {\r\n    code: \"hi\",\r\n    name: \"हिन्दी\",\r\n    englishName: \"Hindi\",\r\n    dir: \"ltr\",\r\n    font: \"Noto Sans Devanagari, sans-serif\",\r\n    script: \"Devanagari\",\r\n    defaultRegion: \"IN\",\r\n    intlLocale: \"hi-IN\",\r\n    numberingSystem: \"deva\",\r\n    defaultCurrency: \"INR\",\r\n  },\r\n  bn: {\r\n    code: \"bn\",\r\n    name: \"বাংলা\",\r\n    englishName: \"Bengali\",\r\n    dir: \"ltr\",\r\n    font: \"Noto Sans Bengali, sans-serif\",\r\n    script: \"Bengali\",\r\n    defaultRegion: \"BD\",\r\n    intlLocale: \"bn-BD\",\r\n    numberingSystem: \"beng\",\r\n    defaultCurrency: \"BDT\",\r\n  },\r\n  ur: {\r\n    code: \"ur\",\r\n    name: \"اردو\",\r\n    englishName: \"Urdu\",\r\n    dir: \"rtl\",\r\n    font: \"Noto Nastaliq Urdu, serif\",\r\n    script: \"Nastaliq\",\r\n    defaultRegion: \"PK\",\r\n    intlLocale: \"ur-PK\",\r\n    numberingSystem: \"arabext\",\r\n    defaultCurrency: \"PKR\",\r\n  },\r\n  ta: {\r\n    code: \"ta\",\r\n    name: \"தமிழ்\",\r\n    englishName: \"Tamil\",\r\n    dir: \"ltr\",\r\n    font: \"Noto Sans Tamil, sans-serif\",\r\n    script: \"Tamil\",\r\n    defaultRegion: \"IN\",\r\n    intlLocale: \"ta-IN\",\r\n    numberingSystem: \"tamldec\",\r\n    defaultCurrency: \"INR\",\r\n  },\r\n  te: {\r\n    code: \"te\",\r\n    name: \"తెలుగు\",\r\n    englishName: \"Telugu\",\r\n    dir: \"ltr\",\r\n    font: \"Noto Sans Telugu, sans-serif\",\r\n    script: \"Telugu\",\r\n    defaultRegion: \"IN\",\r\n    intlLocale: \"te-IN\",\r\n    numberingSystem: \"telu\",\r\n    defaultCurrency: \"INR\",\r\n  },\r\n  mr: {\r\n    code: \"mr\",\r\n    name: \"मराठी\",\r\n    englishName: \"Marathi\",\r\n    dir: \"ltr\",\r\n    font: \"Noto Sans Devanagari, sans-serif\",\r\n    script: \"Devanagari\",\r\n    defaultRegion: \"IN\",\r\n    intlLocale: \"mr-IN\",\r\n    numberingSystem: \"deva\",\r\n    defaultCurrency: \"INR\",\r\n  },\r\n  ne: {\r\n    code: \"ne\",\r\n    name: \"नेपाली\",\r\n    englishName: \"Nepali\",\r\n    dir: \"ltr\",\r\n    font: \"Noto Sans Devanagari, sans-serif\",\r\n    script: \"Devanagari\",\r\n    defaultRegion: \"NP\",\r\n    intlLocale: \"ne-NP\",\r\n    numberingSystem: \"deva\",\r\n    defaultCurrency: \"NPR\",\r\n  },\r\n  pa: {\r\n    code: \"pa\",\r\n    name: \"ਪੰਜਾਬੀ\",\r\n    englishName: \"Punjabi\",\r\n    dir: \"ltr\",\r\n    font: \"Noto Sans Gurmukhi, sans-serif\",\r\n    script: \"Gurmukhi\",\r\n    defaultRegion: \"IN\",\r\n    intlLocale: \"pa-IN\",\r\n    numberingSystem: \"guru\",\r\n    defaultCurrency: \"INR\",\r\n  },\r\n  \"pa-PK\": {\r\n    code: \"pa-PK\",\r\n    name: \"پنجابی\",\r\n    englishName: \"Punjabi (Shahmukhi)\",\r\n    dir: \"rtl\",\r\n    font: \"Noto Nastaliq Urdu, serif\",\r\n    script: \"Shahmukhi\",\r\n    defaultRegion: \"PK\",\r\n    intlLocale: \"pa-Arab-PK\",\r\n    numberingSystem: \"arabext\",\r\n    defaultCurrency: \"PKR\",\r\n  },\r\n  gu: {\r\n    code: \"gu\",\r\n    name: \"ગુજરાતી\",\r\n    englishName: \"Gujarati\",\r\n    dir: \"ltr\",\r\n    font: \"Noto Sans Gujarati, sans-serif\",\r\n    script: \"Gujarati\",\r\n    defaultRegion: \"IN\",\r\n    intlLocale: \"gu-IN\",\r\n    numberingSystem: \"gujr\",\r\n    defaultCurrency: \"INR\",\r\n  },\r\n  kn: {\r\n    code: \"kn\",\r\n    name: \"ಕನ್ನಡ\",\r\n    englishName: \"Kannada\",\r\n    dir: \"ltr\",\r\n    font: \"Noto Sans Kannada, sans-serif\",\r\n    script: \"Kannada\",\r\n    defaultRegion: \"IN\",\r\n    intlLocale: \"kn-IN\",\r\n    numberingSystem: \"knda\",\r\n    defaultCurrency: \"INR\",\r\n  },\r\n  ml: {\r\n    code: \"ml\",\r\n    name: \"മലയാളം\",\r\n    englishName: \"Malayalam\",\r\n    dir: \"ltr\",\r\n    font: \"Noto Sans Malayalam, sans-serif\",\r\n    script: \"Malayalam\",\r\n    defaultRegion: \"IN\",\r\n    intlLocale: \"ml-IN\",\r\n    numberingSystem: \"mlym\",\r\n    defaultCurrency: \"INR\",\r\n  },\r\n  si: {\r\n    code: \"si\",\r\n    name: \"සිංහල\",\r\n    englishName: \"Sinhala\",\r\n    dir: \"ltr\",\r\n    font: \"Noto Sans Sinhala, sans-serif\",\r\n    script: \"Sinhala\",\r\n    defaultRegion: \"LK\",\r\n    intlLocale: \"si-LK\",\r\n    numberingSystem: \"sinh\",\r\n    defaultCurrency: \"LKR\",\r\n  },\r\n\r\n  // ─── Latin-script (Romanized) variants — first-class locales ──────────\r\n  //\r\n  // These are NOT \"broken\" Hindi/Urdu/etc. — they're how Gen-Z South Asians\r\n  // actually type. WhatsApp, Twitter, Discord, dating apps, casual product\r\n  // copy: Latin script dominates. Treating them as their own locales (with\r\n  // their own translation memory, plural rules, fallback chains) is the\r\n  // unique edge no generic i18n tool offers.\r\n  //\r\n  // Naming follows the BCP 47 convention `<lang>-Latn`. The native `name`\r\n  // uses the colloquial term Gen-Z users recognize (\"Hinglish\", \"Banglish\").\r\n\r\n  \"hi-Latn\": {\r\n    code: \"hi-Latn\",\r\n    name: \"Hinglish\",\r\n    englishName: \"Hindi (Roman)\",\r\n    dir: \"ltr\",\r\n    font: \"Inter, sans-serif\",\r\n    script: \"Latin\",\r\n    defaultRegion: \"IN\",\r\n    intlLocale: \"hi-Latn-IN\",\r\n    numberingSystem: \"latn\",\r\n    defaultCurrency: \"INR\",\r\n  },\r\n  \"ne-Latn\": {\r\n    code: \"ne-Latn\",\r\n    name: \"Roman Nepali\",\r\n    englishName: \"Nepali (Roman)\",\r\n    dir: \"ltr\",\r\n    font: \"Inter, sans-serif\",\r\n    script: \"Latin\",\r\n    defaultRegion: \"NP\",\r\n    intlLocale: \"ne-Latn-NP\",\r\n    numberingSystem: \"latn\",\r\n    defaultCurrency: \"NPR\",\r\n  },\r\n  \"ur-Latn\": {\r\n    code: \"ur-Latn\",\r\n    name: \"Roman Urdu\",\r\n    englishName: \"Urdu (Roman)\",\r\n    dir: \"ltr\",\r\n    font: \"Inter, sans-serif\",\r\n    script: \"Latin\",\r\n    defaultRegion: \"PK\",\r\n    intlLocale: \"ur-Latn-PK\",\r\n    numberingSystem: \"latn\",\r\n    defaultCurrency: \"PKR\",\r\n  },\r\n  \"bn-Latn\": {\r\n    code: \"bn-Latn\",\r\n    name: \"Banglish\",\r\n    englishName: \"Bengali (Roman)\",\r\n    dir: \"ltr\",\r\n    font: \"Inter, sans-serif\",\r\n    script: \"Latin\",\r\n    defaultRegion: \"BD\",\r\n    intlLocale: \"bn-Latn-BD\",\r\n    numberingSystem: \"latn\",\r\n    defaultCurrency: \"BDT\",\r\n  },\r\n  \"pa-Latn\": {\r\n    code: \"pa-Latn\",\r\n    name: \"Roman Punjabi\",\r\n    englishName: \"Punjabi (Roman)\",\r\n    dir: \"ltr\",\r\n    font: \"Inter, sans-serif\",\r\n    script: \"Latin\",\r\n    defaultRegion: \"IN\",\r\n    intlLocale: \"pa-Latn-IN\",\r\n    numberingSystem: \"latn\",\r\n    defaultCurrency: \"INR\",\r\n  },\r\n};\r\n\r\n/**\r\n * Culturally-aware fallback chains.\r\n *\r\n * WHY THIS MATTERS:\r\n * If a Bengali translation is missing, what should we show?\r\n * Most i18n tools fall back to English. But a Bengali speaker\r\n * is more likely to understand Hindi than English. So we fall\r\n * back to Hindi first, then English.\r\n *\r\n * IMPORTANT: Dravidian languages (Tamil, Telugu, Kannada, Malayalam)\r\n * do NOT fall back to Hindi. They're from a completely different\r\n * language family. A Tamil speaker is NOT more likely to understand\r\n * Hindi than English.\r\n *\r\n * Developers can override these in the config if they want.\r\n */\r\nexport const FALLBACK_CHAINS: Record<string, string[]> = {\r\n  en: [\"en\"],\r\n  hi: [\"hi\", \"en\"],\r\n  bn: [\"bn\", \"hi\", \"en\"],        // Bengali → Hindi → English\r\n  ur: [\"ur\", \"hi\", \"en\"],        // Urdu → Hindi → English (mutually intelligible spoken)\r\n  ta: [\"ta\", \"en\"],              // Tamil → English (Dravidian — NO Hindi fallback)\r\n  te: [\"te\", \"en\"],              // Telugu → English (Dravidian — NO Hindi fallback)\r\n  mr: [\"mr\", \"hi\", \"en\"],        // Marathi → Hindi → English (both Devanagari)\r\n  ne: [\"ne\", \"hi\", \"en\"],        // Nepali → Hindi → English (very close to Hindi)\r\n  pa: [\"pa\", \"hi\", \"en\"],        // Punjabi (India) → Hindi → English\r\n  \"pa-PK\": [\"pa-PK\", \"ur\", \"en\"],// Punjabi (Pakistan) → Urdu → English\r\n  gu: [\"gu\", \"hi\", \"en\"],        // Gujarati → Hindi → English\r\n  kn: [\"kn\", \"en\"],              // Kannada → English (Dravidian — NO Hindi fallback)\r\n  ml: [\"ml\", \"en\"],              // Malayalam → English (Dravidian — NO Hindi fallback)\r\n  si: [\"si\", \"en\"],              // Sinhala → English\r\n\r\n  // Latin-script chains. Key insight: script bridges harder than language\r\n  // family does. A Roman-Hindi reader prefers English over Devanagari Hindi\r\n  // because the script flip is a worse experience than the language gap.\r\n  \"hi-Latn\": [\"hi-Latn\", \"en\"],                    // Hinglish → English\r\n  \"ne-Latn\": [\"ne-Latn\", \"hi-Latn\", \"en\"],         // Roman Nepali → Hinglish → English (same script + close lang)\r\n  \"ur-Latn\": [\"ur-Latn\", \"hi-Latn\", \"en\"],         // Roman Urdu → Hinglish → English (mutually intelligible)\r\n  \"bn-Latn\": [\"bn-Latn\", \"en\"],                    // Banglish → English (Bengali doesn't bridge to Hindi well in Latin)\r\n  \"pa-Latn\": [\"pa-Latn\", \"hi-Latn\", \"en\"],         // Roman Punjabi → Hinglish → English\r\n};\r\n\r\n/**\r\n * Region overrides for languages that span multiple countries.\r\n *\r\n * Some languages are spoken across borders with different currencies:\r\n * - Bengali: Bangladesh (৳ Taka) vs India (₹ Rupee)\r\n * - Tamil: India (₹ Rupee) vs Sri Lanka (Rs)\r\n * - Urdu: Pakistan (Rs) vs India (₹ Rupee)\r\n *\r\n * Developers pass region=\"IN\" to <I18nProvider> to override defaults.\r\n * The key format is \"{langCode}-{regionCode}\".\r\n */\r\nexport const REGION_OVERRIDES: Record<string, { currency: string; intlLocale: string }> = {\r\n  \"bn-IN\": { currency: \"INR\", intlLocale: \"bn-IN\" },\r\n  \"ta-LK\": { currency: \"LKR\", intlLocale: \"ta-LK\" },\r\n  \"ur-IN\": { currency: \"INR\", intlLocale: \"ur-IN\" },\r\n  \"si-IN\": { currency: \"INR\", intlLocale: \"si-IN\" },\r\n  \"ne-IN\": { currency: \"INR\", intlLocale: \"ne-IN\" },\r\n};\r\n\r\n/**\r\n * Get language info. Returns a default for unknown languages\r\n * so the SDK never crashes on an unrecognized code.\r\n */\r\nexport function getLangInfo(code: string): LangInfo {\r\n  if (LANGUAGES[code]) return LANGUAGES[code];\r\n\r\n  // Unknown code — infer direction so we never render an RTL language\r\n  // left-to-right (the exact South-Asian RTL audience we target). RTL if the\r\n  // base is a known RTL language or the code carries an Arabic-script subtag\r\n  // (e.g. \"ur-IN\", \"pa-Arab\"); a \"-Latn\" romanized variant is always LTR.\r\n  const lower = code.toLowerCase();\r\n  const isLatn = /-latn(-|$)/.test(lower);\r\n  const rtl =\r\n    !isLatn &&\r\n    (/^(ur|ar|fa|ps|sd|ks)(-|$)/.test(lower) || /-arab(-|$)/.test(lower));\r\n  return {\r\n    code,\r\n    name: code,\r\n    englishName: code,\r\n    dir: rtl ? (\"rtl\" as const) : (\"ltr\" as const),\r\n    font: \"sans-serif\",\r\n    script: rtl ? \"Arabic\" : isLatn ? \"Latin\" : \"Unknown\",\r\n    defaultRegion: \"IN\",\r\n    intlLocale: code,\r\n    numberingSystem: \"latn\",\r\n    defaultCurrency: \"INR\",\r\n  };\r\n}\r\n\r\n/**\r\n * Get the fallback chain for a language.\r\n * If no custom chain exists, defaults to [lang, \"en\"].\r\n */\r\nexport function getFallbackChain(lang: string): string[] {\r\n  return FALLBACK_CHAINS[lang] || [lang, \"en\"];\r\n}\r\n\r\n/**\r\n * Resolve the effective locale and currency for a language + optional region.\r\n * Checks REGION_OVERRIDES first, then falls back to the language's defaults.\r\n */\r\nexport function resolveRegion(\r\n  lang: string,\r\n  region?: string\r\n): { intlLocale: string; currency: string } {\r\n  const langInfo = getLangInfo(lang);\r\n\r\n  if (region) {\r\n    const overrideKey = `${lang}-${region}`;\r\n    const override = REGION_OVERRIDES[overrideKey];\r\n    if (override) {\r\n      return { intlLocale: override.intlLocale, currency: override.currency };\r\n    }\r\n    // If no specific override, just swap the region in the locale\r\n    return {\r\n      intlLocale: `${lang}-${region}`,\r\n      currency: langInfo.defaultCurrency,\r\n    };\r\n  }\r\n\r\n  return {\r\n    intlLocale: langInfo.intlLocale,\r\n    currency: langInfo.defaultCurrency,\r\n  };\r\n}\r\n\r\n/**\r\n * Google Fonts CSS URLs for each script.\r\n * We only load the fonts that are actually needed.\r\n */\r\nexport const FONT_URLS: Record<string, string> = {\r\n  \"Noto Sans Devanagari\":\r\n    \"https://fonts.googleapis.com/css2?family=Noto+Sans+Devanagari:wght@400;500;600;700&display=swap\",\r\n  \"Noto Sans Bengali\":\r\n    \"https://fonts.googleapis.com/css2?family=Noto+Sans+Bengali:wght@400;500;600;700&display=swap\",\r\n  \"Noto Nastaliq Urdu\":\r\n    \"https://fonts.googleapis.com/css2?family=Noto+Nastaliq+Urdu:wght@400;500;600;700&display=swap\",\r\n  \"Noto Sans Tamil\":\r\n    \"https://fonts.googleapis.com/css2?family=Noto+Sans+Tamil:wght@400;500;600;700&display=swap\",\r\n  \"Noto Sans Telugu\":\r\n    \"https://fonts.googleapis.com/css2?family=Noto+Sans+Telugu:wght@400;500;600;700&display=swap\",\r\n  \"Noto Sans Gurmukhi\":\r\n    \"https://fonts.googleapis.com/css2?family=Noto+Sans+Gurmukhi:wght@400;500;600;700&display=swap\",\r\n  \"Noto Sans Gujarati\":\r\n    \"https://fonts.googleapis.com/css2?family=Noto+Sans+Gujarati:wght@400;500;600;700&display=swap\",\r\n  \"Noto Sans Kannada\":\r\n    \"https://fonts.googleapis.com/css2?family=Noto+Sans+Kannada:wght@400;500;600;700&display=swap\",\r\n  \"Noto Sans Malayalam\":\r\n    \"https://fonts.googleapis.com/css2?family=Noto+Sans+Malayalam:wght@400;500;600;700&display=swap\",\r\n  \"Noto Sans Sinhala\":\r\n    \"https://fonts.googleapis.com/css2?family=Noto+Sans+Sinhala:wght@400;500;600;700&display=swap\",\r\n};\r\n","// FILE: packages/sdk/src/utils/plurals.ts\r\n//\r\n// CLDR-compliant pluralization for South Asian languages.\r\n//\r\n// WHY THIS IS CRITICAL:\r\n// Hindi treats 0 as singular: \"0 आइटम\" (not \"0 आइटमें\")\r\n// English treats 0 as plural: \"0 items\" (not \"0 item\")\r\n//\r\n// Most i18n tools apply English rules globally. This means Hindi\r\n// pluralization is WRONG in every app using i18next without custom\r\n// configuration. BhashaJS handles this correctly out of the box.\r\n//\r\n// CLDR PLURAL RULES (simplified for South Asian languages):\r\n// We only need \"one\" and \"other\" categories. More complex languages\r\n// (like Arabic with dual/few) are not in our scope.\r\n//\r\n// Group A — 0 AND 1 are \"one\" (singular):\r\n//   Hindi, Bengali, Marathi, Gujarati, Kannada, Sinhala, Punjabi\r\n//   Rule: n is 0 or n is 1 → \"one\"\r\n//\r\n// Group B — Only 1 is \"one\" (singular):\r\n//   English, Urdu, Tamil, Telugu, Malayalam, Nepali\r\n//   Rule: n is 1 → \"one\"\r\n//\r\n// Source: Unicode CLDR plural rules\r\n// https://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html\r\n\r\n/**\r\n * Languages where BOTH 0 and 1 are treated as singular (\"one\").\r\n * This is the South Asian plural rule that most tools get wrong.\r\n *\r\n * Latin-script variants (hi-Latn, bn-Latn, pa-Latn) inherit from their base\r\n * language — switching scripts doesn't change grammatical number rules. The\r\n * `getPluralCategory` function strips the `-Latn` suffix before lookup.\r\n */\r\nconst ZERO_AND_ONE_SINGULAR = new Set([\r\n  \"hi\",     // Hindi\r\n  \"bn\",     // Bengali\r\n  \"mr\",     // Marathi\r\n  \"gu\",     // Gujarati\r\n  \"kn\",     // Kannada\r\n  \"si\",     // Sinhala\r\n  \"pa\",     // Punjabi (Gurmukhi)\r\n  \"pa-PK\",  // Punjabi (Shahmukhi)\r\n]);\r\n\r\n/**\r\n * Map a locale code to its base language for plural-rule lookup.\r\n * `hi-Latn` → `hi`. `pa-PK` is intentionally NOT stripped because it's a\r\n * full locale (different script), not a romanization.\r\n */\r\nfunction baseLangForPlurals(lang: string): string {\r\n  return lang.endsWith(\"-Latn\") ? lang.slice(0, -5) : lang;\r\n}\r\n\r\n/**\r\n * Get the CLDR plural category for a number in a given language.\r\n *\r\n * @param count - The number to pluralize (e.g. 0, 1, 5)\r\n * @param lang  - The language code (e.g. \"hi\", \"en\")\r\n * @returns \"one\" (singular) or \"other\" (plural)\r\n *\r\n * @example\r\n * getPluralCategory(0, \"en\")  // → \"other\"  (English: \"0 items\")\r\n * getPluralCategory(0, \"hi\")  // → \"one\"    (Hindi: \"0 आइटम\")\r\n * getPluralCategory(1, \"en\")  // → \"one\"    (English: \"1 item\")\r\n * getPluralCategory(1, \"hi\")  // → \"one\"    (Hindi: \"1 आइटम\")\r\n * getPluralCategory(5, \"en\")  // → \"other\"  (English: \"5 items\")\r\n * getPluralCategory(5, \"hi\")  // → \"other\"  (Hindi: \"5 आइटमें\")\r\n */\r\nexport function getPluralCategory(\r\n  count: number,\r\n  lang: string\r\n): \"one\" | \"other\" {\r\n  // Use the absolute value for negative numbers\r\n  const n = Math.abs(count);\r\n  const base = baseLangForPlurals(lang);\r\n\r\n  // DELIBERATE MOAT OVERRIDE — South Asian \"0-as-singular\".\r\n  // For the Group-A languages, 0 is grammatically singular (\"0 आइटम\"),\r\n  // even where CLDR/Intl classifies it \"other\" (e.g. Marathi). This is the\r\n  // one intentional divergence from Intl.PluralRules and is allow-listed in\r\n  // cldr-plural.test.ts. It only applies to an EXACT zero — non-zero counts\r\n  // (including decimals like 0.5) defer to CLDR below.\r\n  if (ZERO_AND_ONE_SINGULAR.has(base) && n === 0) {\r\n    return \"one\";\r\n  }\r\n\r\n  // Everything else defers to the platform's CLDR data via Intl.PluralRules,\r\n  // which is correct for decimals (e.g. Sinhala/Punjabi 0.5 → \"other\",\r\n  // Marathi 0.5 → \"other\") where the old hand-rolled table diverged. The SDK\r\n  // only models \"one\"/\"other\", so we collapse Intl's category accordingly\r\n  // (Intl \"one\" → \"one\"; \"zero\"/\"two\"/\"few\"/\"many\"/\"other\" → \"other\").\r\n  try {\r\n    return new Intl.PluralRules(base).select(n) === \"one\" ? \"one\" : \"other\";\r\n  } catch {\r\n    // Unknown/unsupported locale — fall back to the old hand rule. Group-A\r\n    // bases already returned above for n === 0, so here Group A keeps 1 as\r\n    // singular and Group B keeps only 1 as singular.\r\n    if (ZERO_AND_ONE_SINGULAR.has(base)) {\r\n      return n <= 1 ? \"one\" : \"other\";\r\n    }\r\n    return n === 1 ? \"one\" : \"other\";\r\n  }\r\n}\r\n","// FILE: packages/sdk/src/core/client.ts\r\n//\r\n// The TranslationClient is the engine of the SDK.\r\n// It handles:\r\n//   1. Fetching translations from the BhashaJS API per (lang, register)\r\n//   2. Caching them in memory so we don't re-fetch\r\n//   3. Looking up a key with register + language fallback chain support\r\n//   4. String interpolation (replacing {name} with actual values)\r\n//\r\n// IMPORTANT: This class has ZERO React dependency.\r\n// It's pure TypeScript. This means in the future, you could\r\n// create a Vue or Svelte wrapper around the same client.\r\n// The React-specific stuff lives in the hooks and components.\r\n//\r\n// REGISTER FALLBACK:\r\n// A request for \"casual\" Hindi falls back to \"default\" Hindi if the casual\r\n// translation is missing — so a partially-localized casual register still\r\n// produces a usable bundle. Then the language fallback chain kicks in\r\n// (e.g. casual Bengali → default Bengali → default Hindi → English).\r\n\r\nimport { getFallbackChain } from \"../utils/languages\";\r\nimport { getPluralCategory } from \"../utils/plurals\";\r\nimport type { Register } from \"../types\";\r\n\r\nconst DEFAULT_REGISTER: Register = \"default\";\r\ntype ClientOptions = {\r\n  persistCache?: boolean;\r\n};\r\n\r\n/** Compose the cache key. We flatten (lang, register) so the inner cache\r\n *  stays a simple Record<key, string>. */\r\nfunction bundleKey(lang: string, register: Register): string {\r\n  return `${lang}:${register}`;\r\n}\r\n\r\nfunction ownString(obj: Record<string, string>, key: string): string | undefined {\r\n  if (!Object.prototype.hasOwnProperty.call(obj, key)) return undefined;\r\n  const value = obj[key];\r\n  return typeof value === \"string\" ? value : undefined;\r\n}\r\n\r\nfunction ownVoice(\r\n  obj: Record<string, { ipa: string; ssml: string }>,\r\n  key: string\r\n): { ipa: string; ssml: string } | undefined {\r\n  if (!Object.prototype.hasOwnProperty.call(obj, key)) return undefined;\r\n  const value = obj[key];\r\n  if (!value || typeof value !== \"object\") return undefined;\r\n  return value;\r\n}\r\n\r\nexport class TranslationClient {\r\n  private projectId: string;\r\n  private apiUrl: string;\r\n  private apiToken: string;\r\n  private projectKey: string;\r\n  private persistCache: boolean;\r\n  private onBundleUpdate?: () => void;\r\n\r\n  /**\r\n   * Cache structure: keyed by `${lang}:${register}`, mapping to a flat\r\n   * Record<key, translation>. So:\r\n   *   cache[\"hi:default\"] = { \"hero.title\": \"स्वागत\" }\r\n   *   cache[\"hi:casual\"]  = { \"hero.title\": \"Welcome है\" }\r\n   * Once a (lang, register) bundle is fetched, it stays in the cache for the\r\n   * lifetime of the app.\r\n   */\r\n  private cache: Record<string, Record<string, string>> = {};\r\n\r\n  /**\r\n   * Voice cache, parallel to `cache` but per-(lang, register, key) holding\r\n   * { ipa, ssml }. Populated lazily by `fetchVoice` — populated only when\r\n   * the developer enables voice mode or calls `formatPhonetic` / `formatSSML`\r\n   * before the first paint.\r\n   */\r\n  private voiceCache: Record<string, Record<string, { ipa: string; ssml: string }>> = {};\r\n\r\n  /**\r\n   * Tracks which (lang, register) bundles are currently being fetched.\r\n   * Prevents duplicate API calls if a component renders twice\r\n   * before the first fetch completes (React Strict Mode does this).\r\n   */\r\n  private fetchPromises: Record<string, Promise<Record<string, string>>> = {};\r\n\r\n  /** In-flight voice-bundle fetches, indexed the same way as fetchPromises. */\r\n  private voiceFetchPromises: Record<string, Promise<Record<string, { ipa: string; ssml: string }>>> = {};\r\n\r\n  /** List of supported languages, fetched from the project endpoint */\r\n  private supportedLangs: string[] = [];\r\n\r\n  constructor(\r\n    projectId: string,\r\n    apiUrl: string,\r\n    apiToken: string,\r\n    projectKey: string = \"\",\r\n    options: ClientOptions = {}\r\n  ) {\r\n    this.projectId = projectId;\r\n    this.apiUrl = apiUrl;\r\n    this.apiToken = apiToken;\r\n    this.projectKey = projectKey;\r\n    this.persistCache = options.persistCache !== false;\r\n  }\r\n\r\n  /** Whether this client uses the public SDK endpoints (API key auth) */\r\n  private get usePublicEndpoints(): boolean {\r\n    return !!this.projectKey;\r\n  }\r\n\r\n  /**\r\n   * Load preloaded translations into the cache.\r\n   * Accepts both shapes for backwards compat:\r\n   *   1. Flat (legacy):   { \"hi\": { \"hero.title\": \"स्वागत\" } }\r\n   *      → loaded into the \"default\" register.\r\n   *   2. Nested:          { \"hi\": { \"default\": { \"hero.title\": \"स्वागत\" },\r\n   *                                  \"casual\":  { \"hero.title\": \"Welcome है\" } } }\r\n   */\r\n  preload(\r\n    translations: Record<\r\n      string,\r\n      Record<string, string> | Partial<Record<Register, Record<string, string>>>\r\n    >\r\n  ): void {\r\n    for (const [lang, body] of Object.entries(translations)) {\r\n      // Heuristic: a register bundle is a \"register\" key whose value is itself\r\n      // a Record<string, string>. If we see strings as direct values, this is\r\n      // the legacy flat shape and we lift it to \"default\".\r\n      const looksLikeRegisterMap = Object.values(body).every(\r\n        (v) => typeof v === \"object\" && v !== null && !Array.isArray(v)\r\n      );\r\n\r\n      if (looksLikeRegisterMap) {\r\n        for (const [reg, strings] of Object.entries(body)) {\r\n          if (reg !== \"default\" && reg !== \"formal\" && reg !== \"casual\") continue;\r\n          this.cache[bundleKey(lang, reg as Register)] = strings as Record<string, string>;\r\n        }\r\n      } else {\r\n        this.cache[bundleKey(lang, DEFAULT_REGISTER)] = body as Record<string, string>;\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Set the list of supported languages.\r\n   * Called by the provider after fetching project info.\r\n   */\r\n  setSupportedLangs(langs: string[]) {\r\n    this.supportedLangs = langs;\r\n  }\r\n\r\n  setOnBundleUpdate(fn?: (() => void) | null): void {\r\n    this.onBundleUpdate = fn || undefined;\r\n  }\r\n\r\n  getSupportedLangs(): string[] {\r\n    return this.supportedLangs;\r\n  }\r\n\r\n  /**\r\n   * Fetch translations for a specific (language, register) bundle from the API.\r\n   *\r\n   * HOW IT WORKS:\r\n   * 1. Check if the bundle is already in cache → return immediately\r\n   * 2. Check if a fetch is already in progress → wait for that one\r\n   * 3. Otherwise, make the API call, cache the result, return it\r\n   *\r\n   * The API endpoint GET /api/sdk/translations?lang=hi&register=casual\r\n   * returns flat JSON: { \"hero.title\": \"Welcome है\" } — already collapsed\r\n   * server-side with default-register fallback baked in.\r\n   */\r\n  async fetchTranslations(\r\n    lang: string,\r\n    register: Register = DEFAULT_REGISTER\r\n  ): Promise<Record<string, string>> {\r\n    const cacheKey = bundleKey(lang, register);\r\n\r\n    // Already cached? Return immediately (instant language switching!)\r\n    if (this.cache[cacheKey]) {\r\n      return this.cache[cacheKey];\r\n    }\r\n\r\n    const persisted = this.readPersistedBundle(lang, register);\r\n    if (persisted) {\r\n      this.cache[cacheKey] = persisted;\r\n      this.refreshTranslationsInBackground(lang, register, cacheKey, persisted);\r\n      return persisted;\r\n    }\r\n\r\n    // Already fetching? Wait for the existing promise\r\n    // This prevents duplicate API calls in React Strict Mode\r\n    if (cacheKey in this.fetchPromises) {\r\n      return this.fetchPromises[cacheKey];\r\n    }\r\n\r\n    // Build the fetch promise. Errors propagate so the I18nProvider can expose\r\n    // them via its `error` state — silent failure made auth bugs invisible.\r\n    const fetchPromise = (async () => {\r\n      try {\r\n        const params = `lang=${encodeURIComponent(lang)}&register=${encodeURIComponent(register)}`;\r\n        const url = this.usePublicEndpoints\r\n          ? `${this.apiUrl}/sdk/translations?${params}`\r\n          : `${this.apiUrl}/translations/${this.projectId}?${params}`;\r\n\r\n        const headers: Record<string, string> = {\r\n          \"Content-Type\": \"application/json\",\r\n        };\r\n\r\n        if (this.usePublicEndpoints) {\r\n          headers[\"x-api-key\"] = this.projectKey;\r\n        } else if (this.apiToken) {\r\n          headers[\"Authorization\"] = `Bearer ${this.apiToken}`;\r\n        }\r\n\r\n        const response = await fetch(url, { headers });\r\n\r\n        if (!response.ok) {\r\n          const detail = await response.text().catch(() => \"\");\r\n          throw new Error(\r\n            `BhashaJS: failed to load translations for \"${lang}/${register}\" (HTTP ${response.status})${detail ? \": \" + detail : \"\"}`\r\n          );\r\n        }\r\n\r\n        const json = await response.json();\r\n        const translations = json.data || json;\r\n\r\n        this.cache[cacheKey] = translations;\r\n        this.writePersistedBundle(lang, register, translations);\r\n        return translations;\r\n      } finally {\r\n        delete this.fetchPromises[cacheKey];\r\n      }\r\n    })();\r\n\r\n    // Store the promise so concurrent calls can wait for it\r\n    this.fetchPromises[cacheKey] = fetchPromise;\r\n\r\n    return fetchPromise;\r\n  }\r\n\r\n  private refreshTranslationsInBackground(\r\n    lang: string,\r\n    register: Register,\r\n    cacheKey: string,\r\n    current: Record<string, string>\r\n  ): void {\r\n    if (cacheKey in this.fetchPromises) return;\r\n    const fetchPromise = (async () => {\r\n      try {\r\n        const params = `lang=${encodeURIComponent(lang)}&register=${encodeURIComponent(register)}`;\r\n        const url = this.usePublicEndpoints\r\n          ? `${this.apiUrl}/sdk/translations?${params}`\r\n          : `${this.apiUrl}/translations/${this.projectId}?${params}`;\r\n\r\n        const headers: Record<string, string> = {\r\n          \"Content-Type\": \"application/json\",\r\n        };\r\n\r\n        if (this.usePublicEndpoints) {\r\n          headers[\"x-api-key\"] = this.projectKey;\r\n        } else if (this.apiToken) {\r\n          headers[\"Authorization\"] = `Bearer ${this.apiToken}`;\r\n        }\r\n\r\n        const response = await fetch(url, { headers });\r\n        if (!response.ok) return current;\r\n\r\n        const json = await response.json();\r\n        const fresh = json.data || json;\r\n        if (JSON.stringify(fresh) !== JSON.stringify(current)) {\r\n          this.cache[cacheKey] = fresh;\r\n          this.writePersistedBundle(lang, register, fresh);\r\n          this.onBundleUpdate?.();\r\n        }\r\n        return fresh;\r\n      } catch {\r\n        return current;\r\n      } finally {\r\n        delete this.fetchPromises[cacheKey];\r\n      }\r\n    })();\r\n    this.fetchPromises[cacheKey] = fetchPromise;\r\n  }\r\n\r\n  private persistedStorageKey(lang: string, register: Register): string {\r\n    return `bhashajs:b1:${this.projectKey || this.projectId}:${lang}:${register}`;\r\n  }\r\n\r\n  private persistedLangsKey(): string {\r\n    return `bhashajs:p1:${this.projectKey || this.projectId}`;\r\n  }\r\n\r\n  private readPersistedLangs(): string[] | null {\r\n    if (!this.persistCache || typeof localStorage === \"undefined\") return null;\r\n    try {\r\n      const raw = localStorage.getItem(this.persistedLangsKey());\r\n      if (!raw) return null;\r\n      const parsed = JSON.parse(raw);\r\n      if (!parsed || parsed.v !== 1 || !Array.isArray(parsed.langs)) return null;\r\n      return parsed.langs.filter((l: unknown) => typeof l === \"string\");\r\n    } catch {\r\n      return null;\r\n    }\r\n  }\r\n\r\n  private writePersistedLangs(langs: string[]): void {\r\n    if (!this.persistCache || typeof localStorage === \"undefined\") return;\r\n    try {\r\n      localStorage.setItem(\r\n        this.persistedLangsKey(),\r\n        JSON.stringify({ v: 1, t: Date.now(), langs })\r\n      );\r\n    } catch {\r\n      // Storage is best-effort: quota/privacy-mode errors must not break i18n.\r\n    }\r\n  }\r\n\r\n  private readPersistedBundle(lang: string, register: Register): Record<string, string> | null {\r\n    if (!this.persistCache || typeof localStorage === \"undefined\") return null;\r\n    try {\r\n      const raw = localStorage.getItem(this.persistedStorageKey(lang, register));\r\n      if (!raw) return null;\r\n      const parsed = JSON.parse(raw);\r\n      if (!parsed || parsed.v !== 1 || !parsed.data || typeof parsed.data !== \"object\") {\r\n        return null;\r\n      }\r\n      return parsed.data;\r\n    } catch {\r\n      return null;\r\n    }\r\n  }\r\n\r\n  private writePersistedBundle(\r\n    lang: string,\r\n    register: Register,\r\n    data: Record<string, string>\r\n  ): void {\r\n    if (!this.persistCache || typeof localStorage === \"undefined\") return;\r\n    try {\r\n      localStorage.setItem(\r\n        this.persistedStorageKey(lang, register),\r\n        JSON.stringify({ v: 1, t: Date.now(), data })\r\n      );\r\n    } catch {\r\n      // Storage is best-effort: quota/privacy-mode errors must not break i18n.\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Fetch the voice bundle for a (lang, register). Same auth model as\r\n   * `fetchTranslations`, separate endpoint. Cached so future calls are\r\n   * instant. Errors propagate so the provider can expose them.\r\n   */\r\n  async fetchVoice(\r\n    lang: string,\r\n    register: Register = DEFAULT_REGISTER\r\n  ): Promise<Record<string, { ipa: string; ssml: string }>> {\r\n    const cacheKey = bundleKey(lang, register);\r\n    if (this.voiceCache[cacheKey]) return this.voiceCache[cacheKey];\r\n    if (cacheKey in this.voiceFetchPromises) return this.voiceFetchPromises[cacheKey];\r\n\r\n    const fetchPromise = (async () => {\r\n      try {\r\n        const params = `lang=${encodeURIComponent(lang)}&register=${encodeURIComponent(register)}`;\r\n        const url = this.usePublicEndpoints\r\n          ? `${this.apiUrl}/sdk/voice?${params}`\r\n          : `${this.apiUrl}/translations/${this.projectId}?${params}`; // JWT path doesn't have voice yet — return empty\r\n\r\n        const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\r\n        if (this.usePublicEndpoints) headers[\"x-api-key\"] = this.projectKey;\r\n        else if (this.apiToken) headers[\"Authorization\"] = `Bearer ${this.apiToken}`;\r\n\r\n        const response = await fetch(url, { headers });\r\n        if (!response.ok) {\r\n          // Soft-fail: voice data is optional, never block the app.\r\n          this.voiceCache[cacheKey] = {};\r\n          return this.voiceCache[cacheKey];\r\n        }\r\n        const json = await response.json();\r\n        // The /translations endpoint doesn't return a voice bundle; only /sdk/voice does.\r\n        // If the response shape doesn't match { ipa, ssml }, fall back to empty.\r\n        const data = json.data || json;\r\n        const looksLikeVoice =\r\n          data && typeof data === \"object\" &&\r\n          Object.values(data).every((v: any) => v && typeof v === \"object\" && \"ipa\" in v && \"ssml\" in v);\r\n        const bundle: Record<string, { ipa: string; ssml: string }> = looksLikeVoice ? data : {};\r\n        this.voiceCache[cacheKey] = bundle;\r\n        return bundle;\r\n      } finally {\r\n        delete this.voiceFetchPromises[cacheKey];\r\n      }\r\n    })();\r\n\r\n    this.voiceFetchPromises[cacheKey] = fetchPromise;\r\n    return fetchPromise;\r\n  }\r\n\r\n  /**\r\n   * Look up voice data for a key, walking the same fallback chain as\r\n   * `translate()` — register-then-language. Returns undefined if no voice\r\n   * bundle has been loaded for any matching (lang, register).\r\n   */\r\n  getVoice(\r\n    key: string,\r\n    lang: string,\r\n    register: Register = DEFAULT_REGISTER\r\n  ): { ipa: string; ssml: string } | undefined {\r\n    const chain = getFallbackChain(lang);\r\n    for (const fallbackLang of chain) {\r\n      for (const reg of registerFallback(register)) {\r\n        const bundle = this.voiceCache[bundleKey(fallbackLang, reg)];\r\n        if (bundle) {\r\n          const cell = ownVoice(bundle, key);\r\n          if (cell) return cell;\r\n        }\r\n      }\r\n    }\r\n    return undefined;\r\n  }\r\n\r\n  /**\r\n   * Preload voice data into the cache. Useful for SSR or bundling voice with\r\n   * the app. Accepts the same shape as the API response.\r\n   */\r\n  preloadVoice(\r\n    voice: Record<\r\n      string,\r\n      Partial<Record<Register, Record<string, { ipa: string; ssml: string }>>>\r\n    >\r\n  ): void {\r\n    for (const [lang, byRegister] of Object.entries(voice)) {\r\n      for (const [reg, bundle] of Object.entries(byRegister)) {\r\n        if (reg !== \"default\" && reg !== \"formal\" && reg !== \"casual\") continue;\r\n        if (!bundle) continue;\r\n        this.voiceCache[bundleKey(lang, reg as Register)] = bundle;\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Fetch project info to get the list of supported languages.\r\n   * Throws on auth/network failure so the provider can surface the error.\r\n   */\r\n  async fetchProjectInfo(): Promise<string[]> {\r\n    const url = this.usePublicEndpoints\r\n      ? `${this.apiUrl}/sdk/project`\r\n      : `${this.apiUrl}/projects/${this.projectId}`;\r\n\r\n    const headers: Record<string, string> = {\r\n      \"Content-Type\": \"application/json\",\r\n    };\r\n\r\n    if (this.usePublicEndpoints) {\r\n      headers[\"x-api-key\"] = this.projectKey;\r\n    } else if (this.apiToken) {\r\n      headers[\"Authorization\"] = `Bearer ${this.apiToken}`;\r\n    }\r\n\r\n    let response: Response;\r\n    try {\r\n      response = await fetch(url, { headers });\r\n    } catch (networkError) {\r\n      // OFFLINE / network failure (not an HTTP error): fall back to the\r\n      // persisted language list so a cold start can still serve cached\r\n      // bundles. An HTTP-level rejection (e.g. a revoked key → 401) is a real\r\n      // error and still throws below — never masked by the cache.\r\n      const cached = this.readPersistedLangs();\r\n      if (cached && cached.length > 0) {\r\n        this.supportedLangs = cached;\r\n        return this.supportedLangs;\r\n      }\r\n      throw networkError;\r\n    }\r\n\r\n    if (!response.ok) {\r\n      const detail = await response.text().catch(() => \"\");\r\n      throw new Error(\r\n        `BhashaJS: failed to fetch project info (HTTP ${response.status})${detail ? \": \" + detail : \"\"}`\r\n      );\r\n    }\r\n\r\n    const json = await response.json();\r\n    const project = json.data || json;\r\n\r\n    this.supportedLangs = project.supportedLanguages || [];\r\n    this.writePersistedLangs(this.supportedLangs);\r\n    return this.supportedLangs;\r\n  }\r\n\r\n  /**\r\n   * THE CORE FUNCTION — Translate a key.\r\n   *\r\n   * How fallback works:\r\n   *   1. Try the requested (lang, register) bundle.\r\n   *   2. If empty, try the same lang at \"default\" register.\r\n   *   3. If still empty, walk the language fallback chain at \"default\".\r\n   * First match wins.\r\n   *\r\n   * PLURALIZATION:\r\n   * If params contains a \"count\" key, we automatically resolve the\r\n   * correct plural form using CLDR rules for the language.\r\n   *\r\n   * @param key - The translation key (e.g. \"hero.title\")\r\n   * @param lang - The current language code (e.g. \"bn\")\r\n   * @param register - The current register (\"default\" | \"formal\" | \"casual\")\r\n   * @param params - Optional interpolation values (e.g. { name: \"Rohan\" })\r\n   */\r\n  translate(\r\n    key: string,\r\n    lang: string,\r\n    register: Register = DEFAULT_REGISTER,\r\n    params?: Record<string, string | number>\r\n  ): string {\r\n    const chain = getFallbackChain(lang);\r\n    const hasCount = params != null && params.count !== undefined;\r\n    const count = hasCount ? Number(params.count) : 0;\r\n\r\n    let result: string | undefined;\r\n\r\n    // Walk: each fallback lang × [requested register, \"default\"].\r\n    // We try the same register across all langs first? No — if the user wants\r\n    // casual Hindi but only formal Hindi exists, falling back to formal Hindi\r\n    // is better than falling back to casual English. So per-lang we try\r\n    // [register, default], then move on.\r\n    //\r\n    // PLURALIZATION happens PER CELL, using each fallback language's OWN rule —\r\n    // not the requested language's. Otherwise a Hindi count=0 (category \"one\")\r\n    // that falls back to English would pick English's \"_one\" cell and render\r\n    // English's singular (\"0 item\") instead of its correct plural (\"0 items\").\r\n    // A language's own base key also wins over a fallback language's plural form.\r\n    outer: for (const fallbackLang of chain) {\r\n      for (const reg of registerFallback(register)) {\r\n        const langCache = this.cache[bundleKey(fallbackLang, reg)];\r\n        if (!langCache) continue;\r\n\r\n        if (hasCount) {\r\n          const category = getPluralCategory(count, fallbackLang);\r\n          const categoryValue = ownString(langCache, `${key}_${category}`);\r\n          if (categoryValue) {\r\n            result = categoryValue;\r\n            break outer;\r\n          }\r\n          const otherValue = category !== \"other\" ? ownString(langCache, `${key}_other`) : undefined;\r\n          if (otherValue) {\r\n            result = otherValue;\r\n            break outer;\r\n          }\r\n        }\r\n\r\n        const value = ownString(langCache, key);\r\n        if (value) {\r\n          result = value;\r\n          break outer;\r\n        }\r\n      }\r\n    }\r\n\r\n    // If nothing found in any fallback, return the key itself\r\n    if (!result) {\r\n      return key;\r\n    }\r\n\r\n    // Handle interpolation: replace {name} with actual values.\r\n    //\r\n    // We use a literal split/join rather than `String.replace(RegExp, value)`\r\n    // on purpose. The RegExp approach had two real bugs:\r\n    //   1. The param KEY was spliced raw into a RegExp source, so a key\r\n    //      containing a metacharacter (e.g. \"a(b\") threw a SyntaxError and\r\n    //      crashed the render; a key like \"a.b\" silently failed to match.\r\n    //   2. The param VALUE was used as the replacement string, so values\r\n    //      containing `$&`, `$1`, `` $` ``, `$$` were reinterpreted as\r\n    //      replacement patterns and silently corrupted the output.\r\n    // split(literal).join(literal) treats both key and value as plain text,\r\n    // fixing both at once and supporting arbitrary param keys.\r\n    if (params) {\r\n      for (const [paramKey, paramValue] of Object.entries(params)) {\r\n        result = result.split(`{${paramKey}}`).join(String(paramValue));\r\n      }\r\n    }\r\n\r\n    return result;\r\n  }\r\n\r\n}\r\n\r\n/** Within a single language, prefer the requested register but fall back to default. */\r\nfunction registerFallback(register: Register): Register[] {\r\n  return register === DEFAULT_REGISTER ? [DEFAULT_REGISTER] : [register, DEFAULT_REGISTER];\r\n}\r\n","// FILE: packages/sdk/src/utils/fonts.ts\r\n//\r\n// Dynamic font loading for South Asian scripts.\r\n//\r\n// WHY THIS EXISTS:\r\n// Hindi, Bengali, Tamil, etc. all use different scripts that need\r\n// different fonts. If you just render Hindi text with a standard\r\n// font like Arial, the conjunct characters (like क्ष or त्र) will\r\n// look broken or ugly.\r\n//\r\n// Most i18n tools leave this problem to the developer. BhashaJS\r\n// handles it automatically — when you switch to Hindi, we load\r\n// the right font in the background.\r\n//\r\n// HOW IT WORKS:\r\n// We inject a <link> tag into the <head> that loads the Google Font.\r\n// We track which fonts are already loaded so we never load the same\r\n// font twice. The fonts load async, so there's a brief flash of\r\n// unstyled text on first load, but after that it's cached by the browser.\r\n\r\nimport { FONT_URLS, getLangInfo } from \"./languages\";\r\n\r\n// Track which fonts have already been loaded\r\nconst loadedFonts = new Set<string>();\r\n\r\n/**\r\n * Load the appropriate Google Font for a language.\r\n * Does nothing if the font is already loaded.\r\n *\r\n * @param lang - Language code (e.g. \"hi\", \"bn\", \"ur\")\r\n */\r\nexport function loadFontForLang(lang: string): void {\r\n  // No-op during server-side rendering — there's no document to inject into.\r\n  // The font <link> is added on the client after hydration instead.\r\n  if (typeof document === \"undefined\") return;\r\n\r\n  const langInfo = getLangInfo(lang);\r\n  const fontFamily = langInfo.font.split(\",\")[0].trim();\r\n\r\n  // Skip if already loaded or if it's a generic system font\r\n  if (loadedFonts.has(fontFamily) || !FONT_URLS[fontFamily]) {\r\n    return;\r\n  }\r\n\r\n  // Create a <link> element and inject it into <head>\r\n  const link = document.createElement(\"link\");\r\n  link.rel = \"stylesheet\";\r\n  link.href = FONT_URLS[fontFamily];\r\n  link.crossOrigin = \"anonymous\";\r\n  document.head.appendChild(link);\r\n\r\n  // Mark as loaded so we don't do it again\r\n  loadedFonts.add(fontFamily);\r\n}\r\n\r\n/**\r\n * Preload fonts for multiple languages at once.\r\n * Call this at app startup if you know which languages you'll need.\r\n */\r\nexport function preloadFonts(langs: string[]): void {\r\n  for (const lang of langs) {\r\n    loadFontForLang(lang);\r\n  }\r\n}\r\n","// FILE: packages/sdk/src/utils/formatting.ts\r\n//\r\n// South Asian number, currency, and date formatting.\r\n//\r\n// WHY THIS EXISTS:\r\n// South Asia uses a different number grouping system than the West:\r\n//   Western:     1,234,567     (groups of 3)\r\n//   South Asian: 12,34,567     (first group of 3, then groups of 2)\r\n//\r\n// This is called the lakh/crore system:\r\n//   1,00,000 = 1 lakh (100 thousand)\r\n//   1,00,00,000 = 1 crore (10 million)\r\n//\r\n// Additionally, many South Asian scripts have their own digit glyphs:\r\n//   Hindi: ०१२३४५६७८९  Bengali: ০১২৩৪৫৬৭৮৯  Tamil: ௦௧௨௩௪௫௬௭௮௯\r\n//\r\n// The Intl.NumberFormat API supports both lakh/crore grouping and\r\n// native digits via locale extensions (-u-nu-deva for Devanagari).\r\n// We wrap it with a clean API that auto-detects the right settings.\r\n\r\nimport { NumberFormatOptions, CurrencyFormatOptions, DateFormatOptions } from \"../types\";\r\nimport { getLangInfo, resolveRegion } from \"./languages\";\r\n\r\n// ─── South Asian (lakh/crore) grouping ──────────────────────────────\r\n//\r\n// Intl groups hi-IN, bn-BD, ta-IN, en-IN, ne-NP correctly as 12,34,567,\r\n// but some South Asian locales (notably ur-PK for PKR and si-LK for LKR)\r\n// fall back to Western 3-digit grouping. Rather than trust each locale's\r\n// CLDR grouping, we reassemble the integer with explicit 2,2,3 grouping for\r\n// every supported South Asian locale. This is idempotent for the locales\r\n// Intl already gets right (it produces the identical string), so the result\r\n// is consistent across the whole language set.\r\n\r\nconst SOUTH_ASIAN_LANGS = new Set([\r\n  \"en\", \"hi\", \"bn\", \"ur\", \"ta\", \"te\", \"mr\", \"ne\", \"pa\", \"pa-PK\",\r\n  \"gu\", \"kn\", \"ml\", \"si\",\r\n  \"hi-Latn\", \"ne-Latn\", \"ur-Latn\", \"bn-Latn\", \"pa-Latn\",\r\n]);\r\n\r\nfunction needsSouthAsianGrouping(lang: string): boolean {\r\n  if (SOUTH_ASIAN_LANGS.has(lang)) return true;\r\n  return SOUTH_ASIAN_LANGS.has(lang.split(\"-\")[0]);\r\n}\r\n\r\n/** Regroup a bare digit string into South Asian 2,2,3 grouping. Operates on\r\n *  whatever digit glyphs are passed in (Latin or native), so it composes with\r\n *  the `-u-nu-<system>` locale extension. */\r\nfunction groupSouthAsian(digits: string, sep: string): string {\r\n  if (digits.length <= 3) return digits;\r\n  const last3 = digits.slice(-3);\r\n  let rest = digits.slice(0, -3);\r\n  const groups: string[] = [];\r\n  while (rest.length > 2) {\r\n    groups.unshift(rest.slice(-2));\r\n    rest = rest.slice(0, -2);\r\n  }\r\n  if (rest.length) groups.unshift(rest);\r\n  return groups.join(sep) + sep + last3;\r\n}\r\n\r\n/** Rebuild an Intl.NumberFormat parts array with South Asian integer grouping,\r\n *  preserving sign, currency symbol, decimals, and the original digit glyphs. */\r\nfunction reassembleSouthAsianGrouping(parts: Intl.NumberFormatPart[]): string {\r\n  let sep = \",\";\r\n  let intDigits = \"\";\r\n  for (const p of parts) {\r\n    if (p.type === \"integer\") intDigits += p.value;\r\n    else if (p.type === \"group\") sep = p.value;\r\n  }\r\n  const grouped = groupSouthAsian(intDigits, sep);\r\n\r\n  let out = \"\";\r\n  let mergedInteger = false;\r\n  for (const p of parts) {\r\n    if (p.type === \"integer\") {\r\n      if (!mergedInteger) {\r\n        out += grouped;\r\n        mergedInteger = true;\r\n      }\r\n      // subsequent integer parts are already folded into `grouped`\r\n    } else if (p.type === \"group\") {\r\n      // grouping handled above\r\n    } else {\r\n      out += p.value;\r\n    }\r\n  }\r\n  return out;\r\n}\r\n\r\n/**\r\n * Format a number using South Asian conventions.\r\n *\r\n * Uses lakh/crore grouping automatically for South Asian locales.\r\n * Supports native digit rendering and compact notation.\r\n *\r\n * @param value   - The number to format\r\n * @param lang    - Language code (e.g. \"hi\", \"bn\")\r\n * @param region  - Optional region override (e.g. \"IN\", \"BD\")\r\n * @param options - Formatting options\r\n *\r\n * @example\r\n * formatNumber(1234567, \"hi\")                          // → \"12,34,567\"\r\n * formatNumber(1234567, \"hi\", undefined, { useNativeDigits: true })  // → \"१२,३४,५६७\"\r\n * formatNumber(1234567, \"en\")                          // → \"12,34,567\" (en-IN uses lakh/crore)\r\n * formatNumber(1500000, \"hi\", undefined, { compact: true })          // → \"15 लाख\"\r\n */\r\nexport function formatNumber(\r\n  value: number,\r\n  lang: string,\r\n  region?: string,\r\n  options?: NumberFormatOptions\r\n): string {\r\n  const langInfo = getLangInfo(lang);\r\n  const { intlLocale } = resolveRegion(lang, region);\r\n\r\n  // Build the locale string. Force Latin digits unless the caller explicitly\r\n  // opts in via useNativeDigits — otherwise some locales (bn-BD, ta-IN) silently\r\n  // emit native digits even when the developer passed nothing about digits.\r\n  let locale = intlLocale;\r\n  if (options?.useNativeDigits && langInfo.numberingSystem !== \"latn\") {\r\n    locale = `${intlLocale}-u-nu-${langInfo.numberingSystem}`;\r\n  } else {\r\n    locale = `${intlLocale}-u-nu-latn`;\r\n  }\r\n\r\n  const intlOptions: Intl.NumberFormatOptions = {};\r\n\r\n  if (options?.compact) {\r\n    intlOptions.notation = \"compact\";\r\n    intlOptions.compactDisplay = \"long\";\r\n  }\r\n\r\n  try {\r\n    const nf = new Intl.NumberFormat(locale, intlOptions);\r\n    // Compact notation has no thousands grouping, so skip the reassembly.\r\n    if (!options?.compact && needsSouthAsianGrouping(lang)) {\r\n      return reassembleSouthAsianGrouping(nf.formatToParts(value));\r\n    }\r\n    return nf.format(value);\r\n  } catch {\r\n    // Fallback to basic formatting if Intl doesn't support the locale\r\n    return value.toLocaleString();\r\n  }\r\n}\r\n\r\n/**\r\n * Format a currency value with region-aware symbol and lakh/crore grouping.\r\n *\r\n * Auto-detects the correct currency from the language and region:\r\n * - Hindi (IN) → ₹   Bengali (BD) → ৳   Urdu (PK) → Rs\r\n * - Bengali (IN) → ₹  (with region override)\r\n *\r\n * @param value   - The amount to format\r\n * @param lang    - Language code (e.g. \"hi\", \"bn\")\r\n * @param region  - Optional region override\r\n * @param options - Formatting options\r\n *\r\n * @example\r\n * formatCurrency(1234567, \"hi\")                           // → \"₹12,34,567.00\"\r\n * formatCurrency(1234567, \"bn\")                           // → \"৳12,34,567.00\" (Bangladesh default)\r\n * formatCurrency(1234567, \"bn\", \"IN\")                     // → \"₹12,34,567.00\" (India override)\r\n * formatCurrency(1234567, \"hi\", undefined, { display: \"code\" })  // → \"INR 12,34,567.00\"\r\n */\r\nexport function formatCurrency(\r\n  value: number,\r\n  lang: string,\r\n  region?: string,\r\n  options?: CurrencyFormatOptions\r\n): string {\r\n  const langInfo = getLangInfo(lang);\r\n  const resolved = resolveRegion(lang, region);\r\n\r\n  // Use explicit currency or auto-detect from language + region\r\n  const currencyCode = options?.currency || resolved.currency;\r\n\r\n  // Build locale with optional native digits (default to latn for consistency).\r\n  let locale = resolved.intlLocale;\r\n  if (options?.useNativeDigits && langInfo.numberingSystem !== \"latn\") {\r\n    locale = `${resolved.intlLocale}-u-nu-${langInfo.numberingSystem}`;\r\n  } else {\r\n    locale = `${resolved.intlLocale}-u-nu-latn`;\r\n  }\r\n\r\n  const intlOptions: Intl.NumberFormatOptions = {\r\n    style: \"currency\",\r\n    currency: currencyCode,\r\n    currencyDisplay: options?.display || \"symbol\",\r\n  };\r\n\r\n  try {\r\n    const nf = new Intl.NumberFormat(locale, intlOptions);\r\n    if (needsSouthAsianGrouping(lang)) {\r\n      return reassembleSouthAsianGrouping(nf.formatToParts(value));\r\n    }\r\n    return nf.format(value);\r\n  } catch {\r\n    // Fallback: basic format with currency code\r\n    return `${currencyCode} ${value.toLocaleString()}`;\r\n  }\r\n}\r\n\r\n/**\r\n * Format a date using South Asian conventions.\r\n *\r\n * Defaults to DD/MM/YYYY (not the American MM/DD/YYYY).\r\n * Supports four presets and native digit rendering.\r\n *\r\n * @param date    - Date to format (Date object, ISO string, or timestamp)\r\n * @param lang    - Language code\r\n * @param region  - Optional region override\r\n * @param options - Formatting options\r\n *\r\n * @example\r\n * formatDate(new Date(\"2026-03-19\"), \"hi\")                        // → \"19 मार्च 2026\"\r\n * formatDate(new Date(\"2026-03-19\"), \"hi\", undefined, { preset: \"short\" })  // → \"19/3/26\"\r\n * formatDate(new Date(\"2026-03-19\"), \"hi\", undefined, { preset: \"full\" })   // → \"गुरुवार, 19 मार्च 2026\"\r\n * formatDate(new Date(\"2026-03-19\"), \"hi\", undefined, { useNativeDigits: true }) // → \"१९ मार्च २०२६\"\r\n */\r\nexport function formatDate(\r\n  date: Date | string | number,\r\n  lang: string,\r\n  region?: string,\r\n  options?: DateFormatOptions\r\n): string {\r\n  const langInfo = getLangInfo(lang);\r\n  const { intlLocale } = resolveRegion(lang, region);\r\n\r\n  // Normalize the date input\r\n  const dateObj = date instanceof Date ? date : new Date(date);\r\n\r\n  // Guard against invalid input. Without this, Intl renders the literal\r\n  // English string \"Invalid Date\" into every locale's UI — a jarring,\r\n  // untranslated failure. Return an empty string so the caller decides.\r\n  if (isNaN(dateObj.getTime())) {\r\n    return \"\";\r\n  }\r\n\r\n  // Build locale with optional native digits (default to latn for consistency).\r\n  let locale = intlLocale;\r\n  if (options?.useNativeDigits && langInfo.numberingSystem !== \"latn\") {\r\n    locale = `${intlLocale}-u-nu-${langInfo.numberingSystem}`;\r\n  } else {\r\n    locale = `${intlLocale}-u-nu-latn`;\r\n  }\r\n\r\n  // Map presets to Intl.DateTimeFormat options\r\n  const preset = options?.preset || \"medium\";\r\n  const intlOptions = DATE_PRESETS[preset];\r\n\r\n  try {\r\n    return new Intl.DateTimeFormat(locale, intlOptions).format(dateObj);\r\n  } catch {\r\n    // Fallback to ISO date\r\n    return dateObj.toLocaleDateString();\r\n  }\r\n}\r\n\r\n/**\r\n * Date format presets mapped to Intl.DateTimeFormat options.\r\n *\r\n * short:  19/03/26\r\n * medium: 19 Mar 2026\r\n * long:   19 March 2026\r\n * full:   Thursday, 19 March 2026\r\n */\r\nconst DATE_PRESETS: Record<string, Intl.DateTimeFormatOptions> = {\r\n  short: {\r\n    day: \"numeric\",\r\n    month: \"numeric\",\r\n    year: \"2-digit\",\r\n  },\r\n  medium: {\r\n    day: \"numeric\",\r\n    month: \"short\",\r\n    year: \"numeric\",\r\n  },\r\n  long: {\r\n    day: \"numeric\",\r\n    month: \"long\",\r\n    year: \"numeric\",\r\n  },\r\n  full: {\r\n    weekday: \"long\",\r\n    day: \"numeric\",\r\n    month: \"long\",\r\n    year: \"numeric\",\r\n  },\r\n};\r\n","// FILE: packages/sdk/src/components/LanguageSwitcher.tsx\n//\n// A ready-to-use language switcher component.\n//\n// USAGE:\n//   <LanguageSwitcher />                          — simple dropdown\n//   <LanguageSwitcher style=\"floating\" />          — floating button\n//   <LanguageSwitcher position=\"top-left\" style=\"floating\" /> — floating, top-left\n//\n// TWO STYLES:\n//\n// 1. \"dropdown\" (default) — A simple <select> dropdown.\n//    Developers put this in their navbar or header.\n//    It's unstyled by default so it inherits the app's CSS.\n//\n// 2. \"floating\" — A fixed-position button on the screen.\n//    Great for quick integration — add one line and you get\n//    a language switcher without touching your layout.\n//\n// WHY WE SHOW NATIVE SCRIPT NAMES:\n// We show \"हिन्दी\" instead of \"Hindi\" because:\n// - A Hindi speaker can find their language even if the UI is in English\n// - It's the industry standard (Google, Facebook, etc. all do this)\n// - It looks more professional and inclusive\n\nimport { useState, useRef, useEffect } from \"react\";\nimport { LanguageSwitcherProps } from \"../types\";\nimport { useTranslation } from \"../hooks/useTranslation\";\nimport { getLangInfo } from \"../utils/languages\";\n\nexport function LanguageSwitcher({\n  position = \"top-right\",\n  style = \"dropdown\",\n  className = \"\",\n}: LanguageSwitcherProps) {\n  const { currentLang, setLang, supportedLangs, isLoading } = useTranslation();\n\n  // For the floating style, we need to track open/close state\n  const [isOpen, setIsOpen] = useState(false);\n  const menuRef = useRef<HTMLDivElement>(null);\n\n  // Close the floating menu when clicking outside\n  useEffect(() => {\n    function handleClickOutside(e: MouseEvent) {\n      if (menuRef.current && !menuRef.current.contains(e.target as Node)) {\n        setIsOpen(false);\n      }\n    }\n    if (isOpen) {\n      document.addEventListener(\"mousedown\", handleClickOutside);\n      return () => document.removeEventListener(\"mousedown\", handleClickOutside);\n    }\n  }, [isOpen]);\n\n  // ─── Dropdown Style ──────────────────────────────────────────\n  if (style === \"dropdown\") {\n    return (\n      <select\n        value={currentLang}\n        onChange={(e) => setLang(e.target.value)}\n        disabled={isLoading}\n        className={`bhasha-switcher-dropdown ${className}`}\n        aria-label=\"Select language\"\n        style={{\n          cursor: \"pointer\",\n          padding: \"6px 12px\",\n          borderRadius: \"6px\",\n          border: \"1px solid #ccc\",\n          background: \"inherit\",\n          color: \"inherit\",\n          fontSize: \"14px\",\n        }}\n      >\n        {supportedLangs.map((lang) => {\n          const info = getLangInfo(lang);\n          return (\n            <option key={lang} value={lang}>\n              {info.name} ({info.englishName})\n            </option>\n          );\n        })}\n      </select>\n    );\n  }\n\n  // ─── Floating Style ──────────────────────────────────────────\n\n  // Position mapping for fixed positioning\n  const positionStyles: Record<string, React.CSSProperties> = {\n    \"top-right\": { top: \"16px\", right: \"16px\" },\n    \"top-left\": { top: \"16px\", left: \"16px\" },\n    \"bottom-right\": { bottom: \"16px\", right: \"16px\" },\n    \"bottom-left\": { bottom: \"16px\", left: \"16px\" },\n  };\n\n  const currentInfo = getLangInfo(currentLang);\n\n  return (\n    <div\n      ref={menuRef}\n      className={`bhasha-switcher-floating ${className}`}\n      style={{\n        position: \"fixed\",\n        ...positionStyles[position],\n        zIndex: 9999,\n        fontFamily: \"system-ui, -apple-system, sans-serif\",\n      }}\n    >\n      {/* The toggle button — shows current language */}\n      <button\n        onClick={() => setIsOpen(!isOpen)}\n        disabled={isLoading}\n        aria-label=\"Switch language\"\n        aria-expanded={isOpen}\n        style={{\n          display: \"flex\",\n          alignItems: \"center\",\n          gap: \"6px\",\n          padding: \"8px 14px\",\n          borderRadius: \"24px\",\n          border: \"1px solid rgba(255,255,255,0.15)\",\n          background: \"rgba(0,0,0,0.8)\",\n          color: \"#fff\",\n          fontSize: \"14px\",\n          fontWeight: 500,\n          cursor: \"pointer\",\n          backdropFilter: \"blur(8px)\",\n          boxShadow: \"0 4px 12px rgba(0,0,0,0.3)\",\n          transition: \"all 0.15s ease\",\n        }}\n      >\n        {/* Globe icon */}\n        <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\n          strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n          <circle cx=\"12\" cy=\"12\" r=\"10\" />\n          <path d=\"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\" />\n          <path d=\"M2 12h20\" />\n        </svg>\n        {currentInfo.name}\n      </button>\n\n      {/* The dropdown menu — shows all available languages */}\n      {isOpen && (\n        <div\n          style={{\n            position: \"absolute\",\n            [position.includes(\"bottom\") ? \"bottom\" : \"top\"]: \"100%\",\n            [position.includes(\"left\") ? \"left\" : \"right\"]: \"0\",\n            marginTop: position.includes(\"top\") ? \"8px\" : undefined,\n            marginBottom: position.includes(\"bottom\") ? \"8px\" : undefined,\n            background: \"rgba(0,0,0,0.9)\",\n            border: \"1px solid rgba(255,255,255,0.1)\",\n            borderRadius: \"12px\",\n            padding: \"4px\",\n            minWidth: \"180px\",\n            backdropFilter: \"blur(12px)\",\n            boxShadow: \"0 8px 24px rgba(0,0,0,0.4)\",\n          }}\n        >\n          {supportedLangs.map((lang) => {\n            const info = getLangInfo(lang);\n            const isActive = lang === currentLang;\n\n            return (\n              <button\n                key={lang}\n                onClick={() => {\n                  setLang(lang);\n                  setIsOpen(false);\n                }}\n                style={{\n                  display: \"flex\",\n                  alignItems: \"center\",\n                  justifyContent: \"space-between\",\n                  width: \"100%\",\n                  padding: \"10px 14px\",\n                  border: \"none\",\n                  borderRadius: \"8px\",\n                  background: isActive ? \"rgba(224, 122, 58, 0.2)\" : \"transparent\",\n                  color: isActive ? \"#e07a3a\" : \"#fff\",\n                  fontSize: \"14px\",\n                  cursor: \"pointer\",\n                  transition: \"background 0.1s\",\n                  textAlign: \"left\",\n                  fontFamily: \"inherit\",\n                }}\n                onMouseEnter={(e) => {\n                  if (!isActive) {\n                    (e.target as HTMLElement).style.background = \"rgba(255,255,255,0.08)\";\n                  }\n                }}\n                onMouseLeave={(e) => {\n                  if (!isActive) {\n                    (e.target as HTMLElement).style.background = \"transparent\";\n                  }\n                }}\n              >\n                <span style={{ fontWeight: 500 }}>{info.name}</span>\n                <span style={{ fontSize: \"12px\", opacity: 0.5 }}>{info.englishName}</span>\n              </button>\n            );\n          })}\n        </div>\n      )}\n    </div>\n  );\n}\n","// FILE: packages/sdk/src/hooks/useTranslation.ts\r\n//\r\n// THE MAIN HOOK — Used in every component that needs translated text:\r\n//\r\n//   function HomePage() {\r\n//     const { t } = useTranslation();\r\n//     return <h1>{t('hero.title')}</h1>;\r\n//   }\r\n//\r\n// What it returns:\r\n//   - t(key, params?)  → the translated string\r\n//   - currentLang      → the active language code (\"hi\", \"bn\", etc.)\r\n//   - setLang(code)    → switch to a different language\r\n//   - supportedLangs   → list of all available languages\r\n//   - isLoading        → true while translations are being fetched\r\n//   - error            → error message if something went wrong\r\n//\r\n// WHY THIS IS A HOOK:\r\n// React hooks let you \"subscribe\" to state changes. When the language\r\n// changes (via setLang), React knows to re-render every component\r\n// that calls useTranslation(). This is how the entire UI switches\r\n// language instantly — every component re-reads its t() values.\r\n//\r\n// NAMING CONVENTION:\r\n// We named this useTranslation() to match the industry standard.\r\n// react-i18next uses the same name, so developers migrating to\r\n// BhashaJS will feel right at home.\r\n\r\nimport { useContext } from \"react\";\r\nimport { I18nContext } from \"../core/context\";\r\nimport { I18nContextValue } from \"../types\";\r\n\r\nexport function useTranslation(): I18nContextValue {\r\n  const context = useContext(I18nContext);\r\n\r\n  // If someone forgets to wrap their app in <I18nProvider>,\r\n  // give them a clear error instead of a cryptic \"cannot read\r\n  // property 't' of null\"\r\n  if (!context) {\r\n    throw new Error(\r\n      \"[BhashaJS] useTranslation() was called outside of <I18nProvider>.\\n\" +\r\n      \"Make sure your app is wrapped:\\n\\n\" +\r\n      \"  <I18nProvider projectKey=\\\"bjs_...\\\">\\n\" +\r\n      \"    <App />\\n\" +\r\n      \"  </I18nProvider>\"\r\n    );\r\n  }\r\n\r\n  return context;\r\n}\r\n","// FILE: packages/sdk/src/components/Trans.tsx\r\n//\r\n// An alternative way to translate text — as a React component\r\n// instead of a function call.\r\n//\r\n// WHEN TO USE t() vs <Trans>:\r\n//\r\n// Use t() for simple text:\r\n//   <h1>{t('hero.title')}</h1>\r\n//   <p>{t('greeting', { name: 'Rohan' })}</p>\r\n//\r\n// Use <Trans> when you want it to feel more declarative:\r\n//   <Trans id=\"hero.title\" />\r\n//   <Trans id=\"greeting\" params={{ name: 'Rohan' }} />\r\n//\r\n// <Trans> also supports a `as` prop to render as a specific element:\r\n//   <Trans id=\"hero.title\" as=\"h1\" />\r\n//   → renders as <h1>स्वागत</h1>\r\n//\r\n// Both use the exact same translation logic under the hood.\r\n// It's purely a developer preference thing.\r\n\r\nimport { createElement, ElementType } from \"react\";\r\nimport { useTranslation } from \"../hooks/useTranslation\";\r\nimport type { BhashaKey } from \"../types\";\r\n\r\ninterface TransProps {\r\n  /** The translation key (type-safe once `bhasha pull` has run) */\r\n  id: BhashaKey;\r\n  /** Interpolation parameters */\r\n  params?: Record<string, string | number>;\r\n  /** Render as a specific HTML element (default: \"span\") */\r\n  as?: ElementType;\r\n  /** Additional props passed to the rendered element */\r\n  [key: string]: any;\r\n}\r\n\r\nexport function Trans({ id, params, as: Component = \"span\", ...rest }: TransProps) {\r\n  const { t } = useTranslation();\r\n\r\n  return createElement(Component, rest, t(id, params));\r\n}\r\n","// FILE: packages/sdk/src/hooks/useLangInfo.ts\n//\n// Utility hook that gives developers info about the current language.\n//\n// EXAMPLE USE CASE:\n// A developer wants to adjust padding based on text direction:\n//\n//   function Sidebar() {\n//     const { dir, font } = useLangInfo();\n//     return (\n//       <aside style={{\n//         [dir === 'rtl' ? 'paddingRight' : 'paddingLeft']: '2rem',\n//         fontFamily: font,\n//       }}>\n//         ...\n//       </aside>\n//     );\n//   }\n//\n// Most developers won't need this — the SDK handles direction\n// automatically. But it's there for fine-grained control.\n\nimport { useMemo } from \"react\";\nimport { useTranslation } from \"./useTranslation\";\nimport { getLangInfo } from \"../utils/languages\";\nimport { LangInfo } from \"../types\";\n\nexport function useLangInfo(): LangInfo {\n  const { currentLang } = useTranslation();\n\n  // useMemo prevents recreating the object on every render\n  // It only recalculates when currentLang changes\n  return useMemo(() => getLangInfo(currentLang), [currentLang]);\n}\n"],"mappings":"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","names":["DEFAULT_REGISTER","formatNumber","formatCurrency","formatDate","useState","useRef","useEffect","jsx","useState","useRef","useEffect"]}