Files
Claude-Code-Workflow/ccw/frontend/src/test/i18n.tsx
catlog22 75173312c1 feat(queue): implement queue scheduler service and API routes
- Added QueueSchedulerService to manage task queue lifecycle, including state machine, dependency resolution, and session management.
- Implemented HTTP API endpoints for queue scheduling:
  - POST /api/queue/execute: Submit items to the scheduler.
  - GET /api/queue/scheduler/state: Retrieve full scheduler state.
  - POST /api/queue/scheduler/start: Start scheduling loop with items.
  - POST /api/queue/scheduler/pause: Pause scheduling.
  - POST /api/queue/scheduler/stop: Graceful stop of the scheduler.
  - POST /api/queue/scheduler/config: Update scheduler configuration.
- Introduced types for queue items, scheduler state, and WebSocket messages to ensure type safety and compatibility with the backend.
- Added static model lists for LiteLLM as a fallback for available models.
2026-02-27 20:53:46 +08:00

755 lines
37 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ========================================
// i18n Test Helpers
// ========================================
// Test utilities for internationalization
import { render as originalRender, type RenderOptions } from '@testing-library/react';
import { ReactElement } from 'react';
import { IntlProvider } from 'react-intl';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { MemoryRouter } from 'react-router-dom';
import { vi } from 'vitest';
import type { Locale } from '../types/store';
// Mock translation messages for testing
const mockMessages: Record<Locale, Record<string, string>> = {
en: {
// Common
'common.appName': 'CCW',
'common.save': 'Save',
'common.cancel': 'Cancel',
'common.delete': 'Delete',
'common.edit': 'Edit',
'common.close': 'Close',
'common.loading': 'Loading...',
'common.error': 'Error',
'common.success': 'Success',
'common.actions.cancel': 'Cancel',
'common.actions.submit': 'Submit',
'common.actions.close': 'Close',
// Aria labels
'common.aria.toggleNavigation': 'Toggle navigation',
'common.aria.switchToDarkMode': 'Switch to dark mode',
'common.aria.switchToLightMode': 'Switch to light mode',
'common.aria.refreshWorkspace': 'Refresh workspace',
'common.aria.userMenu': 'User menu',
// Navigation - Header
'navigation.header.brand': 'CCW Dashboard',
'navigation.header.brandShort': 'CCW',
'navigation.header.noProject': 'No project selected',
'navigation.header.settings': 'Settings',
'navigation.header.logout': 'Logout',
// Navigation - Sidebar
'navigation.home': 'Home',
'navigation.sessions': 'Sessions',
'navigation.issues': 'Issues',
'navigation.orchestrator': 'Orchestrator',
'navigation.settings': 'Settings',
// Workspace selector
'workspace.selector.noWorkspace': 'No workspace selected',
'workspace.selector.recentPaths': 'Recent Projects',
'workspace.selector.noRecentPaths': 'No recent projects',
'workspace.selector.current': 'Current',
'workspace.selector.browse': 'Select Folder...',
'workspace.selector.removePath': 'Remove from recent',
'workspace.selector.ariaLabel': 'Workspace selector',
'workspace.selector.dialog.title': 'Select Project Folder',
'workspace.selector.dialog.placeholder': 'Enter project path...',
// Notifications
'common.aria.notifications': 'Notifications',
'common.actions.refresh': 'Refresh',
'common.actions.resetLayout': 'Reset Layout',
// Dashboard
'home.dashboard.title': 'Dashboard',
'home.dashboard.description': 'Monitor your project activity and metrics',
'home.dashboard.refreshTooltip': 'Refresh dashboard data',
// Issues - Queue
'issues.queue.pageTitle': 'Issue Queue',
'issues.queue.pageDescription': 'Manage issue execution queue with execution groups',
'issues.queue.title': 'Queue',
'issues.queue.stats.totalItems': 'Total Items',
'issues.queue.stats.groups': 'Groups',
'issues.queue.stats.tasks': 'Tasks',
'issues.queue.stats.solutions': 'Solutions',
'issues.queue.status.active': 'Active',
'issues.queue.status.inactive': 'Inactive',
'issues.queue.status.ready': 'Ready',
'issues.queue.status.pending': 'Pending',
'issues.queue.items': 'Items',
'issues.queue.groups': 'Groups',
'issues.queue.conflicts': 'conflicts',
'issues.queue.conflicts.title': 'Conflicts Detected',
'issues.queue.conflicts.description': 'conflicts detected in queue',
'issues.queue.parallelGroup': 'Parallel',
'issues.queue.sequentialGroup': 'Sequential',
'issues.queue.executionGroups': 'Execution Groups',
'issues.queue.empty': 'No items in queue',
'issues.queue.emptyState.title': 'No Queue Data',
'issues.queue.emptyState.description': 'No queue data available',
'issues.queue.error.title': 'Error Loading Queue',
'issues.queue.error.message': 'Failed to load queue data',
'issues.queue.actions.activate': 'Activate',
'issues.queue.actions.deactivate': 'Deactivate',
'issues.queue.actions.delete': 'Delete',
'issues.queue.actions.merge': 'Merge',
'issues.queue.deleteDialog.title': 'Delete Queue',
'issues.queue.deleteDialog.description': 'Are you sure you want to delete this queue?',
'issues.queue.mergeDialog.title': 'Merge Queues',
'issues.queue.mergeDialog.targetQueueLabel': 'Target Queue',
'issues.queue.mergeDialog.targetQueuePlaceholder': 'Select target queue',
'common.actions.openMenu': 'Open menu',
// Issues - Discovery
'issues.discovery.title': 'Issue Discovery',
'issues.discovery.pageTitle': 'Issue Discovery',
'issues.discovery.description': 'View and manage issue discovery sessions',
'issues.discovery.totalSessions': 'Total Sessions',
'issues.discovery.completedSessions': 'Completed',
'issues.discovery.runningSessions': 'Running',
'issues.discovery.totalFindings': 'Total Findings',
'issues.discovery.sessionList': 'Sessions',
'issues.discovery.findingsDetail': 'Findings Detail',
'issues.discovery.noSessions': 'No Sessions',
'issues.discovery.noSessionsDescription': 'No discovery sessions found',
'issues.discovery.noSessionSelected': 'Select a session to view findings',
'issues.discovery.status.running': 'Running',
'issues.discovery.status.completed': 'Completed',
'issues.discovery.status.failed': 'Failed',
'issues.discovery.progress': 'Progress',
'issues.discovery.findings': 'Findings',
// CodexLens
'codexlens.title': 'CodexLens',
'codexlens.description': 'Semantic code search engine',
'codexlens.bootstrap': 'Bootstrap',
'codexlens.bootstrapping': 'Bootstrapping...',
'codexlens.uninstall': 'Uninstall',
'codexlens.uninstalling': 'Uninstalling...',
'codexlens.confirmUninstall': 'Are you sure you want to uninstall CodexLens?',
'codexlens.notInstalled': 'CodexLens is not installed',
'codexlens.comingSoon': 'Coming Soon',
'codexlens.tabs.overview': 'Overview',
'codexlens.tabs.settings': 'Settings',
'codexlens.tabs.models': 'Models',
'codexlens.tabs.advanced': 'Advanced',
'codexlens.overview.status.installation': 'Installation Status',
'codexlens.overview.status.ready': 'Ready',
'codexlens.overview.status.notReady': 'Not Ready',
'codexlens.overview.status.version': 'Version',
'codexlens.overview.status.indexPath': 'Index Path',
'codexlens.overview.status.indexCount': 'Index Count',
'codexlens.overview.notInstalled.title': 'CodexLens Not Installed',
'codexlens.overview.notInstalled.message': 'Please install CodexLens to use semantic code search features.',
'codexlens.overview.actions.title': 'Quick Actions',
'codexlens.overview.actions.ftsFull': 'FTS Full',
'codexlens.overview.actions.ftsFullDesc': 'Rebuild full-text index',
'codexlens.overview.actions.ftsIncremental': 'FTS Incremental',
'codexlens.overview.actions.ftsIncrementalDesc': 'Incremental update full-text index',
'codexlens.overview.actions.vectorFull': 'Vector Full',
'codexlens.overview.actions.vectorFullDesc': 'Rebuild vector index',
'codexlens.overview.actions.vectorIncremental': 'Vector Incremental',
'codexlens.overview.actions.vectorIncrementalDesc': 'Incremental update vector index',
'codexlens.overview.venv.title': 'Python Virtual Environment Details',
'codexlens.overview.venv.pythonVersion': 'Python Version',
'codexlens.overview.venv.venvPath': 'Virtual Environment Path',
'codexlens.overview.venv.lastCheck': 'Last Check Time',
'codexlens.install.title': 'Install CodexLens',
// Env Groups & Fields
'codexlens.envGroup.embedding': 'Embedding',
'codexlens.envGroup.reranker': 'Reranker',
'codexlens.envGroup.concurrency': 'Concurrency',
'codexlens.envGroup.cascade': 'Cascade Search',
'codexlens.envGroup.indexing': 'Indexing',
'codexlens.envGroup.chunking': 'Chunking',
'codexlens.envField.backend': 'Backend',
'codexlens.envField.model': 'Model',
'codexlens.envField.useGpu': 'Use GPU',
'codexlens.envField.highAvailability': 'High Availability',
'codexlens.envField.loadBalanceStrategy': 'Load Balance Strategy',
'codexlens.envField.rateLimitCooldown': 'Rate Limit Cooldown',
'codexlens.envField.enabled': 'Enabled',
'codexlens.envField.topKResults': 'Top K Results',
'codexlens.envField.maxWorkers': 'Max Workers',
'codexlens.envField.batchSize': 'Batch Size',
'codexlens.envField.dynamicBatchSize': 'Dynamic Batch Size',
'codexlens.envField.batchSizeUtilization': 'Utilization Factor',
'codexlens.envField.batchSizeMax': 'Max Batch Size',
'codexlens.envField.charsPerToken': 'Chars Per Token',
'codexlens.envField.searchStrategy': 'Search Strategy',
'codexlens.envField.coarseK': 'Coarse K',
'codexlens.envField.fineK': 'Fine K',
'codexlens.envField.stagedStage2Mode': 'Stage-2 Mode',
'codexlens.envField.stagedClusteringStrategy': 'Clustering Strategy',
'codexlens.envField.stagedClusteringMinSize': 'Cluster Min Size',
'codexlens.envField.enableStagedRerank': 'Enable Rerank',
'codexlens.envField.useAstGrep': 'Use ast-grep',
'codexlens.envField.staticGraphEnabled': 'Static Graph',
'codexlens.envField.staticGraphRelationshipTypes': 'Relationship Types',
'codexlens.envField.stripComments': 'Strip Comments',
'codexlens.envField.stripDocstrings': 'Strip Docstrings',
'codexlens.envField.testFilePenalty': 'Test File Penalty',
'codexlens.envField.docstringWeight': 'Docstring Weight',
'codexlens.install.description': 'Set up Python virtual environment and install CodexLens package.',
'codexlens.install.checklist': 'What will be installed',
'codexlens.install.pythonVenv': 'Python Virtual Environment',
'codexlens.install.pythonVenvDesc': 'Isolated Python environment for CodexLens',
'codexlens.install.codexlensPackage': 'CodexLens Package',
'codexlens.install.codexlensPackageDesc': 'Core semantic code search engine',
'codexlens.install.sqliteFts': 'SQLite FTS5',
'codexlens.install.sqliteFtsDesc': 'Full-text search extension for fast code lookup',
'codexlens.install.location': 'Install Location',
'codexlens.install.locationPath': '~/.codexlens/venv',
'codexlens.install.timeEstimate': 'Installation may take 1-3 minutes depending on network speed.',
'codexlens.install.stage.creatingVenv': 'Creating Python virtual environment...',
'codexlens.install.stage.installingPip': 'Installing pip dependencies...',
'codexlens.install.stage.installingPackage': 'Installing CodexLens package...',
'codexlens.install.stage.settingUpDeps': 'Setting up dependencies...',
'codexlens.install.stage.finalizing': 'Finalizing installation...',
'codexlens.install.stage.complete': 'Installation complete!',
'codexlens.install.installNow': 'Install Now',
'codexlens.install.installing': 'Installing...',
'codexlens.watcher.title': 'File Watcher',
'codexlens.watcher.status.running': 'Running',
'codexlens.watcher.status.stopped': 'Stopped',
'codexlens.watcher.eventsProcessed': 'Events Processed',
'codexlens.watcher.uptime': 'Uptime',
'codexlens.watcher.start': 'Start Watcher',
'codexlens.watcher.starting': 'Starting...',
'codexlens.watcher.stop': 'Stop Watcher',
'codexlens.watcher.stopping': 'Stopping...',
'codexlens.watcher.started': 'File watcher started',
'codexlens.watcher.stopped': 'File watcher stopped',
'codexlens.settings.currentCount': 'Current Index Count',
'codexlens.settings.currentWorkers': 'Current Workers',
'codexlens.settings.currentBatchSize': 'Current Batch Size',
'codexlens.settings.configTitle': 'Basic Configuration',
'codexlens.settings.indexDir.label': 'Index Directory',
'codexlens.settings.indexDir.placeholder': '~/.codexlens/indexes',
'codexlens.settings.indexDir.hint': 'Directory path for storing code indexes',
'codexlens.settings.maxWorkers.label': 'Max Workers',
'codexlens.settings.maxWorkers.hint': 'API concurrent processing threads (1-32)',
'codexlens.settings.batchSize.label': 'Batch Size',
'codexlens.settings.batchSize.hint': 'Number of files processed per batch (1-64)',
'codexlens.settings.validation.indexDirRequired': 'Index directory is required',
'codexlens.settings.validation.maxWorkersRange': 'Workers must be between 1 and 32',
'codexlens.settings.validation.batchSizeRange': 'Batch size must be between 1 and 64',
'codexlens.settings.save': 'Save',
'codexlens.settings.saving': 'Saving...',
'codexlens.settings.reset': 'Reset',
'codexlens.settings.saveSuccess': 'Configuration saved',
'codexlens.settings.saveFailed': 'Save failed',
'codexlens.settings.configUpdated': 'Configuration updated successfully',
'codexlens.settings.saveError': 'Error saving configuration',
'codexlens.settings.unknownError': 'An unknown error occurred',
'codexlens.models.title': 'Model Management',
'codexlens.models.searchPlaceholder': 'Search models...',
'codexlens.models.downloading': 'Downloading...',
'codexlens.models.status.downloaded': 'Downloaded',
'codexlens.models.status.available': 'Available',
'codexlens.models.types.embedding': 'Embedding Models',
'codexlens.models.types.reranker': 'Reranker Models',
'codexlens.models.filters.label': 'Filter',
'codexlens.models.filters.all': 'All',
'codexlens.models.actions.download': 'Download',
'codexlens.models.actions.delete': 'Delete',
'codexlens.models.actions.cancel': 'Cancel',
'codexlens.models.custom.title': 'Custom Model',
'codexlens.models.custom.placeholder': 'HuggingFace model name (e.g., BAAI/bge-small-zh-v1.5)',
'codexlens.models.custom.description': 'Download custom models from HuggingFace. Ensure the model name is correct.',
'codexlens.models.deleteConfirm': 'Are you sure you want to delete model {modelName}?',
'codexlens.models.notInstalled.title': 'CodexLens Not Installed',
'codexlens.models.notInstalled.description': 'Please install CodexLens to use model management features.',
'codexlens.models.empty.title': 'No models found',
'codexlens.models.empty.description': 'Try adjusting your search or filter criteria',
// Reranker
'codexlens.reranker.title': 'Reranker Configuration',
'codexlens.reranker.description': 'Configure the reranker backend, model, and provider for search result ranking.',
'codexlens.reranker.backend': 'Backend',
'codexlens.reranker.backendHint': 'Inference backend for reranking',
'codexlens.reranker.model': 'Model',
'codexlens.reranker.modelHint': 'Reranker model name or LiteLLM endpoint',
'codexlens.reranker.provider': 'API Provider',
'codexlens.reranker.providerHint': 'API provider for reranker service',
'codexlens.reranker.apiKeyStatus': 'API Key',
'codexlens.reranker.apiKeySet': 'Configured',
'codexlens.reranker.apiKeyNotSet': 'Not configured',
'codexlens.reranker.configSource': 'Config Source',
'codexlens.reranker.save': 'Save Reranker Config',
'codexlens.reranker.saving': 'Saving...',
'codexlens.reranker.saveSuccess': 'Reranker configuration saved',
'codexlens.reranker.saveFailed': 'Failed to save reranker configuration',
'codexlens.reranker.noBackends': 'No backends available',
'codexlens.reranker.noModels': 'No models available',
'codexlens.reranker.noProviders': 'No providers available',
'codexlens.reranker.litellmModels': 'LiteLLM Models',
'codexlens.reranker.selectBackend': 'Select backend...',
'codexlens.reranker.selectModel': 'Select model...',
'codexlens.reranker.selectProvider': 'Select provider...',
// MCP - CCW Tools
'mcp.ccw.title': 'CCW MCP Server',
'mcp.ccw.description': 'Configure CCW MCP tools and paths',
'mcp.ccw.status.installed': 'Installed',
'mcp.ccw.status.notInstalled': 'Not installed',
'mcp.ccw.status.special': 'Special',
'mcp.ccw.actions.enableAll': 'Enable All',
'mcp.ccw.actions.disableAll': 'Disable All',
'mcp.ccw.actions.saveConfig': 'Save Configuration',
'mcp.ccw.actions.saving': 'Saving...',
'mcp.ccw.actions.installing': 'Installing...',
'mcp.ccw.actions.uninstall': 'Uninstall',
'mcp.ccw.actions.uninstalling': 'Uninstalling...',
'mcp.ccw.actions.uninstallConfirm': 'Are you sure you want to uninstall?',
'mcp.ccw.actions.uninstallScopeConfirm': 'Are you sure you want to uninstall from this scope?',
'mcp.ccw.codexNote': 'Codex only supports global installation',
'mcp.ccw.tools.label': 'Tools',
'mcp.ccw.tools.hint': 'Install to edit tools',
'mcp.ccw.tools.core': 'Core',
'mcp.ccw.tools.write_file.name': 'Write File',
'mcp.ccw.tools.write_file.desc': 'Write/create files',
'mcp.ccw.tools.edit_file.name': 'Edit File',
'mcp.ccw.tools.edit_file.desc': 'Edit/replace content',
'mcp.ccw.tools.read_file.name': 'Read File',
'mcp.ccw.tools.read_file.desc': 'Read single file',
'mcp.ccw.tools.read_many_files.name': 'Read Many Files',
'mcp.ccw.tools.read_many_files.desc': 'Read multiple files/dirs',
'mcp.ccw.tools.core_memory.name': 'Core Memory',
'mcp.ccw.tools.core_memory.desc': 'Core memory management',
'mcp.ccw.tools.ask_question.name': 'Ask Question',
'mcp.ccw.tools.ask_question.desc': 'Interactive questions (A2UI)',
'mcp.ccw.tools.smart_search.name': 'Smart Search',
'mcp.ccw.tools.smart_search.desc': 'Intelligent code search',
'mcp.ccw.tools.team_msg.name': 'Team Message',
'mcp.ccw.tools.team_msg.desc': 'Agent team message bus',
'mcp.ccw.paths.label': 'Paths',
'mcp.ccw.paths.projectRoot': 'Project Root',
'mcp.ccw.paths.projectRootPlaceholder': 'e.g. D:\\path\\to\\project',
'mcp.ccw.paths.allowedDirs': 'Allowed Directories',
'mcp.ccw.paths.allowedDirsPlaceholder': 'Comma-separated directories',
'mcp.ccw.paths.allowedDirsHint': 'Separate multiple directories with commas',
'mcp.ccw.paths.enableSandbox': 'Enable Sandbox',
'mcp.ccw.scope.installToGlobal': 'Install to Global',
'mcp.ccw.scope.installToProject': 'Install to Project',
'mcp.ccw.scope.uninstallGlobal': 'Uninstall Global',
'mcp.ccw.scope.uninstallProject': 'Uninstall Project',
'mcp.ccw.feedback.saveSuccess': 'Configuration saved',
'mcp.ccw.feedback.saveError': 'Failed to save configuration',
'navigation.codexlens': 'CodexLens',
},
zh: {
// Common
'common.appName': 'CCW',
'common.save': '保存',
'common.cancel': '取消',
'common.delete': '删除',
'common.edit': '编辑',
'common.close': '关闭',
'common.loading': '加载中...',
'common.error': '错误',
'common.success': '成功',
'common.actions.cancel': '取消',
'common.actions.submit': '提交',
'common.actions.close': '关闭',
// Aria labels
'common.aria.toggleNavigation': '切换导航',
'common.aria.switchToDarkMode': '切换到深色模式',
'common.aria.switchToLightMode': '切换到浅色模式',
'common.aria.refreshWorkspace': '刷新工作区',
'common.aria.userMenu': '用户菜单',
// Navigation - Header
'navigation.header.brand': 'CCW 控制台',
'navigation.header.brandShort': 'CCW',
'navigation.header.noProject': '未选择项目',
'navigation.header.settings': '设置',
'navigation.header.logout': '退出登录',
// Navigation - Sidebar
'navigation.home': '首页',
'navigation.sessions': '会话',
'navigation.issues': '问题',
'navigation.orchestrator': '编排器',
'navigation.settings': '设置',
// Workspace selector
'workspace.selector.noWorkspace': '未选择工作空间',
'workspace.selector.recentPaths': '最近的项目',
'workspace.selector.noRecentPaths': '没有最近的项目',
'workspace.selector.current': '当前',
'workspace.selector.browse': '选择文件夹...',
'workspace.selector.removePath': '从最近记录中移除',
'workspace.selector.ariaLabel': '工作空间选择器',
'workspace.selector.dialog.title': '选择项目文件夹',
'workspace.selector.dialog.placeholder': '输入项目路径...',
// Notifications
'common.aria.notifications': '通知',
'common.actions.refresh': '刷新',
'common.actions.resetLayout': '重置布局',
// Dashboard
'home.dashboard.title': '仪表盘',
'home.dashboard.description': '监控您的项目活动和指标',
'home.dashboard.refreshTooltip': '刷新仪表盘数据',
// Issues - Queue
'issues.queue.pageTitle': '问题队列',
'issues.queue.pageDescription': '管理问题执行队列和执行组',
'issues.queue.title': '队列',
'issues.queue.stats.totalItems': '总项目',
'issues.queue.stats.groups': '执行组',
'issues.queue.stats.tasks': '任务',
'issues.queue.stats.solutions': '解决方案',
'issues.queue.status.active': '活跃',
'issues.queue.status.inactive': '未激活',
'issues.queue.status.ready': '就绪',
'issues.queue.status.pending': '等待中',
'issues.queue.items': '项目',
'issues.queue.groups': '执行组',
'issues.queue.conflicts': '冲突',
'issues.queue.conflicts.title': '检测到冲突',
'issues.queue.conflicts.description': '队列中检测到冲突',
'issues.queue.parallelGroup': '并行',
'issues.queue.sequentialGroup': '顺序',
'issues.queue.executionGroups': '执行组',
'issues.queue.empty': '队列中无项目',
'issues.queue.emptyState.title': '无队列数据',
'issues.queue.emptyState.description': '无队列数据可用',
'issues.queue.error.title': '加载队列错误',
'issues.queue.error.message': '加载队列数据失败',
'issues.queue.actions.activate': '激活',
'issues.queue.actions.deactivate': '停用',
'issues.queue.actions.delete': '删除',
'issues.queue.actions.merge': '合并',
'issues.queue.deleteDialog.title': '删除队列',
'issues.queue.deleteDialog.description': '确定要删除此队列吗?',
'issues.queue.mergeDialog.title': '合并队列',
'issues.queue.mergeDialog.targetQueueLabel': '目标队列',
'issues.queue.mergeDialog.targetQueuePlaceholder': '选择目标队列',
'common.actions.openMenu': '打开菜单',
// Issues - Discovery
'issues.discovery.title': '问题发现',
'issues.discovery.pageTitle': '问题发现',
'issues.discovery.description': '查看和管理问题发现会话',
'issues.discovery.totalSessions': '总会话数',
'issues.discovery.completedSessions': '已完成',
'issues.discovery.runningSessions': '运行中',
'issues.discovery.totalFindings': '总发现数',
'issues.discovery.sessionList': '会话',
'issues.discovery.findingsDetail': '发现详情',
'issues.discovery.noSessions': '无会话',
'issues.discovery.noSessionsDescription': '未发现发现会话',
'issues.discovery.noSessionSelected': '选择会话以查看发现',
'issues.discovery.status.running': '运行中',
'issues.discovery.status.completed': '已完成',
'issues.discovery.status.failed': '失败',
'issues.discovery.progress': '进度',
'issues.discovery.findings': '发现',
// CodexLens
'codexlens.title': 'CodexLens',
'codexlens.description': '语义代码搜索引擎',
'codexlens.bootstrap': '引导安装',
'codexlens.bootstrapping': '安装中...',
'codexlens.uninstall': '卸载',
'codexlens.uninstalling': '卸载中...',
'codexlens.confirmUninstall': '确定要卸载 CodexLens 吗?',
'codexlens.notInstalled': 'CodexLens 尚未安装',
'codexlens.comingSoon': '即将推出',
'codexlens.tabs.overview': '概览',
'codexlens.tabs.settings': '设置',
'codexlens.tabs.models': '模型',
'codexlens.tabs.advanced': '高级',
'codexlens.overview.status.installation': '安装状态',
'codexlens.overview.status.ready': '就绪',
'codexlens.overview.status.notReady': '未就绪',
'codexlens.overview.status.version': '版本',
'codexlens.overview.status.indexPath': '索引路径',
'codexlens.overview.status.indexCount': '索引数量',
'codexlens.overview.notInstalled.title': 'CodexLens 未安装',
'codexlens.overview.notInstalled.message': '请先安装 CodexLens 以使用语义代码搜索功能。',
'codexlens.overview.actions.title': '快速操作',
'codexlens.overview.actions.ftsFull': 'FTS 全量',
'codexlens.overview.actions.ftsFullDesc': '重建全文索引',
'codexlens.overview.actions.ftsIncremental': 'FTS 增量',
'codexlens.overview.actions.ftsIncrementalDesc': '增量更新全文索引',
'codexlens.overview.actions.vectorFull': '向量全量',
'codexlens.overview.actions.vectorFullDesc': '重建向量索引',
'codexlens.overview.actions.vectorIncremental': '向量增量',
'codexlens.overview.actions.vectorIncrementalDesc': '增量更新向量索引',
'codexlens.overview.venv.title': 'Python 虚拟环境详情',
'codexlens.overview.venv.pythonVersion': 'Python 版本',
'codexlens.overview.venv.venvPath': '虚拟环境路径',
'codexlens.overview.venv.lastCheck': '最后检查时间',
'codexlens.install.title': '安装 CodexLens',
// Env Groups & Fields
'codexlens.envGroup.embedding': '嵌入模型',
'codexlens.envGroup.reranker': '重排序',
'codexlens.envGroup.concurrency': '并发',
'codexlens.envGroup.cascade': '级联搜索',
'codexlens.envGroup.indexing': '索引与解析',
'codexlens.envGroup.chunking': '分块',
'codexlens.envField.backend': '后端',
'codexlens.envField.model': '模型',
'codexlens.envField.useGpu': '使用 GPU',
'codexlens.envField.highAvailability': '高可用',
'codexlens.envField.loadBalanceStrategy': '负载均衡策略',
'codexlens.envField.rateLimitCooldown': '限流冷却时间',
'codexlens.envField.enabled': '启用',
'codexlens.envField.topKResults': 'Top K 结果数',
'codexlens.envField.maxWorkers': '最大工作线程',
'codexlens.envField.batchSize': '批次大小',
'codexlens.envField.dynamicBatchSize': '动态批次大小',
'codexlens.envField.batchSizeUtilization': '利用率因子',
'codexlens.envField.batchSizeMax': '最大批次大小',
'codexlens.envField.charsPerToken': '每 Token 字符数',
'codexlens.envField.searchStrategy': '搜索策略',
'codexlens.envField.coarseK': '粗筛 K 值',
'codexlens.envField.fineK': '精筛 K 值',
'codexlens.envField.stagedStage2Mode': 'Stage-2 模式',
'codexlens.envField.stagedClusteringStrategy': '聚类策略',
'codexlens.envField.stagedClusteringMinSize': '最小聚类大小',
'codexlens.envField.enableStagedRerank': '启用重排序',
'codexlens.envField.useAstGrep': '使用 ast-grep',
'codexlens.envField.staticGraphEnabled': '启用静态图',
'codexlens.envField.staticGraphRelationshipTypes': '关系类型',
'codexlens.envField.stripComments': '去除注释',
'codexlens.envField.stripDocstrings': '去除文档字符串',
'codexlens.envField.testFilePenalty': '测试文件惩罚',
'codexlens.envField.docstringWeight': '文档字符串权重',
'codexlens.install.description': '设置 Python 虚拟环境并安装 CodexLens 包。',
'codexlens.install.checklist': '将要安装的内容',
'codexlens.install.pythonVenv': 'Python 虚拟环境',
'codexlens.install.pythonVenvDesc': 'CodexLens 的隔离 Python 环境',
'codexlens.install.codexlensPackage': 'CodexLens 包',
'codexlens.install.codexlensPackageDesc': '核心语义代码搜索引擎',
'codexlens.install.sqliteFts': 'SQLite FTS5',
'codexlens.install.sqliteFtsDesc': '用于快速代码查找的全文搜索扩展',
'codexlens.install.location': '安装位置',
'codexlens.install.locationPath': '~/.codexlens/venv',
'codexlens.install.timeEstimate': '安装可能需要 1-3 分钟,取决于网络速度。',
'codexlens.install.stage.creatingVenv': '正在创建 Python 虚拟环境...',
'codexlens.install.stage.installingPip': '正在安装 pip 依赖...',
'codexlens.install.stage.installingPackage': '正在安装 CodexLens 包...',
'codexlens.install.stage.settingUpDeps': '正在设置依赖项...',
'codexlens.install.stage.finalizing': '正在完成安装...',
'codexlens.install.stage.complete': '安装完成!',
'codexlens.install.installNow': '立即安装',
'codexlens.install.installing': '安装中...',
'codexlens.watcher.title': '文件监听器',
'codexlens.watcher.status.running': '运行中',
'codexlens.watcher.status.stopped': '已停止',
'codexlens.watcher.eventsProcessed': '已处理事件',
'codexlens.watcher.uptime': '运行时间',
'codexlens.watcher.start': '启动监听',
'codexlens.watcher.starting': '启动中...',
'codexlens.watcher.stop': '停止监听',
'codexlens.watcher.stopping': '停止中...',
'codexlens.watcher.started': '文件监听器已启动',
'codexlens.watcher.stopped': '文件监听器已停止',
'codexlens.settings.currentCount': '当前索引数量',
'codexlens.settings.currentWorkers': '当前工作线程',
'codexlens.settings.currentBatchSize': '当前批次大小',
'codexlens.settings.configTitle': '基本配置',
'codexlens.settings.indexDir.label': '索引目录',
'codexlens.settings.indexDir.placeholder': '~/.codexlens/indexes',
'codexlens.settings.indexDir.hint': '存储代码索引的目录路径',
'codexlens.settings.maxWorkers.label': '最大工作线程',
'codexlens.settings.maxWorkers.hint': 'API 并发处理线程数 (1-32)',
'codexlens.settings.batchSize.label': '批次大小',
'codexlens.settings.batchSize.hint': '每次批量处理的文件数量 (1-64)',
'codexlens.settings.validation.indexDirRequired': '索引目录不能为空',
'codexlens.settings.validation.maxWorkersRange': '工作线程数必须在 1-32 之间',
'codexlens.settings.validation.batchSizeRange': '批次大小必须在 1-64 之间',
'codexlens.settings.save': '保存',
'codexlens.settings.saving': '保存中...',
'codexlens.settings.reset': '重置',
'codexlens.settings.saveSuccess': '配置已保存',
'codexlens.settings.saveFailed': '保存失败',
'codexlens.settings.configUpdated': '配置更新成功',
'codexlens.settings.saveError': '保存配置时出错',
'codexlens.settings.unknownError': '发生未知错误',
'codexlens.models.title': '模型管理',
'codexlens.models.searchPlaceholder': '搜索模型...',
'codexlens.models.downloading': '下载中...',
'codexlens.models.status.downloaded': '已下载',
'codexlens.models.status.available': '可用',
'codexlens.models.types.embedding': '嵌入模型',
'codexlens.models.types.reranker': '重排序模型',
'codexlens.models.filters.label': '筛选',
'codexlens.models.filters.all': '全部',
'codexlens.models.actions.download': '下载',
'codexlens.models.actions.delete': '删除',
'codexlens.models.actions.cancel': '取消',
'codexlens.models.custom.title': '自定义模型',
'codexlens.models.custom.placeholder': 'HuggingFace 模型名称 (如: BAAI/bge-small-zh-v1.5)',
'codexlens.models.custom.description': '从 HuggingFace 下载自定义模型。请确保模型名称正确。',
'codexlens.models.deleteConfirm': '确定要删除模型 {modelName} 吗?',
'codexlens.models.notInstalled.title': 'CodexLens 未安装',
'codexlens.models.notInstalled.description': '请先安装 CodexLens 以使用模型管理功能。',
'codexlens.models.empty.title': '没有找到模型',
'codexlens.models.empty.description': '尝试调整搜索或筛选条件',
// Reranker
'codexlens.reranker.title': '重排序配置',
'codexlens.reranker.description': '配置重排序后端、模型和提供商,用于搜索结果排序。',
'codexlens.reranker.backend': '后端',
'codexlens.reranker.backendHint': '重排序推理后端',
'codexlens.reranker.model': '模型',
'codexlens.reranker.modelHint': '重排序模型名称或 LiteLLM 端点',
'codexlens.reranker.provider': 'API 提供商',
'codexlens.reranker.providerHint': '重排序服务的 API 提供商',
'codexlens.reranker.apiKeyStatus': 'API 密钥',
'codexlens.reranker.apiKeySet': '已配置',
'codexlens.reranker.apiKeyNotSet': '未配置',
'codexlens.reranker.configSource': '配置来源',
'codexlens.reranker.save': '保存重排序配置',
'codexlens.reranker.saving': '保存中...',
'codexlens.reranker.saveSuccess': '重排序配置已保存',
'codexlens.reranker.saveFailed': '保存重排序配置失败',
'codexlens.reranker.noBackends': '无可用后端',
'codexlens.reranker.noModels': '无可用模型',
'codexlens.reranker.noProviders': '无可用提供商',
'codexlens.reranker.litellmModels': 'LiteLLM 模型',
'codexlens.reranker.selectBackend': '选择后端...',
'codexlens.reranker.selectModel': '选择模型...',
'codexlens.reranker.selectProvider': '选择提供商...',
// MCP - CCW Tools
'mcp.ccw.title': 'CCW MCP 服务器',
'mcp.ccw.description': '配置 CCW MCP 工具与路径',
'mcp.ccw.status.installed': '已安装',
'mcp.ccw.status.notInstalled': '未安装',
'mcp.ccw.status.special': '特殊',
'mcp.ccw.actions.enableAll': '全选',
'mcp.ccw.actions.disableAll': '全不选',
'mcp.ccw.actions.saveConfig': '保存配置',
'mcp.ccw.actions.saving': '保存中...',
'mcp.ccw.actions.installing': '安装中...',
'mcp.ccw.actions.uninstall': '卸载',
'mcp.ccw.actions.uninstalling': '卸载中...',
'mcp.ccw.actions.uninstallConfirm': '确定要卸载吗?',
'mcp.ccw.actions.uninstallScopeConfirm': '确定要从该作用域卸载吗?',
'mcp.ccw.codexNote': 'Codex 仅支持全局安装',
'mcp.ccw.tools.label': '工具',
'mcp.ccw.tools.hint': '安装后可编辑工具',
'mcp.ccw.tools.core': '核心',
'mcp.ccw.tools.write_file.name': '写入文件',
'mcp.ccw.tools.write_file.desc': '写入/创建文件',
'mcp.ccw.tools.edit_file.name': '编辑文件',
'mcp.ccw.tools.edit_file.desc': '编辑/替换内容',
'mcp.ccw.tools.read_file.name': '读取文件',
'mcp.ccw.tools.read_file.desc': '读取单个文件',
'mcp.ccw.tools.read_many_files.name': '读取多个文件',
'mcp.ccw.tools.read_many_files.desc': '读取多个文件/目录',
'mcp.ccw.tools.core_memory.name': '核心记忆',
'mcp.ccw.tools.core_memory.desc': '核心记忆管理',
'mcp.ccw.tools.ask_question.name': '提问',
'mcp.ccw.tools.ask_question.desc': '交互式问题A2UI',
'mcp.ccw.tools.smart_search.name': '智能搜索',
'mcp.ccw.tools.smart_search.desc': '智能代码搜索',
'mcp.ccw.tools.team_msg.name': '团队消息',
'mcp.ccw.tools.team_msg.desc': '代理团队消息总线',
'mcp.ccw.paths.label': '路径',
'mcp.ccw.paths.projectRoot': '项目根目录',
'mcp.ccw.paths.projectRootPlaceholder': '例如D:\\path\\to\\project',
'mcp.ccw.paths.allowedDirs': '允许目录',
'mcp.ccw.paths.allowedDirsPlaceholder': '用逗号分隔的目录',
'mcp.ccw.paths.allowedDirsHint': '使用逗号分隔多个目录',
'mcp.ccw.paths.enableSandbox': '启用沙箱',
'mcp.ccw.scope.installToGlobal': '安装到全局',
'mcp.ccw.scope.installToProject': '安装到项目',
'mcp.ccw.scope.uninstallGlobal': '卸载全局',
'mcp.ccw.scope.uninstallProject': '卸载项目',
'mcp.ccw.feedback.saveSuccess': '配置已保存',
'mcp.ccw.feedback.saveError': '保存配置失败',
'navigation.codexlens': 'CodexLens',
},
};
/**
* Create a test QueryClient
*/
function createTestQueryClient() {
return new QueryClient({
defaultOptions: {
queries: {
retry: false,
gcTime: 0,
},
},
});
}
/**
* Wrapper component that includes i18n providers
*/
interface I18nWrapperProps {
children: React.ReactNode;
locale?: Locale;
}
function I18nWrapper({ children, locale = 'en' }: I18nWrapperProps) {
const queryClient = createTestQueryClient();
return (
<MemoryRouter>
<QueryClientProvider client={queryClient}>
<IntlProvider locale={locale} messages={mockMessages[locale]}>
{children}
</IntlProvider>
</QueryClientProvider>
</MemoryRouter>
);
}
/**
* Custom render function with i18n support
*/
interface RenderWithI18nOptions extends Omit<RenderOptions, 'wrapper'> {
locale?: Locale;
}
export function renderWithI18n(
ui: ReactElement,
{ locale = 'en', ...renderOptions }: RenderWithI18nOptions = {}
) {
return originalRender(ui, {
wrapper: ({ children }) => <I18nWrapper locale={locale}>{children}</I18nWrapper>,
...renderOptions,
});
}
/**
* Mock locale utilities
*/
export const mockLocaleUtils = {
getInitialLocale: (locale: Locale = 'en'): Locale => locale,
updateIntl: vi.fn(),
getIntl: vi.fn(() => ({
formatMessage: ({ id }: { id: string }) => id,
})),
formatMessage: (id: string) => id,
};
/**
* Create a mock i18n context
*/
export function mockI18nContext(locale: Locale = 'en') {
return {
locale,
messages: mockMessages[locale],
formatMessage: (id: string, values?: Record<string, unknown>) => {
const message = mockMessages[locale][id];
if (!message) return id;
if (!values) return message;
// Simple placeholder replacement
return message.replace(/\{(\w+)\}/g, (_, key) => String(values[key] ?? key));
},
};
}
/**
* Re-export commonly used testing utilities
*/
export {
screen,
waitFor,
waitForElementToBeRemoved,
within,
fireEvent,
} from '@testing-library/react';
export { default as userEvent } from '@testing-library/user-event';
// Export renderWithI18n as the default render for convenience
export { renderWithI18n as render };