Initialize the browser i18next instance with lazy per-locale catalog loading, localStorage->navigator->htmlTag detection, script-aware zh fallback, and the shared @fusion/i18n config. Catalogs are synced from @fusion/i18n into a gitignored app/locales/ (predev/prebuild) and imported app-relative so Vite emits one chunk per locale/namespace (verified: 15 chunks, none inlined into the main bundle). First paint is gated on i18nReady to avoid raw-key flashes; <I18nextProvider> wraps the App provider stack; vendor-i18n manualChunk added. A build-assertion script (verify:locale-chunks) guards the KTD3a splitting invariant. Fallback/namespace behavior is covered by @fusion/i18n config tests; the live instance is verified via the build assertion rather than a unit test (the dynamic catalog backend is impractical to exercise in vitest). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
40 lines
1.5 KiB
TypeScript
40 lines
1.5 KiB
TypeScript
import { StrictMode } from "react";
|
|
import { createRoot } from "react-dom/client";
|
|
import { RootErrorBoundary } from "./components/ErrorBoundary";
|
|
import { DesktopLaunchGate } from "./components/DesktopLaunchGate";
|
|
import { App } from "./App";
|
|
import { installAuthFetch } from "./auth";
|
|
import { installVersionCheck } from "./versionCheck";
|
|
import { installSwUpdate } from "./swUpdate";
|
|
import { bootstrapShellHostContext } from "./shell-host";
|
|
import { registerBundledPluginViews } from "./plugins/registerBundledPluginViews";
|
|
import { i18nReady } from "./i18n";
|
|
import "./styles.css";
|
|
|
|
// Install the bearer-token fetch wrapper before React mounts so every API
|
|
// call (including ones fired synchronously during the first render) picks up
|
|
// the token that was either captured from `?token=` in the launch URL or
|
|
// stored from a previous session.
|
|
installAuthFetch();
|
|
installVersionCheck();
|
|
bootstrapShellHostContext();
|
|
registerBundledPluginViews();
|
|
|
|
// Gate first paint on the active locale's catalogs so the UI never flashes raw
|
|
// translation keys. The catalog is a small local chunk, so this is a brief
|
|
// wait; `.finally` ensures we still render if i18n init fails (strings then
|
|
// fall back to keys/en rather than blocking the app).
|
|
void i18nReady.finally(() => {
|
|
createRoot(document.getElementById("root")!).render(
|
|
<StrictMode>
|
|
<RootErrorBoundary>
|
|
<DesktopLaunchGate>
|
|
<App />
|
|
</DesktopLaunchGate>
|
|
</RootErrorBoundary>
|
|
</StrictMode>,
|
|
);
|
|
|
|
installSwUpdate();
|
|
});
|