zeroclaw/web/src/lib/i18n.ts
Argenis 48733d5ee2
feat(cron): add Edit button and modal for updating cron jobs (#4132)
- Backend: add PATCH /api/cron/{id} handler (handle_api_cron_patch)
  using update_shell_job_with_approval with approved=false; validates
  job exists (404 on miss), accepts name/schedule/command patch fields
- Router: register PATCH on /api/cron/{id} alongside existing DELETE
- Frontend API: add patchCronJob(id, patch) calling PATCH /api/cron/{id}
- i18n: add cron.edit, cron.edit_modal_title, cron.edit_error,
  cron.saving, cron.save keys to all 3 locales (zh, en, tr)
- UI: Edit (Pencil) button in Actions column opens a pre-populated modal
  with the job's current name, schedule expression, and command;
  submitting PATCHes the job and updates the table row in-place

Co-authored-by: WareWolf-MoonWall <chris.hengge@gmail.com>
2026-03-21 05:50:23 -04:00

1010 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.

import { useState, useEffect } from 'react';
import { getStatus } from './api';
// ---------------------------------------------------------------------------
// Translation dictionaries
// ---------------------------------------------------------------------------
export type Locale = 'en' | 'zh' | 'tr';
const translations: Record<Locale, Record<string, string>> = {
zh: {
// Navigation
'nav.dashboard': '仪表盘',
'nav.agent': '智能体',
'nav.tools': '工具',
'nav.cron': '定时任务',
'nav.integrations': '集成',
'nav.memory': '记忆',
'nav.config': '配置',
'nav.cost': '成本追踪',
'nav.logs': '日志',
'nav.doctor': '诊断',
// Dashboard
'dashboard.title': '仪表盘',
'dashboard.provider': '提供商',
'dashboard.model': '模型',
'dashboard.uptime': '运行时间',
'dashboard.temperature': '温度',
'dashboard.gateway_port': '网关端口',
'dashboard.memory_backend': '记忆后端',
'dashboard.paired': '已配对',
'dashboard.channels': '频道',
'dashboard.health': '健康状态',
'dashboard.status': '状态',
'dashboard.overview': '概览',
'dashboard.system_info': '系统信息',
'dashboard.quick_actions': '快速操作',
// Agent / Chat
'agent.title': '智能体对话',
'agent.send': '发送',
'agent.placeholder': '输入消息...',
'agent.start_conversation': '发送消息开始对话',
'agent.type_message': '输入消息...',
'agent.connecting': '连接中...',
'agent.connected': '已连接',
'agent.disconnected': '已断开',
'agent.reconnecting': '重新连接中...',
'agent.thinking': '思考中...',
'agent.tool_call': '工具调用',
'agent.tool_result': '工具结果',
'agent.connection_error': '连接错误,正在尝试重连...',
'agent.tool_call_prefix': '[工具调用]',
'agent.tool_result_prefix': '[工具结果]',
'agent.error_prefix': '[错误]',
'agent.unknown_error': '未知错误',
'agent.send_error': '发送消息失败,请重试。',
'agent.copy_message': '复制消息',
'agent.connected_status': '已连接',
'agent.disconnected_status': '已断开',
// Tools
'tools.title': '可用工具',
'tools.name': '名称',
'tools.description': '描述',
'tools.parameters': '参数',
'tools.search': '搜索工具...',
'tools.empty': '暂无可用工具。',
'tools.count': '工具总数',
'tools.agent_tools': '智能体工具箱',
'tools.cli_tools': 'CLI 工具箱',
'tools.parameter_schema': '参数结构',
'tools.path': '路径',
'tools.version': '版本',
'tools.category': '类别',
'tools.load_error': '加载工具失败',
// Cron
'cron.title': '定时任务',
'cron.scheduled_tasks': '定时任务',
'cron.add': '添加任务',
'cron.add_job': '添加任务',
'cron.add_modal_title': '添加 Cron 任务',
'cron.delete': '删除',
'cron.enable': '启用',
'cron.disable': '禁用',
'cron.name': '名称',
'cron.name_optional': '名称(可选)',
'cron.command': '命令',
'cron.command_required': '命令',
'cron.schedule': '计划',
'cron.schedule_required': '计划',
'cron.next_run': '下次执行',
'cron.last_run': '上次执行',
'cron.last_status': '上次状态',
'cron.enabled': '已启用',
'cron.enabled_status': '启用',
'cron.disabled_status': '禁用',
'cron.empty': '暂无定时任务。',
'cron.confirm_delete': '确定要删除此任务吗?',
'cron.load_error': '加载定时任务失败',
'cron.validation_error': '计划和命令是必需的。',
'cron.add_error': '添加任务失败',
'cron.delete_error': '删除任务失败',
'cron.cancel': '取消',
'cron.adding': '添加中...',
'cron.id': 'ID',
'cron.actions': '操作',
'cron.loading_run_history': '加载运行历史...',
'cron.load_run_history_error': '加载运行历史失败',
'cron.no_runs': '暂无运行记录。',
'cron.recent_runs': '最近运行',
'cron.yes': '是',
'cron.no': '否',
'cron.edit': '编辑',
'cron.edit_modal_title': '编辑 Cron 任务',
'cron.edit_error': '更新任务失败',
'cron.saving': '保存中...',
'cron.save': '保存',
// Integrations
'integrations.title': '集成',
'integrations.available': '可用',
'integrations.active': '活跃',
'integrations.coming_soon': '即将推出',
'integrations.category': '类别',
'integrations.status': '状态',
'integrations.search': '搜索集成...',
'integrations.empty': '未找到集成。',
'integrations.activate': '激活',
'integrations.deactivate': '停用',
'integrations.load_error': '加载集成失败',
'integrations.status_active': '活跃',
'integrations.status_available': '可用',
'integrations.status_coming_soon': '即将推出',
// Memory
'memory.title': '记忆存储',
'memory.memory_title': '记忆',
'memory.search': '搜索记忆...',
'memory.search_placeholder': '搜索记忆条目...',
'memory.add': '存储记忆',
'memory.add_memory': '添加记忆',
'memory.add_modal_title': '添加记忆',
'memory.delete': '删除',
'memory.key': '键',
'memory.key_required': '键',
'memory.content': '内容',
'memory.content_required': '内容',
'memory.category': '类别',
'memory.category_optional': '类别(可选)',
'memory.timestamp': '时间戳',
'memory.session': '会话',
'memory.score': '分数',
'memory.empty': '未找到记忆条目。',
'memory.confirm_delete': '确定要删除此记忆条目吗?',
'memory.all_categories': '所有类别',
'memory.search_button': '搜索',
'memory.load_error': '加载记忆失败',
'memory.saving': '保存中...',
'memory.validation_error': '键和内容是必需的。',
'memory.store_error': '保存记忆失败',
'memory.delete_error': '删除记忆失败',
'memory.delete_confirm': '删除?',
'memory.yes': '是',
'memory.no': '否',
'memory.cancel': '取消',
// Config
'config.title': '配置',
'config.save': '保存',
'config.saving': '保存中...',
'config.reset': '重置',
'config.saved': '配置保存成功。',
'config.error': '配置保存失败。',
'config.loading': '加载配置中...',
'config.editor_placeholder': 'TOML 配置...',
'config.configuration_title': '配置',
'config.sensitive_title': '敏感字段已隐藏',
'config.sensitive_hint': 'API 密钥、令牌和密码已隐藏以保护安全。要更新已隐藏的字段,请将整个隐藏值替换为您的新值。',
'config.save_success': '配置保存成功。',
'config.save_error': '保存配置失败',
'config.toml_label': 'TOML 配置',
'config.lines': '行',
// Cost
'cost.title': '成本追踪',
'cost.session': '会话成本',
'cost.daily': '每日成本',
'cost.monthly': '每月成本',
'cost.total_tokens': '总 Tokens',
'cost.request_count': '请求数',
'cost.by_model': '按模型统计',
'cost.model': '模型',
'cost.tokens': 'Token',
'cost.requests': '请求',
'cost.usd': '成本(美元)',
'cost.load_error': '加载成本数据失败',
'cost.session_cost': '会话成本',
'cost.daily_cost': '每日成本',
'cost.monthly_cost': '每月成本',
'cost.total_requests': '总请求数',
'cost.token_statistics': 'Token 统计',
'cost.avg_tokens_per_request': '平均 Token / 请求',
'cost.cost_per_1k_tokens': '每 1K Token 成本',
'cost.model_breakdown': '模型细分',
'cost.no_model_data': '没有模型数据可用。',
'cost.cost': '成本',
'cost.share': '占比',
// Logs
'logs.title': '实时日志',
'logs.live_logs': '实时日志',
'logs.clear': '清除',
'logs.pause': '暂停',
'logs.resume': '继续',
'logs.filter': '筛选日志...',
'logs.filter_label': '筛选',
'logs.empty': '暂无日志条目。',
'logs.connected': '已连接',
'logs.disconnected': '已断开',
'logs.events': '事件',
'logs.jump_to_bottom': '跳转到底部',
'logs.paused_hint': '日志流已暂停。',
'logs.waiting_hint': '等待事件...',
// Doctor
'doctor.title': '系统诊断',
'doctor.diagnostics_title': '系统诊断',
'doctor.run': '运行诊断',
'doctor.run_diagnostics': '运行诊断',
'doctor.running': '正在运行诊断...',
'doctor.running_btn': '运行中...',
'doctor.running_desc': '正在运行诊断...',
'doctor.running_hint': '这可能需要几秒钟。',
'doctor.ok': '正常',
'doctor.warn': '警告',
'doctor.error': '错误',
'doctor.severity': '严重程度',
'doctor.category': '类别',
'doctor.message': '消息',
'doctor.empty': '尚未运行诊断。',
'doctor.summary': '诊断摘要',
'doctor.issues_found': '发现问题',
'doctor.warnings_summary': '警告',
'doctor.all_clear': '一切正常',
'doctor.system_diagnostics': '系统诊断',
'doctor.empty_hint': '点击"运行诊断"检查您的 ZeroClaw 安装。',
// Auth / Pairing
'auth.pair': '配对设备',
'auth.pairing_code': '配对码',
'auth.pair_button': '配对',
'auth.logout': '退出',
'auth.pairing_success': '配对成功!',
'auth.pairing_failed': '配对失败,请重试。',
'auth.enter_code': '请输入配对码以连接到智能体。',
// Common
'common.loading': '加载中...',
'common.error': '发生错误。',
'common.retry': '重试',
'common.cancel': '取消',
'common.confirm': '确认',
'common.save': '保存',
'common.delete': '删除',
'common.edit': '编辑',
'common.close': '关闭',
'common.yes': '是',
'common.no': '否',
'common.search': '搜索...',
'common.no_data': '暂无数据。',
'common.refresh': '刷新',
'common.back': '返回',
'common.actions': '操作',
'common.name': '名称',
'common.description': '描述',
'common.status': '状态',
'common.created': '创建时间',
'common.updated': '更新时间',
// Health
'health.title': '系统健康',
'health.component': '组件',
'health.status': '状态',
'health.last_ok': '上次正常',
'health.last_error': '上次错误',
'health.restart_count': '重启次数',
'health.pid': '进程 ID',
'health.uptime': '运行时间',
'health.updated_at': '最后更新',
// Dashboard specific labels
'dashboard.provider_model': '提供商 / 模型',
'dashboard.since_last_restart': '自上次重启',
'dashboard.paired_yes': '是',
'dashboard.paired_no': '否',
'dashboard.cost_overview': '成本概览',
'dashboard.active_channels': '活跃频道',
'dashboard.filter_active': '活跃',
'dashboard.filter_all': '全部',
'dashboard.no_active_channels': '没有活跃频道',
'dashboard.component_health': '组件健康',
'dashboard.load_error': '加载仪表盘失败',
'dashboard.session_label': '会话',
'dashboard.daily_label': '每日',
'dashboard.monthly_label': '每月',
'dashboard.total_tokens_label': '总 Tokens',
'dashboard.requests_label': '请求',
'dashboard.no_channels': '未配置频道',
'dashboard.active': '活跃',
'dashboard.inactive': '非活跃',
'dashboard.no_components': '没有组件报告',
'dashboard.restarts': '重启次数',
},
en: {
// Navigation
'nav.dashboard': 'Dashboard',
'nav.agent': 'Agent',
'nav.tools': 'Tools',
'nav.cron': 'Scheduled Jobs',
'nav.integrations': 'Integrations',
'nav.memory': 'Memory',
'nav.config': 'Configuration',
'nav.cost': 'Cost Tracker',
'nav.logs': 'Logs',
'nav.doctor': 'Doctor',
// Dashboard
'dashboard.title': 'Dashboard',
'dashboard.provider': 'Provider',
'dashboard.model': 'Model',
'dashboard.uptime': 'Uptime',
'dashboard.temperature': 'Temperature',
'dashboard.gateway_port': 'Gateway Port',
'dashboard.memory_backend': 'Memory Backend',
'dashboard.paired': 'Paired',
'dashboard.channels': 'Channels',
'dashboard.health': 'Health',
'dashboard.status': 'Status',
'dashboard.overview': 'Overview',
'dashboard.system_info': 'System Information',
'dashboard.quick_actions': 'Quick Actions',
// Agent / Chat
'agent.title': 'Agent Chat',
'agent.send': 'Send',
'agent.placeholder': 'Type a message...',
'agent.start_conversation': 'Send a message to start the conversation',
'agent.type_message': 'Type a message...',
'agent.connecting': 'Connecting...',
'agent.connected': 'Connected',
'agent.disconnected': 'Disconnected',
'agent.reconnecting': 'Reconnecting...',
'agent.thinking': 'Thinking...',
'agent.tool_call': 'Tool Call',
'agent.tool_result': 'Tool Result',
'agent.connection_error': 'Connection error. Attempting to reconnect...',
'agent.tool_call_prefix': '[Tool Call]',
'agent.tool_result_prefix': '[Tool Result]',
'agent.error_prefix': '[Error]',
'agent.unknown_error': 'Unknown error',
'agent.send_error': 'Failed to send message. Please try again.',
'agent.copy_message': 'Copy message',
'agent.connected_status': 'Connected',
'agent.disconnected_status': 'Disconnected',
// Tools
'tools.title': 'Available Tools',
'tools.name': 'Name',
'tools.description': 'Description',
'tools.parameters': 'Parameters',
'tools.search': 'Search tools...',
'tools.empty': 'No tools available.',
'tools.count': 'Total tools',
'tools.agent_tools': 'Agent Tools',
'tools.cli_tools': 'CLI Tools',
'tools.parameter_schema': 'Parameter Schema',
'tools.path': 'Path',
'tools.version': 'Version',
'tools.category': 'Category',
'tools.load_error': 'Failed to load tools',
// Cron
'cron.title': 'Scheduled Jobs',
'cron.scheduled_tasks': 'Scheduled Tasks',
'cron.add': 'Add Job',
'cron.add_job': 'Add Job',
'cron.add_modal_title': 'Add Cron Job',
'cron.delete': 'Delete',
'cron.enable': 'Enable',
'cron.disable': 'Disable',
'cron.name': 'Name',
'cron.name_optional': 'Name (optional)',
'cron.command': 'Command',
'cron.command_required': 'Command',
'cron.schedule': 'Schedule',
'cron.schedule_required': 'Schedule',
'cron.next_run': 'Next Run',
'cron.last_run': 'Last Run',
'cron.last_status': 'Last Status',
'cron.enabled': 'Enabled',
'cron.enabled_status': 'Enabled',
'cron.disabled_status': 'Disabled',
'cron.empty': 'No scheduled jobs.',
'cron.confirm_delete': 'Are you sure you want to delete this job?',
'cron.load_error': 'Failed to load cron jobs',
'cron.validation_error': 'Schedule and command are required.',
'cron.add_error': 'Failed to add job',
'cron.delete_error': 'Failed to delete job',
'cron.cancel': 'Cancel',
'cron.adding': 'Adding...',
'cron.id': 'ID',
'cron.actions': 'Actions',
'cron.loading_run_history': 'Loading run history...',
'cron.load_run_history_error': 'Failed to load run history',
'cron.no_runs': 'No runs recorded yet.',
'cron.recent_runs': 'Recent Runs',
'cron.yes': 'Yes',
'cron.no': 'No',
'cron.edit': 'Edit',
'cron.edit_modal_title': 'Edit Cron Job',
'cron.edit_error': 'Failed to update job',
'cron.saving': 'Saving...',
'cron.save': 'Save',
// Integrations
'integrations.title': 'Integrations',
'integrations.available': 'Available',
'integrations.active': 'Active',
'integrations.coming_soon': 'Coming Soon',
'integrations.category': 'Category',
'integrations.status': 'Status',
'integrations.search': 'Search integrations...',
'integrations.empty': 'No integrations found.',
'integrations.activate': 'Activate',
'integrations.deactivate': 'Deactivate',
'integrations.load_error': 'Failed to load integrations',
'integrations.status_active': 'Active',
'integrations.status_available': 'Available',
'integrations.status_coming_soon': 'Coming Soon',
// Memory
'memory.title': 'Memory Store',
'memory.memory_title': 'Memory',
'memory.search': 'Search memory...',
'memory.search_placeholder': 'Search memory entries...',
'memory.add': 'Store Memory',
'memory.add_memory': 'Add Memory',
'memory.add_modal_title': 'Add Memory',
'memory.delete': 'Delete',
'memory.key': 'Key',
'memory.key_required': 'Key',
'memory.content': 'Content',
'memory.content_required': 'Content',
'memory.category': 'Category',
'memory.category_optional': 'Category (optional)',
'memory.timestamp': 'Timestamp',
'memory.session': 'Session',
'memory.score': 'Score',
'memory.empty': 'No memory entries found.',
'memory.confirm_delete': 'Are you sure you want to delete this memory entry?',
'memory.all_categories': 'All Categories',
'memory.search_button': 'Search',
'memory.load_error': 'Failed to load memory',
'memory.saving': 'Saving...',
'memory.validation_error': 'Key and content are required.',
'memory.store_error': 'Failed to store memory',
'memory.delete_error': 'Failed to delete memory',
'memory.delete_confirm': 'Delete?',
'memory.yes': 'Yes',
'memory.no': 'No',
'memory.cancel': 'Cancel',
// Config
'config.title': 'Configuration',
'config.save': 'Save',
'config.saving': 'Saving...',
'config.reset': 'Reset',
'config.saved': 'Configuration saved successfully.',
'config.error': 'Failed to save configuration.',
'config.loading': 'Loading configuration...',
'config.editor_placeholder': 'TOML configuration...',
'config.configuration_title': 'Configuration',
'config.sensitive_title': 'Sensitive fields are masked',
'config.sensitive_hint': 'API keys, tokens, and passwords are hidden for security. To update a masked field, replace the entire masked value with your new value.',
'config.save_success': 'Configuration saved successfully.',
'config.save_error': 'Failed to save configuration',
'config.toml_label': 'TOML Configuration',
'config.lines': 'lines',
// Cost
'cost.title': 'Cost Tracker',
'cost.session': 'Session Cost',
'cost.daily': 'Daily Cost',
'cost.monthly': 'Monthly Cost',
'cost.total_tokens': 'Total Tokens',
'cost.request_count': 'Requests',
'cost.by_model': 'Cost by Model',
'cost.model': 'Model',
'cost.tokens': 'Tokens',
'cost.requests': 'Requests',
'cost.usd': 'Cost (USD)',
'cost.load_error': 'Failed to load cost data',
'cost.session_cost': 'Session Cost',
'cost.daily_cost': 'Daily Cost',
'cost.monthly_cost': 'Monthly Cost',
'cost.total_requests': 'Total Requests',
'cost.token_statistics': 'Token Statistics',
'cost.avg_tokens_per_request': 'Avg Tokens / Request',
'cost.cost_per_1k_tokens': 'Cost per 1K Tokens',
'cost.model_breakdown': 'Model Breakdown',
'cost.no_model_data': 'No model data available.',
'cost.cost': 'Cost',
'cost.share': 'Share',
// Logs
'logs.title': 'Live Logs',
'logs.live_logs': 'Live Logs',
'logs.clear': 'Clear',
'logs.pause': 'Pause',
'logs.resume': 'Resume',
'logs.filter': 'Filter logs...',
'logs.filter_label': 'Filter',
'logs.empty': 'No log entries.',
'logs.connected': 'Connected',
'logs.disconnected': 'Disconnected',
'logs.events': 'events',
'logs.jump_to_bottom': 'Jump to bottom',
'logs.paused_hint': 'Log streaming is paused.',
'logs.waiting_hint': 'Waiting for events...',
// Doctor
'doctor.title': 'System Diagnostics',
'doctor.diagnostics_title': 'Diagnostics',
'doctor.run': 'Run Diagnostics',
'doctor.run_diagnostics': 'Run Diagnostics',
'doctor.running': 'Running diagnostics...',
'doctor.running_btn': 'Running...',
'doctor.running_desc': 'Running diagnostics...',
'doctor.running_hint': 'This may take a few seconds.',
'doctor.ok': 'OK',
'doctor.warn': 'Warning',
'doctor.error': 'Error',
'doctor.severity': 'Severity',
'doctor.category': 'Category',
'doctor.message': 'Message',
'doctor.empty': 'No diagnostics have been run yet.',
'doctor.summary': 'Diagnostic Summary',
'doctor.issues_found': 'Issues Found',
'doctor.warnings_summary': 'Warnings',
'doctor.all_clear': 'All Clear',
'doctor.system_diagnostics': 'System Diagnostics',
'doctor.empty_hint': 'Click "Run Diagnostics" to check your ZeroClaw installation.',
// Auth / Pairing
'auth.pair': 'Pair Device',
'auth.pairing_code': 'Pairing Code',
'auth.pair_button': 'Pair',
'auth.logout': 'Logout',
'auth.pairing_success': 'Pairing successful!',
'auth.pairing_failed': 'Pairing failed. Please try again.',
'auth.enter_code': 'Enter your pairing code to connect to the agent.',
// Common
'common.loading': 'Loading...',
'common.error': 'An error occurred.',
'common.retry': 'Retry',
'common.cancel': 'Cancel',
'common.confirm': 'Confirm',
'common.save': 'Save',
'common.delete': 'Delete',
'common.edit': 'Edit',
'common.close': 'Close',
'common.yes': 'Yes',
'common.no': 'No',
'common.search': 'Search...',
'common.no_data': 'No data available.',
'common.refresh': 'Refresh',
'common.back': 'Back',
'common.actions': 'Actions',
'common.name': 'Name',
'common.description': 'Description',
'common.status': 'Status',
'common.created': 'Created',
'common.updated': 'Updated',
// Health
'health.title': 'System Health',
'health.component': 'Component',
'health.status': 'Status',
'health.last_ok': 'Last OK',
'health.last_error': 'Last Error',
'health.restart_count': 'Restarts',
'health.pid': 'Process ID',
'health.uptime': 'Uptime',
'health.updated_at': 'Last Updated',
// Dashboard specific labels
'dashboard.provider_model': 'Provider / Model',
'dashboard.since_last_restart': 'Since last restart',
'dashboard.paired_yes': 'Yes',
'dashboard.paired_no': 'No',
'dashboard.cost_overview': 'Cost Overview',
'dashboard.active_channels': 'Active Channels',
'dashboard.filter_active': 'Active',
'dashboard.filter_all': 'All',
'dashboard.no_active_channels': 'No active channels',
'dashboard.component_health': 'Component Health',
'dashboard.load_error': 'Failed to load dashboard',
'dashboard.session_label': 'Session',
'dashboard.daily_label': 'Daily',
'dashboard.monthly_label': 'Monthly',
'dashboard.total_tokens_label': 'Total Tokens',
'dashboard.requests_label': 'Requests',
'dashboard.no_channels': 'No channels configured',
'dashboard.active': 'Active',
'dashboard.inactive': 'Inactive',
'dashboard.no_components': 'No components reporting',
'dashboard.restarts': 'Restarts',
},
tr: {
// Navigation
'nav.dashboard': 'Kontrol Paneli',
'nav.agent': 'Ajan',
'nav.tools': 'Araçlar',
'nav.cron': 'Zamanlanmış Görevler',
'nav.integrations': 'Entegrasyonlar',
'nav.memory': 'Hafıza',
'nav.config': 'Yapılandırma',
'nav.cost': 'Maliyet Takibi',
'nav.logs': 'Kayıtlar',
'nav.doctor': 'Doktor',
// Dashboard
'dashboard.title': 'Kontrol Paneli',
'dashboard.provider': 'Sağlayıcı',
'dashboard.model': 'Model',
'dashboard.uptime': 'Çalışma Süresi',
'dashboard.temperature': 'Sıcaklık',
'dashboard.gateway_port': 'Ağ Geçidi Portu',
'dashboard.locale': 'Dil',
'dashboard.memory_backend': 'Hafıza Motoru',
'dashboard.paired': 'Eşleştirilmiş',
'dashboard.channels': 'Kanallar',
'dashboard.health': 'Sağlık',
'dashboard.status': 'Durum',
'dashboard.overview': 'Genel Bakış',
'dashboard.system_info': 'Sistem Bilgisi',
'dashboard.quick_actions': 'Hızlı İşlemler',
'dashboard.provider_model': 'Sağlayıcı / Model',
'dashboard.since_last_restart': 'Son Yeniden Başlatmadan Beri',
'dashboard.paired_yes': 'Evet',
'dashboard.paired_no': 'Hayır',
'dashboard.cost_overview': 'Maliyet Genel Bakışı',
'dashboard.active_channels': 'Aktif Kanallar',
'dashboard.filter_active': 'Aktif',
'dashboard.filter_all': 'Tümü',
'dashboard.no_active_channels': 'Aktif kanal yok',
'dashboard.component_health': 'Bileşen Sağlığı',
'dashboard.load_error': 'Kontrol paneli yüklenemedi',
'dashboard.session_label': 'Oturum',
'dashboard.daily_label': 'Günlük',
'dashboard.monthly_label': 'Aylık',
'dashboard.total_tokens_label': 'Toplam Token',
'dashboard.requests_label': 'İstekler',
'dashboard.no_channels': 'Kanal yapılandırılmamış',
'dashboard.active': 'Aktif',
'dashboard.inactive': 'Aktif Değil',
'dashboard.no_components': 'Bileşen raporlamıyor',
'dashboard.restarts': 'Yeniden Başlatmalar',
// Agent / Chat
'agent.title': 'Ajan Sohbeti',
'agent.send': 'Gönder',
'agent.placeholder': 'Bir mesaj yazın...',
'agent.start_conversation': 'Sohbeti başlatmak için mesaj gönderin',
'agent.type_message': 'Bir mesaj yazın...',
'agent.connecting': 'Bağlanıyor...',
'agent.connected': 'Bağlandı',
'agent.disconnected': 'Bağlantı kesildi',
'agent.reconnecting': 'Yeniden bağlanıyor...',
'agent.thinking': 'Düşünüyor...',
'agent.tool_call': 'Araç Çağrısı',
'agent.tool_result': 'Araç Sonucu',
'agent.connection_error': 'Bağlantı hatası. Yeniden bağlanmaya çalışılıyor...',
'agent.tool_call_prefix': '[Araç Çağrısı]',
'agent.tool_result_prefix': '[Araç Sonucu]',
'agent.error_prefix': '[Hata]',
'agent.unknown_error': 'Bilinmeyen hata',
'agent.send_error': 'Mesaj gönderilemedi. Lütfen tekrar deneyin.',
'agent.copy_message': 'Mesajı kopyala',
'agent.connected_status': 'Bağlandı',
'agent.disconnected_status': 'Bağlantı kesildi',
// Tools
'tools.title': 'Mevcut Araçlar',
'tools.name': 'Ad',
'tools.description': 'Açıklama',
'tools.parameters': 'Parametreler',
'tools.search': 'Araç ara...',
'tools.empty': 'Araç bulunamadı.',
'tools.count': 'Toplam araç',
'tools.agent_tools': 'Ajan Araçları',
'tools.cli_tools': 'CLI Araçları',
'tools.parameter_schema': 'Parametre Şeması',
'tools.path': 'Yol',
'tools.version': 'Sürüm',
'tools.category': 'Kategori',
'tools.load_error': 'Araçlar yüklenemedi',
// Cron
'cron.title': 'Zamanlanmış Görevler',
'cron.scheduled_tasks': 'Zamanlanmış Görevler',
'cron.add': 'Görev Ekle',
'cron.add_job': 'Görev Ekle',
'cron.add_modal_title': 'Cron Görevi Ekle',
'cron.delete': 'Sil',
'cron.enable': 'Etkinleştir',
'cron.disable': 'Devre Dışı Bırak',
'cron.name': 'Ad',
'cron.name_optional': 'Ad (isteğe bağlı)',
'cron.command': 'Komut',
'cron.command_required': 'Komut',
'cron.schedule': 'Zamanlama',
'cron.schedule_required': 'Zamanlama',
'cron.next_run': 'Sonraki Çalıştırma',
'cron.last_run': 'Son Çalıştırma',
'cron.last_status': 'Son Durum',
'cron.enabled': 'Etkin',
'cron.enabled_status': 'Etkin',
'cron.disabled_status': 'Devre Dışı',
'cron.empty': 'Zamanlanmış görev bulunamadı.',
'cron.confirm_delete': 'Bu görevi silmek istediğinizden emin misiniz?',
'cron.load_error': 'Cron görevleri yüklenemedi',
'cron.validation_error': 'Zamanlama ve komut gereklidir.',
'cron.add_error': 'Görev eklenemedi',
'cron.delete_error': 'Görev silinemedi',
'cron.cancel': 'İptal',
'cron.adding': 'Ekleniyor...',
'cron.id': 'ID',
'cron.actions': 'İşlemler',
'cron.loading_run_history': 'Çalıştırma geçmişi yükleniyor...',
'cron.load_run_history_error': 'Çalıştırma geçmişi yüklenemedi',
'cron.no_runs': 'Henüz çalıştırma kaydı yok.',
'cron.recent_runs': 'Son Çalıştırmalar',
'cron.yes': 'Evet',
'cron.no': 'Hayır',
'cron.edit': 'Düzenle',
'cron.edit_modal_title': 'Cron Görevini Düzenle',
'cron.edit_error': 'Görev güncellenemedi',
'cron.saving': 'Kaydediliyor...',
'cron.save': 'Kaydet',
// Integrations
'integrations.title': 'Entegrasyonlar',
'integrations.available': 'Mevcut',
'integrations.active': 'Aktif',
'integrations.coming_soon': 'Yakında',
'integrations.category': 'Kategori',
'integrations.status': 'Durum',
'integrations.search': 'Entegrasyon ara...',
'integrations.empty': 'Entegrasyon bulunamadı.',
'integrations.activate': 'Etkinleştir',
'integrations.deactivate': 'Devre Dışı Bırak',
'integrations.load_error': 'Entegrasyonlar yüklenemedi',
'integrations.all': 'Tümü',
'integrations.status_active': 'Aktif',
'integrations.status_available': 'Mevcut',
'integrations.status_coming_soon': 'Yakında',
// Memory
'memory.title': 'Hafıza Deposu',
'memory.memory_title': 'Hafıza',
'memory.search': 'Hafıza ara...',
'memory.search_placeholder': 'Hafıza girişleri ara...',
'memory.add': 'Hafıza Ekle',
'memory.add_memory': 'Hafıza Ekle',
'memory.add_modal_title': 'Hafıza Ekle',
'memory.delete': 'Sil',
'memory.key': 'Anahtar',
'memory.key_required': 'Anahtar',
'memory.content': 'İçerik',
'memory.content_required': 'İçerik',
'memory.category': 'Kategori',
'memory.category_optional': 'Kategori (isteğe bağlı)',
'memory.timestamp': 'Zaman Damgası',
'memory.session': 'Oturum',
'memory.score': 'Puan',
'memory.empty': 'Hafıza girişi bulunamadı.',
'memory.confirm_delete': 'Bu hafıza girişini silmek istediğinizden emin misiniz?',
'memory.all_categories': 'Tüm Kategoriler',
'memory.search_button': 'Ara',
'memory.load_error': 'Hafıza yüklenemedi',
'memory.saving': 'Kaydediliyor...',
'memory.validation_error': 'Anahtar ve içerik gereklidir.',
'memory.store_error': 'Hafıza kaydedilemedi',
'memory.delete_error': 'Hafıza silinemedi',
'memory.delete_confirm': 'Sil?',
'memory.yes': 'Evet',
'memory.no': 'Hayır',
'memory.cancel': 'İptal',
// Config
'config.title': 'Yapılandırma',
'config.save': 'Kaydet',
'config.saving': 'Kaydediliyor...',
'config.reset': 'Sıfırla',
'config.saved': 'Yapılandırma başarıyla kaydedildi.',
'config.error': 'Yapılandırma kaydedilemedi.',
'config.loading': 'Yapılandırma yükleniyor...',
'config.editor_placeholder': 'TOML yapılandırması...',
'config.configuration_title': 'Yapılandırma',
'config.sensitive_title': 'Hassas alanlar gizlendi',
'config.sensitive_hint': 'API anahtarları, belirteçler ve parolalar güvenlik için gizlendi. Maskeli bir alanı güncellemek için, tüm maskeli değeri yeni değerinizle değiştirin.',
'config.save_success': 'Yapılandırma başarıyla kaydedildi.',
'config.save_error': 'Yapılandırma kaydedilemedi',
'config.toml_label': 'TOML Yapılandırması',
'config.lines': 'satır',
// Cost
'cost.title': 'Maliyet Takibi',
'cost.session': 'Oturum Maliyeti',
'cost.daily': 'Günlük Maliyet',
'cost.monthly': 'Aylık Maliyet',
'cost.total_tokens': 'Toplam Token',
'cost.request_count': 'İstek Sayısı',
'cost.by_model': 'Modele Göre Maliyet',
'cost.model': 'Model',
'cost.tokens': 'Token',
'cost.requests': 'İstekler',
'cost.usd': 'Maliyet (USD)',
'cost.load_error': 'Maliyet verileri yüklenemedi',
'cost.session_cost': 'Oturum Maliyeti',
'cost.daily_cost': 'Günlük Maliyet',
'cost.monthly_cost': 'Aylık Maliyet',
'cost.total_requests': 'Toplam İstek',
'cost.token_statistics': 'Token İstatistikleri',
'cost.avg_tokens_per_request': 'Ortalama Token / İstek',
'cost.cost_per_1k_tokens': '1K Token Başına Maliyet',
'cost.model_breakdown': 'Model Detayı',
'cost.no_model_data': 'Model verisi mevcut değil.',
'cost.cost': 'Maliyet',
'cost.share': 'Pay',
// Logs
'logs.title': 'Canlı Kayıtlar',
'logs.live_logs': 'Canlı Kayıtlar',
'logs.clear': 'Temizle',
'logs.pause': 'Duraklat',
'logs.resume': 'Devam Et',
'logs.filter': 'Kayıtları filtrele...',
'logs.filter_label': 'Filtre',
'logs.empty': 'Kayıt girişi bulunamadı.',
'logs.connected': 'Bağlandı',
'logs.disconnected': 'Bağlantı kesildi',
'logs.events': 'olay',
'logs.jump_to_bottom': 'En alta atla',
'logs.paused_hint': 'Kayıt akışı duraklatıldı.',
'logs.waiting_hint': 'Olay bekleniyor...',
// Doctor
'doctor.title': 'Sistem Tanıları',
'doctor.diagnostics_title': 'Tanılar',
'doctor.run': 'Tanı Çalıştır',
'doctor.run_diagnostics': 'Tanı Çalıştır',
'doctor.running': 'Tanı çalıştırılıyor...',
'doctor.running_btn': 'Çalıştırılıyor...',
'doctor.running_desc': 'Tanı çalıştırılıyor...',
'doctor.running_hint': 'Bu birkaç saniye sürebilir.',
'doctor.ok': 'Tamam',
'doctor.warn': 'Uyarı',
'doctor.error': 'Hata',
'doctor.severity': 'Şiddet',
'doctor.category': 'Kategori',
'doctor.message': 'Mesaj',
'doctor.empty': 'Henüz tanı çalıştırılmadı.',
'doctor.summary': 'Tanı Özeti',
'doctor.issues_found': 'Sorunlar Bulundu',
'doctor.warnings_summary': 'Uyarılar',
'doctor.all_clear': 'Her Şey Yolunda',
'doctor.system_diagnostics': 'Sistem Tanıları',
'doctor.empty_hint': 'ZeroClaw kurulumunuzu kontrol etmek için "Tanı Çalıştır" düğmesine tıklayın.',
// Auth / Pairing
'auth.pair': 'Cihaz Eşleştir',
'auth.pairing_code': 'Eşleştirme Kodu',
'auth.pair_button': 'Eşleştir',
'auth.logout': ıkış Yap',
'auth.pairing_success': 'Eşleştirme başarılı!',
'auth.pairing_failed': 'Eşleştirme başarısız. Lütfen tekrar deneyin.',
'auth.enter_code': 'Akıllı birine bağlanmak için eşleştirme kodunuzu girin.',
// Common
'common.loading': 'Yükleniyor...',
'common.error': 'Bir hata oluştu.',
'common.retry': 'Tekrar Dene',
'common.cancel': 'İptal',
'common.confirm': 'Onayla',
'common.save': 'Kaydet',
'common.delete': 'Sil',
'common.edit': 'Düzenle',
'common.close': 'Kapat',
'common.yes': 'Evet',
'common.no': 'Hayır',
'common.search': 'Ara...',
'common.no_data': 'Veri mevcut değil.',
'common.refresh': 'Yenile',
'common.back': 'Geri',
'common.actions': 'İşlemler',
'common.name': 'Ad',
'common.description': 'Açıklama',
'common.status': 'Durum',
'common.created': 'Oluşturulma',
'common.updated': 'Güncellenme',
// Health
'health.title': 'Sistem Sağlığı',
'health.component': 'Bileşen',
'health.status': 'Durum',
'health.last_ok': 'Son Başarılı',
'health.last_error': 'Son Hata',
'health.restart_count': 'Yeniden Başlatmalar',
'health.pid': 'İşlem Kimliği',
'health.uptime': 'Çalışma Süresi',
'health.updated_at': 'Son Güncelleme',
},
};
// ---------------------------------------------------------------------------
// Current locale state
// ---------------------------------------------------------------------------
let currentLocale: Locale = 'en';
export function getLocale(): Locale {
return currentLocale;
}
export function setLocale(locale: Locale): void {
currentLocale = locale;
}
// ---------------------------------------------------------------------------
// Translation function
// ---------------------------------------------------------------------------
/**
* Translate a key using the current locale. Returns the key itself if no
* translation is found.
*/
export function t(key: string): string {
return translations[currentLocale]?.[key] ?? translations.en[key] ?? key;
}
/**
* Get the translation for a specific locale. Falls back to English, then to the
* raw key.
*/
export function tLocale(key: string, locale: Locale): string {
return translations[locale]?.[key] ?? translations.en[key] ?? key;
}
// ---------------------------------------------------------------------------
// React hook
// ---------------------------------------------------------------------------
/**
* React hook that fetches the locale from /api/status on mount and keeps the
* i18n module in sync. Returns the current locale and a `t` helper bound to it.
*/
export function useLocale(): { locale: Locale; t: (key: string) => string } {
const [locale, setLocaleState] = useState<Locale>(currentLocale);
useEffect(() => {
let cancelled = false;
getStatus()
.then((status) => {
if (cancelled) return;
const localeStr = status.locale?.toLowerCase() ?? '';
let detected: Locale;
if (localeStr.startsWith('zh')) {
detected = 'zh';
} else if (localeStr.startsWith('tr')) {
detected = 'tr';
} else {
detected = 'en';
}
setLocale(detected);
setLocaleState(detected);
})
.catch(() => {
// Keep default locale on error
});
return () => {
cancelled = true;
};
}, []);
return {
locale,
t: (key: string) => tLocale(key, locale),
};
}