import { ReactNode } from 'react'; /** * Assistant copy, namespaced by product. * * The assistant UI is shared but its translations are not: every product seeds * its own keys under its own namespace. So a shared component cannot hardcode a * key prefix — it must ask for a RELATIVE key and let the product decide the * namespace. * * ★★ HealthyBowl's 96 `healthybowl.assistant.*` keys carry 571 published * translations across en/zh/hi/es/ar/ta as of 2026-09-05. Before that date the * KEYS existed but every one was `status: DEPRECATED`, and the i18n service's * `exportTranslations` — which is what the app actually fetches — silently omits * deprecated keys. So the assistant rendered English in every locale while the * keys looked present, translations reported `successCount` on write, and the * rows were genuinely `PUBLISHED`. Publishing a translation is NOT enough; the * key must also be ACTIVE. * * ★ If a product's copy is unexpectedly English, check * `translationKeyByKey(productId, key) { status }` BEFORE assuming the keys were * never seeded. The export alone cannot distinguish "absent" from "deprecated", * and that ambiguity produced two wrong diagnoses here. * * ★★ The shape below is chosen to be byte-compatible with what HealthyBowl * already ships. `assistantTranslationKey('healthybowl', 'header.title')` is * exactly `'healthybowl.assistant.header.title'`, which is the key already * seeded and already translated. Any other shape would silently drop every * non-English user back to the English fallback while every test still passed — * the migration would look clean and quietly un-translate the product. * * Products other than HealthyBowl simply have no keys yet, so they get the * English fallback until they seed theirs. That is a known, visible gap rather * than a regression. */ /** * How a relative key becomes a full translation key. * * Pure and exported precisely so the compatibility claim above is testable * without rendering anything. */ export declare function assistantTranslationKey(namespace: string, key: string): string; export interface AssistantI18nProviderProps { namespace: string; children: ReactNode; } /** * Supplies the product namespace to every assistant component beneath it. * * Mount it once, as high as the assistant goes — the same product id the * transport already needs for `AI_ASSISTANT_PRODUCT`, so there is one answer to * "which product is this?" rather than two that can disagree. */ export declare function AssistantI18nProvider({ namespace, children, }: AssistantI18nProviderProps): import("react/jsx-runtime").JSX.Element; /** The namespace in force, or null when no provider is mounted. */ export declare function useAssistantI18nNamespace(): string | null; export type AssistantTr = (key: string, fallback: string, params?: Record) => string; /** * Translate a RELATIVE assistant key, e.g. `tr('header.title', 'Assistant')`. * * Fallback semantics match the products' existing `useTr`: the I18n provider * returns the key itself when it has no translation, and the caller's English * string is used instead so a raw key never reaches the UI. * * ★ With no provider mounted this returns the English fallback rather than * throwing. A missing provider is a configuration mistake, but a thrown error * inside render is a white screen, and English copy is strictly better than * that. It complains once to the console so the mistake is still findable — the * failure this guards against is the assistant silently rendering English in * every locale, which is exactly what happened to the fe-libs shell. */ export declare function useAssistantTr(): AssistantTr; //# sourceMappingURL=i18n.d.ts.map