/** * @file index.ts * @description i18next bootstrap for the dashboard client. Registers bundled JSON * locale files for English (`en`) and Vietnamese (`vi`), wires browser language detection, and exports the configured * singleton consumed by `react-i18next`. * * ## Namespaces * Translations are split by feature area (`dashboard`, `sessions`, `settings`, * etc.) so pages import only the keys they need via `useTranslation("ns")`. * `common` is the default namespace for shared labels and buttons. * * ## Detection order * 1. `localStorage` key `i18nextLng` (user override from Settings) * 2. `navigator.language` fallback * * Unknown regional variants (e.g. `en-US`) map to supported base languages via * `nonExplicitSupportedLngs`. * * @author Nguyễn Ngọc Trí Vĩ */ /* ============================================================================= * MODULE_GUIDE — extended in-file reference (comments only; safe to read, never executed) * ============================================================================= * **Purpose:** Dashboard module consumed by the React client, MCP tools, or desktop shell depending on deployment mode. * * ## Design constraints * - Local-first: no telemetry leaves the machine unless the user configures webhooks. * - Fail-safe hooks path on the server must never block Claude Code; UI mirrors that * philosophy by degrading gracefully (empty states, stale badges, reconnect loops). * - Destructive flows stay behind explicit confirmation modals and server-side gates. * - Internationalization: user-visible strings belong in i18n JSON, not literals here. * * ## Remote data & SSH * Remote Data Sources let operators aggregate multiple machines. SSH entries describe * how to reach a peer dashboard; the global data scope (`dataScope.ts`) narrows every * scoped GET via `?sources=`. Health checks and import history surface in Settings. * * ## Internal dependencies * - `./locales/en/common.json` * - `./locales/vi/common.json` * - `./locales/en/nav.json` * - `./locales/vi/nav.json` * - `./locales/en/dashboard.json` * - `./locales/vi/dashboard.json` * - `./locales/en/sessions.json` * - `./locales/vi/sessions.json` * * ## Testing pointers * - Prefer colocated `__tests__` with Vitest + Testing Library for UI. * - Server contract changes require `npm run test:server` and OpenAPI sync. * - MCP edits: `npm run mcp:typecheck` and `npm run mcp:build`. * * ## Related docs * - `ARCHITECTURE.md` — hooks → API → SQLite → WebSocket → UI pipeline. * - `docs/API.md` — REST reference. * - `.claude/skills/file-headers/` — mandatory `@author` header policy. * ============================================================================= */ import i18n from "i18next"; import { initReactI18next } from "react-i18next"; import LanguageDetector from "i18next-browser-languagedetector"; import common_en from "./locales/en/common.json"; import common_vi from "./locales/vi/common.json"; import nav_en from "./locales/en/nav.json"; import nav_vi from "./locales/vi/nav.json"; import dashboard_en from "./locales/en/dashboard.json"; import dashboard_vi from "./locales/vi/dashboard.json"; import sessions_en from "./locales/en/sessions.json"; import sessions_vi from "./locales/vi/sessions.json"; import activity_en from "./locales/en/activity.json"; import activity_vi from "./locales/vi/activity.json"; import analytics_en from "./locales/en/analytics.json"; import analytics_vi from "./locales/vi/analytics.json"; import workflows_en from "./locales/en/workflows.json"; import workflows_vi from "./locales/vi/workflows.json"; import settings_en from "./locales/en/settings.json"; import settings_vi from "./locales/vi/settings.json"; import kanban_en from "./locales/en/kanban.json"; import kanban_vi from "./locales/vi/kanban.json"; import errors_en from "./locales/en/errors.json"; import errors_vi from "./locales/vi/errors.json"; import updates_en from "./locales/en/updates.json"; import updates_vi from "./locales/vi/updates.json"; import ccConfig_en from "./locales/en/ccConfig.json"; import ccConfig_vi from "./locales/vi/ccConfig.json"; import run_en from "./locales/en/run.json"; import run_vi from "./locales/vi/run.json"; import alerts_en from "./locales/en/alerts.json"; import alerts_vi from "./locales/vi/alerts.json"; import splash_en from "./locales/en/splash.json"; import splash_vi from "./locales/vi/splash.json"; import lanes_en from "./locales/en/lanes.json"; import lanes_vi from "./locales/vi/lanes.json"; i18n .use(LanguageDetector) .use(initReactI18next) .init({ resources: { en: { common: common_en, nav: nav_en, dashboard: dashboard_en, sessions: sessions_en, activity: activity_en, analytics: analytics_en, workflows: workflows_en, settings: settings_en, kanban: kanban_en, errors: errors_en, updates: updates_en, ccConfig: ccConfig_en, run: run_en, alerts: alerts_en, splash: splash_en, lanes: lanes_en, }, vi: { common: common_vi, nav: nav_vi, dashboard: dashboard_vi, sessions: sessions_vi, activity: activity_vi, analytics: analytics_vi, workflows: workflows_vi, settings: settings_vi, kanban: kanban_vi, errors: errors_vi, updates: updates_vi, ccConfig: ccConfig_vi, run: run_vi, alerts: alerts_vi, splash: splash_vi, lanes: lanes_vi, }, }, supportedLngs: ["en", "vi"], nonExplicitSupportedLngs: true, fallbackLng: "en", ns: [ "common", "nav", "dashboard", "sessions", "activity", "analytics", "workflows", "settings", "kanban", "errors", "updates", "ccConfig", "run", "alerts", "splash", "lanes", ], defaultNS: "common", interpolation: { escapeValue: false }, detection: { order: ["localStorage", "navigator"], caches: ["localStorage"], lookupLocalStorage: "i18nextLng", }, }); /** Configured i18next instance — import side effects run {@link init}. */ export default i18n;