- Select a project from the sidebar to start coding with Claude. Each project contains your chat sessions and file history.
+ {t('mainContent.selectProjectDescription')}
- No MCP servers configured
+ {t('mcpServers.empty')}
)}
@@ -210,16 +215,17 @@ function CursorMcpServers({ servers, onAdd, onEdit, onDelete }) {
// Codex MCP Servers
function CodexMcpServers({ servers, onAdd, onEdit, onDelete }) {
+ const { t } = useTranslation('settings');
return (
- No MCP servers configured
+ {t('mcpServers.empty')}
)}
{/* Help Section */}
- Permission Mode
+ {t('permissions.codex.permissionMode')}
- Controls how Codex handles file modifications and command execution
+ {t('permissions.codex.description')}
{/* Default Mode */}
@@ -513,10 +517,9 @@ function CodexPermissions({ permissionMode, setPermissionMode }) {
className="mt-1 w-4 h-4 text-green-600"
/>
-
Default
+
{t('permissions.codex.modes.default.title')}
- Only trusted commands (ls, cat, grep, git status, etc.) run automatically.
- Other commands are skipped. Can write to workspace.
+ {t('permissions.codex.modes.default.description')}
@@ -540,10 +543,9 @@ function CodexPermissions({ permissionMode, setPermissionMode }) {
className="mt-1 w-4 h-4 text-green-600"
/>
-
Accept Edits
+
{t('permissions.codex.modes.acceptEdits.title')}
- All commands run automatically within the workspace.
- Full auto mode with sandboxed execution.
+ {t('permissions.codex.modes.acceptEdits.description')}
@@ -568,12 +570,11 @@ function CodexPermissions({ permissionMode, setPermissionMode }) {
/>
- Bypass Permissions
+ {t('permissions.codex.modes.bypassPermissions.title')}
- Full system access with no restrictions. All commands run automatically
- with full disk and network access. Use with caution.
+ {t('permissions.codex.modes.bypassPermissions.description')}
@@ -582,13 +583,13 @@ function CodexPermissions({ permissionMode, setPermissionMode }) {
{/* Technical Details */}
- Technical details
+ {t('permissions.codex.technicalDetails')}
-
Default: sandboxMode=workspace-write, approvalPolicy=untrusted. Trusted commands: cat, cd, grep, head, ls, pwd, tail, git status/log/diff/show, find (without -exec), etc.
-
Accept Edits: sandboxMode=workspace-write, approvalPolicy=never. All commands auto-execute within project directory.
-
Bypass Permissions: sandboxMode=danger-full-access, approvalPolicy=never. Full system access, use only in trusted environments.
-
You can override this per-session using the mode button in the chat interface.
+
{t('permissions.codex.modes.default.title')}: {t('permissions.codex.technicalInfo.default')}
+
{t('permissions.codex.modes.acceptEdits.title')}: {t('permissions.codex.technicalInfo.acceptEdits')}
+
{t('permissions.codex.modes.bypassPermissions.title')}: {t('permissions.codex.technicalInfo.bypassPermissions')}
+
{t('permissions.codex.technicalInfo.overrideNote')}
diff --git a/src/i18n/config.js b/src/i18n/config.js
new file mode 100644
index 00000000..789b9939
--- /dev/null
+++ b/src/i18n/config.js
@@ -0,0 +1,125 @@
+/**
+ * i18n Configuration
+ *
+ * Configures i18next for internationalization support.
+ * Features:
+ * - Lazy-loading of translation namespaces
+ * - Language detection from localStorage
+ * - Fallback to English for missing translations
+ * - Development mode warnings for missing keys
+ */
+
+import i18n from 'i18next';
+import { initReactI18next } from 'react-i18next';
+import LanguageDetector from 'i18next-browser-languagedetector';
+
+// Import translation resources
+import enCommon from './locales/en/common.json';
+import enSettings from './locales/en/settings.json';
+import enAuth from './locales/en/auth.json';
+import enSidebar from './locales/en/sidebar.json';
+import enChat from './locales/en/chat.json';
+
+import zhCommon from './locales/zh-CN/common.json';
+import zhSettings from './locales/zh-CN/settings.json';
+import zhAuth from './locales/zh-CN/auth.json';
+import zhSidebar from './locales/zh-CN/sidebar.json';
+import zhChat from './locales/zh-CN/chat.json';
+
+// Import supported languages configuration
+import { languages } from './languages.js';
+
+// Get saved language preference from localStorage
+const getSavedLanguage = () => {
+ try {
+ const saved = localStorage.getItem('userLanguage');
+ // Validate that the saved language is supported
+ if (saved && languages.some(lang => lang.value === saved)) {
+ return saved;
+ }
+ return 'en';
+ } catch {
+ return 'en';
+ }
+};
+
+// Initialize i18next
+i18n
+ .use(LanguageDetector) // Detect user language
+ .use(initReactI18next) // Pass i18n instance to react-i18next
+ .init({
+ // Resources containing all translations
+ resources: {
+ en: {
+ common: enCommon,
+ settings: enSettings,
+ auth: enAuth,
+ sidebar: enSidebar,
+ chat: enChat,
+ },
+ 'zh-CN': {
+ common: zhCommon,
+ settings: zhSettings,
+ auth: zhAuth,
+ sidebar: zhSidebar,
+ chat: zhChat,
+ },
+ },
+
+ // Default language
+ lng: getSavedLanguage(),
+
+ // Fallback language when a translation is missing
+ fallbackLng: 'en',
+
+ // Enable debug mode in development (logs missing keys to console)
+ debug: import.meta.env.DEV,
+
+ // Namespaces - load only what's needed
+ ns: ['common', 'settings', 'auth', 'sidebar', 'chat'],
+ defaultNS: 'common',
+
+ // Key separator for nested keys (default: '.')
+ keySeparator: '.',
+
+ // Namespace separator (default: ':')
+ nsSeparator: ':',
+
+ // Save missing translations (disabled - requires manual review)
+ saveMissing: false,
+
+ // Interpolation settings
+ interpolation: {
+ escapeValue: false, // React already escapes values
+ },
+
+ // React-specific settings
+ react: {
+ useSuspense: true, // Use Suspense for lazy-loading
+ bindI18n: 'languageChanged', // Re-render on language change
+ bindI18nStore: false, // Don't re-render on resource changes
+ },
+
+ // Detection options
+ detection: {
+ // Order of language detection (local storage first)
+ order: ['localStorage'],
+
+ // Keys to look for in localStorage
+ lookupLocalStorage: 'userLanguage',
+
+ // Cache user language
+ caches: ['localStorage'],
+ },
+ });
+
+// Save language preference when it changes
+i18n.on('languageChanged', (lng) => {
+ try {
+ localStorage.setItem('userLanguage', lng);
+ } catch (error) {
+ console.error('Failed to save language preference:', error);
+ }
+});
+
+export default i18n;
diff --git a/src/i18n/languages.js b/src/i18n/languages.js
new file mode 100644
index 00000000..78555f0c
--- /dev/null
+++ b/src/i18n/languages.js
@@ -0,0 +1,48 @@
+/**
+ * Supported Languages Configuration
+ *
+ * This file contains the list of supported languages for the application.
+ * Each language includes:
+ * - value: Language code (e.g., 'en', 'zh-CN')
+ * - label: Display name in English
+ * - nativeName: Native language name for display
+ */
+
+export const languages = [
+ {
+ value: 'en',
+ label: 'English',
+ nativeName: 'English',
+ },
+ {
+ value: 'zh-CN',
+ label: 'Simplified Chinese',
+ nativeName: '简体中文',
+ },
+];
+
+/**
+ * Get language object by value
+ * @param {string} value - Language code
+ * @returns {Object|undefined} Language object or undefined if not found
+ */
+export const getLanguage = (value) => {
+ return languages.find(lang => lang.value === value);
+};
+
+/**
+ * Get all language values
+ * @returns {string[]} Array of language codes
+ */
+export const getLanguageValues = () => {
+ return languages.map(lang => lang.value);
+};
+
+/**
+ * Check if a language is supported
+ * @param {string} value - Language code to check
+ * @returns {boolean} True if language is supported
+ */
+export const isLanguageSupported = (value) => {
+ return languages.some(lang => lang.value === value);
+};
diff --git a/src/i18n/locales/en/auth.json b/src/i18n/locales/en/auth.json
new file mode 100644
index 00000000..2788855f
--- /dev/null
+++ b/src/i18n/locales/en/auth.json
@@ -0,0 +1,37 @@
+{
+ "login": {
+ "title": "Welcome Back",
+ "description": "Sign in to your Claude Code UI account",
+ "username": "Username",
+ "password": "Password",
+ "submit": "Sign In",
+ "loading": "Signing in...",
+ "errors": {
+ "invalidCredentials": "Invalid username or password",
+ "requiredFields": "Please fill in all fields",
+ "networkError": "Network error. Please try again."
+ },
+ "placeholders": {
+ "username": "Enter your username",
+ "password": "Enter your password"
+ }
+ },
+ "register": {
+ "title": "Create Account",
+ "username": "Username",
+ "password": "Password",
+ "confirmPassword": "Confirm Password",
+ "submit": "Create Account",
+ "loading": "Creating account...",
+ "errors": {
+ "passwordMismatch": "Passwords do not match",
+ "usernameTaken": "Username is already taken",
+ "weakPassword": "Password is too weak"
+ }
+ },
+ "logout": {
+ "title": "Sign Out",
+ "confirm": "Are you sure you want to sign out?",
+ "button": "Sign Out"
+ }
+}
diff --git a/src/i18n/locales/en/chat.json b/src/i18n/locales/en/chat.json
new file mode 100644
index 00000000..2804554e
--- /dev/null
+++ b/src/i18n/locales/en/chat.json
@@ -0,0 +1,147 @@
+{
+ "codeBlock": {
+ "copy": "Copy",
+ "copied": "Copied",
+ "copyCode": "Copy code"
+ },
+ "messageTypes": {
+ "user": "U",
+ "error": "Error",
+ "tool": "Tool",
+ "claude": "Claude",
+ "cursor": "Cursor",
+ "codex": "Codex"
+ },
+ "tools": {
+ "settings": "Tool Settings",
+ "error": "Tool Error",
+ "result": "Tool Result",
+ "viewParams": "View input parameters",
+ "viewRawParams": "View raw parameters",
+ "viewDiff": "View edit diff for",
+ "creatingFile": "Creating new file:",
+ "updatingTodo": "Updating Todo List",
+ "read": "Read",
+ "readFile": "Read file",
+ "updateTodo": "Update todo list",
+ "readTodo": "Read todo list",
+ "searchResults": "results"
+ },
+ "search": {
+ "found": "Found {{count}} {{type}}",
+ "file": "file",
+ "files": "files",
+ "pattern": "pattern:",
+ "in": "in:"
+ },
+ "fileOperations": {
+ "updated": "File updated successfully",
+ "created": "File created successfully",
+ "written": "File written successfully",
+ "diff": "Diff",
+ "newFile": "New File",
+ "viewContent": "View file content",
+ "viewFullOutput": "View full output ({{count}} chars)",
+ "contentDisplayed": "The file content is displayed in the diff view above"
+ },
+ "interactive": {
+ "title": "Interactive Prompt",
+ "waiting": "Waiting for your response in the CLI",
+ "instruction": "Please select an option in your terminal where Claude is running.",
+ "selectedOption": "✓ Claude selected option {{number}}",
+ "instructionDetail": "In the CLI, you would select this option interactively using arrow keys or by typing the number."
+ },
+ "thinking": {
+ "title": "Thinking...",
+ "emoji": "💭 Thinking..."
+ },
+ "json": {
+ "response": "JSON Response"
+ },
+ "permissions": {
+ "grant": "Grant permission for {{tool}}",
+ "added": "Permission added",
+ "addTo": "Adds {{entry}} to Allowed Tools.",
+ "retry": "Permission saved. Retry the request to use the tool.",
+ "error": "Unable to update permissions. Please try again.",
+ "openSettings": "Open settings"
+ },
+ "todo": {
+ "updated": "Todo list has been updated successfully",
+ "current": "Current Todo List"
+ },
+ "plan": {
+ "viewPlan": "📋 View implementation plan",
+ "title": "Implementation Plan"
+ },
+ "usageLimit": {
+ "resetAt": "Claude usage limit reached. Your limit will reset at **{{time}} {{timezone}}** - {{date}}"
+ },
+ "codex": {
+ "permissionMode": "Permission Mode",
+ "modes": {
+ "default": "Default Mode",
+ "acceptEdits": "Accept Edits",
+ "bypassPermissions": "Bypass Permissions",
+ "plan": "Plan Mode"
+ },
+ "descriptions": {
+ "default": "Only trusted commands (ls, cat, grep, git status, etc.) run automatically. Other commands are skipped. Can write to workspace.",
+ "acceptEdits": "All commands run automatically within the workspace. Full auto mode with sandboxed execution.",
+ "bypassPermissions": "Full system access with no restrictions. All commands run automatically with full disk and network access. Use with caution.",
+ "plan": "Planning mode - no commands are executed"
+ },
+ "technicalDetails": "Technical details"
+ },
+ "input": {
+ "placeholder": "Type / for commands, @ for files, or ask {{provider}} anything...",
+ "placeholderDefault": "Type your message...",
+ "disabled": "Input disabled",
+ "attachFiles": "Attach files",
+ "attachImages": "Attach images",
+ "send": "Send",
+ "stop": "Stop",
+ "hintText": {
+ "ctrlEnter": "Ctrl+Enter to send • Shift+Enter for new line • Tab to change modes • / for slash commands",
+ "enter": "Enter to send • Shift+Enter for new line • Tab to change modes • / for slash commands"
+ },
+ "clickToChangeMode": "Click to change permission mode (or press Tab in input)",
+ "showAllCommands": "Show all commands"
+ },
+ "thinkingMode": {
+ "selector": {
+ "title": "Thinking Mode",
+ "description": "Extended thinking gives Claude more time to evaluate alternatives",
+ "active": "Active",
+ "tip": "Higher thinking modes take more time but provide more thorough analysis"
+ },
+ "modes": {
+ "none": {
+ "name": "Standard",
+ "description": "Regular Claude response",
+ "prefix": ""
+ },
+ "think": {
+ "name": "Think",
+ "description": "Basic extended thinking",
+ "prefix": "think"
+ },
+ "thinkHard": {
+ "name": "Think Hard",
+ "description": "More thorough evaluation",
+ "prefix": "think hard"
+ },
+ "thinkHarder": {
+ "name": "Think Harder",
+ "description": "Deep analysis with alternatives",
+ "prefix": "think harder"
+ },
+ "ultrathink": {
+ "name": "Ultrathink",
+ "description": "Maximum thinking budget",
+ "prefix": "ultrathink"
+ }
+ },
+ "buttonTitle": "Thinking mode: {{mode}}"
+ }
+}
diff --git a/src/i18n/locales/en/common.json b/src/i18n/locales/en/common.json
new file mode 100644
index 00000000..ffc79720
--- /dev/null
+++ b/src/i18n/locales/en/common.json
@@ -0,0 +1,190 @@
+{
+ "buttons": {
+ "save": "Save",
+ "cancel": "Cancel",
+ "delete": "Delete",
+ "create": "Create",
+ "edit": "Edit",
+ "close": "Close",
+ "confirm": "Confirm",
+ "submit": "Submit",
+ "retry": "Retry",
+ "refresh": "Refresh",
+ "search": "Search",
+ "clear": "Clear",
+ "copy": "Copy",
+ "download": "Download",
+ "upload": "Upload",
+ "browse": "Browse"
+ },
+ "tabs": {
+ "chat": "Chat",
+ "shell": "Shell",
+ "files": "Files",
+ "git": "Source Control",
+ "tasks": "Tasks"
+ },
+ "status": {
+ "loading": "Loading...",
+ "success": "Success",
+ "error": "Error",
+ "failed": "Failed",
+ "pending": "Pending",
+ "completed": "Completed",
+ "inProgress": "In Progress"
+ },
+ "messages": {
+ "savedSuccessfully": "Saved successfully",
+ "deletedSuccessfully": "Deleted successfully",
+ "updatedSuccessfully": "Updated successfully",
+ "operationFailed": "Operation failed",
+ "networkError": "Network error. Please check your connection.",
+ "unauthorized": "Unauthorized. Please log in.",
+ "notFound": "Not found",
+ "invalidInput": "Invalid input",
+ "requiredField": "This field is required",
+ "unknownError": "An unknown error occurred"
+ },
+ "navigation": {
+ "settings": "Settings",
+ "home": "Home",
+ "back": "Back",
+ "next": "Next",
+ "previous": "Previous",
+ "logout": "Logout"
+ },
+ "common": {
+ "language": "Language",
+ "theme": "Theme",
+ "darkMode": "Dark Mode",
+ "lightMode": "Light Mode",
+ "name": "Name",
+ "description": "Description",
+ "enabled": "Enabled",
+ "disabled": "Disabled",
+ "optional": "Optional",
+ "version": "Version",
+ "select": "Select",
+ "selectAll": "Select All",
+ "deselectAll": "Deselect All"
+ },
+ "time": {
+ "justNow": "Just now",
+ "minutesAgo": "{{count}} mins ago",
+ "hoursAgo": "{{count}} hours ago",
+ "daysAgo": "{{count}} days ago",
+ "yesterday": "Yesterday"
+ },
+ "fileOperations": {
+ "newFile": "New File",
+ "newFolder": "New Folder",
+ "rename": "Rename",
+ "move": "Move",
+ "copyPath": "Copy Path",
+ "openInEditor": "Open in Editor"
+ },
+ "mainContent": {
+ "loading": "Loading Claude Code UI",
+ "settingUpWorkspace": "Setting up your workspace...",
+ "chooseProject": "Choose Your Project",
+ "selectProjectDescription": "Select a project from the sidebar to start coding with Claude. Each project contains your chat sessions and file history.",
+ "tip": "Tip",
+ "createProjectMobile": "Tap the menu button above to access projects",
+ "createProjectDesktop": "Create a new project by clicking the folder icon in the sidebar",
+ "newSession": "New Session",
+ "untitledSession": "Untitled Session",
+ "projectFiles": "Project Files"
+ },
+ "fileTree": {
+ "loading": "Loading files...",
+ "files": "Files",
+ "simpleView": "Simple view",
+ "compactView": "Compact view",
+ "detailedView": "Detailed view",
+ "searchPlaceholder": "Search files and folders...",
+ "clearSearch": "Clear search",
+ "name": "Name",
+ "size": "Size",
+ "modified": "Modified",
+ "permissions": "Permissions",
+ "noFilesFound": "No files found",
+ "checkProjectPath": "Check if the project path is accessible",
+ "noMatchesFound": "No matches found",
+ "tryDifferentSearch": "Try a different search term or clear the search",
+ "justNow": "just now",
+ "minAgo": "{{count}} min ago",
+ "hoursAgo": "{{count}} hours ago",
+ "daysAgo": "{{count}} days ago"
+ },
+ "projectWizard": {
+ "title": "Create New Project",
+ "steps": {
+ "type": "Type",
+ "configure": "Configure",
+ "confirm": "Confirm"
+ },
+ "step1": {
+ "question": "Do you already have a workspace, or would you like to create a new one?",
+ "existing": {
+ "title": "Existing Workspace",
+ "description": "I already have a workspace on my server and just need to add it to the project list"
+ },
+ "new": {
+ "title": "New Workspace",
+ "description": "Create a new workspace, optionally clone from a GitHub repository"
+ }
+ },
+ "step2": {
+ "existingPath": "Workspace Path",
+ "newPath": "Where should the workspace be created?",
+ "existingPlaceholder": "/path/to/existing/workspace",
+ "newPlaceholder": "/path/to/new/workspace",
+ "existingHelp": "Full path to your existing workspace directory",
+ "newHelp": "Full path where the new workspace will be created",
+ "githubUrl": "GitHub URL (Optional)",
+ "githubPlaceholder": "https://github.com/username/repository",
+ "githubHelp": "Leave empty to create an empty workspace, or provide a GitHub URL to clone",
+ "githubAuth": "GitHub Authentication (Optional)",
+ "githubAuthHelp": "Only required for private repositories. Public repos can be cloned without authentication.",
+ "loadingTokens": "Loading stored tokens...",
+ "storedToken": "Stored Token",
+ "newToken": "New Token",
+ "nonePublic": "None (Public)",
+ "selectToken": "Select Token",
+ "selectTokenPlaceholder": "-- Select a token --",
+ "tokenPlaceholder": "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "tokenHelp": "This token will be used only for this operation",
+ "publicRepoInfo": "Public repositories don't require authentication. You can skip providing a token if cloning a public repo.",
+ "noTokensHelp": "No stored tokens available. You can add tokens in Settings → API Keys for easier reuse.",
+ "optionalTokenPublic": "GitHub Token (Optional for Public Repos)",
+ "tokenPublicPlaceholder": "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (leave empty for public repos)"
+ },
+ "step3": {
+ "reviewConfig": "Review Your Configuration",
+ "workspaceType": "Workspace Type:",
+ "existingWorkspace": "Existing Workspace",
+ "newWorkspace": "New Workspace",
+ "path": "Path:",
+ "cloneFrom": "Clone From:",
+ "authentication": "Authentication:",
+ "usingStoredToken": "Using stored token:",
+ "usingProvidedToken": "Using provided token",
+ "noAuthentication": "No authentication",
+ "existingInfo": "The workspace will be added to your project list and will be available for Claude/Cursor sessions.",
+ "newWithClone": "A new workspace will be created and the repository will be cloned from GitHub.",
+ "newEmpty": "An empty workspace directory will be created at the specified path."
+ },
+ "buttons": {
+ "cancel": "Cancel",
+ "back": "Back",
+ "next": "Next",
+ "createProject": "Create Project",
+ "creating": "Creating..."
+ },
+ "errors": {
+ "selectType": "Please select whether you have an existing workspace or want to create a new one",
+ "providePath": "Please provide a workspace path",
+ "failedToCreate": "Failed to create workspace"
+ }
+ }
+}
diff --git a/src/i18n/locales/en/settings.json b/src/i18n/locales/en/settings.json
new file mode 100644
index 00000000..c0155923
--- /dev/null
+++ b/src/i18n/locales/en/settings.json
@@ -0,0 +1,401 @@
+{
+ "title": "Settings",
+ "tabs": {
+ "account": "Account",
+ "permissions": "Permissions",
+ "mcpServers": "MCP Servers",
+ "appearance": "Appearance"
+ },
+ "account": {
+ "title": "Account",
+ "language": "Language",
+ "languageLabel": "Display Language",
+ "languageDescription": "Choose your preferred language for the interface",
+ "username": "Username",
+ "email": "Email",
+ "profile": "Profile",
+ "changePassword": "Change Password"
+ },
+ "mcp": {
+ "title": "MCP Servers",
+ "addServer": "Add Server",
+ "editServer": "Edit Server",
+ "deleteServer": "Delete Server",
+ "serverName": "Server Name",
+ "serverType": "Server Type",
+ "config": "Configuration",
+ "testConnection": "Test Connection",
+ "status": "Status",
+ "connected": "Connected",
+ "disconnected": "Disconnected",
+ "scope": {
+ "label": "Scope",
+ "user": "User",
+ "project": "Project"
+ }
+ },
+ "appearance": {
+ "title": "Appearance",
+ "theme": "Theme",
+ "codeEditor": "Code Editor",
+ "editorTheme": "Editor Theme",
+ "wordWrap": "Word Wrap",
+ "showMinimap": "Show Minimap",
+ "lineNumbers": "Line Numbers",
+ "fontSize": "Font Size"
+ },
+ "actions": {
+ "saveChanges": "Save Changes",
+ "resetToDefaults": "Reset to Defaults",
+ "cancelChanges": "Cancel Changes"
+ },
+ "quickSettings": {
+ "title": "Quick Settings",
+ "sections": {
+ "appearance": "Appearance",
+ "toolDisplay": "Tool Display",
+ "viewOptions": "View Options",
+ "inputSettings": "Input Settings",
+ "whisperDictation": "Whisper Dictation"
+ },
+ "darkMode": "Dark Mode",
+ "autoExpandTools": "Auto-expand tools",
+ "showRawParameters": "Show raw parameters",
+ "showThinking": "Show thinking",
+ "autoScrollToBottom": "Auto-scroll to bottom",
+ "sendByCtrlEnter": "Send by Ctrl+Enter",
+ "sendByCtrlEnterDescription": "When enabled, pressing Ctrl+Enter will send the message instead of just Enter. This is useful for IME users to avoid accidental sends."
+ },
+ "mainTabs": {
+ "agents": "Agents",
+ "appearance": "Appearance",
+ "git": "Git",
+ "apiTokens": "API & Tokens",
+ "tasks": "Tasks"
+ },
+ "appearanceSettings": {
+ "darkMode": {
+ "label": "Dark Mode",
+ "description": "Toggle between light and dark themes"
+ },
+ "projectSorting": {
+ "label": "Project Sorting",
+ "description": "How projects are ordered in the sidebar",
+ "alphabetical": "Alphabetical",
+ "recentActivity": "Recent Activity"
+ },
+ "codeEditor": {
+ "title": "Code Editor",
+ "theme": {
+ "label": "Editor Theme",
+ "description": "Default theme for the code editor"
+ },
+ "wordWrap": {
+ "label": "Word Wrap",
+ "description": "Enable word wrapping by default in the editor"
+ },
+ "showMinimap": {
+ "label": "Show Minimap",
+ "description": "Display a minimap for easier navigation in diff view"
+ },
+ "lineNumbers": {
+ "label": "Show Line Numbers",
+ "description": "Display line numbers in the editor"
+ },
+ "fontSize": {
+ "label": "Font Size",
+ "description": "Editor font size in pixels"
+ }
+ }
+ },
+ "mcpForm": {
+ "title": {
+ "add": "Add MCP Server",
+ "edit": "Edit MCP Server"
+ },
+ "importMode": {
+ "form": "Form Input",
+ "json": "JSON Import"
+ },
+ "scope": {
+ "label": "Scope",
+ "userGlobal": "User (Global)",
+ "projectLocal": "Project (Local)",
+ "userDescription": "User scope: Available across all projects on your machine",
+ "projectDescription": "Local scope: Only available in the selected project",
+ "cannotChange": "Scope cannot be changed when editing an existing server"
+ },
+ "fields": {
+ "serverName": "Server Name",
+ "transportType": "Transport Type",
+ "command": "Command",
+ "arguments": "Arguments (one per line)",
+ "jsonConfig": "JSON Configuration",
+ "url": "URL",
+ "envVars": "Environment Variables (KEY=value, one per line)",
+ "headers": "Headers (KEY=value, one per line)",
+ "selectProject": "Select a project..."
+ },
+ "placeholders": {
+ "serverName": "my-server"
+ },
+ "validation": {
+ "missingType": "Missing required field: type",
+ "stdioRequiresCommand": "stdio type requires a command field",
+ "httpRequiresUrl": "{{type}} type requires a url field",
+ "invalidJson": "Invalid JSON format",
+ "jsonHelp": "Paste your MCP server configuration in JSON format. Example formats:",
+ "jsonExampleStdio": "• stdio: {\"type\":\"stdio\",\"command\":\"npx\",\"args\":[\"@upstash/context7-mcp\"]}",
+ "jsonExampleHttp": "• http/sse: {\"type\":\"http\",\"url\":\"https://api.example.com/mcp\"}"
+ },
+ "configDetails": "Configuration Details (from {{configFile}})",
+ "projectPath": "Path: {{path}}",
+ "actions": {
+ "cancel": "Cancel",
+ "saving": "Saving...",
+ "addServer": "Add Server",
+ "updateServer": "Update Server"
+ }
+ },
+ "saveStatus": {
+ "success": "Settings saved successfully!",
+ "error": "Failed to save settings",
+ "saving": "Saving..."
+ },
+ "footerActions": {
+ "save": "Save Settings",
+ "cancel": "Cancel"
+ },
+ "git": {
+ "title": "Git Configuration",
+ "description": "Configure your git identity for commits. These settings will be applied globally via git config --global",
+ "name": {
+ "label": "Git Name",
+ "help": "Your name for git commits"
+ },
+ "email": {
+ "label": "Git Email",
+ "help": "Your email for git commits"
+ },
+ "actions": {
+ "save": "Save Configuration",
+ "saving": "Saving..."
+ },
+ "status": {
+ "success": "Saved successfully"
+ }
+ },
+ "apiKeys": {
+ "title": "API Keys",
+ "description": "Generate API keys to access the external API from other applications.",
+ "newKey": {
+ "alertTitle": "⚠️ Save Your API Key",
+ "alertMessage": "This is the only time you'll see this key. Store it securely.",
+ "iveSavedIt": "I've saved it"
+ },
+ "form": {
+ "placeholder": "API Key Name (e.g., Production Server)",
+ "createButton": "Create",
+ "cancelButton": "Cancel"
+ },
+ "newButton": "New API Key",
+ "empty": "No API keys created yet.",
+ "list": {
+ "created": "Created:",
+ "lastUsed": "Last used:"
+ },
+ "confirmDelete": "Are you sure you want to delete this API key?",
+ "status": {
+ "active": "Active",
+ "inactive": "Inactive"
+ },
+ "github": {
+ "title": "GitHub Tokens",
+ "description": "Add GitHub Personal Access Tokens to clone private repositories via the external API.",
+ "descriptionAlt": "Add GitHub Personal Access Tokens to clone private repositories. You can also pass tokens directly in API requests without storing them.",
+ "addButton": "Add Token",
+ "form": {
+ "namePlaceholder": "Token Name (e.g., Personal Repos)",
+ "tokenPlaceholder": "GitHub Personal Access Token (ghp_...)",
+ "descriptionPlaceholder": "Description (optional)",
+ "addButton": "Add Token",
+ "cancelButton": "Cancel",
+ "howToCreate": "How to create a GitHub Personal Access Token →"
+ },
+ "empty": "No GitHub tokens added yet.",
+ "added": "Added:",
+ "confirmDelete": "Are you sure you want to delete this GitHub token?"
+ },
+ "apiDocsLink": "API Documentation",
+ "documentation": {
+ "title": "External API Documentation",
+ "description": "Learn how to use the external API to trigger Claude/Cursor sessions from your applications.",
+ "viewLink": "View API Documentation →"
+ },
+ "loading": "Loading...",
+ "version": {
+ "updateAvailable": "Update available: v{{version}}"
+ }
+ },
+ "tasks": {
+ "checking": "Checking TaskMaster installation...",
+ "notInstalled": {
+ "title": "TaskMaster AI CLI Not Installed",
+ "description": "TaskMaster CLI is required to use task management features. Install it to get started:",
+ "installCommand": "npm install -g task-master-ai",
+ "viewOnGitHub": "View on GitHub",
+ "afterInstallation": "After installation:",
+ "steps": {
+ "restart": "Restart this application",
+ "autoAvailable": "TaskMaster features will automatically become available",
+ "initCommand": "Use task-master init in your project directory"
+ }
+ },
+ "settings": {
+ "enableLabel": "Enable TaskMaster Integration",
+ "enableDescription": "Show TaskMaster tasks, banners, and sidebar indicators across the interface"
+ }
+ },
+ "agents": {
+ "authStatus": {
+ "checking": "Checking...",
+ "connected": "Connected",
+ "notConnected": "Not connected",
+ "disconnected": "Disconnected",
+ "checkingAuth": "Checking authentication status...",
+ "loggedInAs": "Logged in as {{email}}",
+ "authenticatedUser": "authenticated user"
+ },
+ "account": {
+ "claude": {
+ "description": "Anthropic Claude AI assistant"
+ },
+ "cursor": {
+ "description": "Cursor AI-powered code editor"
+ },
+ "codex": {
+ "description": "OpenAI Codex AI assistant"
+ }
+ },
+ "connectionStatus": "Connection Status",
+ "login": {
+ "title": "Login",
+ "reAuthenticate": "Re-authenticate",
+ "description": "Sign in to your {{agent}} account to enable AI features",
+ "reAuthDescription": "Sign in with a different account or refresh credentials",
+ "button": "Login",
+ "reLoginButton": "Re-login"
+ },
+ "error": "Error: {{error}}"
+ },
+ "permissions": {
+ "title": "Permission Settings",
+ "skipPermissions": {
+ "label": "Skip permission prompts (use with caution)",
+ "claudeDescription": "Equivalent to --dangerously-skip-permissions flag",
+ "cursorDescription": "Equivalent to -f flag in Cursor CLI"
+ },
+ "allowedTools": {
+ "title": "Allowed Tools",
+ "description": "Tools that are automatically allowed without prompting for permission",
+ "placeholder": "e.g., \"Bash(git log:*)\" or \"Write\"",
+ "quickAdd": "Quick add common tools:",
+ "empty": "No allowed tools configured"
+ },
+ "blockedTools": {
+ "title": "Blocked Tools",
+ "description": "Tools that are automatically blocked without prompting for permission",
+ "placeholder": "e.g., \"Bash(rm:*)\"",
+ "empty": "No blocked tools configured"
+ },
+ "allowedCommands": {
+ "title": "Allowed Shell Commands",
+ "description": "Shell commands that are automatically allowed without prompting",
+ "placeholder": "e.g., \"Shell(ls)\" or \"Shell(git status)\"",
+ "quickAdd": "Quick add common commands:",
+ "empty": "No allowed commands configured"
+ },
+ "blockedCommands": {
+ "title": "Blocked Shell Commands",
+ "description": "Shell commands that are automatically blocked",
+ "placeholder": "e.g., \"Shell(rm -rf)\" or \"Shell(sudo)\"",
+ "empty": "No blocked commands configured"
+ },
+ "toolExamples": {
+ "title": "Tool Pattern Examples:",
+ "bashGitLog": "- Allow all git log commands",
+ "bashGitDiff": "- Allow all git diff commands",
+ "write": "- Allow all Write tool usage",
+ "bashRm": "- Block all rm commands (dangerous)"
+ },
+ "shellExamples": {
+ "title": "Shell Command Examples:",
+ "ls": "- Allow ls command",
+ "gitStatus": "- Allow git status",
+ "npmInstall": "- Allow npm install",
+ "rmRf": "- Block recursive delete"
+ },
+ "codex": {
+ "permissionMode": "Permission Mode",
+ "description": "Controls how Codex handles file modifications and command execution",
+ "modes": {
+ "default": {
+ "title": "Default",
+ "description": "Only trusted commands (ls, cat, grep, git status, etc.) run automatically. Other commands are skipped. Can write to workspace."
+ },
+ "acceptEdits": {
+ "title": "Accept Edits",
+ "description": "All commands run automatically within the workspace. Full auto mode with sandboxed execution."
+ },
+ "bypassPermissions": {
+ "title": "Bypass Permissions",
+ "description": "Full system access with no restrictions. All commands run automatically with full disk and network access. Use with caution."
+ }
+ },
+ "technicalDetails": "Technical details",
+ "technicalInfo": {
+ "default": "sandboxMode=workspace-write, approvalPolicy=untrusted. Trusted commands: cat, cd, grep, head, ls, pwd, tail, git status/log/diff/show, find (without -exec), etc.",
+ "acceptEdits": "sandboxMode=workspace-write, approvalPolicy=never. All commands auto-execute within project directory.",
+ "bypassPermissions": "sandboxMode=danger-full-access, approvalPolicy=never. Full system access, use only in trusted environments.",
+ "overrideNote": "You can override this per-session using the mode button in the chat interface."
+ }
+ },
+ "actions": {
+ "add": "Add"
+ }
+ },
+ "mcpServers": {
+ "title": "MCP Servers",
+ "description": {
+ "claude": "Model Context Protocol servers provide additional tools and data sources to Claude",
+ "cursor": "Model Context Protocol servers provide additional tools and data sources to Cursor",
+ "codex": "Model Context Protocol servers provide additional tools and data sources to Codex"
+ },
+ "addButton": "Add MCP Server",
+ "empty": "No MCP servers configured",
+ "serverType": "Type",
+ "scope": {
+ "local": "local",
+ "user": "user"
+ },
+ "config": {
+ "command": "Command",
+ "url": "URL",
+ "args": "Args",
+ "environment": "Environment"
+ },
+ "tools": {
+ "title": "Tools",
+ "count": "({{count}}):",
+ "more": "+{{count}} more"
+ },
+ "actions": {
+ "edit": "Edit server",
+ "delete": "Delete server"
+ },
+ "help": {
+ "title": "About Codex MCP",
+ "description": "Codex supports stdio-based MCP servers. You can add servers that extend Codex's capabilities with additional tools and resources."
+ }
+ }
+}
diff --git a/src/i18n/locales/en/sidebar.json b/src/i18n/locales/en/sidebar.json
new file mode 100644
index 00000000..eb7a0d91
--- /dev/null
+++ b/src/i18n/locales/en/sidebar.json
@@ -0,0 +1,102 @@
+{
+ "projects": {
+ "title": "Projects",
+ "newProject": "New Project",
+ "deleteProject": "Delete Project",
+ "renameProject": "Rename Project",
+ "noProjects": "No projects found",
+ "loadingProjects": "Loading projects...",
+ "searchPlaceholder": "Search projects...",
+ "projectNamePlaceholder": "Project name",
+ "starred": "Starred",
+ "all": "All",
+ "untitledSession": "Untitled Session",
+ "newSession": "New Session",
+ "codexSession": "Codex Session",
+ "fetchingProjects": "Fetching your Claude projects and sessions",
+ "noMatchingProjects": "No matching projects",
+ "tryDifferentSearch": "Try adjusting your search term",
+ "runClaudeCli": "Run Claude CLI in a project directory to get started"
+ },
+ "app": {
+ "title": "Claude Code UI",
+ "subtitle": "AI coding assistant interface"
+ },
+ "sessions": {
+ "title": "Sessions",
+ "newSession": "New Session",
+ "deleteSession": "Delete Session",
+ "renameSession": "Rename Session",
+ "noSessions": "No sessions yet",
+ "loadingSessions": "Loading sessions...",
+ "unnamed": "Unnamed",
+ "loading": "Loading...",
+ "showMore": "Show more sessions"
+ },
+ "tooltips": {
+ "viewEnvironments": "View Environments",
+ "hideSidebar": "Hide sidebar",
+ "createProject": "Create new project",
+ "refresh": "Refresh projects and sessions (Ctrl+R)",
+ "renameProject": "Rename project (F2)",
+ "deleteProject": "Delete empty project (Delete)",
+ "addToFavorites": "Add to favorites",
+ "removeFromFavorites": "Remove from favorites",
+ "editSessionName": "Manually edit session name",
+ "deleteSession": "Delete this session permanently",
+ "save": "Save",
+ "cancel": "Cancel"
+ },
+ "navigation": {
+ "chat": "Chat",
+ "files": "Files",
+ "git": "Git",
+ "terminal": "Terminal",
+ "tasks": "Tasks"
+ },
+ "actions": {
+ "refresh": "Refresh",
+ "settings": "Settings",
+ "collapseAll": "Collapse All",
+ "expandAll": "Expand All",
+ "cancel": "Cancel",
+ "save": "Save",
+ "delete": "Delete",
+ "rename": "Rename"
+ },
+ "status": {
+ "active": "Active",
+ "inactive": "Inactive",
+ "thinking": "Thinking...",
+ "error": "Error",
+ "aborted": "Aborted",
+ "unknown": "Unknown"
+ },
+ "time": {
+ "justNow": "Just now",
+ "oneMinuteAgo": "1 min ago",
+ "minutesAgo": "{{count}} mins ago",
+ "oneHourAgo": "1 hour ago",
+ "hoursAgo": "{{count}} hours ago",
+ "oneDayAgo": "1 day ago",
+ "daysAgo": "{{count}} days ago"
+ },
+ "messages": {
+ "deleteConfirm": "Are you sure you want to delete this?",
+ "renameSuccess": "Renamed successfully",
+ "deleteSuccess": "Deleted successfully",
+ "errorOccurred": "An error occurred",
+ "deleteSessionConfirm": "Are you sure you want to delete this session? This action cannot be undone.",
+ "deleteProjectConfirm": "Are you sure you want to delete this empty project? This action cannot be undone.",
+ "enterProjectPath": "Please enter a project path",
+ "deleteSessionFailed": "Failed to delete session. Please try again.",
+ "deleteSessionError": "Error deleting session. Please try again.",
+ "deleteProjectFailed": "Failed to delete project. Please try again.",
+ "deleteProjectError": "Error deleting project. Please try again.",
+ "createProjectFailed": "Failed to create project. Please try again.",
+ "createProjectError": "Error creating project. Please try again."
+ },
+ "version": {
+ "updateAvailable": "Update available"
+ }
+}
diff --git a/src/i18n/locales/zh-CN/auth.json b/src/i18n/locales/zh-CN/auth.json
new file mode 100644
index 00000000..3905c2bd
--- /dev/null
+++ b/src/i18n/locales/zh-CN/auth.json
@@ -0,0 +1,37 @@
+{
+ "login": {
+ "title": "欢迎回来",
+ "description": "登录您的 Claude Code UI 账户",
+ "username": "用户名",
+ "password": "密码",
+ "submit": "登录",
+ "loading": "登录中...",
+ "errors": {
+ "invalidCredentials": "用户名或密码无效",
+ "requiredFields": "请填写所有字段",
+ "networkError": "网络错误,请重试。"
+ },
+ "placeholders": {
+ "username": "输入您的用户名",
+ "password": "输入您的密码"
+ }
+ },
+ "register": {
+ "title": "创建账户",
+ "username": "用户名",
+ "password": "密码",
+ "confirmPassword": "确认密码",
+ "submit": "创建账户",
+ "loading": "创建账户中...",
+ "errors": {
+ "passwordMismatch": "密码不匹配",
+ "usernameTaken": "用户名已被占用",
+ "weakPassword": "密码强度太弱"
+ }
+ },
+ "logout": {
+ "title": "退出登录",
+ "confirm": "确定要退出登录吗?",
+ "button": "退出登录"
+ }
+}
diff --git a/src/i18n/locales/zh-CN/chat.json b/src/i18n/locales/zh-CN/chat.json
new file mode 100644
index 00000000..87782e6f
--- /dev/null
+++ b/src/i18n/locales/zh-CN/chat.json
@@ -0,0 +1,147 @@
+{
+ "codeBlock": {
+ "copy": "复制",
+ "copied": "已复制",
+ "copyCode": "复制代码"
+ },
+ "messageTypes": {
+ "user": "U",
+ "error": "错误",
+ "tool": "工具",
+ "claude": "Claude",
+ "cursor": "Cursor",
+ "codex": "Codex"
+ },
+ "tools": {
+ "settings": "工具设置",
+ "error": "工具错误",
+ "result": "工具结果",
+ "viewParams": "查看输入参数",
+ "viewRawParams": "查看原始参数",
+ "viewDiff": "查看编辑差异",
+ "creatingFile": "创建新文件:",
+ "updatingTodo": "更新待办事项",
+ "read": "读取",
+ "readFile": "读取文件",
+ "updateTodo": "更新待办列表",
+ "readTodo": "读取待办列表",
+ "searchResults": "结果"
+ },
+ "search": {
+ "found": "找到 {{count}} 个{{type}}",
+ "file": "文件",
+ "files": "文件",
+ "pattern": "模式:",
+ "in": "在:"
+ },
+ "fileOperations": {
+ "updated": "文件更新成功",
+ "created": "文件创建成功",
+ "written": "文件写入成功",
+ "diff": "差异",
+ "newFile": "新文件",
+ "viewContent": "查看文件内容",
+ "viewFullOutput": "查看完整输出({{count}} 个字符)",
+ "contentDisplayed": "文件内容显示在上面的差异视图中"
+ },
+ "interactive": {
+ "title": "交互式提示",
+ "waiting": "等待您在 CLI 中响应",
+ "instruction": "请在 Claude 运行的终端中选择一个选项。",
+ "selectedOption": "✓ Claude 选择了选项 {{number}}",
+ "instructionDetail": "在 CLI 中,您可以使用方向键或输入数字来交互式地选择此选项。"
+ },
+ "thinking": {
+ "title": "思考中...",
+ "emoji": "💭 思考中..."
+ },
+ "json": {
+ "response": "JSON 响应"
+ },
+ "permissions": {
+ "grant": "授予 {{tool}} 权限",
+ "added": "权限已添加",
+ "addTo": "将 {{entry}} 添加到允许的工具。",
+ "retry": "权限已保存。重试请求以使用该工具。",
+ "error": "无法更新权限。请重试。",
+ "openSettings": "打开设置"
+ },
+ "todo": {
+ "updated": "待办列表已成功更新",
+ "current": "当前待办列表"
+ },
+ "plan": {
+ "viewPlan": "📋 查看实施计划",
+ "title": "实施计划"
+ },
+ "usageLimit": {
+ "resetAt": "Claude 使用限制已达到。您的限制将在 **{{time}} {{timezone}}** - {{date}} 重置"
+ },
+ "codex": {
+ "permissionMode": "权限模式",
+ "modes": {
+ "default": "默认模式",
+ "acceptEdits": "编辑模式",
+ "bypassPermissions": "无限制模式",
+ "plan": "计划模式"
+ },
+ "descriptions": {
+ "default": "只有受信任的命令(ls、cat、grep、git status 等)自动运行。其他命令将被跳过。可以写入工作区。",
+ "acceptEdits": "工作区内的所有命令自动运行。完全自动模式,具有沙盒执行功能。",
+ "bypassPermissions": "完全的系统访问,无限制。所有命令自动运行,具有完整的磁盘和网络访问权限。请谨慎使用。",
+ "plan": "计划模式 - 不执行任何命令"
+ },
+ "technicalDetails": "技术细节"
+ },
+ "input": {
+ "placeholder": "输入 / 调用命令,@ 选择文件,或向 {{provider}} 提问...",
+ "placeholderDefault": "输入您的消息...",
+ "disabled": "输入已禁用",
+ "attachFiles": "附加文件",
+ "attachImages": "附加图片",
+ "send": "发送",
+ "stop": "停止",
+ "hintText": {
+ "ctrlEnter": "Ctrl+Enter 发送 • Shift+Enter 换行 • Tab 切换模式 • / 斜杠命令",
+ "enter": "Enter 发送 • Shift+Enter 换行 • Tab 切换模式 • / 斜杠命令"
+ },
+ "clickToChangeMode": "点击更改权限模式(或在输入框中按 Tab)",
+ "showAllCommands": "显示所有命令"
+ },
+ "thinkingMode": {
+ "selector": {
+ "title": "思考模式",
+ "description": "扩展思考给 Claude 更多时间来评估替代方案",
+ "active": "激活",
+ "tip": "更高的思考模式需要更多时间,但提供更彻底的分析"
+ },
+ "modes": {
+ "none": {
+ "name": "标准",
+ "description": "常规 Claude 响应",
+ "prefix": ""
+ },
+ "think": {
+ "name": "思考",
+ "description": "基本扩展思考",
+ "prefix": "思考"
+ },
+ "thinkHard": {
+ "name": "深入思考",
+ "description": "更彻底的评估",
+ "prefix": "深入思考"
+ },
+ "thinkHarder": {
+ "name": "更深入思考",
+ "description": "考虑替代方案的深度分析",
+ "prefix": "更深入思考"
+ },
+ "ultrathink": {
+ "name": "超级思考",
+ "description": "最大思考预算",
+ "prefix": "超级思考"
+ }
+ },
+ "buttonTitle": "思考模式:{{mode}}"
+ }
+}
diff --git a/src/i18n/locales/zh-CN/common.json b/src/i18n/locales/zh-CN/common.json
new file mode 100644
index 00000000..1f8bc043
--- /dev/null
+++ b/src/i18n/locales/zh-CN/common.json
@@ -0,0 +1,190 @@
+{
+ "buttons": {
+ "save": "保存",
+ "cancel": "取消",
+ "delete": "删除",
+ "create": "创建",
+ "edit": "编辑",
+ "close": "关闭",
+ "confirm": "确认",
+ "submit": "提交",
+ "retry": "重试",
+ "refresh": "刷新",
+ "search": "搜索",
+ "clear": "清除",
+ "copy": "复制",
+ "download": "下载",
+ "upload": "上传",
+ "browse": "浏览"
+ },
+ "tabs": {
+ "chat": "聊天",
+ "shell": "终端",
+ "files": "文件",
+ "git": "源代码管理",
+ "tasks": "任务"
+ },
+ "status": {
+ "loading": "加载中...",
+ "success": "成功",
+ "error": "错误",
+ "failed": "失败",
+ "pending": "待处理",
+ "completed": "已完成",
+ "inProgress": "进行中"
+ },
+ "messages": {
+ "savedSuccessfully": "保存成功",
+ "deletedSuccessfully": "删除成功",
+ "updatedSuccessfully": "更新成功",
+ "operationFailed": "操作失败",
+ "networkError": "网络错误,请检查您的连接。",
+ "unauthorized": "未授权,请登录。",
+ "notFound": "未找到",
+ "invalidInput": "输入无效",
+ "requiredField": "此字段为必填项",
+ "unknownError": "发生未知错误"
+ },
+ "navigation": {
+ "settings": "设置",
+ "home": "首页",
+ "back": "返回",
+ "next": "下一步",
+ "previous": "上一步",
+ "logout": "退出登录"
+ },
+ "common": {
+ "language": "语言",
+ "theme": "主题",
+ "darkMode": "深色模式",
+ "lightMode": "浅色模式",
+ "name": "名称",
+ "description": "描述",
+ "enabled": "已启用",
+ "disabled": "已禁用",
+ "optional": "可选",
+ "version": "版本",
+ "select": "选择",
+ "selectAll": "全选",
+ "deselectAll": "取消全选"
+ },
+ "time": {
+ "justNow": "刚刚",
+ "minutesAgo": "{{count}} 分钟前",
+ "hoursAgo": "{{count}} 小时前",
+ "daysAgo": "{{count}} 天前",
+ "yesterday": "昨天"
+ },
+ "fileOperations": {
+ "newFile": "新建文件",
+ "newFolder": "新建文件夹",
+ "rename": "重命名",
+ "move": "移动",
+ "copyPath": "复制路径",
+ "openInEditor": "在编辑器中打开"
+ },
+ "mainContent": {
+ "loading": "正在加载 Claude Code UI",
+ "settingUpWorkspace": "正在设置您的工作空间...",
+ "chooseProject": "选择您的项目",
+ "selectProjectDescription": "从侧边栏选择一个项目以开始使用 Claude 进行编程。每个项目包含您的聊天会话和文件历史。",
+ "tip": "提示",
+ "createProjectMobile": "点击上方的菜单按钮以访问项目",
+ "createProjectDesktop": "点击侧边栏中的文件夹图标以创建新项目",
+ "newSession": "新会话",
+ "untitledSession": "未命名会话",
+ "projectFiles": "项目文件"
+ },
+ "fileTree": {
+ "loading": "正在加载文件...",
+ "files": "文件",
+ "simpleView": "简单视图",
+ "compactView": "紧凑视图",
+ "detailedView": "详细视图",
+ "searchPlaceholder": "搜索文件和文件夹...",
+ "clearSearch": "清除搜索",
+ "name": "名称",
+ "size": "大小",
+ "modified": "修改时间",
+ "permissions": "权限",
+ "noFilesFound": "未找到文件",
+ "checkProjectPath": "检查项目路径是否可访问",
+ "noMatchesFound": "未找到匹配项",
+ "tryDifferentSearch": "尝试不同的搜索词或清除搜索",
+ "justNow": "刚刚",
+ "minAgo": "{{count}} 分钟前",
+ "hoursAgo": "{{count}} 小时前",
+ "daysAgo": "{{count}} 天前"
+ },
+ "projectWizard": {
+ "title": "创建新项目",
+ "steps": {
+ "type": "类型",
+ "configure": "配置",
+ "confirm": "确认"
+ },
+ "step1": {
+ "question": "您已经有工作区,还是想创建一个新的工作区?",
+ "existing": {
+ "title": "现有工作区",
+ "description": "我的服务器上已经有工作区,只需要将其添加到项目列表中"
+ },
+ "new": {
+ "title": "新建工作区",
+ "description": "创建一个新工作区,可选择从 GitHub 仓库克隆"
+ }
+ },
+ "step2": {
+ "existingPath": "工作区路径",
+ "newPath": "应该在哪里创建工作区?",
+ "existingPlaceholder": "/path/to/existing/workspace",
+ "newPlaceholder": "/path/to/new/workspace",
+ "existingHelp": "您现有工作区目录的完整路径",
+ "newHelp": "将创建新工作区的完整路径",
+ "githubUrl": "GitHub URL(可选)",
+ "githubPlaceholder": "https://github.com/username/repository",
+ "githubHelp": "留空以创建空工作区,或提供 GitHub URL 以克隆",
+ "githubAuth": "GitHub 身份验证(可选)",
+ "githubAuthHelp": "仅私有仓库需要。公共仓库无需身份验证即可克隆。",
+ "loadingTokens": "正在加载已保存的令牌...",
+ "storedToken": "已保存的令牌",
+ "newToken": "新令牌",
+ "nonePublic": "无(公共)",
+ "selectToken": "选择令牌",
+ "selectTokenPlaceholder": "-- 选择令牌 --",
+ "tokenPlaceholder": "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "tokenHelp": "此令牌仅用于此操作",
+ "publicRepoInfo": "公共仓库不需要身份验证。如果克隆公共仓库,可以跳过提供令牌。",
+ "noTokensHelp": "没有可用的已保存令牌。您可以在 设置 → API 密钥 中添加令牌以便重复使用。",
+ "optionalTokenPublic": "GitHub 令牌(公共仓库可选)",
+ "tokenPublicPlaceholder": "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(公共仓库可留空)"
+ },
+ "step3": {
+ "reviewConfig": "查看您的配置",
+ "workspaceType": "工作区类型:",
+ "existingWorkspace": "现有工作区",
+ "newWorkspace": "新建工作区",
+ "path": "路径:",
+ "cloneFrom": "克隆自:",
+ "authentication": "身份验证:",
+ "usingStoredToken": "使用已保存的令牌:",
+ "usingProvidedToken": "使用提供的令牌",
+ "noAuthentication": "无身份验证",
+ "existingInfo": "工作区将被添加到您的项目列表中,并可用于 Claude/Cursor 会话。",
+ "newWithClone": "将创建新工作区,并从 GitHub 克隆仓库。",
+ "newEmpty": "将在指定路径创建一个空的工作区目录。"
+ },
+ "buttons": {
+ "cancel": "取消",
+ "back": "返回",
+ "next": "下一步",
+ "createProject": "创建项目",
+ "creating": "创建中..."
+ },
+ "errors": {
+ "selectType": "请选择您已有现有工作区还是想创建新工作区",
+ "providePath": "请提供工作区路径",
+ "failedToCreate": "创建工作区失败"
+ }
+ }
+}
diff --git a/src/i18n/locales/zh-CN/settings.json b/src/i18n/locales/zh-CN/settings.json
new file mode 100644
index 00000000..9aaaec93
--- /dev/null
+++ b/src/i18n/locales/zh-CN/settings.json
@@ -0,0 +1,401 @@
+{
+ "title": "设置",
+ "tabs": {
+ "account": "账户",
+ "permissions": "权限",
+ "mcpServers": "MCP 服务器",
+ "appearance": "外观"
+ },
+ "account": {
+ "title": "账户",
+ "language": "语言",
+ "languageLabel": "显示语言",
+ "languageDescription": "选择您偏好的界面语言",
+ "username": "用户名",
+ "email": "邮箱",
+ "profile": "个人资料",
+ "changePassword": "修改密码"
+ },
+ "mcp": {
+ "title": "MCP 服务器",
+ "addServer": "添加服务器",
+ "editServer": "编辑服务器",
+ "deleteServer": "删除服务器",
+ "serverName": "服务器名称",
+ "serverType": "服务器类型",
+ "config": "配置",
+ "testConnection": "测试连接",
+ "status": "状态",
+ "connected": "已连接",
+ "disconnected": "未连接",
+ "scope": {
+ "label": "范围",
+ "user": "用户",
+ "project": "项目"
+ }
+ },
+ "appearance": {
+ "title": "外观",
+ "theme": "主题",
+ "codeEditor": "代码编辑器",
+ "editorTheme": "编辑器主题",
+ "wordWrap": "自动换行",
+ "showMinimap": "显示缩略图",
+ "lineNumbers": "行号",
+ "fontSize": "字体大小"
+ },
+ "actions": {
+ "saveChanges": "保存更改",
+ "resetToDefaults": "重置为默认值",
+ "cancelChanges": "取消更改"
+ },
+ "quickSettings": {
+ "title": "快速设置",
+ "sections": {
+ "appearance": "外观",
+ "toolDisplay": "工具显示",
+ "viewOptions": "视图选项",
+ "inputSettings": "输入设置",
+ "whisperDictation": "Whisper 听写"
+ },
+ "darkMode": "深色模式",
+ "autoExpandTools": "自动展开工具",
+ "showRawParameters": "显示原始参数",
+ "showThinking": "显示思考过程",
+ "autoScrollToBottom": "自动滚动到底部",
+ "sendByCtrlEnter": "使用 Ctrl+Enter 发送",
+ "sendByCtrlEnterDescription": "启用后,按 Ctrl+Enter 发送消息,而不是仅按 Enter。这对于使用输入法的用户可以避免意外发送。"
+ },
+ "mainTabs": {
+ "agents": "智能体",
+ "appearance": "外观",
+ "git": "Git",
+ "apiTokens": "API 和令牌",
+ "tasks": "任务"
+ },
+ "appearanceSettings": {
+ "darkMode": {
+ "label": "深色模式",
+ "description": "切换浅色和深色主题"
+ },
+ "projectSorting": {
+ "label": "项目排序",
+ "description": "项目在侧边栏中的排列方式",
+ "alphabetical": "按字母顺序",
+ "recentActivity": "最近活动"
+ },
+ "codeEditor": {
+ "title": "代码编辑器",
+ "theme": {
+ "label": "编辑器主题",
+ "description": "代码编辑器的默认主题"
+ },
+ "wordWrap": {
+ "label": "自动换行",
+ "description": "在编辑器中默认启用自动换行"
+ },
+ "showMinimap": {
+ "label": "显示缩略图",
+ "description": "在差异视图中显示缩略图以便于导航"
+ },
+ "lineNumbers": {
+ "label": "显示行号",
+ "description": "在编辑器中显示行号"
+ },
+ "fontSize": {
+ "label": "字体大小",
+ "description": "编辑器字体大小(px)"
+ }
+ }
+ },
+ "mcpForm": {
+ "title": {
+ "add": "添加 MCP 服务器",
+ "edit": "编辑 MCP 服务器"
+ },
+ "importMode": {
+ "form": "表单输入",
+ "json": "JSON 导入"
+ },
+ "scope": {
+ "label": "范围",
+ "userGlobal": "用户(全局)",
+ "projectLocal": "项目(本地)",
+ "userDescription": "用户范围:在您机器上的所有项目中可用",
+ "projectDescription": "本地范围:仅在选定项目中可用",
+ "cannotChange": "编辑现有服务器时无法更改范围"
+ },
+ "fields": {
+ "serverName": "服务器名称",
+ "transportType": "传输类型",
+ "command": "命令",
+ "arguments": "参数(每行一个)",
+ "jsonConfig": "JSON 配置",
+ "url": "URL",
+ "envVars": "环境变量(KEY=值,每行一个)",
+ "headers": "请求头(KEY=值,每行一个)",
+ "selectProject": "选择项目..."
+ },
+ "placeholders": {
+ "serverName": "我的服务"
+ },
+ "validation": {
+ "missingType": "缺少必填字段:type",
+ "stdioRequiresCommand": "stdio 类型需要 command 字段",
+ "httpRequiresUrl": "{{type}} 类型需要 url 字段",
+ "invalidJson": "无效的 JSON 格式",
+ "jsonHelp": "粘贴您的 MCP 服务器配置(JSON 格式)。示例格式:",
+ "jsonExampleStdio": "• stdio: {\"type\":\"stdio\",\"command\":\"npx\",\"args\":[\"@upstash/context7-mcp\"]}",
+ "jsonExampleHttp": "• http/sse: {\"type\":\"http\",\"url\":\"https://api.example.com/mcp\"}"
+ },
+ "configDetails": "配置详细信息(来自 {{configFile}})",
+ "projectPath": "路径:{{path}}",
+ "actions": {
+ "cancel": "取消",
+ "saving": "保存中...",
+ "addServer": "添加服务器",
+ "updateServer": "更新服务器"
+ }
+ },
+ "saveStatus": {
+ "success": "设置保存成功!",
+ "error": "保存设置失败",
+ "saving": "保存中..."
+ },
+ "footerActions": {
+ "save": "保存设置",
+ "cancel": "取消"
+ },
+ "git": {
+ "title": "Git 配置",
+ "description": "配置您的 git 提交身份。这些设置将通过 git config --global 全局应用",
+ "name": {
+ "label": "Git 名称",
+ "help": "您的 git 提交名称"
+ },
+ "email": {
+ "label": "Git 邮箱",
+ "help": "您的 git 提交邮箱"
+ },
+ "actions": {
+ "save": "保存配置",
+ "saving": "保存中..."
+ },
+ "status": {
+ "success": "保存成功"
+ }
+ },
+ "apiKeys": {
+ "title": "API 密钥",
+ "description": "生成 API 密钥以从其他应用访问外部 API。",
+ "newKey": {
+ "alertTitle": "⚠️ 保存您的 API 密钥",
+ "alertMessage": "这是您唯一一次看到此密钥。请妥善保存。",
+ "iveSavedIt": "我已保存"
+ },
+ "form": {
+ "placeholder": "API 密钥名称(例如:生产服务器)",
+ "createButton": "创建",
+ "cancelButton": "取消"
+ },
+ "newButton": "新建 API 密钥",
+ "empty": "尚未创建 API 密钥。",
+ "list": {
+ "created": "创建时间:",
+ "lastUsed": "最后使用:"
+ },
+ "confirmDelete": "确定要删除此 API 密钥吗?",
+ "status": {
+ "active": "激活",
+ "inactive": "未激活"
+ },
+ "github": {
+ "title": "GitHub 令牌",
+ "description": "添加 GitHub 个人访问令牌以通过外部 API 克隆私有仓库。",
+ "descriptionAlt": "添加 GitHub 个人访问令牌以克隆私有仓库。您也可以直接在 API 请求中传递令牌而无需存储。",
+ "addButton": "添加令牌",
+ "form": {
+ "namePlaceholder": "令牌名称(例如:个人仓库)",
+ "tokenPlaceholder": "GitHub 个人访问令牌(ghp_...)",
+ "descriptionPlaceholder": "描述(可选)",
+ "addButton": "添加令牌",
+ "cancelButton": "取消",
+ "howToCreate": "如何创建 GitHub 个人访问令牌 →"
+ },
+ "empty": "尚未添加 GitHub 令牌。",
+ "added": "添加时间:",
+ "confirmDelete": "确定要删除此 GitHub 令牌吗?"
+ },
+ "apiDocsLink": "API 文档",
+ "documentation": {
+ "title": "外部 API 文档",
+ "description": "了解如何使用外部 API 从您的应用程序触发 Claude/Cursor 会话。",
+ "viewLink": "查看 API 文档 →"
+ },
+ "loading": "加载中...",
+ "version": {
+ "updateAvailable": "有可用更新:v{{version}}"
+ }
+ },
+ "tasks": {
+ "checking": "正在检查 TaskMaster 安装...",
+ "notInstalled": {
+ "title": "未安装 TaskMaster AI CLI",
+ "description": "需要 TaskMaster CLI 才能使用任务管理功能。安装它以开始使用:",
+ "installCommand": "npm install -g task-master-ai",
+ "viewOnGitHub": "在 GitHub 上查看",
+ "afterInstallation": "安装后:",
+ "steps": {
+ "restart": "重启此应用程序",
+ "autoAvailable": "TaskMaster 功能将自动可用",
+ "initCommand": "在项目目录中使用 task-master init"
+ }
+ },
+ "settings": {
+ "enableLabel": "启用 TaskMaster 集成",
+ "enableDescription": "在整个界面中显示 TaskMaster 任务、横幅和侧边栏指示器"
+ }
+ },
+ "agents": {
+ "authStatus": {
+ "checking": "检查中...",
+ "connected": "已连接",
+ "notConnected": "未连接",
+ "disconnected": "已断开",
+ "checkingAuth": "正在检查认证状态...",
+ "loggedInAs": "登录为 {{email}}",
+ "authenticatedUser": "已认证用户"
+ },
+ "account": {
+ "claude": {
+ "description": "Anthropic Claude AI 助手"
+ },
+ "cursor": {
+ "description": "Cursor AI 驱动的代码编辑器"
+ },
+ "codex": {
+ "description": "OpenAI Codex AI 助手"
+ }
+ },
+ "connectionStatus": "连接状态",
+ "login": {
+ "title": "登录",
+ "reAuthenticate": "重新认证",
+ "description": "登录您的 {{agent}} 账户以启用 AI 功能",
+ "reAuthDescription": "使用其他账户登录或刷新凭据",
+ "button": "登录",
+ "reLoginButton": "重新登录"
+ },
+ "error": "错误:{{error}}"
+ },
+ "permissions": {
+ "title": "权限设置",
+ "skipPermissions": {
+ "label": "跳过权限提示(请谨慎使用)",
+ "claudeDescription": "等同于 --dangerously-skip-permissions 标志",
+ "cursorDescription": "等同于 Cursor CLI 中的 -f 标志"
+ },
+ "allowedTools": {
+ "title": "允许的工具",
+ "description": "无需权限提示即可自动使用的工具",
+ "placeholder": "例如:\"Bash(git log:*)\" 或 \"Write\"",
+ "quickAdd": "快速添加常用工具:",
+ "empty": "未配置允许的工具"
+ },
+ "blockedTools": {
+ "title": "禁用的工具",
+ "description": "无需权限提示即可自动禁用的工具",
+ "placeholder": "例如:\"Bash(rm:*)\"",
+ "empty": "未配置禁用的工具"
+ },
+ "allowedCommands": {
+ "title": "允许的 Shell 命令",
+ "description": "无需权限提示即可自动执行的 Shell 命令",
+ "placeholder": "例如:\"Shell(ls)\" 或 \"Shell(git status)\"",
+ "quickAdd": "快速添加常用命令:",
+ "empty": "未配置允许的命令"
+ },
+ "blockedCommands": {
+ "title": "阻止的 Shell 命令",
+ "description": "自动阻止的 Shell 命令",
+ "placeholder": "例如:\"Shell(rm -rf)\" 或 \"Shell(sudo)\"",
+ "empty": "未配置阻止的命令"
+ },
+ "toolExamples": {
+ "title": "工具模式示例:",
+ "bashGitLog": "- 允许所有 git log 命令",
+ "bashGitDiff": "- 允许所有 git diff 命令",
+ "write": "- 允许所有 Write 工具使用",
+ "bashRm": "- 阻止所有 rm 命令(危险)"
+ },
+ "shellExamples": {
+ "title": "Shell 命令示例:",
+ "ls": "- 允许 ls 命令",
+ "gitStatus": "- 允许 git status",
+ "npmInstall": "- 允许 npm install",
+ "rmRf": "- 阻止递归删除"
+ },
+ "codex": {
+ "permissionMode": "权限模式",
+ "description": "控制 Codex 如何处理文件修改和命令执行",
+ "modes": {
+ "default": {
+ "title": "默认",
+ "description": "只有受信任的命令(ls、cat、grep、git status 等)会自动运行。其他命令将被跳过。可以写入工作区。"
+ },
+ "acceptEdits": {
+ "title": "接受编辑",
+ "description": "所有命令在工作区内自动运行。具有沙箱执行的全自动模式。"
+ },
+ "bypassPermissions": {
+ "title": "绕过权限",
+ "description": "完全系统访问,无任何限制。所有命令自动运行,具有完整的磁盘和网络访问权限。请谨慎使用。"
+ }
+ },
+ "technicalDetails": "技术详情",
+ "technicalInfo": {
+ "default": "sandboxMode=workspace-write, approvalPolicy=untrusted。受信任的命令:cat、cd、grep、head、ls、pwd、tail、git status/log/diff/show、find(不带 -exec)等。",
+ "acceptEdits": "sandboxMode=workspace-write, approvalPolicy=never。所有命令在项目目录内自动执行。",
+ "bypassPermissions": "sandboxMode=danger-full-access, approvalPolicy=never。完全系统访问权限,仅在可信环境中使用。",
+ "overrideNote": "您可以使用聊天界面中的模式按钮按会话覆盖此设置。"
+ }
+ },
+ "actions": {
+ "add": "添加"
+ }
+ },
+ "mcpServers": {
+ "title": "MCP 服务器",
+ "description": {
+ "claude": "Model Context Protocol 服务器为 Claude 提供额外的工具和数据源",
+ "cursor": "Model Context Protocol 服务器为 Cursor 提供额外的工具和数据源",
+ "codex": "Model Context Protocol 服务器为 Codex 提供额外的工具和数据源"
+ },
+ "addButton": "添加 MCP 服务器",
+ "empty": "未配置 MCP 服务器",
+ "serverType": "类型",
+ "scope": {
+ "local": "本地",
+ "user": "用户"
+ },
+ "config": {
+ "command": "命令",
+ "url": "URL",
+ "args": "参数",
+ "environment": "环境变量"
+ },
+ "tools": {
+ "title": "工具",
+ "count": "({{count}}):",
+ "more": "还有 {{count}} 个"
+ },
+ "actions": {
+ "edit": "编辑服务器",
+ "delete": "删除服务器"
+ },
+ "help": {
+ "title": "关于 Codex MCP",
+ "description": "Codex 支持基于 stdio 的 MCP 服务器。您可以添加服务器,通过额外的工具和资源来扩展 Codex 的功能。"
+ }
+ }
+}
diff --git a/src/i18n/locales/zh-CN/sidebar.json b/src/i18n/locales/zh-CN/sidebar.json
new file mode 100644
index 00000000..e5e3c655
--- /dev/null
+++ b/src/i18n/locales/zh-CN/sidebar.json
@@ -0,0 +1,102 @@
+{
+ "projects": {
+ "title": "项目",
+ "newProject": "新建项目",
+ "deleteProject": "删除项目",
+ "renameProject": "重命名项目",
+ "noProjects": "未找到项目",
+ "loadingProjects": "加载项目中...",
+ "searchPlaceholder": "搜索项目...",
+ "projectNamePlaceholder": "项目名称",
+ "starred": "星标",
+ "all": "全部",
+ "untitledSession": "未命名会话",
+ "newSession": "新会话",
+ "codexSession": "Codex 会话",
+ "fetchingProjects": "正在获取您的 Claude 项目和会话",
+ "noMatchingProjects": "未找到匹配的项目",
+ "tryDifferentSearch": "尝试调整您的搜索词",
+ "runClaudeCli": "在项目目录中运行 Claude CLI 以开始使用"
+ },
+ "app": {
+ "title": "Claude Code UI",
+ "subtitle": "AI 编程助手"
+ },
+ "sessions": {
+ "title": "会话",
+ "newSession": "新建会话",
+ "deleteSession": "删除会话",
+ "renameSession": "重命名会话",
+ "noSessions": "暂无会话",
+ "loadingSessions": "加载会话中...",
+ "unnamed": "未命名",
+ "loading": "加载中...",
+ "showMore": "显示更多会话"
+ },
+ "tooltips": {
+ "viewEnvironments": "查看环境",
+ "hideSidebar": "隐藏侧边栏",
+ "createProject": "创建新项目",
+ "refresh": "刷新项目和会话 (Ctrl+R)",
+ "renameProject": "重命名项目 (F2)",
+ "deleteProject": "删除空项目 (Delete)",
+ "addToFavorites": "添加到收藏",
+ "removeFromFavorites": "从收藏移除",
+ "editSessionName": "手动编辑会话名称",
+ "deleteSession": "永久删除此会话",
+ "save": "保存",
+ "cancel": "取消"
+ },
+ "navigation": {
+ "chat": "聊天",
+ "files": "文件",
+ "git": "Git",
+ "terminal": "终端",
+ "tasks": "任务"
+ },
+ "actions": {
+ "refresh": "刷新",
+ "settings": "设置",
+ "collapseAll": "全部折叠",
+ "expandAll": "全部展开",
+ "cancel": "取消",
+ "save": "保存",
+ "delete": "删除",
+ "rename": "重命名"
+ },
+ "status": {
+ "active": "活动",
+ "inactive": "非活动",
+ "thinking": "思考中...",
+ "error": "错误",
+ "aborted": "已中止",
+ "unknown": "未知"
+ },
+ "time": {
+ "justNow": "刚刚",
+ "oneMinuteAgo": "1 分钟前",
+ "minutesAgo": "{{count}} 分钟前",
+ "oneHourAgo": "1 小时前",
+ "hoursAgo": "{{count}} 小时前",
+ "oneDayAgo": "1 天前",
+ "daysAgo": "{{count}} 天前"
+ },
+ "messages": {
+ "deleteConfirm": "确定要删除吗?",
+ "renameSuccess": "重命名成功",
+ "deleteSuccess": "删除成功",
+ "errorOccurred": "发生错误",
+ "deleteSessionConfirm": "确定要删除此会话吗?此操作无法撤销。",
+ "deleteProjectConfirm": "确定要删除此空项目吗?此操作无法撤销。",
+ "enterProjectPath": "请输入项目路径",
+ "deleteSessionFailed": "删除会话失败,请重试。",
+ "deleteSessionError": "删除会话时出错,请重试。",
+ "deleteProjectFailed": "删除项目失败,请重试。",
+ "deleteProjectError": "删除项目时出错,请重试。",
+ "createProjectFailed": "创建项目失败,请重试。",
+ "createProjectError": "创建项目时出错,请重试。"
+ },
+ "version": {
+ "updateAvailable": "有可用更新"
+ }
+}
diff --git a/src/main.jsx b/src/main.jsx
index f80d47a7..02ca6b13 100644
--- a/src/main.jsx
+++ b/src/main.jsx
@@ -4,6 +4,9 @@ import App from './App.jsx'
import './index.css'
import 'katex/dist/katex.min.css'
+// Initialize i18n
+import './i18n/config.js'
+
// Clean up stale service workers on app load to prevent caching issues after builds
if ('serviceWorker' in navigator) {
navigator.serviceWorker.getRegistrations().then(registrations => {