From 8e6dad86f369a9789363b8647539893f9f3000a0 Mon Sep 17 00:00:00 2001 From: Aakriti Arya Date: Wed, 8 Jul 2026 01:24:17 +0530 Subject: [PATCH] feat: initialize i18next for dashboard localization --- frontend/package-lock.json | 82 ++++++++++++++++++- frontend/package.json | 2 + .../src/renderer/components/SessionsBoard.tsx | 28 ++++--- frontend/src/renderer/i18n/index.ts | 50 +++++++++++ frontend/src/renderer/i18n/locales/en.json | 31 +++++++ frontend/src/renderer/i18n/locales/zh-CN.json | 31 +++++++ frontend/src/renderer/main.tsx | 3 + 7 files changed, 210 insertions(+), 17 deletions(-) create mode 100644 frontend/src/renderer/i18n/index.ts create mode 100644 frontend/src/renderer/i18n/locales/en.json create mode 100644 frontend/src/renderer/i18n/locales/zh-CN.json diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 67ed1ebd7c..0291b01f8f 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "agent-orchestrator", - "version": "0.0.0", + "version": "0.10.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "agent-orchestrator", - "version": "0.0.0", + "version": "0.10.0", "license": "MIT", "dependencies": { "@radix-ui/react-dialog": "^1.1.16", @@ -25,12 +25,14 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "electron-updater": "^6.8.9", + "i18next": "^26.3.4", "lucide-react": "^1.17.0", "openapi-fetch": "^0.17.0", "posthog-js": "^1.390.2", "radix-ui": "^1.5.0", "react": "^19.2.7", "react-dom": "^19.2.7", + "react-i18next": "^17.0.8", "react-resizable-panels": "^4.11.2", "tailwind-merge": "^3.6.0", "zustand": "^5.0.14" @@ -338,7 +340,6 @@ "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -10629,6 +10630,15 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, + "node_modules/html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "license": "MIT", + "dependencies": { + "void-elements": "3.1.0" + } + }, "node_modules/http-cache-semantics": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", @@ -10688,6 +10698,34 @@ "ms": "^2.0.0" } }, + "node_modules/i18next": { + "version": "26.3.4", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-26.3.4.tgz", + "integrity": "sha512-pa7m0d7pBDqGHZxljT+WPFeyFgQ7P7SciPPo1tTqYuO0z4sqADYhwnBESmmGp/wEof1inwdls/k8ZgTg8rxFHA==", + "funding": [ + { + "type": "individual", + "url": "https://www.locize.com/i18next" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + }, + { + "type": "individual", + "url": "https://www.locize.com" + } + ], + "license": "MIT", + "peerDependencies": { + "typescript": "^5 || ^6" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -13538,6 +13576,33 @@ "react": "^19.2.7" } }, + "node_modules/react-i18next": { + "version": "17.0.8", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-17.0.8.tgz", + "integrity": "sha512-0ooKbGLU8JXhe1zwpQUWIeXSgLPOfwJmgheWRIUpcoA0CpyabpGhayjdG+/eA5esC1AQ8h2jWpXjJfzQzeDOCw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2", + "html-parse-stringify": "^3.0.1", + "use-sync-external-store": "^1.6.0" + }, + "peerDependencies": { + "i18next": ">= 26.2.0", + "react": ">= 16.8.0", + "typescript": "^5 || ^6" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", @@ -14953,7 +15018,7 @@ "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -15402,6 +15467,15 @@ } } }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/w3c-xmlserializer": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index a70a05a573..3e39fd1e10 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -70,12 +70,14 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "electron-updater": "^6.8.9", + "i18next": "^26.3.4", "lucide-react": "^1.17.0", "openapi-fetch": "^0.17.0", "posthog-js": "^1.390.2", "radix-ui": "^1.5.0", "react": "^19.2.7", "react-dom": "^19.2.7", + "react-i18next": "^17.0.8", "react-resizable-panels": "^4.11.2", "tailwind-merge": "^3.6.0", "zustand": "^5.0.14" diff --git a/frontend/src/renderer/components/SessionsBoard.tsx b/frontend/src/renderer/components/SessionsBoard.tsx index 0f0d20b14b..64a101edae 100644 --- a/frontend/src/renderer/components/SessionsBoard.tsx +++ b/frontend/src/renderer/components/SessionsBoard.tsx @@ -22,6 +22,7 @@ import { restartProjectOrchestrator } from "../lib/restart-orchestrator"; import { prBrowserUrl, sessionPRDisplaySummaries } from "../lib/pr-display"; import { cn } from "../lib/utils"; import { useUiStore } from "../stores/ui-store"; +import { useTranslation } from "react-i18next"; type SessionsBoardProps = { /** When set, the board shows only this project's sessions. */ @@ -75,6 +76,7 @@ const COLUMNS: Column[] = [ ]; export function SessionsBoard({ projectId }: SessionsBoardProps) { + const { t } = useTranslation(); const navigate = useNavigate(); const queryClient = useQueryClient(); const workspaceQuery = useWorkspaceQuery(); @@ -160,7 +162,7 @@ export function SessionsBoard({ projectId }: SessionsBoardProps) { // Never fail silently: the daemon's message (e.g. a worktree/branch // conflict) is the only actionable signal the user gets. console.error("Failed to spawn orchestrator:", err); - setSpawnError(err instanceof Error ? err.message : "Could not spawn orchestrator"); + setSpawnError(err instanceof Error ? err.message : t("board.errors.spawnFailed")); } finally { setIsSpawning(false); } @@ -194,17 +196,17 @@ export function SessionsBoard({ projectId }: SessionsBoardProps) { )} ) : undefined; @@ -229,8 +231,8 @@ export function SessionsBoard({ projectId }: SessionsBoardProps) { (review feedback on #2432). */} {!showWelcome && ( )} @@ -248,13 +250,13 @@ export function SessionsBoard({ projectId }: SessionsBoardProps) { type="button" >