diff --git a/web/src/components/controls/LanguageSelector.tsx b/web/src/components/controls/LanguageSelector.tsx
index 2c60ab3b5..43eb1a1d2 100644
--- a/web/src/components/controls/LanguageSelector.tsx
+++ b/web/src/components/controls/LanguageSelector.tsx
@@ -2,7 +2,6 @@ import { Check, ChevronDown } from 'lucide-react';
import { useEffect, useRef, useState } from 'react';
import {
getLanguageOption,
- getLanguageOptionLabel,
getLocaleDirection,
LANGUAGE_OPTIONS,
type Locale,
@@ -58,7 +57,6 @@ export default function LanguageSelector({
return (
@@ -115,7 +113,7 @@ export default function LanguageSelector({
{option.flag}
- {getLanguageOptionLabel(option)}
+ {option.label}
{selected ? : null}
diff --git a/web/src/lib/i18n.ts b/web/src/lib/i18n.ts
deleted file mode 100644
index 3a3d2fe04..000000000
--- a/web/src/lib/i18n.ts
+++ /dev/null
@@ -1,1702 +0,0 @@
-import { useState, useEffect } from 'react';
-import { getStatus } from './api';
-
-export type Locale =
- | 'en'
- | 'zh-CN'
- | 'ja'
- | 'ko'
- | 'vi'
- | 'tl'
- | 'es'
- | 'pt'
- | 'it'
- | 'de'
- | 'fr'
- | 'ar'
- | 'hi'
- | 'ru'
- | 'bn'
- | 'he'
- | 'pl'
- | 'cs'
- | 'nl'
- | 'tr'
- | 'uk'
- | 'id'
- | 'th'
- | 'ur'
- | 'ro'
- | 'sv'
- | 'el'
- | 'hu'
- | 'fi'
- | 'da'
- | 'nb';
-
-export const LANGUAGE_SWITCH_ORDER: ReadonlyArray = [
- 'en',
- 'zh-CN',
- 'ja',
- 'ko',
- 'vi',
- 'tl',
- 'es',
- 'pt',
- 'it',
- 'de',
- 'fr',
- 'ar',
- 'hi',
- 'ru',
- 'bn',
- 'he',
- 'pl',
- 'cs',
- 'nl',
- 'tr',
- 'uk',
- 'id',
- 'th',
- 'ur',
- 'ro',
- 'sv',
- 'el',
- 'hu',
- 'fi',
- 'da',
- 'nb',
-];
-
-export type LocaleDirection = 'ltr' | 'rtl';
-
-export interface LanguageOption {
- value: Locale;
- label: string;
- flag: string;
- direction: LocaleDirection;
-}
-
-export const LANGUAGE_OPTIONS: ReadonlyArray = [
- { value: 'en', label: 'English', flag: '🇺🇸', direction: 'ltr' },
- { value: 'zh-CN', label: '简体中文', flag: '🇨🇳', direction: 'ltr' },
- { value: 'ja', label: '日本語', flag: '🇯🇵', direction: 'ltr' },
- { value: 'ko', label: '한국어', flag: '🇰🇷', direction: 'ltr' },
- { value: 'vi', label: 'Tiếng Việt', flag: '🇻🇳', direction: 'ltr' },
- { value: 'tl', label: 'Tagalog', flag: '🇵🇭', direction: 'ltr' },
- { value: 'es', label: 'Español', flag: '🇪🇸', direction: 'ltr' },
- { value: 'pt', label: 'Português', flag: '🇵🇹', direction: 'ltr' },
- { value: 'it', label: 'Italiano', flag: '🇮🇹', direction: 'ltr' },
- { value: 'de', label: 'Deutsch', flag: '🇩🇪', direction: 'ltr' },
- { value: 'fr', label: 'Français', flag: '🇫🇷', direction: 'ltr' },
- { value: 'ar', label: 'العربية', flag: '🇸🇦', direction: 'rtl' },
- { value: 'hi', label: 'हिन्दी', flag: '🇮🇳', direction: 'ltr' },
- { value: 'ru', label: 'Русский', flag: '🇷🇺', direction: 'ltr' },
- { value: 'bn', label: 'বাংলা', flag: '🇧🇩', direction: 'ltr' },
- { value: 'he', label: 'עברית', flag: '🇮🇱', direction: 'rtl' },
- { value: 'pl', label: 'Polski', flag: '🇵🇱', direction: 'ltr' },
- { value: 'cs', label: 'Čeština', flag: '🇨🇿', direction: 'ltr' },
- { value: 'nl', label: 'Nederlands', flag: '🇳🇱', direction: 'ltr' },
- { value: 'tr', label: 'Türkçe', flag: '🇹🇷', direction: 'ltr' },
- { value: 'uk', label: 'Українська', flag: '🇺🇦', direction: 'ltr' },
- { value: 'id', label: 'Bahasa Indonesia', flag: '🇮🇩', direction: 'ltr' },
- { value: 'th', label: 'ไทย', flag: '🇹🇭', direction: 'ltr' },
- { value: 'ur', label: 'اردو', flag: '🇵🇰', direction: 'rtl' },
- { value: 'ro', label: 'Română', flag: '🇷🇴', direction: 'ltr' },
- { value: 'sv', label: 'Svenska', flag: '🇸🇪', direction: 'ltr' },
- { value: 'el', label: 'Ελληνικά', flag: '🇬🇷', direction: 'ltr' },
- { value: 'hu', label: 'Magyar', flag: '🇭🇺', direction: 'ltr' },
- { value: 'fi', label: 'Suomi', flag: '🇫🇮', direction: 'ltr' },
- { value: 'da', label: 'Dansk', flag: '🇩🇰', direction: 'ltr' },
- { value: 'nb', label: 'Norsk Bokmål', flag: '🇳🇴', direction: 'ltr' },
-];
-
-const RTL_LOCALES = new Set(['ar', 'he', 'ur']);
-
-export function getLocaleDirection(locale: Locale): LocaleDirection {
- return RTL_LOCALES.has(locale) ? 'rtl' : 'ltr';
-}
-
-export function getLanguageOption(locale: Locale): LanguageOption {
- const matched = LANGUAGE_OPTIONS.find((option) => option.value === locale);
- if (matched) {
- return matched;
- }
-
- const fallback = LANGUAGE_OPTIONS.find((option) => option.value === 'en');
- if (!fallback) {
- throw new Error('English locale metadata is missing.');
- }
-
- return fallback;
-}
-
-export function getLanguageOptionLabel(option: LanguageOption): string {
- return option.label;
-}
-
-export interface LocaleDocumentTarget {
- documentElement?: { lang?: string; dir?: string };
- body?: { dir?: string } | null;
-}
-
-export function applyLocaleToDocument(locale: Locale, target: LocaleDocumentTarget): void {
- const direction = getLocaleDirection(locale);
-
- if (target.documentElement) {
- target.documentElement.lang = locale;
- target.documentElement.dir = direction;
- }
-
- if (target.body) {
- target.body.dir = direction;
- }
-}
-
-export const LANGUAGE_BUTTON_LABELS: Record = {
- en: 'EN',
- 'zh-CN': '中文',
- ja: '日本語',
- ko: 'KO',
- vi: 'VI',
- tl: 'TL',
- es: 'ES',
- pt: 'PT',
- it: 'IT',
- de: 'DE',
- fr: 'FR',
- ar: 'AR',
- hi: 'HI',
- ru: 'RU',
- bn: 'BN',
- he: 'HE',
- pl: 'PL',
- cs: 'CS',
- nl: 'NL',
- tr: 'TR',
- uk: 'UK',
- id: 'ID',
- th: 'TH',
- ur: 'UR',
- ro: 'RO',
- sv: 'SV',
- el: 'EL',
- hu: 'HU',
- fi: 'FI',
- da: 'DA',
- nb: 'NB',
-};
-
-const en = {
- '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.title': 'Dashboard',
- 'dashboard.provider': 'Provider',
- 'dashboard.model': 'Model',
- 'dashboard.uptime': 'Uptime',
- 'dashboard.temperature': 'Temperature',
- 'dashboard.gateway_port': 'Gateway Port',
- 'dashboard.locale': 'Locale',
- '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',
- 'dashboard.load_failed': 'Dashboard load failed',
- 'dashboard.load_unknown_error': 'Unknown dashboard load error',
- 'dashboard.hero_eyebrow': 'ZeroClaw Command Deck',
- 'dashboard.hero_title': 'Electric Runtime Dashboard',
- 'dashboard.hero_subtitle': 'Real-time telemetry, cost pulse, and operations status in a single collapsible surface.',
- 'dashboard.live_gateway': 'Live Gateway',
- 'dashboard.unpaired': 'Unpaired',
- 'dashboard.provider_model': 'Provider / Model',
- 'dashboard.since_last_restart': 'Since last restart',
- 'dashboard.pairing_active': 'Pairing active',
- 'dashboard.no_paired_devices': 'No paired devices',
- 'dashboard.cost_pulse': 'Cost Pulse',
- 'dashboard.cost_subtitle': 'Session, daily, and monthly runtime spend',
- 'dashboard.session': 'Session',
- 'dashboard.daily': 'Daily',
- 'dashboard.monthly': 'Monthly',
- 'dashboard.channel_activity': 'Channel Activity',
- 'dashboard.channel_subtitle': 'Live integrations and route connectivity',
- 'dashboard.no_channels': 'No channels configured.',
- 'dashboard.active': 'Active',
- 'dashboard.inactive': 'Inactive',
- 'dashboard.component_health': 'Component Health',
- 'dashboard.component_subtitle': 'Runtime heartbeat and restart awareness',
- 'dashboard.no_component_health': 'No component health is currently available.',
- 'dashboard.restarts': 'Restarts',
- 'dashboard.unknown_provider': 'Unknown',
-
- 'agent.title': 'Agent Chat',
- 'agent.send': 'Send',
- 'agent.placeholder': '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.failed_send': 'Failed to send message. Please try again.',
- 'agent.empty_title': 'ZeroClaw Agent',
- 'agent.empty_subtitle': 'Send a message to start the conversation',
- 'agent.unknown_error': 'Unknown error',
-
- '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.no_search_results': 'No tools match your search.',
- 'tools.parameter_schema': 'Parameter Schema',
- 'tools.path': 'Path',
- 'tools.version': 'Version',
- 'tools.load_failed': 'Failed to load tools',
-
- 'cron.title': 'Scheduled Jobs',
- 'cron.add': 'Add Job',
- 'cron.delete': 'Delete',
- 'cron.enable': 'Enable',
- 'cron.disable': 'Disable',
- 'cron.name': 'Name',
- 'cron.command': 'Command',
- 'cron.schedule': 'Schedule',
- 'cron.next_run': 'Next Run',
- 'cron.last_run': 'Last Run',
- 'cron.last_status': 'Last Status',
- 'cron.enabled': 'Enabled',
- 'cron.empty': 'No scheduled jobs.',
- 'cron.confirm_delete': 'Are you sure you want to delete this job?',
- 'cron.scheduled_tasks': 'Scheduled Tasks',
- 'cron.add_cron_job': 'Add Cron Job',
- 'cron.name_optional': 'Name (optional)',
- 'cron.schedule_required_command_required': 'Schedule and command are required.',
- 'cron.adding': 'Adding...',
- 'cron.no_tasks_configured': 'No scheduled tasks configured.',
- 'cron.load_failed': 'Failed to load cron jobs',
- 'cron.failed_add': 'Failed to add job',
- 'cron.failed_delete': 'Failed to delete job',
- 'cron.delete_prompt': 'Delete?',
- 'cron.id': 'ID',
- 'cron.disabled': 'Disabled',
-
- '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_failed': 'Failed to load integrations',
- 'integrations.all': 'all',
-
- 'memory.title': 'Memory Store',
- 'memory.search': 'Search memory...',
- 'memory.add': 'Store Memory',
- 'memory.delete': 'Delete',
- 'memory.key': 'Key',
- 'memory.content': 'Content',
- 'memory.category': 'Category',
- '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.add_memory': 'Add Memory',
- 'memory.search_entries': 'Search memory entries...',
- 'memory.load_failed': 'Failed to load memory',
- 'memory.key_content_required': 'Key and content are required.',
- 'memory.failed_store': 'Failed to store memory',
- 'memory.failed_delete': 'Failed to delete memory',
- 'memory.category_optional': 'Category (optional)',
- 'memory.key_placeholder': 'e.g. user_preferences',
- 'memory.content_placeholder': 'Memory content...',
- 'memory.category_placeholder': 'e.g. preferences, context, facts',
- 'memory.search_button': 'Search',
- 'memory.saving': 'Saving...',
- 'memory.delete_prompt': 'Delete?',
-
- 'config.title': 'Configuration',
- 'config.save': 'Save',
- 'config.reset': 'Reset',
- 'config.saved': 'Configuration saved successfully.',
- 'config.error': 'Failed to save configuration.',
- 'config.loading': 'Loading configuration...',
- 'config.editor_placeholder': 'TOML configuration...',
- 'config.saving': 'Saving...',
- 'config.masked_title': 'Sensitive fields are masked',
- 'config.masked_description': 'API keys, tokens, and passwords are hidden for security. To update a masked field, replace the entire masked value with your new value.',
- 'config.toml_configuration': 'TOML Configuration',
- 'config.lines': 'lines',
-
- '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.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.share': 'Share',
- 'cost.load_failed': 'Failed to load cost data',
-
- 'logs.title': 'Live Logs',
- 'logs.clear': 'Clear',
- 'logs.pause': 'Pause',
- 'logs.resume': 'Resume',
- 'logs.filter': 'Filter logs...',
- 'logs.empty': 'No log entries.',
- 'logs.connected': 'Connected to event stream.',
- 'logs.disconnected': 'Disconnected from event stream.',
- 'logs.events': 'events',
- 'logs.jump_to_bottom': 'Jump to bottom',
- 'logs.filter_label': 'Filter:',
- 'logs.paused_stream': 'Log streaming is paused.',
- 'logs.waiting_for_events': 'Waiting for events...',
-
- 'doctor.title': 'System Diagnostics',
- 'doctor.run': 'Run Diagnostics',
- 'doctor.running': 'Running diagnostics...',
- '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.running_short': 'Running...',
- 'doctor.running_hint': 'This may take a few seconds.',
- 'doctor.issues_found': 'Issues Found',
- 'doctor.warnings': 'Warnings',
- 'doctor.all_clear': 'All Clear',
- 'doctor.instructions': 'Click "Run Diagnostics" to check your ZeroClaw installation.',
-
- '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 the one-time pairing code from your terminal',
- 'auth.code_placeholder': '6-digit code',
- 'auth.pairing_progress': 'Pairing...',
-
- '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',
- 'common.languages': 'Languages',
- 'common.select_language': 'Select language',
- 'common.connecting': 'Connecting...',
-
- 'health.title': 'System Health',
- 'health.component': 'Component',
- 'health.status': 'Status',
- 'health.last_ok': 'Last OK',
- 'health.last_error': 'Last Error',
- 'health.restart_count': 'Restart Count',
- 'health.pid': 'Process ID',
- 'health.uptime': 'Uptime',
- 'health.updated_at': 'Updated At',
-
- 'header.dashboard_tagline': 'ZeroClaw dashboard',
- 'sidebar.gateway_dashboard': 'Gateway + Dashboard',
- 'sidebar.runtime_mode': 'Runtime Mode',
- 'navigation.open': 'Open navigation',
- 'navigation.close': 'Close navigation',
- 'navigation.expand': 'Expand navigation',
- 'navigation.collapse': 'Collapse navigation',
-} satisfies Record;
-
-const tr = {
- ...en,
- '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',
- 'agent.title': 'Ajan Sohbeti',
- 'agent.send': 'Gönder',
- 'agent.placeholder': 'Bir mesaj yazın...',
- 'agent.connecting': 'Bağlanıyor...',
- 'agent.connected': 'Bağlı',
- '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.failed_send': 'Mesaj gönderilemedi. Lütfen tekrar deneyin.',
- 'agent.empty_title': 'ZeroClaw Ajanı',
- 'agent.empty_subtitle': 'Konuşmayı başlatmak için bir mesaj gönderin',
- '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': 'Yerel Ayar',
- 'dashboard.memory_backend': 'Hafıza Arka Ucu',
- 'dashboard.hero_eyebrow': 'ZeroClaw Komuta Güvertesi',
- 'dashboard.hero_title': 'Elektrik Çalışma Zamanı Paneli',
- 'dashboard.hero_subtitle': 'Gerçek zamanlı telemetri, maliyet akışı ve operasyon durumunu tek bir daraltılabilir yüzeyde görün.',
- 'dashboard.live_gateway': 'Canlı Ağ Geçidi',
- 'dashboard.unpaired': 'Eşleşmemiş',
- 'dashboard.provider_model': 'Sağlayıcı / Model',
- 'dashboard.since_last_restart': 'Son yeniden başlatmadan beri',
- 'dashboard.pairing_active': 'Eşleştirme etkin',
- 'dashboard.no_paired_devices': 'Eşleşmiş cihaz yok',
- 'dashboard.cost_pulse': 'Maliyet Nabzı',
- 'dashboard.cost_subtitle': 'Oturum, günlük ve aylık çalışma zamanı harcaması',
- 'dashboard.session': 'Oturum',
- 'dashboard.daily': 'Günlük',
- 'dashboard.monthly': 'Aylık',
- 'dashboard.channel_activity': 'Kanal Etkinliği',
- 'dashboard.channel_subtitle': 'Canlı entegrasyonlar ve rota bağlantısı',
- 'dashboard.no_channels': 'Hiç kanal yapılandırılmamış.',
- 'dashboard.active': 'Aktif',
- 'dashboard.inactive': 'Pasif',
- 'dashboard.component_health': 'Bileşen Sağlığı',
- 'dashboard.component_subtitle': 'Çalışma zamanı nabzı ve yeniden başlatma farkındalığı',
- 'dashboard.no_component_health': 'Şu anda bileşen sağlığı bilgisi yok.',
- 'dashboard.restarts': 'Yeniden Başlatmalar',
- 'tools.title': 'Mevcut Araçlar',
- 'tools.search': 'Araç ara...',
- 'tools.agent_tools': 'Ajan Araçları',
- 'tools.cli_tools': 'CLI Araçları',
- 'tools.no_search_results': 'Aramanızla eşleşen araç yok.',
- 'tools.parameter_schema': 'Parametre Şeması',
- 'tools.path': 'Yol',
- 'tools.version': 'Sürüm',
- 'cron.title': 'Zamanlanmış Görevler',
- 'cron.add': 'Görev Ekle',
- 'cron.scheduled_tasks': 'Zamanlanmış Görevler',
- 'cron.add_cron_job': 'Cron Görevi Ekle',
- 'cron.name_optional': 'Ad (isteğe bağlı)',
- 'cron.schedule_required_command_required': 'Zamanlama ve komut gereklidir.',
- 'cron.adding': 'Ekleniyor...',
- 'cron.no_tasks_configured': 'Zamanlanmış görev yapılandırılmamış.',
- 'cron.load_failed': 'Cron görevleri yüklenemedi',
- 'cron.failed_add': 'Görev eklenemedi',
- 'cron.failed_delete': 'Görev silinemedi',
- 'cron.delete_prompt': 'Silinsin mi?',
- 'cron.disabled': 'Devre Dışı',
- 'integrations.title': 'Entegrasyonlar',
- 'integrations.available': 'Mevcut',
- 'integrations.active': 'Aktif',
- 'integrations.coming_soon': 'Yakında',
- 'integrations.empty': 'Entegrasyon bulunamadı.',
- 'integrations.load_failed': 'Entegrasyonlar yüklenemedi',
- 'memory.title': 'Hafıza Deposu',
- 'memory.add_memory': 'Hafıza Ekle',
- 'memory.search_entries': 'Hafıza girdilerinde ara...',
- 'memory.all_categories': 'Tüm Kategoriler',
- 'memory.search_button': 'Ara',
- 'memory.load_failed': 'Hafıza yüklenemedi',
- 'memory.key_content_required': 'Anahtar ve içerik gereklidir.',
- 'memory.failed_store': 'Hafıza kaydedilemedi',
- 'memory.failed_delete': 'Hafıza silinemedi',
- 'memory.category_optional': 'Kategori (isteğe bağlı)',
- 'memory.key_placeholder': 'örn. kullanici_tercihleri',
- 'memory.content_placeholder': 'Hafıza içeriği...',
- 'memory.category_placeholder': 'örn. tercihler, bağlam, gerçekler',
- 'memory.saving': 'Kaydediliyor...',
- 'memory.delete_prompt': 'Silinsin mi?',
- 'config.title': 'Yapılandırma',
- 'config.save': 'Kaydet',
- 'config.saved': 'Yapılandırma başarıyla kaydedildi.',
- 'config.saving': 'Kaydediliyor...',
- 'config.masked_title': 'Hassas alanlar maskelendi',
- 'config.masked_description': 'Güvenlik için API anahtarları, belirteçler ve parolalar gizlenir. Maskelenmiş bir alanı güncellemek için tüm maskeli değeri yeni değerinizle değiştirin.',
- 'config.toml_configuration': 'TOML Yapılandırması',
- 'config.lines': 'satır',
- 'cost.title': 'Maliyet Takibi',
- 'cost.session': 'Oturum Maliyeti',
- 'cost.daily': 'Günlük Maliyet',
- 'cost.monthly': 'Aylık Maliyet',
- 'cost.total_requests': 'Toplam İstek',
- 'cost.token_statistics': 'Belirteç İstatistikleri',
- 'cost.avg_tokens_per_request': 'İstek Başına Ort. Belirteç',
- 'cost.cost_per_1k_tokens': '1K Belirteç Başına Maliyet',
- 'cost.model_breakdown': 'Model Dağılımı',
- 'cost.no_model_data': 'Model verisi yok.',
- 'cost.share': 'Pay',
- 'cost.load_failed': 'Maliyet verisi yüklenemedi',
- 'logs.title': 'Canlı Kayıtlar',
- 'logs.pause': 'Duraklat',
- 'logs.resume': 'Sürdür',
- 'logs.events': 'olay',
- 'logs.jump_to_bottom': 'Alta git',
- 'logs.filter_label': 'Filtre:',
- 'logs.paused_stream': 'Kayıt akışı duraklatıldı.',
- 'logs.waiting_for_events': 'Olaylar bekleniyor...',
- 'doctor.title': 'Sistem Teşhisleri',
- 'doctor.run': 'Teşhisleri Çalıştır',
- 'doctor.running': 'Teşhisler çalıştırılıyor...',
- 'doctor.running_short': 'Çalışıyor...',
- 'doctor.running_hint': 'Bu birkaç saniye sürebilir.',
- 'doctor.warn': 'Uyarı',
- 'doctor.issues_found': 'Sorunlar Bulundu',
- 'doctor.warnings': 'Uyarılar',
- 'doctor.all_clear': 'Temiz',
- 'doctor.instructions': 'ZeroClaw kurulumunuzu kontrol etmek için "Teşhisleri Çalıştır" düğmesine tıklayın.',
- 'auth.pair': 'Cihazı Eşle',
- 'auth.pair_button': 'Eşle',
- 'auth.logout': 'Çıkış Yap',
- 'auth.enter_code': 'Terminalinizdeki tek kullanımlık eşleştirme kodunu girin',
- 'auth.code_placeholder': '6 haneli kod',
- 'auth.pairing_progress': 'Eşleştiriliyor...',
- 'common.languages': 'Diller',
- 'common.select_language': 'Dil seçin',
- 'common.connecting': 'Bağlanıyor...',
- 'header.dashboard_tagline': 'ZeroClaw paneli',
- 'sidebar.gateway_dashboard': 'Ağ Geçidi + Panel',
- 'sidebar.runtime_mode': 'Çalışma Modu',
- 'navigation.open': 'Gezinmeyi aç',
- 'navigation.close': 'Gezinmeyi kapat',
- 'navigation.expand': 'Gezinmeyi genişlet',
- 'navigation.collapse': 'Gezinmeyi daralt',
-};
-
-const zhCn = {
- ...en,
- 'nav.dashboard': '仪表盘',
- 'nav.agent': '代理',
- 'nav.tools': '工具',
- 'nav.cron': '定时任务',
- 'nav.integrations': '集成',
- 'nav.memory': '记忆',
- 'nav.config': '配置',
- 'nav.cost': '成本跟踪',
- 'nav.logs': '日志',
- 'nav.doctor': '诊断',
- 'dashboard.hero_title': '电光运行仪表盘',
- 'dashboard.live_gateway': '在线网关',
- 'dashboard.unpaired': '未配对',
- 'agent.title': '代理聊天',
- 'agent.placeholder': '输入消息…',
- 'agent.connecting': '正在连接…',
- 'agent.connected': '已连接',
- 'agent.disconnected': '已断开',
- 'tools.search': '搜索工具…',
- 'tools.agent_tools': '代理工具',
- 'tools.cli_tools': 'CLI 工具',
- 'cron.add': '添加任务',
- 'cron.scheduled_tasks': '定时任务',
- 'integrations.title': '集成',
- 'memory.add_memory': '添加记忆',
- 'memory.search_entries': '搜索记忆条目…',
- 'config.save': '保存',
- 'config.saving': '正在保存…',
- 'cost.session': '会话成本',
- 'cost.daily': '每日成本',
- 'cost.monthly': '每月成本',
- 'logs.title': '实时日志',
- 'logs.pause': '暂停',
- 'logs.resume': '继续',
- 'doctor.title': '系统诊断',
- 'doctor.run': '运行诊断',
- 'doctor.running_short': '运行中…',
- 'auth.pair_button': '配对',
- 'auth.enter_code': '输入终端中的一次性配对码',
- 'auth.code_placeholder': '6 位代码',
- 'auth.pairing_progress': '正在配对…',
- 'auth.logout': '退出',
- 'common.languages': '语言',
- 'common.select_language': '选择语言',
- 'header.dashboard_tagline': 'ZeroClaw 仪表盘',
-};
-
-const ja = {
- ...en,
- 'nav.dashboard': 'ダッシュボード',
- 'nav.agent': 'エージェント',
- 'nav.tools': 'ツール',
- 'nav.cron': 'スケジュール',
- 'nav.integrations': '連携',
- 'nav.memory': 'メモリ',
- 'nav.config': '設定',
- 'nav.cost': 'コスト',
- 'nav.logs': 'ログ',
- 'nav.doctor': '診断',
- 'dashboard.hero_title': 'エレクトリック・ランタイム・ダッシュボード',
- 'dashboard.live_gateway': 'ライブゲートウェイ',
- 'dashboard.unpaired': '未ペア',
- 'agent.title': 'エージェントチャット',
- 'agent.placeholder': 'メッセージを入力…',
- 'agent.connecting': '接続中…',
- 'agent.connected': '接続済み',
- 'agent.disconnected': '切断済み',
- 'tools.search': 'ツールを検索…',
- 'tools.agent_tools': 'エージェントツール',
- 'tools.cli_tools': 'CLI ツール',
- 'cron.add': 'ジョブを追加',
- 'cron.scheduled_tasks': 'スケジュールされたジョブ',
- 'integrations.title': '連携',
- 'memory.add_memory': 'メモリを追加',
- 'memory.search_entries': 'メモリエントリを検索…',
- 'config.save': '保存',
- 'config.saving': '保存中…',
- 'cost.session': 'セッションコスト',
- 'cost.daily': '日次コスト',
- 'cost.monthly': '月次コスト',
- 'logs.title': 'ライブログ',
- 'logs.pause': '一時停止',
- 'logs.resume': '再開',
- 'doctor.title': 'システム診断',
- 'doctor.run': '診断を実行',
- 'doctor.running_short': '実行中…',
- 'auth.pair_button': 'ペアリング',
- 'auth.enter_code': '端末のワンタイムペアリングコードを入力してください',
- 'auth.code_placeholder': '6桁のコード',
- 'auth.pairing_progress': 'ペアリング中…',
- 'auth.logout': 'ログアウト',
- 'common.languages': '言語',
- 'common.select_language': '言語を選択',
- 'header.dashboard_tagline': 'ZeroClaw ダッシュボード',
-};
-
-const ru = {
- ...en,
- 'nav.dashboard': 'Панель',
- 'nav.agent': 'Агент',
- 'nav.tools': 'Инструменты',
- 'nav.cron': 'Задания',
- 'nav.integrations': 'Интеграции',
- 'nav.memory': 'Память',
- 'nav.config': 'Конфигурация',
- 'nav.cost': 'Расходы',
- 'nav.logs': 'Логи',
- 'nav.doctor': 'Диагностика',
- 'dashboard.hero_title': 'Панель электрического рантайма',
- 'dashboard.live_gateway': 'Живой шлюз',
- 'dashboard.unpaired': 'Не сопряжено',
- 'agent.title': 'Чат агента',
- 'agent.placeholder': 'Введите сообщение…',
- 'agent.connecting': 'Подключение…',
- 'agent.connected': 'Подключено',
- 'agent.disconnected': 'Отключено',
- 'tools.search': 'Поиск инструментов…',
- 'tools.agent_tools': 'Инструменты агента',
- 'tools.cli_tools': 'CLI-инструменты',
- 'cron.add': 'Добавить задачу',
- 'cron.scheduled_tasks': 'Запланированные задания',
- 'integrations.title': 'Интеграции',
- 'memory.add_memory': 'Добавить память',
- 'memory.search_entries': 'Искать записи памяти…',
- 'config.save': 'Сохранить',
- 'config.saving': 'Сохранение…',
- 'cost.session': 'Стоимость сессии',
- 'cost.daily': 'Стоимость за день',
- 'cost.monthly': 'Стоимость за месяц',
- 'logs.title': 'Живые логи',
- 'logs.pause': 'Пауза',
- 'logs.resume': 'Продолжить',
- 'doctor.title': 'Диагностика системы',
- 'doctor.run': 'Запустить диагностику',
- 'doctor.running_short': 'Выполняется…',
- 'auth.pair_button': 'Сопрячь',
- 'auth.enter_code': 'Введите одноразовый код сопряжения из терминала',
- 'auth.code_placeholder': '6-значный код',
- 'auth.pairing_progress': 'Сопряжение…',
- 'auth.logout': 'Выйти',
- 'common.languages': 'Языки',
- 'common.select_language': 'Выберите язык',
- 'header.dashboard_tagline': 'Панель ZeroClaw',
-};
-
-const fr = {
- ...en,
- 'nav.dashboard': 'Tableau de bord',
- 'nav.agent': 'Agent',
- 'nav.tools': 'Outils',
- 'nav.cron': 'Tâches planifiées',
- 'nav.integrations': 'Intégrations',
- 'nav.memory': 'Mémoire',
- 'nav.config': 'Configuration',
- 'nav.cost': 'Coûts',
- 'nav.logs': 'Journaux',
- 'nav.doctor': 'Diagnostic',
- 'dashboard.hero_title': 'Tableau de bord runtime électrique',
- 'dashboard.live_gateway': 'Passerelle active',
- 'dashboard.unpaired': 'Non appairé',
- 'agent.title': 'Chat agent',
- 'agent.placeholder': 'Saisissez un message…',
- 'agent.connecting': 'Connexion…',
- 'agent.connected': 'Connecté',
- 'agent.disconnected': 'Déconnecté',
- 'tools.search': 'Rechercher des outils…',
- 'tools.agent_tools': 'Outils agent',
- 'tools.cli_tools': 'Outils CLI',
- 'cron.add': 'Ajouter une tâche',
- 'cron.scheduled_tasks': 'Tâches planifiées',
- 'integrations.title': 'Intégrations',
- 'memory.add_memory': 'Ajouter une mémoire',
- 'memory.search_entries': 'Rechercher dans la mémoire…',
- 'config.save': 'Enregistrer',
- 'config.saving': 'Enregistrement…',
- 'cost.session': 'Coût de session',
- 'cost.daily': 'Coût journalier',
- 'cost.monthly': 'Coût mensuel',
- 'logs.title': 'Journaux en direct',
- 'logs.pause': 'Pause',
- 'logs.resume': 'Reprendre',
- 'doctor.title': 'Diagnostic système',
- 'doctor.run': 'Lancer le diagnostic',
- 'doctor.running_short': 'Exécution…',
- 'auth.pair_button': 'Associer',
- 'auth.enter_code': 'Entrez le code d’appairage à usage unique affiché dans le terminal',
- 'auth.code_placeholder': 'Code à 6 chiffres',
- 'auth.pairing_progress': 'Appairage…',
- 'auth.logout': 'Déconnexion',
- 'common.languages': 'Langues',
- 'common.select_language': 'Choisir la langue',
- 'header.dashboard_tagline': 'Tableau de bord ZeroClaw',
-};
-
-const vi = {
- ...en,
- 'nav.dashboard': 'Bảng điều khiển',
- 'nav.agent': 'Tác tử',
- 'nav.tools': 'Công cụ',
- 'nav.cron': 'Lịch tác vụ',
- 'nav.integrations': 'Tích hợp',
- 'nav.memory': 'Bộ nhớ',
- 'nav.config': 'Cấu hình',
- 'nav.cost': 'Chi phí',
- 'nav.logs': 'Nhật ký',
- 'nav.doctor': 'Chẩn đoán',
- 'dashboard.hero_title': 'Bảng điều khiển runtime điện xanh',
- 'dashboard.live_gateway': 'Cổng hoạt động',
- 'dashboard.unpaired': 'Chưa ghép đôi',
- 'agent.title': 'Trò chuyện với tác tử',
- 'agent.placeholder': 'Nhập tin nhắn…',
- 'agent.connecting': 'Đang kết nối…',
- 'agent.connected': 'Đã kết nối',
- 'agent.disconnected': 'Đã ngắt kết nối',
- 'tools.search': 'Tìm công cụ…',
- 'tools.agent_tools': 'Công cụ tác tử',
- 'tools.cli_tools': 'Công cụ CLI',
- 'cron.add': 'Thêm tác vụ',
- 'cron.scheduled_tasks': 'Tác vụ đã lên lịch',
- 'integrations.title': 'Tích hợp',
- 'memory.add_memory': 'Thêm bộ nhớ',
- 'memory.search_entries': 'Tìm trong bộ nhớ…',
- 'config.save': 'Lưu',
- 'config.saving': 'Đang lưu…',
- 'cost.session': 'Chi phí phiên',
- 'cost.daily': 'Chi phí ngày',
- 'cost.monthly': 'Chi phí tháng',
- 'logs.title': 'Nhật ký trực tiếp',
- 'logs.pause': 'Tạm dừng',
- 'logs.resume': 'Tiếp tục',
- 'doctor.title': 'Chẩn đoán hệ thống',
- 'doctor.run': 'Chạy chẩn đoán',
- 'doctor.running_short': 'Đang chạy…',
- 'auth.pair_button': 'Ghép đôi',
- 'auth.enter_code': 'Nhập mã ghép đôi một lần từ terminal',
- 'auth.code_placeholder': 'Mã 6 chữ số',
- 'auth.pairing_progress': 'Đang ghép đôi…',
- 'auth.logout': 'Đăng xuất',
- 'common.languages': 'Ngôn ngữ',
- 'common.select_language': 'Chọn ngôn ngữ',
- 'header.dashboard_tagline': 'Bảng điều khiển ZeroClaw',
-};
-
-
-const createLocale = (overrides: Record) => ({
- ...en,
- ...overrides,
-});
-
-const ko = createLocale({
- 'nav.dashboard': '대시보드',
- 'nav.agent': '에이전트',
- 'nav.tools': '도구',
- 'nav.cron': '예약 작업',
- 'nav.integrations': '통합',
- 'nav.memory': '메모리',
- 'nav.config': '설정',
- 'nav.cost': '비용 추적',
- 'nav.logs': '로그',
- 'nav.doctor': '진단',
- 'dashboard.hero_title': '전기 런타임 대시보드',
- 'agent.placeholder': '메시지를 입력하세요…',
- 'tools.search': '도구 검색…',
- 'cron.add': '작업 추가',
- 'memory.add_memory': '메모리 추가',
- 'config.save': '저장',
- 'cost.token_statistics': '토큰 통계',
- 'logs.title': '실시간 로그',
- 'doctor.title': '시스템 진단',
- 'auth.pair_button': '페어링',
- 'auth.enter_code': '터미널에 표시된 일회용 페어링 코드를 입력하세요',
- 'auth.code_placeholder': '6자리 코드',
- 'auth.pairing_progress': '페어링 중…',
- 'auth.logout': '로그아웃',
- 'common.languages': '언어',
- 'common.select_language': '언어 선택',
- 'header.dashboard_tagline': 'ZeroClaw 대시보드',
-});
-
-const tl = createLocale({
- 'nav.dashboard': 'Dashboard',
- 'nav.agent': 'Ahente',
- 'nav.tools': 'Mga Tool',
- 'nav.cron': 'Naka-iskedyul na Trabaho',
- 'nav.integrations': 'Mga Integrasyon',
- 'nav.memory': 'Alaala',
- 'nav.config': 'Konpigurasyon',
- 'nav.cost': 'Pagsubaybay sa Gastos',
- 'nav.logs': 'Mga Log',
- 'nav.doctor': 'Diyagnostiko',
- 'dashboard.hero_title': 'Elektrikong Dashboard ng Runtime',
- 'agent.placeholder': 'Mag-type ng mensahe…',
- 'tools.search': 'Maghanap ng tool…',
- 'cron.add': 'Magdagdag ng gawain',
- 'memory.add_memory': 'Magdagdag ng alaala',
- 'config.save': 'I-save',
- 'cost.token_statistics': 'Estadistika ng Token',
- 'logs.title': 'Mga Live Log',
- 'doctor.title': 'Diyagnostiko ng System',
- 'auth.pair_button': 'Ipares',
- 'auth.enter_code': 'Ilagay ang isang beses na pairing code mula sa terminal',
- 'auth.code_placeholder': '6-digit na code',
- 'auth.pairing_progress': 'Pinapares…',
- 'auth.logout': 'Mag-logout',
- 'common.languages': 'Mga Wika',
- 'common.select_language': 'Piliin ang wika',
- 'header.dashboard_tagline': 'Dashboard ng ZeroClaw',
-});
-
-const es = createLocale({
- 'nav.dashboard': 'Panel',
- 'nav.agent': 'Agente',
- 'nav.tools': 'Herramientas',
- 'nav.cron': 'Tareas programadas',
- 'nav.integrations': 'Integraciones',
- 'nav.memory': 'Memoria',
- 'nav.config': 'Configuración',
- 'nav.cost': 'Costos',
- 'nav.logs': 'Registros',
- 'nav.doctor': 'Diagnóstico',
- 'dashboard.hero_title': 'Panel eléctrico del runtime',
- 'agent.placeholder': 'Escribe un mensaje…',
- 'tools.search': 'Buscar herramientas…',
- 'cron.add': 'Agregar tarea',
- 'memory.add_memory': 'Agregar memoria',
- 'config.save': 'Guardar',
- 'cost.token_statistics': 'Estadísticas de tokens',
- 'logs.title': 'Registros en vivo',
- 'doctor.title': 'Diagnóstico del sistema',
- 'auth.pair_button': 'Vincular',
- 'auth.enter_code': 'Introduce el código de vinculación de un solo uso del terminal',
- 'auth.code_placeholder': 'Código de 6 dígitos',
- 'auth.pairing_progress': 'Vinculando…',
- 'auth.logout': 'Cerrar sesión',
- 'common.languages': 'Idiomas',
- 'common.select_language': 'Elegir idioma',
- 'header.dashboard_tagline': 'Panel de ZeroClaw',
-});
-
-const pt = createLocale({
- 'nav.dashboard': 'Painel',
- 'nav.agent': 'Agente',
- 'nav.tools': 'Ferramentas',
- 'nav.cron': 'Tarefas agendadas',
- 'nav.integrations': 'Integrações',
- 'nav.memory': 'Memória',
- 'nav.config': 'Configuração',
- 'nav.cost': 'Custos',
- 'nav.logs': 'Logs',
- 'nav.doctor': 'Diagnóstico',
- 'dashboard.hero_title': 'Painel elétrico do runtime',
- 'agent.placeholder': 'Digite uma mensagem…',
- 'tools.search': 'Buscar ferramentas…',
- 'cron.add': 'Adicionar tarefa',
- 'memory.add_memory': 'Adicionar memória',
- 'config.save': 'Salvar',
- 'cost.token_statistics': 'Estatísticas de tokens',
- 'logs.title': 'Logs ao vivo',
- 'doctor.title': 'Diagnóstico do sistema',
- 'auth.pair_button': 'Parear',
- 'auth.enter_code': 'Digite o código único de pareamento mostrado no terminal',
- 'auth.code_placeholder': 'Código de 6 dígitos',
- 'auth.pairing_progress': 'Pareando…',
- 'auth.logout': 'Sair',
- 'common.languages': 'Idiomas',
- 'common.select_language': 'Escolher idioma',
- 'header.dashboard_tagline': 'Painel do ZeroClaw',
-});
-
-const it = createLocale({
- 'nav.dashboard': 'Dashboard',
- 'nav.agent': 'Agente',
- 'nav.tools': 'Strumenti',
- 'nav.cron': 'Attività pianificate',
- 'nav.integrations': 'Integrazioni',
- 'nav.memory': 'Memoria',
- 'nav.config': 'Configurazione',
- 'nav.cost': 'Costi',
- 'nav.logs': 'Log',
- 'nav.doctor': 'Diagnostica',
- 'dashboard.hero_title': 'Dashboard runtime elettrica',
- 'agent.placeholder': 'Scrivi un messaggio…',
- 'tools.search': 'Cerca strumenti…',
- 'cron.add': 'Aggiungi attività',
- 'memory.add_memory': 'Aggiungi memoria',
- 'config.save': 'Salva',
- 'cost.token_statistics': 'Statistiche token',
- 'logs.title': 'Log in tempo reale',
- 'doctor.title': 'Diagnostica di sistema',
- 'auth.pair_button': 'Associa',
- 'auth.enter_code': 'Inserisci il codice di associazione monouso dal terminale',
- 'auth.code_placeholder': 'Codice a 6 cifre',
- 'auth.pairing_progress': 'Associazione…',
- 'auth.logout': 'Disconnetti',
- 'common.languages': 'Lingue',
- 'common.select_language': 'Scegli lingua',
- 'header.dashboard_tagline': 'Dashboard di ZeroClaw',
-});
-
-const de = createLocale({
- 'nav.dashboard': 'Dashboard',
- 'nav.agent': 'Agent',
- 'nav.tools': 'Werkzeuge',
- 'nav.cron': 'Geplante Aufgaben',
- 'nav.integrations': 'Integrationen',
- 'nav.memory': 'Speicher',
- 'nav.config': 'Konfiguration',
- 'nav.cost': 'Kosten',
- 'nav.logs': 'Protokolle',
- 'nav.doctor': 'Diagnose',
- 'dashboard.hero_title': 'Elektrisches Runtime-Dashboard',
- 'agent.placeholder': 'Nachricht eingeben…',
- 'tools.search': 'Werkzeuge suchen…',
- 'cron.add': 'Aufgabe hinzufügen',
- 'memory.add_memory': 'Speicher hinzufügen',
- 'config.save': 'Speichern',
- 'cost.token_statistics': 'Token-Statistiken',
- 'logs.title': 'Live-Protokolle',
- 'doctor.title': 'Systemdiagnose',
- 'auth.pair_button': 'Koppeln',
- 'auth.enter_code': 'Geben Sie den einmaligen Kopplungscode aus dem Terminal ein',
- 'auth.code_placeholder': '6-stelliger Code',
- 'auth.pairing_progress': 'Kopplung…',
- 'auth.logout': 'Abmelden',
- 'common.languages': 'Sprachen',
- 'common.select_language': 'Sprache auswählen',
- 'header.dashboard_tagline': 'ZeroClaw-Dashboard',
-});
-
-const ar = createLocale({
- 'nav.dashboard': 'لوحة التحكم',
- 'nav.agent': 'الوكيل',
- 'nav.tools': 'الأدوات',
- 'nav.cron': 'المهام المجدولة',
- 'nav.integrations': 'التكاملات',
- 'nav.memory': 'الذاكرة',
- 'nav.config': 'الإعدادات',
- 'nav.cost': 'تتبع التكلفة',
- 'nav.logs': 'السجلات',
- 'nav.doctor': 'التشخيص',
- 'dashboard.hero_title': 'لوحة تشغيل كهربائية',
- 'agent.placeholder': 'اكتب رسالة…',
- 'tools.search': 'ابحث في الأدوات…',
- 'cron.add': 'إضافة مهمة',
- 'memory.add_memory': 'إضافة ذاكرة',
- 'config.save': 'حفظ',
- 'cost.token_statistics': 'إحصاءات الرموز',
- 'logs.title': 'السجلات المباشرة',
- 'doctor.title': 'تشخيص النظام',
- 'auth.pair_button': 'اقتران',
- 'auth.enter_code': 'أدخل رمز الاقتران لمرة واحدة من الطرفية',
- 'auth.code_placeholder': 'رمز من 6 أرقام',
- 'auth.pairing_progress': 'جارٍ الاقتران…',
- 'auth.logout': 'تسجيل الخروج',
- 'common.languages': 'اللغات',
- 'common.select_language': 'اختر اللغة',
- 'header.dashboard_tagline': 'لوحة ZeroClaw',
-});
-
-const hi = createLocale({
- 'nav.dashboard': 'डैशबोर्ड',
- 'nav.agent': 'एजेंट',
- 'nav.tools': 'टूल्स',
- 'nav.cron': 'निर्धारित कार्य',
- 'nav.integrations': 'इंटीग्रेशन',
- 'nav.memory': 'मेमोरी',
- 'nav.config': 'कॉन्फ़िगरेशन',
- 'nav.cost': 'लागत ट्रैकर',
- 'nav.logs': 'लॉग्स',
- 'nav.doctor': 'जाँच',
- 'dashboard.hero_title': 'इलेक्ट्रिक रनटाइम डैशबोर्ड',
- 'agent.placeholder': 'संदेश लिखें…',
- 'tools.search': 'टूल खोजें…',
- 'cron.add': 'कार्य जोड़ें',
- 'memory.add_memory': 'मेमोरी जोड़ें',
- 'config.save': 'सहेजें',
- 'cost.token_statistics': 'टोकन आँकड़े',
- 'logs.title': 'लाइव लॉग्स',
- 'doctor.title': 'सिस्टम जाँच',
- 'auth.pair_button': 'पेयर करें',
- 'auth.enter_code': 'टर्मिनल से एक-बार वाला पेयरिंग कोड दर्ज करें',
- 'auth.code_placeholder': '6-अंकों का कोड',
- 'auth.pairing_progress': 'पेयर किया जा रहा है…',
- 'auth.logout': 'लॉग आउट',
- 'common.languages': 'भाषाएँ',
- 'common.select_language': 'भाषा चुनें',
- 'header.dashboard_tagline': 'ZeroClaw डैशबोर्ड',
-});
-
-const bn = createLocale({
- 'nav.dashboard': 'ড্যাশবোর্ড',
- 'nav.agent': 'এজেন্ট',
- 'nav.tools': 'টুলস',
- 'nav.cron': 'নির্ধারিত কাজ',
- 'nav.integrations': 'ইন্টিগ্রেশন',
- 'nav.memory': 'মেমরি',
- 'nav.config': 'কনফিগারেশন',
- 'nav.cost': 'খরচ ট্র্যাকার',
- 'nav.logs': 'লগ',
- 'nav.doctor': 'ডায়াগনস্টিক',
- 'dashboard.hero_title': 'ইলেকট্রিক রানটাইম ড্যাশবোর্ড',
- 'agent.placeholder': 'একটি বার্তা লিখুন…',
- 'tools.search': 'টুল খুঁজুন…',
- 'cron.add': 'কাজ যোগ করুন',
- 'memory.add_memory': 'মেমরি যোগ করুন',
- 'config.save': 'সংরক্ষণ করুন',
- 'cost.token_statistics': 'টোকেন পরিসংখ্যান',
- 'logs.title': 'লাইভ লগ',
- 'doctor.title': 'সিস্টেম ডায়াগনস্টিক',
- 'auth.pair_button': 'পেয়ার করুন',
- 'auth.enter_code': 'টার্মিনাল থেকে একবারের পেয়ারিং কোড লিখুন',
- 'auth.code_placeholder': '৬-সংখ্যার কোড',
- 'auth.pairing_progress': 'পেয়ার করা হচ্ছে…',
- 'auth.logout': 'লগ আউট',
- 'common.languages': 'ভাষাসমূহ',
- 'common.select_language': 'ভাষা বেছে নিন',
- 'header.dashboard_tagline': 'ZeroClaw ড্যাশবোর্ড',
-});
-
-const he = createLocale({
- 'nav.dashboard': 'לוח מחוונים',
- 'nav.agent': 'סוכן',
- 'nav.tools': 'כלים',
- 'nav.cron': 'משימות מתוזמנות',
- 'nav.integrations': 'אינטגרציות',
- 'nav.memory': 'זיכרון',
- 'nav.config': 'תצורה',
- 'nav.cost': 'מעקב עלויות',
- 'nav.logs': 'יומנים',
- 'nav.doctor': 'אבחון',
- 'dashboard.hero_title': 'לוח מחוונים חשמלי של זמן הריצה',
- 'agent.placeholder': 'הקלד הודעה…',
- 'tools.search': 'חפש כלים…',
- 'cron.add': 'הוסף משימה',
- 'memory.add_memory': 'הוסף זיכרון',
- 'config.save': 'שמור',
- 'cost.token_statistics': 'סטטיסטיקות אסימונים',
- 'logs.title': 'יומנים חיים',
- 'doctor.title': 'אבחון מערכת',
- 'auth.pair_button': 'התאמה',
- 'auth.enter_code': 'הזן את קוד ההתאמה החד-פעמי מהמסוף',
- 'auth.code_placeholder': 'קוד בן 6 ספרות',
- 'auth.pairing_progress': 'מתבצעת התאמה…',
- 'auth.logout': 'התנתק',
- 'common.languages': 'שפות',
- 'common.select_language': 'בחר שפה',
- 'header.dashboard_tagline': 'לוח המחוונים של ZeroClaw',
-});
-
-const pl = createLocale({
- 'nav.dashboard': 'Pulpit',
- 'nav.agent': 'Agent',
- 'nav.tools': 'Narzędzia',
- 'nav.cron': 'Zaplanowane zadania',
- 'nav.integrations': 'Integracje',
- 'nav.memory': 'Pamięć',
- 'nav.config': 'Konfiguracja',
- 'nav.cost': 'Koszty',
- 'nav.logs': 'Logi',
- 'nav.doctor': 'Diagnostyka',
- 'dashboard.hero_title': 'Elektryczny pulpit runtime',
- 'agent.placeholder': 'Wpisz wiadomość…',
- 'tools.search': 'Szukaj narzędzi…',
- 'cron.add': 'Dodaj zadanie',
- 'memory.add_memory': 'Dodaj pamięć',
- 'config.save': 'Zapisz',
- 'cost.token_statistics': 'Statystyki tokenów',
- 'logs.title': 'Logi na żywo',
- 'doctor.title': 'Diagnostyka systemu',
- 'auth.pair_button': 'Sparuj',
- 'auth.enter_code': 'Wprowadź jednorazowy kod parowania z terminala',
- 'auth.code_placeholder': '6-cyfrowy kod',
- 'auth.pairing_progress': 'Parowanie…',
- 'auth.logout': 'Wyloguj',
- 'common.languages': 'Języki',
- 'common.select_language': 'Wybierz język',
- 'header.dashboard_tagline': 'Pulpit ZeroClaw',
-});
-
-const cs = createLocale({
- 'nav.dashboard': 'Nástěnka',
- 'nav.agent': 'Agent',
- 'nav.tools': 'Nástroje',
- 'nav.cron': 'Plánované úlohy',
- 'nav.integrations': 'Integrace',
- 'nav.memory': 'Paměť',
- 'nav.config': 'Konfigurace',
- 'nav.cost': 'Náklady',
- 'nav.logs': 'Logy',
- 'nav.doctor': 'Diagnostika',
- 'dashboard.hero_title': 'Elektrický runtime panel',
- 'agent.placeholder': 'Napište zprávu…',
- 'tools.search': 'Hledat nástroje…',
- 'cron.add': 'Přidat úlohu',
- 'memory.add_memory': 'Přidat paměť',
- 'config.save': 'Uložit',
- 'cost.token_statistics': 'Statistiky tokenů',
- 'logs.title': 'Živé logy',
- 'doctor.title': 'Diagnostika systému',
- 'auth.pair_button': 'Spárovat',
- 'auth.enter_code': 'Zadejte jednorázový párovací kód z terminálu',
- 'auth.code_placeholder': '6místný kód',
- 'auth.pairing_progress': 'Párování…',
- 'auth.logout': 'Odhlásit se',
- 'common.languages': 'Jazyky',
- 'common.select_language': 'Vyberte jazyk',
- 'header.dashboard_tagline': 'Panel ZeroClaw',
-});
-
-const nl = createLocale({
- 'nav.dashboard': 'Dashboard',
- 'nav.agent': 'Agent',
- 'nav.tools': 'Tools',
- 'nav.cron': 'Geplande taken',
- 'nav.integrations': 'Integraties',
- 'nav.memory': 'Geheugen',
- 'nav.config': 'Configuratie',
- 'nav.cost': 'Kosten',
- 'nav.logs': 'Logs',
- 'nav.doctor': 'Diagnose',
- 'dashboard.hero_title': 'Elektrisch runtime-dashboard',
- 'agent.placeholder': 'Typ een bericht…',
- 'tools.search': 'Tools zoeken…',
- 'cron.add': 'Taak toevoegen',
- 'memory.add_memory': 'Geheugen toevoegen',
- 'config.save': 'Opslaan',
- 'cost.token_statistics': 'Tokenstatistieken',
- 'logs.title': 'Live-logs',
- 'doctor.title': 'Systeemdiagnose',
- 'auth.pair_button': 'Koppelen',
- 'auth.enter_code': 'Voer de eenmalige koppelcode uit de terminal in',
- 'auth.code_placeholder': '6-cijferige code',
- 'auth.pairing_progress': 'Koppelen…',
- 'auth.logout': 'Afmelden',
- 'common.languages': 'Talen',
- 'common.select_language': 'Kies taal',
- 'header.dashboard_tagline': 'ZeroClaw-dashboard',
-});
-
-const uk = createLocale({
- 'nav.dashboard': 'Панель',
- 'nav.agent': 'Агент',
- 'nav.tools': 'Інструменти',
- 'nav.cron': 'Заплановані завдання',
- 'nav.integrations': 'Інтеграції',
- 'nav.memory': 'Пам’ять',
- 'nav.config': 'Конфігурація',
- 'nav.cost': 'Витрати',
- 'nav.logs': 'Журнали',
- 'nav.doctor': 'Діагностика',
- 'dashboard.hero_title': 'Електрична панель runtime',
- 'agent.placeholder': 'Введіть повідомлення…',
- 'tools.search': 'Пошук інструментів…',
- 'cron.add': 'Додати завдання',
- 'memory.add_memory': 'Додати пам’ять',
- 'config.save': 'Зберегти',
- 'cost.token_statistics': 'Статистика токенів',
- 'logs.title': 'Живі журнали',
- 'doctor.title': 'Діагностика системи',
- 'auth.pair_button': 'З’єднати',
- 'auth.enter_code': 'Введіть одноразовий код з’єднання з термінала',
- 'auth.code_placeholder': '6-значний код',
- 'auth.pairing_progress': 'З’єднання…',
- 'auth.logout': 'Вийти',
- 'common.languages': 'Мови',
- 'common.select_language': 'Оберіть мову',
- 'header.dashboard_tagline': 'Панель ZeroClaw',
-});
-
-const id = createLocale({
- 'nav.dashboard': 'Dasbor',
- 'nav.agent': 'Agen',
- 'nav.tools': 'Alat',
- 'nav.cron': 'Tugas terjadwal',
- 'nav.integrations': 'Integrasi',
- 'nav.memory': 'Memori',
- 'nav.config': 'Konfigurasi',
- 'nav.cost': 'Biaya',
- 'nav.logs': 'Log',
- 'nav.doctor': 'Diagnosis',
- 'dashboard.hero_title': 'Dasbor runtime elektrik',
- 'agent.placeholder': 'Tulis pesan…',
- 'tools.search': 'Cari alat…',
- 'cron.add': 'Tambah tugas',
- 'memory.add_memory': 'Tambah memori',
- 'config.save': 'Simpan',
- 'cost.token_statistics': 'Statistik token',
- 'logs.title': 'Log langsung',
- 'doctor.title': 'Diagnosis sistem',
- 'auth.pair_button': 'Pasangkan',
- 'auth.enter_code': 'Masukkan kode pairing sekali pakai dari terminal',
- 'auth.code_placeholder': 'Kode 6 digit',
- 'auth.pairing_progress': 'Sedang memasangkan…',
- 'auth.logout': 'Keluar',
- 'common.languages': 'Bahasa',
- 'common.select_language': 'Pilih bahasa',
- 'header.dashboard_tagline': 'Dasbor ZeroClaw',
-});
-
-const th = createLocale({
- 'nav.dashboard': 'แดชบอร์ด',
- 'nav.agent': 'เอเจนต์',
- 'nav.tools': 'เครื่องมือ',
- 'nav.cron': 'งานที่ตั้งเวลา',
- 'nav.integrations': 'การเชื่อมต่อ',
- 'nav.memory': 'หน่วยความจำ',
- 'nav.config': 'การกำหนดค่า',
- 'nav.cost': 'ต้นทุน',
- 'nav.logs': 'บันทึก',
- 'nav.doctor': 'วินิจฉัย',
- 'dashboard.hero_title': 'แดชบอร์ดรันไทม์ไฟฟ้า',
- 'agent.placeholder': 'พิมพ์ข้อความ…',
- 'tools.search': 'ค้นหาเครื่องมือ…',
- 'cron.add': 'เพิ่มงาน',
- 'memory.add_memory': 'เพิ่มหน่วยความจำ',
- 'config.save': 'บันทึก',
- 'cost.token_statistics': 'สถิติโทเค็น',
- 'logs.title': 'บันทึกสด',
- 'doctor.title': 'วินิจฉัยระบบ',
- 'auth.pair_button': 'จับคู่',
- 'auth.enter_code': 'ป้อนรหัสจับคู่แบบใช้ครั้งเดียวจากเทอร์มินัล',
- 'auth.code_placeholder': 'รหัส 6 หลัก',
- 'auth.pairing_progress': 'กำลังจับคู่…',
- 'auth.logout': 'ออกจากระบบ',
- 'common.languages': 'ภาษา',
- 'common.select_language': 'เลือกภาษา',
- 'header.dashboard_tagline': 'แดชบอร์ด ZeroClaw',
-});
-
-const ur = createLocale({
- 'nav.dashboard': 'ڈیش بورڈ',
- 'nav.agent': 'ایجنٹ',
- 'nav.tools': 'ٹولز',
- 'nav.cron': 'شیڈول شدہ کام',
- 'nav.integrations': 'انضمامات',
- 'nav.memory': 'میموری',
- 'nav.config': 'ترتیبات',
- 'nav.cost': 'لاگت',
- 'nav.logs': 'لاگز',
- 'nav.doctor': 'تشخیص',
- 'dashboard.hero_title': 'الیکٹرک رن ٹائم ڈیش بورڈ',
- 'agent.placeholder': 'پیغام لکھیں…',
- 'tools.search': 'ٹولز تلاش کریں…',
- 'cron.add': 'کام شامل کریں',
- 'memory.add_memory': 'میموری شامل کریں',
- 'config.save': 'محفوظ کریں',
- 'cost.token_statistics': 'ٹوکن کے اعدادوشمار',
- 'logs.title': 'لائیو لاگز',
- 'doctor.title': 'سسٹم تشخیص',
- 'auth.pair_button': 'جوڑیں',
- 'auth.enter_code': 'ٹرمینل سے ایک بار استعمال ہونے والا پیئرنگ کوڈ درج کریں',
- 'auth.code_placeholder': '6 ہندسوں کا کوڈ',
- 'auth.pairing_progress': 'جوڑا جا رہا ہے…',
- 'auth.logout': 'لاگ آؤٹ',
- 'common.languages': 'زبانیں',
- 'common.select_language': 'زبان منتخب کریں',
- 'header.dashboard_tagline': 'ZeroClaw ڈیش بورڈ',
-});
-
-const ro = createLocale({
- 'nav.dashboard': 'Tablou de bord',
- 'nav.agent': 'Agent',
- 'nav.tools': 'Unelte',
- 'nav.cron': 'Sarcini programate',
- 'nav.integrations': 'Integrări',
- 'nav.memory': 'Memorie',
- 'nav.config': 'Configurație',
- 'nav.cost': 'Costuri',
- 'nav.logs': 'Jurnale',
- 'nav.doctor': 'Diagnostic',
- 'dashboard.hero_title': 'Tablou de bord runtime electric',
- 'agent.placeholder': 'Scrie un mesaj…',
- 'tools.search': 'Caută unelte…',
- 'cron.add': 'Adaugă sarcină',
- 'memory.add_memory': 'Adaugă memorie',
- 'config.save': 'Salvează',
- 'cost.token_statistics': 'Statistici tokenuri',
- 'logs.title': 'Jurnale live',
- 'doctor.title': 'Diagnostic sistem',
- 'auth.pair_button': 'Asociază',
- 'auth.enter_code': 'Introdu codul unic de asociere din terminal',
- 'auth.code_placeholder': 'Cod din 6 cifre',
- 'auth.pairing_progress': 'Asociere…',
- 'auth.logout': 'Deconectare',
- 'common.languages': 'Limbi',
- 'common.select_language': 'Alege limba',
- 'header.dashboard_tagline': 'Tabloul ZeroClaw',
-});
-
-const sv = createLocale({
- 'nav.dashboard': 'Instrumentpanel',
- 'nav.agent': 'Agent',
- 'nav.tools': 'Verktyg',
- 'nav.cron': 'Schemalagda jobb',
- 'nav.integrations': 'Integrationer',
- 'nav.memory': 'Minne',
- 'nav.config': 'Konfiguration',
- 'nav.cost': 'Kostnader',
- 'nav.logs': 'Loggar',
- 'nav.doctor': 'Diagnostik',
- 'dashboard.hero_title': 'Elektrisk runtimepanel',
- 'agent.placeholder': 'Skriv ett meddelande…',
- 'tools.search': 'Sök verktyg…',
- 'cron.add': 'Lägg till jobb',
- 'memory.add_memory': 'Lägg till minne',
- 'config.save': 'Spara',
- 'cost.token_statistics': 'Tokenstatistik',
- 'logs.title': 'Live-loggar',
- 'doctor.title': 'Systemdiagnostik',
- 'auth.pair_button': 'Para',
- 'auth.enter_code': 'Ange engångskoden från terminalen',
- 'auth.code_placeholder': '6-siffrig kod',
- 'auth.pairing_progress': 'Parar…',
- 'auth.logout': 'Logga ut',
- 'common.languages': 'Språk',
- 'common.select_language': 'Välj språk',
- 'header.dashboard_tagline': 'ZeroClaw-panel',
-});
-
-const el = createLocale({
- 'nav.dashboard': 'Πίνακας ελέγχου',
- 'nav.agent': 'Πράκτορας',
- 'nav.tools': 'Εργαλεία',
- 'nav.cron': 'Προγραμματισμένες εργασίες',
- 'nav.integrations': 'Ενσωματώσεις',
- 'nav.memory': 'Μνήμη',
- 'nav.config': 'Ρυθμίσεις',
- 'nav.cost': 'Κόστος',
- 'nav.logs': 'Αρχεία καταγραφής',
- 'nav.doctor': 'Διάγνωση',
- 'dashboard.hero_title': 'Ηλεκτρικός πίνακας runtime',
- 'agent.placeholder': 'Πληκτρολογήστε μήνυμα…',
- 'tools.search': 'Αναζήτηση εργαλείων…',
- 'cron.add': 'Προσθήκη εργασίας',
- 'memory.add_memory': 'Προσθήκη μνήμης',
- 'config.save': 'Αποθήκευση',
- 'cost.token_statistics': 'Στατιστικά token',
- 'logs.title': 'Ζωντανά αρχεία καταγραφής',
- 'doctor.title': 'Διάγνωση συστήματος',
- 'auth.pair_button': 'Σύζευξη',
- 'auth.enter_code': 'Εισαγάγετε τον εφάπαξ κωδικό σύζευξης από το terminal',
- 'auth.code_placeholder': '6ψήφιος κωδικός',
- 'auth.pairing_progress': 'Σύζευξη…',
- 'auth.logout': 'Αποσύνδεση',
- 'common.languages': 'Γλώσσες',
- 'common.select_language': 'Επιλέξτε γλώσσα',
- 'header.dashboard_tagline': 'Πίνακας ZeroClaw',
-});
-
-const hu = createLocale({
- 'nav.dashboard': 'Irányítópult',
- 'nav.agent': 'Ügynök',
- 'nav.tools': 'Eszközök',
- 'nav.cron': 'Ütemezett feladatok',
- 'nav.integrations': 'Integrációk',
- 'nav.memory': 'Memória',
- 'nav.config': 'Konfiguráció',
- 'nav.cost': 'Költségek',
- 'nav.logs': 'Naplók',
- 'nav.doctor': 'Diagnosztika',
- 'dashboard.hero_title': 'Elektromos runtime irányítópult',
- 'agent.placeholder': 'Írjon üzenetet…',
- 'tools.search': 'Eszközök keresése…',
- 'cron.add': 'Feladat hozzáadása',
- 'memory.add_memory': 'Memória hozzáadása',
- 'config.save': 'Mentés',
- 'cost.token_statistics': 'Tokenstatisztika',
- 'logs.title': 'Élő naplók',
- 'doctor.title': 'Rendszerdiagnosztika',
- 'auth.pair_button': 'Párosítás',
- 'auth.enter_code': 'Adja meg a terminál egyszer használatos párosítási kódját',
- 'auth.code_placeholder': '6 számjegyű kód',
- 'auth.pairing_progress': 'Párosítás…',
- 'auth.logout': 'Kijelentkezés',
- 'common.languages': 'Nyelvek',
- 'common.select_language': 'Nyelv kiválasztása',
- 'header.dashboard_tagline': 'ZeroClaw irányítópult',
-});
-
-const fi = createLocale({
- 'nav.dashboard': 'Hallintapaneeli',
- 'nav.agent': 'Agentti',
- 'nav.tools': 'Työkalut',
- 'nav.cron': 'Ajastetut tehtävät',
- 'nav.integrations': 'Integraatiot',
- 'nav.memory': 'Muisti',
- 'nav.config': 'Asetukset',
- 'nav.cost': 'Kustannukset',
- 'nav.logs': 'Lokit',
- 'nav.doctor': 'Diagnostiikka',
- 'dashboard.hero_title': 'Sähköinen runtime-hallintapaneeli',
- 'agent.placeholder': 'Kirjoita viesti…',
- 'tools.search': 'Etsi työkaluja…',
- 'cron.add': 'Lisää tehtävä',
- 'memory.add_memory': 'Lisää muisti',
- 'config.save': 'Tallenna',
- 'cost.token_statistics': 'Token-tilastot',
- 'logs.title': 'Live-lokit',
- 'doctor.title': 'Järjestelmädiagnostiikka',
- 'auth.pair_button': 'Yhdistä',
- 'auth.enter_code': 'Syötä terminaalin kertakäyttöinen parituskoodi',
- 'auth.code_placeholder': '6-numeroinen koodi',
- 'auth.pairing_progress': 'Yhdistetään…',
- 'auth.logout': 'Kirjaudu ulos',
- 'common.languages': 'Kielet',
- 'common.select_language': 'Valitse kieli',
- 'header.dashboard_tagline': 'ZeroClaw-hallintapaneeli',
-});
-
-const da = createLocale({
- 'nav.dashboard': 'Kontrolpanel',
- 'nav.agent': 'Agent',
- 'nav.tools': 'Værktøjer',
- 'nav.cron': 'Planlagte job',
- 'nav.integrations': 'Integrationer',
- 'nav.memory': 'Hukommelse',
- 'nav.config': 'Konfiguration',
- 'nav.cost': 'Omkostninger',
- 'nav.logs': 'Logge',
- 'nav.doctor': 'Diagnostik',
- 'dashboard.hero_title': 'Elektrisk runtime-kontrolpanel',
- 'agent.placeholder': 'Skriv en besked…',
- 'tools.search': 'Søg værktøjer…',
- 'cron.add': 'Tilføj job',
- 'memory.add_memory': 'Tilføj hukommelse',
- 'config.save': 'Gem',
- 'cost.token_statistics': 'Tokenstatistik',
- 'logs.title': 'Live-logge',
- 'doctor.title': 'Systemdiagnostik',
- 'auth.pair_button': 'Par',
- 'auth.enter_code': 'Indtast engangskoden fra terminalen',
- 'auth.code_placeholder': '6-cifret kode',
- 'auth.pairing_progress': 'Parrer…',
- 'auth.logout': 'Log ud',
- 'common.languages': 'Sprog',
- 'common.select_language': 'Vælg sprog',
- 'header.dashboard_tagline': 'ZeroClaw-kontrolpanel',
-});
-
-const nb = createLocale({
- 'nav.dashboard': 'Kontrollpanel',
- 'nav.agent': 'Agent',
- 'nav.tools': 'Verktøy',
- 'nav.cron': 'Planlagte jobber',
- 'nav.integrations': 'Integrasjoner',
- 'nav.memory': 'Minne',
- 'nav.config': 'Konfigurasjon',
- 'nav.cost': 'Kostnader',
- 'nav.logs': 'Logger',
- 'nav.doctor': 'Diagnostikk',
- 'dashboard.hero_title': 'Elektrisk runtime-kontrollpanel',
- 'agent.placeholder': 'Skriv en melding…',
- 'tools.search': 'Søk etter verktøy…',
- 'cron.add': 'Legg til jobb',
- 'memory.add_memory': 'Legg til minne',
- 'config.save': 'Lagre',
- 'cost.token_statistics': 'Tokenstatistikk',
- 'logs.title': 'Live-logger',
- 'doctor.title': 'Systemdiagnostikk',
- 'auth.pair_button': 'Koble til',
- 'auth.enter_code': 'Skriv inn engangskoden fra terminalen',
- 'auth.code_placeholder': '6-sifret kode',
- 'auth.pairing_progress': 'Kobler til…',
- 'auth.logout': 'Logg ut',
- 'common.languages': 'Språk',
- 'common.select_language': 'Velg språk',
- 'header.dashboard_tagline': 'ZeroClaw-kontrollpanel',
-});
-
-
-const translations: Record> = {
- en,
- 'zh-CN': zhCn,
- ja,
- ko,
- vi,
- tl,
- es,
- pt,
- it,
- de,
- fr,
- ar,
- hi,
- ru,
- bn,
- he,
- pl,
- cs,
- nl,
- tr,
- uk,
- id,
- th,
- ur,
- ro,
- sv,
- el,
- hu,
- fi,
- da,
- nb,
-};
-
-let currentLocale: Locale = 'en';
-
-export function getLocale(): Locale {
- return currentLocale;
-}
-
-export function setLocale(locale: Locale): void {
- currentLocale = locale;
-}
-
-export function coerceLocale(locale: string | undefined): Locale {
- if (!locale) return 'en';
- const normalized = locale.toLowerCase();
- if (normalized.startsWith('zh')) return 'zh-CN';
- if (normalized.startsWith('ja')) return 'ja';
- if (normalized.startsWith('ko')) return 'ko';
- if (normalized.startsWith('vi')) return 'vi';
- if (normalized.startsWith('tl')) return 'tl';
- if (normalized.startsWith('es')) return 'es';
- if (normalized.startsWith('pt')) return 'pt';
- if (normalized.startsWith('it')) return 'it';
- if (normalized.startsWith('de')) return 'de';
- if (normalized.startsWith('fr')) return 'fr';
- if (normalized.startsWith('ar')) return 'ar';
- if (normalized.startsWith('hi')) return 'hi';
- if (normalized.startsWith('ru')) return 'ru';
- if (normalized.startsWith('bn')) return 'bn';
- if (normalized.startsWith('iw') || normalized.startsWith('he')) return 'he';
- if (normalized.startsWith('pl')) return 'pl';
- if (normalized.startsWith('cs')) return 'cs';
- if (normalized.startsWith('nl')) return 'nl';
- if (normalized.startsWith('tr')) return 'tr';
- if (normalized.startsWith('uk')) return 'uk';
- if (normalized.startsWith('id')) return 'id';
- if (normalized.startsWith('th')) return 'th';
- if (normalized.startsWith('ur')) return 'ur';
- if (normalized.startsWith('ro')) return 'ro';
- if (normalized.startsWith('sv')) return 'sv';
- if (normalized.startsWith('el')) return 'el';
- if (normalized.startsWith('hu')) return 'hu';
- if (normalized.startsWith('fi')) return 'fi';
- if (normalized.startsWith('da')) return 'da';
- if (normalized.startsWith('nb') || normalized.startsWith('no')) return 'nb';
- return 'en';
-}
-
-export function t(key: string): string {
- return translations[currentLocale]?.[key] ?? translations.en[key] ?? key;
-}
-
-export function tLocale(key: string, locale: Locale): string {
- return translations[locale]?.[key] ?? translations.en[key] ?? key;
-}
-
-export function useLocale(): { locale: Locale; t: (key: string) => string } {
- const [locale, setLocaleState] = useState(currentLocale);
-
- useEffect(() => {
- let cancelled = false;
-
- getStatus()
- .then((status) => {
- if (cancelled) return;
- const detected = coerceLocale(status.locale);
- setLocale(detected);
- setLocaleState(detected);
- })
- .catch(() => {
- // Keep default locale on error
- });
-
- return () => {
- cancelled = true;
- };
- }, []);
-
- return {
- locale,
- t: (key: string) => tLocale(key, locale),
- };
-}
diff --git a/web/src/lib/i18n.test.ts b/web/src/lib/i18n/index.test.ts
similarity index 95%
rename from web/src/lib/i18n.test.ts
rename to web/src/lib/i18n/index.test.ts
index d760fd3ea..88edf1e9c 100644
--- a/web/src/lib/i18n.test.ts
+++ b/web/src/lib/i18n/index.test.ts
@@ -3,11 +3,10 @@ import {
applyLocaleToDocument,
coerceLocale,
getLanguageOption,
- getLanguageOptionLabel,
getLocaleDirection,
LANGUAGE_OPTIONS,
LANGUAGE_SWITCH_ORDER,
-} from './i18n';
+} from '.';
describe('language metadata', () => {
it('keeps language options aligned with switch order', () => {
@@ -18,7 +17,7 @@ describe('language metadata', () => {
it('provides a flag-backed label for every locale', () => {
for (const option of LANGUAGE_OPTIONS) {
expect(getLanguageOption(option.value)).toEqual(option);
- expect(getLanguageOptionLabel(option)).toBe(option.label);
+ expect(option.label.length).toBeGreaterThan(0);
expect(option.flag.length).toBeGreaterThan(0);
}
});
diff --git a/web/src/lib/i18n/index.ts b/web/src/lib/i18n/index.ts
new file mode 100644
index 000000000..e4d2eb2e0
--- /dev/null
+++ b/web/src/lib/i18n/index.ts
@@ -0,0 +1,4 @@
+export type { Locale, LocaleDirection, LanguageOption, LocaleDocumentTarget } from './types';
+export { LANGUAGE_OPTIONS, LANGUAGE_SWITCH_ORDER, getLocaleDirection, getLanguageOption } from './languages';
+export { coerceLocale, getLocale, setLocale, t, tLocale, applyLocaleToDocument } from './translate';
+export { translations } from './locales';
diff --git a/web/src/lib/i18n/languages.ts b/web/src/lib/i18n/languages.ts
new file mode 100644
index 000000000..b6d1b20bc
--- /dev/null
+++ b/web/src/lib/i18n/languages.ts
@@ -0,0 +1,58 @@
+import type { LanguageOption, Locale, LocaleDirection } from './types';
+
+export const LANGUAGE_OPTIONS: ReadonlyArray = [
+ { value: 'en', label: 'English', flag: '🇺🇸', direction: 'ltr' },
+ { value: 'zh-CN', label: '简体中文', flag: '🇨🇳', direction: 'ltr' },
+ { value: 'ja', label: '日本語', flag: '🇯🇵', direction: 'ltr' },
+ { value: 'ko', label: '한국어', flag: '🇰🇷', direction: 'ltr' },
+ { value: 'vi', label: 'Tiếng Việt', flag: '🇻🇳', direction: 'ltr' },
+ { value: 'tl', label: 'Tagalog', flag: '🇵🇭', direction: 'ltr' },
+ { value: 'es', label: 'Español', flag: '🇪🇸', direction: 'ltr' },
+ { value: 'pt', label: 'Português', flag: '🇵🇹', direction: 'ltr' },
+ { value: 'it', label: 'Italiano', flag: '🇮🇹', direction: 'ltr' },
+ { value: 'de', label: 'Deutsch', flag: '🇩🇪', direction: 'ltr' },
+ { value: 'fr', label: 'Français', flag: '🇫🇷', direction: 'ltr' },
+ { value: 'ar', label: 'العربية', flag: '🇸🇦', direction: 'rtl' },
+ { value: 'hi', label: 'हिन्दी', flag: '🇮🇳', direction: 'ltr' },
+ { value: 'ru', label: 'Русский', flag: '🇷🇺', direction: 'ltr' },
+ { value: 'bn', label: 'বাংলা', flag: '🇧🇩', direction: 'ltr' },
+ { value: 'he', label: 'עברית', flag: '🇮🇱', direction: 'rtl' },
+ { value: 'pl', label: 'Polski', flag: '🇵🇱', direction: 'ltr' },
+ { value: 'cs', label: 'Čeština', flag: '🇨🇿', direction: 'ltr' },
+ { value: 'nl', label: 'Nederlands', flag: '🇳🇱', direction: 'ltr' },
+ { value: 'tr', label: 'Türkçe', flag: '🇹🇷', direction: 'ltr' },
+ { value: 'uk', label: 'Українська', flag: '🇺🇦', direction: 'ltr' },
+ { value: 'id', label: 'Bahasa Indonesia', flag: '🇮🇩', direction: 'ltr' },
+ { value: 'th', label: 'ไทย', flag: '🇹🇭', direction: 'ltr' },
+ { value: 'ur', label: 'اردو', flag: '🇵🇰', direction: 'rtl' },
+ { value: 'ro', label: 'Română', flag: '🇷🇴', direction: 'ltr' },
+ { value: 'sv', label: 'Svenska', flag: '🇸🇪', direction: 'ltr' },
+ { value: 'el', label: 'Ελληνικά', flag: '🇬🇷', direction: 'ltr' },
+ { value: 'hu', label: 'Magyar', flag: '🇭🇺', direction: 'ltr' },
+ { value: 'fi', label: 'Suomi', flag: '🇫🇮', direction: 'ltr' },
+ { value: 'da', label: 'Dansk', flag: '🇩🇰', direction: 'ltr' },
+ { value: 'nb', label: 'Norsk Bokmål', flag: '🇳🇴', direction: 'ltr' },
+];
+
+export const LANGUAGE_SWITCH_ORDER: ReadonlyArray =
+ LANGUAGE_OPTIONS.map((option) => option.value);
+
+const RTL_LOCALES = new Set(['ar', 'he', 'ur']);
+
+export function getLocaleDirection(locale: Locale): LocaleDirection {
+ return RTL_LOCALES.has(locale) ? 'rtl' : 'ltr';
+}
+
+export function getLanguageOption(locale: Locale): LanguageOption {
+ const matched = LANGUAGE_OPTIONS.find((option) => option.value === locale);
+ if (matched) {
+ return matched;
+ }
+
+ const fallback = LANGUAGE_OPTIONS.find((option) => option.value === 'en');
+ if (!fallback) {
+ throw new Error('English locale metadata is missing.');
+ }
+
+ return fallback;
+}
diff --git a/web/src/lib/i18n/locales/ar.ts b/web/src/lib/i18n/locales/ar.ts
new file mode 100644
index 000000000..da191039e
--- /dev/null
+++ b/web/src/lib/i18n/locales/ar.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const ar: Partial = {
+ 'nav.dashboard': 'لوحة التحكم',
+ 'nav.agent': 'الوكيل',
+ 'nav.tools': 'الأدوات',
+ 'nav.cron': 'المهام المجدولة',
+ 'nav.integrations': 'التكاملات',
+ 'nav.memory': 'الذاكرة',
+ 'nav.config': 'الإعدادات',
+ 'nav.cost': 'تتبع التكلفة',
+ 'nav.logs': 'السجلات',
+ 'nav.doctor': 'التشخيص',
+ 'dashboard.hero_title': 'لوحة تشغيل كهربائية',
+ 'agent.placeholder': 'اكتب رسالة…',
+ 'tools.search': 'ابحث في الأدوات…',
+ 'cron.add': 'إضافة مهمة',
+ 'memory.add_memory': 'إضافة ذاكرة',
+ 'config.save': 'حفظ',
+ 'cost.token_statistics': 'إحصاءات الرموز',
+ 'logs.title': 'السجلات المباشرة',
+ 'doctor.title': 'تشخيص النظام',
+ 'auth.pair_button': 'اقتران',
+ 'auth.enter_code': 'أدخل رمز الاقتران لمرة واحدة من الطرفية',
+ 'auth.code_placeholder': 'رمز من 6 أرقام',
+ 'auth.pairing_progress': 'جارٍ الاقتران…',
+ 'auth.logout': 'تسجيل الخروج',
+ 'common.languages': 'اللغات',
+ 'common.select_language': 'اختر اللغة',
+ 'header.dashboard_tagline': 'لوحة ZeroClaw',
+};
+
+export default ar;
diff --git a/web/src/lib/i18n/locales/bn.ts b/web/src/lib/i18n/locales/bn.ts
new file mode 100644
index 000000000..464fb9493
--- /dev/null
+++ b/web/src/lib/i18n/locales/bn.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const bn: Partial = {
+ 'nav.dashboard': 'ড্যাশবোর্ড',
+ 'nav.agent': 'এজেন্ট',
+ 'nav.tools': 'টুলস',
+ 'nav.cron': 'নির্ধারিত কাজ',
+ 'nav.integrations': 'ইন্টিগ্রেশন',
+ 'nav.memory': 'মেমরি',
+ 'nav.config': 'কনফিগারেশন',
+ 'nav.cost': 'খরচ ট্র্যাকার',
+ 'nav.logs': 'লগ',
+ 'nav.doctor': 'ডায়াগনস্টিক',
+ 'dashboard.hero_title': 'ইলেকট্রিক রানটাইম ড্যাশবোর্ড',
+ 'agent.placeholder': 'একটি বার্তা লিখুন…',
+ 'tools.search': 'টুল খুঁজুন…',
+ 'cron.add': 'কাজ যোগ করুন',
+ 'memory.add_memory': 'মেমরি যোগ করুন',
+ 'config.save': 'সংরক্ষণ করুন',
+ 'cost.token_statistics': 'টোকেন পরিসংখ্যান',
+ 'logs.title': 'লাইভ লগ',
+ 'doctor.title': 'সিস্টেম ডায়াগনস্টিক',
+ 'auth.pair_button': 'পেয়ার করুন',
+ 'auth.enter_code': 'টার্মিনাল থেকে একবারের পেয়ারিং কোড লিখুন',
+ 'auth.code_placeholder': '৬-সংখ্যার কোড',
+ 'auth.pairing_progress': 'পেয়ার করা হচ্ছে…',
+ 'auth.logout': 'লগ আউট',
+ 'common.languages': 'ভাষাসমূহ',
+ 'common.select_language': 'ভাষা বেছে নিন',
+ 'header.dashboard_tagline': 'ZeroClaw ড্যাশবোর্ড',
+};
+
+export default bn;
diff --git a/web/src/lib/i18n/locales/cs.ts b/web/src/lib/i18n/locales/cs.ts
new file mode 100644
index 000000000..fbf488aa1
--- /dev/null
+++ b/web/src/lib/i18n/locales/cs.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const cs: Partial = {
+ 'nav.dashboard': 'Nástěnka',
+ 'nav.agent': 'Agent',
+ 'nav.tools': 'Nástroje',
+ 'nav.cron': 'Plánované úlohy',
+ 'nav.integrations': 'Integrace',
+ 'nav.memory': 'Paměť',
+ 'nav.config': 'Konfigurace',
+ 'nav.cost': 'Náklady',
+ 'nav.logs': 'Logy',
+ 'nav.doctor': 'Diagnostika',
+ 'dashboard.hero_title': 'Elektrický runtime panel',
+ 'agent.placeholder': 'Napište zprávu…',
+ 'tools.search': 'Hledat nástroje…',
+ 'cron.add': 'Přidat úlohu',
+ 'memory.add_memory': 'Přidat paměť',
+ 'config.save': 'Uložit',
+ 'cost.token_statistics': 'Statistiky tokenů',
+ 'logs.title': 'Živé logy',
+ 'doctor.title': 'Diagnostika systému',
+ 'auth.pair_button': 'Spárovat',
+ 'auth.enter_code': 'Zadejte jednorázový párovací kód z terminálu',
+ 'auth.code_placeholder': '6místný kód',
+ 'auth.pairing_progress': 'Párování…',
+ 'auth.logout': 'Odhlásit se',
+ 'common.languages': 'Jazyky',
+ 'common.select_language': 'Vyberte jazyk',
+ 'header.dashboard_tagline': 'Panel ZeroClaw',
+};
+
+export default cs;
diff --git a/web/src/lib/i18n/locales/da.ts b/web/src/lib/i18n/locales/da.ts
new file mode 100644
index 000000000..dc1d7976b
--- /dev/null
+++ b/web/src/lib/i18n/locales/da.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const da: Partial = {
+ 'nav.dashboard': 'Kontrolpanel',
+ 'nav.agent': 'Agent',
+ 'nav.tools': 'Værktøjer',
+ 'nav.cron': 'Planlagte job',
+ 'nav.integrations': 'Integrationer',
+ 'nav.memory': 'Hukommelse',
+ 'nav.config': 'Konfiguration',
+ 'nav.cost': 'Omkostninger',
+ 'nav.logs': 'Logge',
+ 'nav.doctor': 'Diagnostik',
+ 'dashboard.hero_title': 'Elektrisk runtime-kontrolpanel',
+ 'agent.placeholder': 'Skriv en besked…',
+ 'tools.search': 'Søg værktøjer…',
+ 'cron.add': 'Tilføj job',
+ 'memory.add_memory': 'Tilføj hukommelse',
+ 'config.save': 'Gem',
+ 'cost.token_statistics': 'Tokenstatistik',
+ 'logs.title': 'Live-logge',
+ 'doctor.title': 'Systemdiagnostik',
+ 'auth.pair_button': 'Par',
+ 'auth.enter_code': 'Indtast engangskoden fra terminalen',
+ 'auth.code_placeholder': '6-cifret kode',
+ 'auth.pairing_progress': 'Parrer…',
+ 'auth.logout': 'Log ud',
+ 'common.languages': 'Sprog',
+ 'common.select_language': 'Vælg sprog',
+ 'header.dashboard_tagline': 'ZeroClaw-kontrolpanel',
+};
+
+export default da;
diff --git a/web/src/lib/i18n/locales/de.ts b/web/src/lib/i18n/locales/de.ts
new file mode 100644
index 000000000..e96481aa3
--- /dev/null
+++ b/web/src/lib/i18n/locales/de.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const de: Partial = {
+ 'nav.dashboard': 'Dashboard',
+ 'nav.agent': 'Agent',
+ 'nav.tools': 'Werkzeuge',
+ 'nav.cron': 'Geplante Aufgaben',
+ 'nav.integrations': 'Integrationen',
+ 'nav.memory': 'Speicher',
+ 'nav.config': 'Konfiguration',
+ 'nav.cost': 'Kosten',
+ 'nav.logs': 'Protokolle',
+ 'nav.doctor': 'Diagnose',
+ 'dashboard.hero_title': 'Elektrisches Runtime-Dashboard',
+ 'agent.placeholder': 'Nachricht eingeben…',
+ 'tools.search': 'Werkzeuge suchen…',
+ 'cron.add': 'Aufgabe hinzufügen',
+ 'memory.add_memory': 'Speicher hinzufügen',
+ 'config.save': 'Speichern',
+ 'cost.token_statistics': 'Token-Statistiken',
+ 'logs.title': 'Live-Protokolle',
+ 'doctor.title': 'Systemdiagnose',
+ 'auth.pair_button': 'Koppeln',
+ 'auth.enter_code': 'Geben Sie den einmaligen Kopplungscode aus dem Terminal ein',
+ 'auth.code_placeholder': '6-stelliger Code',
+ 'auth.pairing_progress': 'Kopplung…',
+ 'auth.logout': 'Abmelden',
+ 'common.languages': 'Sprachen',
+ 'common.select_language': 'Sprache auswählen',
+ 'header.dashboard_tagline': 'ZeroClaw-Dashboard',
+};
+
+export default de;
diff --git a/web/src/lib/i18n/locales/el.ts b/web/src/lib/i18n/locales/el.ts
new file mode 100644
index 000000000..6cd023b8c
--- /dev/null
+++ b/web/src/lib/i18n/locales/el.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const el: Partial = {
+ 'nav.dashboard': 'Πίνακας ελέγχου',
+ 'nav.agent': 'Πράκτορας',
+ 'nav.tools': 'Εργαλεία',
+ 'nav.cron': 'Προγραμματισμένες εργασίες',
+ 'nav.integrations': 'Ενσωματώσεις',
+ 'nav.memory': 'Μνήμη',
+ 'nav.config': 'Ρυθμίσεις',
+ 'nav.cost': 'Κόστος',
+ 'nav.logs': 'Αρχεία καταγραφής',
+ 'nav.doctor': 'Διάγνωση',
+ 'dashboard.hero_title': 'Ηλεκτρικός πίνακας runtime',
+ 'agent.placeholder': 'Πληκτρολογήστε μήνυμα…',
+ 'tools.search': 'Αναζήτηση εργαλείων…',
+ 'cron.add': 'Προσθήκη εργασίας',
+ 'memory.add_memory': 'Προσθήκη μνήμης',
+ 'config.save': 'Αποθήκευση',
+ 'cost.token_statistics': 'Στατιστικά token',
+ 'logs.title': 'Ζωντανά αρχεία καταγραφής',
+ 'doctor.title': 'Διάγνωση συστήματος',
+ 'auth.pair_button': 'Σύζευξη',
+ 'auth.enter_code': 'Εισαγάγετε τον εφάπαξ κωδικό σύζευξης από το terminal',
+ 'auth.code_placeholder': '6ψήφιος κωδικός',
+ 'auth.pairing_progress': 'Σύζευξη…',
+ 'auth.logout': 'Αποσύνδεση',
+ 'common.languages': 'Γλώσσες',
+ 'common.select_language': 'Επιλέξτε γλώσσα',
+ 'header.dashboard_tagline': 'Πίνακας ZeroClaw',
+};
+
+export default el;
diff --git a/web/src/lib/i18n/locales/en.ts b/web/src/lib/i18n/locales/en.ts
new file mode 100644
index 000000000..f16e28229
--- /dev/null
+++ b/web/src/lib/i18n/locales/en.ts
@@ -0,0 +1,273 @@
+const en = {
+ '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.title': 'Dashboard',
+ 'dashboard.provider': 'Provider',
+ 'dashboard.model': 'Model',
+ 'dashboard.uptime': 'Uptime',
+ 'dashboard.temperature': 'Temperature',
+ 'dashboard.gateway_port': 'Gateway Port',
+ 'dashboard.locale': 'Locale',
+ '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',
+ 'dashboard.load_failed': 'Dashboard load failed',
+ 'dashboard.load_unknown_error': 'Unknown dashboard load error',
+ 'dashboard.hero_eyebrow': 'ZeroClaw Command Deck',
+ 'dashboard.hero_title': 'Electric Runtime Dashboard',
+ 'dashboard.hero_subtitle': 'Real-time telemetry, cost pulse, and operations status in a single collapsible surface.',
+ 'dashboard.live_gateway': 'Live Gateway',
+ 'dashboard.unpaired': 'Unpaired',
+ 'dashboard.provider_model': 'Provider / Model',
+ 'dashboard.since_last_restart': 'Since last restart',
+ 'dashboard.pairing_active': 'Pairing active',
+ 'dashboard.no_paired_devices': 'No paired devices',
+ 'dashboard.cost_pulse': 'Cost Pulse',
+ 'dashboard.cost_subtitle': 'Session, daily, and monthly runtime spend',
+ 'dashboard.session': 'Session',
+ 'dashboard.daily': 'Daily',
+ 'dashboard.monthly': 'Monthly',
+ 'dashboard.channel_activity': 'Channel Activity',
+ 'dashboard.channel_subtitle': 'Live integrations and route connectivity',
+ 'dashboard.no_channels': 'No channels configured.',
+ 'dashboard.active': 'Active',
+ 'dashboard.inactive': 'Inactive',
+ 'dashboard.component_health': 'Component Health',
+ 'dashboard.component_subtitle': 'Runtime heartbeat and restart awareness',
+ 'dashboard.no_component_health': 'No component health is currently available.',
+ 'dashboard.restarts': 'Restarts',
+ 'dashboard.unknown_provider': 'Unknown',
+
+ 'agent.title': 'Agent Chat',
+ 'agent.send': 'Send',
+ 'agent.placeholder': '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.failed_send': 'Failed to send message. Please try again.',
+ 'agent.empty_title': 'ZeroClaw Agent',
+ 'agent.empty_subtitle': 'Send a message to start the conversation',
+ 'agent.unknown_error': 'Unknown error',
+
+ '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.no_search_results': 'No tools match your search.',
+ 'tools.parameter_schema': 'Parameter Schema',
+ 'tools.path': 'Path',
+ 'tools.version': 'Version',
+ 'tools.load_failed': 'Failed to load tools',
+
+ 'cron.title': 'Scheduled Jobs',
+ 'cron.add': 'Add Job',
+ 'cron.delete': 'Delete',
+ 'cron.enable': 'Enable',
+ 'cron.disable': 'Disable',
+ 'cron.name': 'Name',
+ 'cron.command': 'Command',
+ 'cron.schedule': 'Schedule',
+ 'cron.next_run': 'Next Run',
+ 'cron.last_run': 'Last Run',
+ 'cron.last_status': 'Last Status',
+ 'cron.enabled': 'Enabled',
+ 'cron.empty': 'No scheduled jobs.',
+ 'cron.confirm_delete': 'Are you sure you want to delete this job?',
+ 'cron.scheduled_tasks': 'Scheduled Tasks',
+ 'cron.add_cron_job': 'Add Cron Job',
+ 'cron.name_optional': 'Name (optional)',
+ 'cron.schedule_required_command_required': 'Schedule and command are required.',
+ 'cron.adding': 'Adding...',
+ 'cron.no_tasks_configured': 'No scheduled tasks configured.',
+ 'cron.load_failed': 'Failed to load cron jobs',
+ 'cron.failed_add': 'Failed to add job',
+ 'cron.failed_delete': 'Failed to delete job',
+ 'cron.delete_prompt': 'Delete?',
+ 'cron.id': 'ID',
+ 'cron.disabled': 'Disabled',
+
+ '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_failed': 'Failed to load integrations',
+ 'integrations.all': 'all',
+
+ 'memory.title': 'Memory Store',
+ 'memory.search': 'Search memory...',
+ 'memory.add': 'Store Memory',
+ 'memory.delete': 'Delete',
+ 'memory.key': 'Key',
+ 'memory.content': 'Content',
+ 'memory.category': 'Category',
+ '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.add_memory': 'Add Memory',
+ 'memory.search_entries': 'Search memory entries...',
+ 'memory.load_failed': 'Failed to load memory',
+ 'memory.key_content_required': 'Key and content are required.',
+ 'memory.failed_store': 'Failed to store memory',
+ 'memory.failed_delete': 'Failed to delete memory',
+ 'memory.category_optional': 'Category (optional)',
+ 'memory.key_placeholder': 'e.g. user_preferences',
+ 'memory.content_placeholder': 'Memory content...',
+ 'memory.category_placeholder': 'e.g. preferences, context, facts',
+ 'memory.search_button': 'Search',
+ 'memory.saving': 'Saving...',
+ 'memory.delete_prompt': 'Delete?',
+
+ 'config.title': 'Configuration',
+ 'config.save': 'Save',
+ 'config.reset': 'Reset',
+ 'config.saved': 'Configuration saved successfully.',
+ 'config.error': 'Failed to save configuration.',
+ 'config.loading': 'Loading configuration...',
+ 'config.editor_placeholder': 'TOML configuration...',
+ 'config.saving': 'Saving...',
+ 'config.masked_title': 'Sensitive fields are masked',
+ 'config.masked_description': 'API keys, tokens, and passwords are hidden for security. To update a masked field, replace the entire masked value with your new value.',
+ 'config.toml_configuration': 'TOML Configuration',
+ 'config.lines': 'lines',
+
+ '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.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.share': 'Share',
+ 'cost.load_failed': 'Failed to load cost data',
+
+ 'logs.title': 'Live Logs',
+ 'logs.clear': 'Clear',
+ 'logs.pause': 'Pause',
+ 'logs.resume': 'Resume',
+ 'logs.filter': 'Filter logs...',
+ 'logs.empty': 'No log entries.',
+ 'logs.connected': 'Connected to event stream.',
+ 'logs.disconnected': 'Disconnected from event stream.',
+ 'logs.events': 'events',
+ 'logs.jump_to_bottom': 'Jump to bottom',
+ 'logs.filter_label': 'Filter:',
+ 'logs.paused_stream': 'Log streaming is paused.',
+ 'logs.waiting_for_events': 'Waiting for events...',
+
+ 'doctor.title': 'System Diagnostics',
+ 'doctor.run': 'Run Diagnostics',
+ 'doctor.running': 'Running diagnostics...',
+ '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.running_short': 'Running...',
+ 'doctor.running_hint': 'This may take a few seconds.',
+ 'doctor.issues_found': 'Issues Found',
+ 'doctor.warnings': 'Warnings',
+ 'doctor.all_clear': 'All Clear',
+ 'doctor.instructions': 'Click "Run Diagnostics" to check your ZeroClaw installation.',
+
+ '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 the one-time pairing code from your terminal',
+ 'auth.code_placeholder': '6-digit code',
+ 'auth.pairing_progress': 'Pairing...',
+
+ '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',
+ 'common.languages': 'Languages',
+ 'common.select_language': 'Select language',
+ 'common.connecting': 'Connecting...',
+
+ 'health.title': 'System Health',
+ 'health.component': 'Component',
+ 'health.status': 'Status',
+ 'health.last_ok': 'Last OK',
+ 'health.last_error': 'Last Error',
+ 'health.restart_count': 'Restart Count',
+ 'health.pid': 'Process ID',
+ 'health.uptime': 'Uptime',
+ 'health.updated_at': 'Updated At',
+
+ 'header.dashboard_tagline': 'ZeroClaw dashboard',
+ 'sidebar.gateway_dashboard': 'Gateway + Dashboard',
+ 'sidebar.runtime_mode': 'Runtime Mode',
+ 'navigation.open': 'Open navigation',
+ 'navigation.close': 'Close navigation',
+ 'navigation.expand': 'Expand navigation',
+ 'navigation.collapse': 'Collapse navigation',
+} satisfies Record;
+
+export type TranslationKeys = typeof en;
+export default en;
diff --git a/web/src/lib/i18n/locales/es.ts b/web/src/lib/i18n/locales/es.ts
new file mode 100644
index 000000000..5dc1be139
--- /dev/null
+++ b/web/src/lib/i18n/locales/es.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const es: Partial = {
+ 'nav.dashboard': 'Panel',
+ 'nav.agent': 'Agente',
+ 'nav.tools': 'Herramientas',
+ 'nav.cron': 'Tareas programadas',
+ 'nav.integrations': 'Integraciones',
+ 'nav.memory': 'Memoria',
+ 'nav.config': 'Configuración',
+ 'nav.cost': 'Costos',
+ 'nav.logs': 'Registros',
+ 'nav.doctor': 'Diagnóstico',
+ 'dashboard.hero_title': 'Panel eléctrico del runtime',
+ 'agent.placeholder': 'Escribe un mensaje…',
+ 'tools.search': 'Buscar herramientas…',
+ 'cron.add': 'Agregar tarea',
+ 'memory.add_memory': 'Agregar memoria',
+ 'config.save': 'Guardar',
+ 'cost.token_statistics': 'Estadísticas de tokens',
+ 'logs.title': 'Registros en vivo',
+ 'doctor.title': 'Diagnóstico del sistema',
+ 'auth.pair_button': 'Vincular',
+ 'auth.enter_code': 'Introduce el código de vinculación de un solo uso del terminal',
+ 'auth.code_placeholder': 'Código de 6 dígitos',
+ 'auth.pairing_progress': 'Vinculando…',
+ 'auth.logout': 'Cerrar sesión',
+ 'common.languages': 'Idiomas',
+ 'common.select_language': 'Elegir idioma',
+ 'header.dashboard_tagline': 'Panel de ZeroClaw',
+};
+
+export default es;
diff --git a/web/src/lib/i18n/locales/fi.ts b/web/src/lib/i18n/locales/fi.ts
new file mode 100644
index 000000000..f1605f39a
--- /dev/null
+++ b/web/src/lib/i18n/locales/fi.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const fi: Partial = {
+ 'nav.dashboard': 'Hallintapaneeli',
+ 'nav.agent': 'Agentti',
+ 'nav.tools': 'Työkalut',
+ 'nav.cron': 'Ajastetut tehtävät',
+ 'nav.integrations': 'Integraatiot',
+ 'nav.memory': 'Muisti',
+ 'nav.config': 'Asetukset',
+ 'nav.cost': 'Kustannukset',
+ 'nav.logs': 'Lokit',
+ 'nav.doctor': 'Diagnostiikka',
+ 'dashboard.hero_title': 'Sähköinen runtime-hallintapaneeli',
+ 'agent.placeholder': 'Kirjoita viesti…',
+ 'tools.search': 'Etsi työkaluja…',
+ 'cron.add': 'Lisää tehtävä',
+ 'memory.add_memory': 'Lisää muisti',
+ 'config.save': 'Tallenna',
+ 'cost.token_statistics': 'Token-tilastot',
+ 'logs.title': 'Live-lokit',
+ 'doctor.title': 'Järjestelmädiagnostiikka',
+ 'auth.pair_button': 'Yhdistä',
+ 'auth.enter_code': 'Syötä terminaalin kertakäyttöinen parituskoodi',
+ 'auth.code_placeholder': '6-numeroinen koodi',
+ 'auth.pairing_progress': 'Yhdistetään…',
+ 'auth.logout': 'Kirjaudu ulos',
+ 'common.languages': 'Kielet',
+ 'common.select_language': 'Valitse kieli',
+ 'header.dashboard_tagline': 'ZeroClaw-hallintapaneeli',
+};
+
+export default fi;
diff --git a/web/src/lib/i18n/locales/fr.ts b/web/src/lib/i18n/locales/fr.ts
new file mode 100644
index 000000000..33478ee8b
--- /dev/null
+++ b/web/src/lib/i18n/locales/fr.ts
@@ -0,0 +1,51 @@
+import type { TranslationKeys } from './en';
+
+const fr: Partial = {
+ 'nav.dashboard': 'Tableau de bord',
+ 'nav.agent': 'Agent',
+ 'nav.tools': 'Outils',
+ 'nav.cron': 'Tâches planifiées',
+ 'nav.integrations': 'Intégrations',
+ 'nav.memory': 'Mémoire',
+ 'nav.config': 'Configuration',
+ 'nav.cost': 'Coûts',
+ 'nav.logs': 'Journaux',
+ 'nav.doctor': 'Diagnostic',
+ 'dashboard.hero_title': 'Tableau de bord runtime électrique',
+ 'dashboard.live_gateway': 'Passerelle active',
+ 'dashboard.unpaired': 'Non appairé',
+ 'agent.title': 'Chat agent',
+ 'agent.placeholder': 'Saisissez un message…',
+ 'agent.connecting': 'Connexion…',
+ 'agent.connected': 'Connecté',
+ 'agent.disconnected': 'Déconnecté',
+ 'tools.search': 'Rechercher des outils…',
+ 'tools.agent_tools': 'Outils agent',
+ 'tools.cli_tools': 'Outils CLI',
+ 'cron.add': 'Ajouter une tâche',
+ 'cron.scheduled_tasks': 'Tâches planifiées',
+ 'integrations.title': 'Intégrations',
+ 'memory.add_memory': 'Ajouter une mémoire',
+ 'memory.search_entries': 'Rechercher dans la mémoire…',
+ 'config.save': 'Enregistrer',
+ 'config.saving': 'Enregistrement…',
+ 'cost.session': 'Coût de session',
+ 'cost.daily': 'Coût journalier',
+ 'cost.monthly': 'Coût mensuel',
+ 'logs.title': 'Journaux en direct',
+ 'logs.pause': 'Pause',
+ 'logs.resume': 'Reprendre',
+ 'doctor.title': 'Diagnostic système',
+ 'doctor.run': 'Lancer le diagnostic',
+ 'doctor.running_short': 'Exécution…',
+ 'auth.pair_button': 'Associer',
+ 'auth.enter_code': 'Entrez le code d\u2019appairage à usage unique affiché dans le terminal',
+ 'auth.code_placeholder': 'Code à 6 chiffres',
+ 'auth.pairing_progress': 'Appairage…',
+ 'auth.logout': 'Déconnexion',
+ 'common.languages': 'Langues',
+ 'common.select_language': 'Choisir la langue',
+ 'header.dashboard_tagline': 'Tableau de bord ZeroClaw',
+};
+
+export default fr;
diff --git a/web/src/lib/i18n/locales/he.ts b/web/src/lib/i18n/locales/he.ts
new file mode 100644
index 000000000..304576148
--- /dev/null
+++ b/web/src/lib/i18n/locales/he.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const he: Partial = {
+ 'nav.dashboard': 'לוח מחוונים',
+ 'nav.agent': 'סוכן',
+ 'nav.tools': 'כלים',
+ 'nav.cron': 'משימות מתוזמנות',
+ 'nav.integrations': 'אינטגרציות',
+ 'nav.memory': 'זיכרון',
+ 'nav.config': 'תצורה',
+ 'nav.cost': 'מעקב עלויות',
+ 'nav.logs': 'יומנים',
+ 'nav.doctor': 'אבחון',
+ 'dashboard.hero_title': 'לוח מחוונים חשמלי של זמן הריצה',
+ 'agent.placeholder': 'הקלד הודעה…',
+ 'tools.search': 'חפש כלים…',
+ 'cron.add': 'הוסף משימה',
+ 'memory.add_memory': 'הוסף זיכרון',
+ 'config.save': 'שמור',
+ 'cost.token_statistics': 'סטטיסטיקות אסימונים',
+ 'logs.title': 'יומנים חיים',
+ 'doctor.title': 'אבחון מערכת',
+ 'auth.pair_button': 'התאמה',
+ 'auth.enter_code': 'הזן את קוד ההתאמה החד-פעמי מהמסוף',
+ 'auth.code_placeholder': 'קוד בן 6 ספרות',
+ 'auth.pairing_progress': 'מתבצעת התאמה…',
+ 'auth.logout': 'התנתק',
+ 'common.languages': 'שפות',
+ 'common.select_language': 'בחר שפה',
+ 'header.dashboard_tagline': 'לוח המחוונים של ZeroClaw',
+};
+
+export default he;
diff --git a/web/src/lib/i18n/locales/hi.ts b/web/src/lib/i18n/locales/hi.ts
new file mode 100644
index 000000000..271f70e5d
--- /dev/null
+++ b/web/src/lib/i18n/locales/hi.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const hi: Partial = {
+ 'nav.dashboard': 'डैशबोर्ड',
+ 'nav.agent': 'एजेंट',
+ 'nav.tools': 'टूल्स',
+ 'nav.cron': 'निर्धारित कार्य',
+ 'nav.integrations': 'इंटीग्रेशन',
+ 'nav.memory': 'मेमोरी',
+ 'nav.config': 'कॉन्फ़िगरेशन',
+ 'nav.cost': 'लागत ट्रैकर',
+ 'nav.logs': 'लॉग्स',
+ 'nav.doctor': 'जाँच',
+ 'dashboard.hero_title': 'इलेक्ट्रिक रनटाइम डैशबोर्ड',
+ 'agent.placeholder': 'संदेश लिखें…',
+ 'tools.search': 'टूल खोजें…',
+ 'cron.add': 'कार्य जोड़ें',
+ 'memory.add_memory': 'मेमोरी जोड़ें',
+ 'config.save': 'सहेजें',
+ 'cost.token_statistics': 'टोकन आँकड़े',
+ 'logs.title': 'लाइव लॉग्स',
+ 'doctor.title': 'सिस्टम जाँच',
+ 'auth.pair_button': 'पेयर करें',
+ 'auth.enter_code': 'टर्मिनल से एक-बार वाला पेयरिंग कोड दर्ज करें',
+ 'auth.code_placeholder': '6-अंकों का कोड',
+ 'auth.pairing_progress': 'पेयर किया जा रहा है…',
+ 'auth.logout': 'लॉग आउट',
+ 'common.languages': 'भाषाएँ',
+ 'common.select_language': 'भाषा चुनें',
+ 'header.dashboard_tagline': 'ZeroClaw डैशबोर्ड',
+};
+
+export default hi;
diff --git a/web/src/lib/i18n/locales/hu.ts b/web/src/lib/i18n/locales/hu.ts
new file mode 100644
index 000000000..40bb464c9
--- /dev/null
+++ b/web/src/lib/i18n/locales/hu.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const hu: Partial = {
+ 'nav.dashboard': 'Irányítópult',
+ 'nav.agent': 'Ügynök',
+ 'nav.tools': 'Eszközök',
+ 'nav.cron': 'Ütemezett feladatok',
+ 'nav.integrations': 'Integrációk',
+ 'nav.memory': 'Memória',
+ 'nav.config': 'Konfiguráció',
+ 'nav.cost': 'Költségek',
+ 'nav.logs': 'Naplók',
+ 'nav.doctor': 'Diagnosztika',
+ 'dashboard.hero_title': 'Elektromos runtime irányítópult',
+ 'agent.placeholder': 'Írjon üzenetet…',
+ 'tools.search': 'Eszközök keresése…',
+ 'cron.add': 'Feladat hozzáadása',
+ 'memory.add_memory': 'Memória hozzáadása',
+ 'config.save': 'Mentés',
+ 'cost.token_statistics': 'Tokenstatisztika',
+ 'logs.title': 'Élő naplók',
+ 'doctor.title': 'Rendszerdiagnosztika',
+ 'auth.pair_button': 'Párosítás',
+ 'auth.enter_code': 'Adja meg a terminál egyszer használatos párosítási kódját',
+ 'auth.code_placeholder': '6 számjegyű kód',
+ 'auth.pairing_progress': 'Párosítás…',
+ 'auth.logout': 'Kijelentkezés',
+ 'common.languages': 'Nyelvek',
+ 'common.select_language': 'Nyelv kiválasztása',
+ 'header.dashboard_tagline': 'ZeroClaw irányítópult',
+};
+
+export default hu;
diff --git a/web/src/lib/i18n/locales/id.ts b/web/src/lib/i18n/locales/id.ts
new file mode 100644
index 000000000..7c179bdab
--- /dev/null
+++ b/web/src/lib/i18n/locales/id.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const id: Partial = {
+ 'nav.dashboard': 'Dasbor',
+ 'nav.agent': 'Agen',
+ 'nav.tools': 'Alat',
+ 'nav.cron': 'Tugas terjadwal',
+ 'nav.integrations': 'Integrasi',
+ 'nav.memory': 'Memori',
+ 'nav.config': 'Konfigurasi',
+ 'nav.cost': 'Biaya',
+ 'nav.logs': 'Log',
+ 'nav.doctor': 'Diagnosis',
+ 'dashboard.hero_title': 'Dasbor runtime elektrik',
+ 'agent.placeholder': 'Tulis pesan…',
+ 'tools.search': 'Cari alat…',
+ 'cron.add': 'Tambah tugas',
+ 'memory.add_memory': 'Tambah memori',
+ 'config.save': 'Simpan',
+ 'cost.token_statistics': 'Statistik token',
+ 'logs.title': 'Log langsung',
+ 'doctor.title': 'Diagnosis sistem',
+ 'auth.pair_button': 'Pasangkan',
+ 'auth.enter_code': 'Masukkan kode pairing sekali pakai dari terminal',
+ 'auth.code_placeholder': 'Kode 6 digit',
+ 'auth.pairing_progress': 'Sedang memasangkan…',
+ 'auth.logout': 'Keluar',
+ 'common.languages': 'Bahasa',
+ 'common.select_language': 'Pilih bahasa',
+ 'header.dashboard_tagline': 'Dasbor ZeroClaw',
+};
+
+export default id;
diff --git a/web/src/lib/i18n/locales/index.ts b/web/src/lib/i18n/locales/index.ts
new file mode 100644
index 000000000..f65eb25a7
--- /dev/null
+++ b/web/src/lib/i18n/locales/index.ts
@@ -0,0 +1,70 @@
+import type { Locale } from '../types';
+import en from './en';
+import zhCN from './zh-CN';
+import ja from './ja';
+import ko from './ko';
+import vi from './vi';
+import tl from './tl';
+import es from './es';
+import pt from './pt';
+import it from './it';
+import de from './de';
+import fr from './fr';
+import ar from './ar';
+import hi from './hi';
+import ru from './ru';
+import bn from './bn';
+import he from './he';
+import pl from './pl';
+import cs from './cs';
+import nl from './nl';
+import tr from './tr';
+import uk from './uk';
+import id from './id';
+import th from './th';
+import ur from './ur';
+import ro from './ro';
+import sv from './sv';
+import el from './el';
+import hu from './hu';
+import fi from './fi';
+import da from './da';
+import nb from './nb';
+
+function merge(overrides: Partial): Record {
+ return { ...en, ...overrides };
+}
+
+export const translations: Record> = {
+ en,
+ 'zh-CN': merge(zhCN),
+ ja: merge(ja),
+ ko: merge(ko),
+ vi: merge(vi),
+ tl: merge(tl),
+ es: merge(es),
+ pt: merge(pt),
+ it: merge(it),
+ de: merge(de),
+ fr: merge(fr),
+ ar: merge(ar),
+ hi: merge(hi),
+ ru: merge(ru),
+ bn: merge(bn),
+ he: merge(he),
+ pl: merge(pl),
+ cs: merge(cs),
+ nl: merge(nl),
+ tr: merge(tr),
+ uk: merge(uk),
+ id: merge(id),
+ th: merge(th),
+ ur: merge(ur),
+ ro: merge(ro),
+ sv: merge(sv),
+ el: merge(el),
+ hu: merge(hu),
+ fi: merge(fi),
+ da: merge(da),
+ nb: merge(nb),
+};
diff --git a/web/src/lib/i18n/locales/it.ts b/web/src/lib/i18n/locales/it.ts
new file mode 100644
index 000000000..0c6d9f8dd
--- /dev/null
+++ b/web/src/lib/i18n/locales/it.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const it: Partial = {
+ 'nav.dashboard': 'Dashboard',
+ 'nav.agent': 'Agente',
+ 'nav.tools': 'Strumenti',
+ 'nav.cron': 'Attività pianificate',
+ 'nav.integrations': 'Integrazioni',
+ 'nav.memory': 'Memoria',
+ 'nav.config': 'Configurazione',
+ 'nav.cost': 'Costi',
+ 'nav.logs': 'Log',
+ 'nav.doctor': 'Diagnostica',
+ 'dashboard.hero_title': 'Dashboard runtime elettrica',
+ 'agent.placeholder': 'Scrivi un messaggio…',
+ 'tools.search': 'Cerca strumenti…',
+ 'cron.add': 'Aggiungi attività',
+ 'memory.add_memory': 'Aggiungi memoria',
+ 'config.save': 'Salva',
+ 'cost.token_statistics': 'Statistiche token',
+ 'logs.title': 'Log in tempo reale',
+ 'doctor.title': 'Diagnostica di sistema',
+ 'auth.pair_button': 'Associa',
+ 'auth.enter_code': 'Inserisci il codice di associazione monouso dal terminale',
+ 'auth.code_placeholder': 'Codice a 6 cifre',
+ 'auth.pairing_progress': 'Associazione…',
+ 'auth.logout': 'Disconnetti',
+ 'common.languages': 'Lingue',
+ 'common.select_language': 'Scegli lingua',
+ 'header.dashboard_tagline': 'Dashboard di ZeroClaw',
+};
+
+export default it;
diff --git a/web/src/lib/i18n/locales/ja.ts b/web/src/lib/i18n/locales/ja.ts
new file mode 100644
index 000000000..338c053e2
--- /dev/null
+++ b/web/src/lib/i18n/locales/ja.ts
@@ -0,0 +1,51 @@
+import type { TranslationKeys } from './en';
+
+const ja: Partial = {
+ 'nav.dashboard': 'ダッシュボード',
+ 'nav.agent': 'エージェント',
+ 'nav.tools': 'ツール',
+ 'nav.cron': 'スケジュール',
+ 'nav.integrations': '連携',
+ 'nav.memory': 'メモリ',
+ 'nav.config': '設定',
+ 'nav.cost': 'コスト',
+ 'nav.logs': 'ログ',
+ 'nav.doctor': '診断',
+ 'dashboard.hero_title': 'エレクトリック・ランタイム・ダッシュボード',
+ 'dashboard.live_gateway': 'ライブゲートウェイ',
+ 'dashboard.unpaired': '未ペア',
+ 'agent.title': 'エージェントチャット',
+ 'agent.placeholder': 'メッセージを入力…',
+ 'agent.connecting': '接続中…',
+ 'agent.connected': '接続済み',
+ 'agent.disconnected': '切断済み',
+ 'tools.search': 'ツールを検索…',
+ 'tools.agent_tools': 'エージェントツール',
+ 'tools.cli_tools': 'CLI ツール',
+ 'cron.add': 'ジョブを追加',
+ 'cron.scheduled_tasks': 'スケジュールされたジョブ',
+ 'integrations.title': '連携',
+ 'memory.add_memory': 'メモリを追加',
+ 'memory.search_entries': 'メモリエントリを検索…',
+ 'config.save': '保存',
+ 'config.saving': '保存中…',
+ 'cost.session': 'セッションコスト',
+ 'cost.daily': '日次コスト',
+ 'cost.monthly': '月次コスト',
+ 'logs.title': 'ライブログ',
+ 'logs.pause': '一時停止',
+ 'logs.resume': '再開',
+ 'doctor.title': 'システム診断',
+ 'doctor.run': '診断を実行',
+ 'doctor.running_short': '実行中…',
+ 'auth.pair_button': 'ペアリング',
+ 'auth.enter_code': '端末のワンタイムペアリングコードを入力してください',
+ 'auth.code_placeholder': '6桁のコード',
+ 'auth.pairing_progress': 'ペアリング中…',
+ 'auth.logout': 'ログアウト',
+ 'common.languages': '言語',
+ 'common.select_language': '言語を選択',
+ 'header.dashboard_tagline': 'ZeroClaw ダッシュボード',
+};
+
+export default ja;
diff --git a/web/src/lib/i18n/locales/ko.ts b/web/src/lib/i18n/locales/ko.ts
new file mode 100644
index 000000000..e9e772813
--- /dev/null
+++ b/web/src/lib/i18n/locales/ko.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const ko: Partial = {
+ 'nav.dashboard': '대시보드',
+ 'nav.agent': '에이전트',
+ 'nav.tools': '도구',
+ 'nav.cron': '예약 작업',
+ 'nav.integrations': '통합',
+ 'nav.memory': '메모리',
+ 'nav.config': '설정',
+ 'nav.cost': '비용 추적',
+ 'nav.logs': '로그',
+ 'nav.doctor': '진단',
+ 'dashboard.hero_title': '전기 런타임 대시보드',
+ 'agent.placeholder': '메시지를 입력하세요…',
+ 'tools.search': '도구 검색…',
+ 'cron.add': '작업 추가',
+ 'memory.add_memory': '메모리 추가',
+ 'config.save': '저장',
+ 'cost.token_statistics': '토큰 통계',
+ 'logs.title': '실시간 로그',
+ 'doctor.title': '시스템 진단',
+ 'auth.pair_button': '페어링',
+ 'auth.enter_code': '터미널에 표시된 일회용 페어링 코드를 입력하세요',
+ 'auth.code_placeholder': '6자리 코드',
+ 'auth.pairing_progress': '페어링 중…',
+ 'auth.logout': '로그아웃',
+ 'common.languages': '언어',
+ 'common.select_language': '언어 선택',
+ 'header.dashboard_tagline': 'ZeroClaw 대시보드',
+};
+
+export default ko;
diff --git a/web/src/lib/i18n/locales/nb.ts b/web/src/lib/i18n/locales/nb.ts
new file mode 100644
index 000000000..d1e7a19e8
--- /dev/null
+++ b/web/src/lib/i18n/locales/nb.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const nb: Partial = {
+ 'nav.dashboard': 'Kontrollpanel',
+ 'nav.agent': 'Agent',
+ 'nav.tools': 'Verktøy',
+ 'nav.cron': 'Planlagte jobber',
+ 'nav.integrations': 'Integrasjoner',
+ 'nav.memory': 'Minne',
+ 'nav.config': 'Konfigurasjon',
+ 'nav.cost': 'Kostnader',
+ 'nav.logs': 'Logger',
+ 'nav.doctor': 'Diagnostikk',
+ 'dashboard.hero_title': 'Elektrisk runtime-kontrollpanel',
+ 'agent.placeholder': 'Skriv en melding…',
+ 'tools.search': 'Søk etter verktøy…',
+ 'cron.add': 'Legg til jobb',
+ 'memory.add_memory': 'Legg til minne',
+ 'config.save': 'Lagre',
+ 'cost.token_statistics': 'Tokenstatistikk',
+ 'logs.title': 'Live-logger',
+ 'doctor.title': 'Systemdiagnostikk',
+ 'auth.pair_button': 'Koble til',
+ 'auth.enter_code': 'Skriv inn engangskoden fra terminalen',
+ 'auth.code_placeholder': '6-sifret kode',
+ 'auth.pairing_progress': 'Kobler til…',
+ 'auth.logout': 'Logg ut',
+ 'common.languages': 'Språk',
+ 'common.select_language': 'Velg språk',
+ 'header.dashboard_tagline': 'ZeroClaw-kontrollpanel',
+};
+
+export default nb;
diff --git a/web/src/lib/i18n/locales/nl.ts b/web/src/lib/i18n/locales/nl.ts
new file mode 100644
index 000000000..2dd62390c
--- /dev/null
+++ b/web/src/lib/i18n/locales/nl.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const nl: Partial = {
+ 'nav.dashboard': 'Dashboard',
+ 'nav.agent': 'Agent',
+ 'nav.tools': 'Tools',
+ 'nav.cron': 'Geplande taken',
+ 'nav.integrations': 'Integraties',
+ 'nav.memory': 'Geheugen',
+ 'nav.config': 'Configuratie',
+ 'nav.cost': 'Kosten',
+ 'nav.logs': 'Logs',
+ 'nav.doctor': 'Diagnose',
+ 'dashboard.hero_title': 'Elektrisch runtime-dashboard',
+ 'agent.placeholder': 'Typ een bericht…',
+ 'tools.search': 'Tools zoeken…',
+ 'cron.add': 'Taak toevoegen',
+ 'memory.add_memory': 'Geheugen toevoegen',
+ 'config.save': 'Opslaan',
+ 'cost.token_statistics': 'Tokenstatistieken',
+ 'logs.title': 'Live-logs',
+ 'doctor.title': 'Systeemdiagnose',
+ 'auth.pair_button': 'Koppelen',
+ 'auth.enter_code': 'Voer de eenmalige koppelcode uit de terminal in',
+ 'auth.code_placeholder': '6-cijferige code',
+ 'auth.pairing_progress': 'Koppelen…',
+ 'auth.logout': 'Afmelden',
+ 'common.languages': 'Talen',
+ 'common.select_language': 'Kies taal',
+ 'header.dashboard_tagline': 'ZeroClaw-dashboard',
+};
+
+export default nl;
diff --git a/web/src/lib/i18n/locales/pl.ts b/web/src/lib/i18n/locales/pl.ts
new file mode 100644
index 000000000..521b17db6
--- /dev/null
+++ b/web/src/lib/i18n/locales/pl.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const pl: Partial = {
+ 'nav.dashboard': 'Pulpit',
+ 'nav.agent': 'Agent',
+ 'nav.tools': 'Narzędzia',
+ 'nav.cron': 'Zaplanowane zadania',
+ 'nav.integrations': 'Integracje',
+ 'nav.memory': 'Pamięć',
+ 'nav.config': 'Konfiguracja',
+ 'nav.cost': 'Koszty',
+ 'nav.logs': 'Logi',
+ 'nav.doctor': 'Diagnostyka',
+ 'dashboard.hero_title': 'Elektryczny pulpit runtime',
+ 'agent.placeholder': 'Wpisz wiadomość…',
+ 'tools.search': 'Szukaj narzędzi…',
+ 'cron.add': 'Dodaj zadanie',
+ 'memory.add_memory': 'Dodaj pamięć',
+ 'config.save': 'Zapisz',
+ 'cost.token_statistics': 'Statystyki tokenów',
+ 'logs.title': 'Logi na żywo',
+ 'doctor.title': 'Diagnostyka systemu',
+ 'auth.pair_button': 'Sparuj',
+ 'auth.enter_code': 'Wprowadź jednorazowy kod parowania z terminala',
+ 'auth.code_placeholder': '6-cyfrowy kod',
+ 'auth.pairing_progress': 'Parowanie…',
+ 'auth.logout': 'Wyloguj',
+ 'common.languages': 'Języki',
+ 'common.select_language': 'Wybierz język',
+ 'header.dashboard_tagline': 'Pulpit ZeroClaw',
+};
+
+export default pl;
diff --git a/web/src/lib/i18n/locales/pt.ts b/web/src/lib/i18n/locales/pt.ts
new file mode 100644
index 000000000..2f0d255d9
--- /dev/null
+++ b/web/src/lib/i18n/locales/pt.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const pt: Partial = {
+ 'nav.dashboard': 'Painel',
+ 'nav.agent': 'Agente',
+ 'nav.tools': 'Ferramentas',
+ 'nav.cron': 'Tarefas agendadas',
+ 'nav.integrations': 'Integrações',
+ 'nav.memory': 'Memória',
+ 'nav.config': 'Configuração',
+ 'nav.cost': 'Custos',
+ 'nav.logs': 'Logs',
+ 'nav.doctor': 'Diagnóstico',
+ 'dashboard.hero_title': 'Painel elétrico do runtime',
+ 'agent.placeholder': 'Digite uma mensagem…',
+ 'tools.search': 'Buscar ferramentas…',
+ 'cron.add': 'Adicionar tarefa',
+ 'memory.add_memory': 'Adicionar memória',
+ 'config.save': 'Salvar',
+ 'cost.token_statistics': 'Estatísticas de tokens',
+ 'logs.title': 'Logs ao vivo',
+ 'doctor.title': 'Diagnóstico do sistema',
+ 'auth.pair_button': 'Parear',
+ 'auth.enter_code': 'Digite o código único de pareamento mostrado no terminal',
+ 'auth.code_placeholder': 'Código de 6 dígitos',
+ 'auth.pairing_progress': 'Pareando…',
+ 'auth.logout': 'Sair',
+ 'common.languages': 'Idiomas',
+ 'common.select_language': 'Escolher idioma',
+ 'header.dashboard_tagline': 'Painel do ZeroClaw',
+};
+
+export default pt;
diff --git a/web/src/lib/i18n/locales/ro.ts b/web/src/lib/i18n/locales/ro.ts
new file mode 100644
index 000000000..3db6359c2
--- /dev/null
+++ b/web/src/lib/i18n/locales/ro.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const ro: Partial = {
+ 'nav.dashboard': 'Tablou de bord',
+ 'nav.agent': 'Agent',
+ 'nav.tools': 'Unelte',
+ 'nav.cron': 'Sarcini programate',
+ 'nav.integrations': 'Integrări',
+ 'nav.memory': 'Memorie',
+ 'nav.config': 'Configurație',
+ 'nav.cost': 'Costuri',
+ 'nav.logs': 'Jurnale',
+ 'nav.doctor': 'Diagnostic',
+ 'dashboard.hero_title': 'Tablou de bord runtime electric',
+ 'agent.placeholder': 'Scrie un mesaj…',
+ 'tools.search': 'Caută unelte…',
+ 'cron.add': 'Adaugă sarcină',
+ 'memory.add_memory': 'Adaugă memorie',
+ 'config.save': 'Salvează',
+ 'cost.token_statistics': 'Statistici tokenuri',
+ 'logs.title': 'Jurnale live',
+ 'doctor.title': 'Diagnostic sistem',
+ 'auth.pair_button': 'Asociază',
+ 'auth.enter_code': 'Introdu codul unic de asociere din terminal',
+ 'auth.code_placeholder': 'Cod din 6 cifre',
+ 'auth.pairing_progress': 'Asociere…',
+ 'auth.logout': 'Deconectare',
+ 'common.languages': 'Limbi',
+ 'common.select_language': 'Alege limba',
+ 'header.dashboard_tagline': 'Tabloul ZeroClaw',
+};
+
+export default ro;
diff --git a/web/src/lib/i18n/locales/ru.ts b/web/src/lib/i18n/locales/ru.ts
new file mode 100644
index 000000000..a6a3bb44f
--- /dev/null
+++ b/web/src/lib/i18n/locales/ru.ts
@@ -0,0 +1,51 @@
+import type { TranslationKeys } from './en';
+
+const ru: Partial = {
+ 'nav.dashboard': 'Панель',
+ 'nav.agent': 'Агент',
+ 'nav.tools': 'Инструменты',
+ 'nav.cron': 'Задания',
+ 'nav.integrations': 'Интеграции',
+ 'nav.memory': 'Память',
+ 'nav.config': 'Конфигурация',
+ 'nav.cost': 'Расходы',
+ 'nav.logs': 'Логи',
+ 'nav.doctor': 'Диагностика',
+ 'dashboard.hero_title': 'Панель электрического рантайма',
+ 'dashboard.live_gateway': 'Живой шлюз',
+ 'dashboard.unpaired': 'Не сопряжено',
+ 'agent.title': 'Чат агента',
+ 'agent.placeholder': 'Введите сообщение…',
+ 'agent.connecting': 'Подключение…',
+ 'agent.connected': 'Подключено',
+ 'agent.disconnected': 'Отключено',
+ 'tools.search': 'Поиск инструментов…',
+ 'tools.agent_tools': 'Инструменты агента',
+ 'tools.cli_tools': 'CLI-инструменты',
+ 'cron.add': 'Добавить задачу',
+ 'cron.scheduled_tasks': 'Запланированные задания',
+ 'integrations.title': 'Интеграции',
+ 'memory.add_memory': 'Добавить память',
+ 'memory.search_entries': 'Искать записи памяти…',
+ 'config.save': 'Сохранить',
+ 'config.saving': 'Сохранение…',
+ 'cost.session': 'Стоимость сессии',
+ 'cost.daily': 'Стоимость за день',
+ 'cost.monthly': 'Стоимость за месяц',
+ 'logs.title': 'Живые логи',
+ 'logs.pause': 'Пауза',
+ 'logs.resume': 'Продолжить',
+ 'doctor.title': 'Диагностика системы',
+ 'doctor.run': 'Запустить диагностику',
+ 'doctor.running_short': 'Выполняется…',
+ 'auth.pair_button': 'Сопрячь',
+ 'auth.enter_code': 'Введите одноразовый код сопряжения из терминала',
+ 'auth.code_placeholder': '6-значный код',
+ 'auth.pairing_progress': 'Сопряжение…',
+ 'auth.logout': 'Выйти',
+ 'common.languages': 'Языки',
+ 'common.select_language': 'Выберите язык',
+ 'header.dashboard_tagline': 'Панель ZeroClaw',
+};
+
+export default ru;
diff --git a/web/src/lib/i18n/locales/sv.ts b/web/src/lib/i18n/locales/sv.ts
new file mode 100644
index 000000000..48ee8d9e1
--- /dev/null
+++ b/web/src/lib/i18n/locales/sv.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const sv: Partial = {
+ 'nav.dashboard': 'Instrumentpanel',
+ 'nav.agent': 'Agent',
+ 'nav.tools': 'Verktyg',
+ 'nav.cron': 'Schemalagda jobb',
+ 'nav.integrations': 'Integrationer',
+ 'nav.memory': 'Minne',
+ 'nav.config': 'Konfiguration',
+ 'nav.cost': 'Kostnader',
+ 'nav.logs': 'Loggar',
+ 'nav.doctor': 'Diagnostik',
+ 'dashboard.hero_title': 'Elektrisk runtimepanel',
+ 'agent.placeholder': 'Skriv ett meddelande…',
+ 'tools.search': 'Sök verktyg…',
+ 'cron.add': 'Lägg till jobb',
+ 'memory.add_memory': 'Lägg till minne',
+ 'config.save': 'Spara',
+ 'cost.token_statistics': 'Tokenstatistik',
+ 'logs.title': 'Live-loggar',
+ 'doctor.title': 'Systemdiagnostik',
+ 'auth.pair_button': 'Para',
+ 'auth.enter_code': 'Ange engångskoden från terminalen',
+ 'auth.code_placeholder': '6-siffrig kod',
+ 'auth.pairing_progress': 'Parar…',
+ 'auth.logout': 'Logga ut',
+ 'common.languages': 'Språk',
+ 'common.select_language': 'Välj språk',
+ 'header.dashboard_tagline': 'ZeroClaw-panel',
+};
+
+export default sv;
diff --git a/web/src/lib/i18n/locales/th.ts b/web/src/lib/i18n/locales/th.ts
new file mode 100644
index 000000000..d09c182c9
--- /dev/null
+++ b/web/src/lib/i18n/locales/th.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const th: Partial = {
+ 'nav.dashboard': 'แดชบอร์ด',
+ 'nav.agent': 'เอเจนต์',
+ 'nav.tools': 'เครื่องมือ',
+ 'nav.cron': 'งานที่ตั้งเวลา',
+ 'nav.integrations': 'การเชื่อมต่อ',
+ 'nav.memory': 'หน่วยความจำ',
+ 'nav.config': 'การกำหนดค่า',
+ 'nav.cost': 'ต้นทุน',
+ 'nav.logs': 'บันทึก',
+ 'nav.doctor': 'วินิจฉัย',
+ 'dashboard.hero_title': 'แดชบอร์ดรันไทม์ไฟฟ้า',
+ 'agent.placeholder': 'พิมพ์ข้อความ…',
+ 'tools.search': 'ค้นหาเครื่องมือ…',
+ 'cron.add': 'เพิ่มงาน',
+ 'memory.add_memory': 'เพิ่มหน่วยความจำ',
+ 'config.save': 'บันทึก',
+ 'cost.token_statistics': 'สถิติโทเค็น',
+ 'logs.title': 'บันทึกสด',
+ 'doctor.title': 'วินิจฉัยระบบ',
+ 'auth.pair_button': 'จับคู่',
+ 'auth.enter_code': 'ป้อนรหัสจับคู่แบบใช้ครั้งเดียวจากเทอร์มินัล',
+ 'auth.code_placeholder': 'รหัส 6 หลัก',
+ 'auth.pairing_progress': 'กำลังจับคู่…',
+ 'auth.logout': 'ออกจากระบบ',
+ 'common.languages': 'ภาษา',
+ 'common.select_language': 'เลือกภาษา',
+ 'header.dashboard_tagline': 'แดชบอร์ด ZeroClaw',
+};
+
+export default th;
diff --git a/web/src/lib/i18n/locales/tl.ts b/web/src/lib/i18n/locales/tl.ts
new file mode 100644
index 000000000..acd9f428d
--- /dev/null
+++ b/web/src/lib/i18n/locales/tl.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const tl: Partial = {
+ 'nav.dashboard': 'Dashboard',
+ 'nav.agent': 'Ahente',
+ 'nav.tools': 'Mga Tool',
+ 'nav.cron': 'Naka-iskedyul na Trabaho',
+ 'nav.integrations': 'Mga Integrasyon',
+ 'nav.memory': 'Alaala',
+ 'nav.config': 'Konpigurasyon',
+ 'nav.cost': 'Pagsubaybay sa Gastos',
+ 'nav.logs': 'Mga Log',
+ 'nav.doctor': 'Diyagnostiko',
+ 'dashboard.hero_title': 'Elektrikong Dashboard ng Runtime',
+ 'agent.placeholder': 'Mag-type ng mensahe…',
+ 'tools.search': 'Maghanap ng tool…',
+ 'cron.add': 'Magdagdag ng gawain',
+ 'memory.add_memory': 'Magdagdag ng alaala',
+ 'config.save': 'I-save',
+ 'cost.token_statistics': 'Estadistika ng Token',
+ 'logs.title': 'Mga Live Log',
+ 'doctor.title': 'Diyagnostiko ng System',
+ 'auth.pair_button': 'Ipares',
+ 'auth.enter_code': 'Ilagay ang isang beses na pairing code mula sa terminal',
+ 'auth.code_placeholder': '6-digit na code',
+ 'auth.pairing_progress': 'Pinapares…',
+ 'auth.logout': 'Mag-logout',
+ 'common.languages': 'Mga Wika',
+ 'common.select_language': 'Piliin ang wika',
+ 'header.dashboard_tagline': 'Dashboard ng ZeroClaw',
+};
+
+export default tl;
diff --git a/web/src/lib/i18n/locales/tr.ts b/web/src/lib/i18n/locales/tr.ts
new file mode 100644
index 000000000..6abd0aca8
--- /dev/null
+++ b/web/src/lib/i18n/locales/tr.ts
@@ -0,0 +1,157 @@
+import type { TranslationKeys } from './en';
+
+const tr: Partial = {
+ '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',
+ 'agent.title': 'Ajan Sohbeti',
+ 'agent.send': 'Gönder',
+ 'agent.placeholder': 'Bir mesaj yazın...',
+ 'agent.connecting': 'Bağlanıyor...',
+ 'agent.connected': 'Bağlı',
+ '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.failed_send': 'Mesaj gönderilemedi. Lütfen tekrar deneyin.',
+ 'agent.empty_title': 'ZeroClaw Ajanı',
+ 'agent.empty_subtitle': 'Konuşmayı başlatmak için bir mesaj gönderin',
+ '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': 'Yerel Ayar',
+ 'dashboard.memory_backend': 'Hafıza Arka Ucu',
+ 'dashboard.hero_eyebrow': 'ZeroClaw Komuta Güvertesi',
+ 'dashboard.hero_title': 'Elektrik Çalışma Zamanı Paneli',
+ 'dashboard.hero_subtitle': 'Gerçek zamanlı telemetri, maliyet akışı ve operasyon durumunu tek bir daraltılabilir yüzeyde görün.',
+ 'dashboard.live_gateway': 'Canlı Ağ Geçidi',
+ 'dashboard.unpaired': 'Eşleşmemiş',
+ 'dashboard.provider_model': 'Sağlayıcı / Model',
+ 'dashboard.since_last_restart': 'Son yeniden başlatmadan beri',
+ 'dashboard.pairing_active': 'Eşleştirme etkin',
+ 'dashboard.no_paired_devices': 'Eşleşmiş cihaz yok',
+ 'dashboard.cost_pulse': 'Maliyet Nabzı',
+ 'dashboard.cost_subtitle': 'Oturum, günlük ve aylık çalışma zamanı harcaması',
+ 'dashboard.session': 'Oturum',
+ 'dashboard.daily': 'Günlük',
+ 'dashboard.monthly': 'Aylık',
+ 'dashboard.channel_activity': 'Kanal Etkinliği',
+ 'dashboard.channel_subtitle': 'Canlı entegrasyonlar ve rota bağlantısı',
+ 'dashboard.no_channels': 'Hiç kanal yapılandırılmamış.',
+ 'dashboard.active': 'Aktif',
+ 'dashboard.inactive': 'Pasif',
+ 'dashboard.component_health': 'Bileşen Sağlığı',
+ 'dashboard.component_subtitle': 'Çalışma zamanı nabzı ve yeniden başlatma farkındalığı',
+ 'dashboard.no_component_health': 'Şu anda bileşen sağlığı bilgisi yok.',
+ 'dashboard.restarts': 'Yeniden Başlatmalar',
+ 'tools.title': 'Mevcut Araçlar',
+ 'tools.search': 'Araç ara...',
+ 'tools.agent_tools': 'Ajan Araçları',
+ 'tools.cli_tools': 'CLI Araçları',
+ 'tools.no_search_results': 'Aramanızla eşleşen araç yok.',
+ 'tools.parameter_schema': 'Parametre Şeması',
+ 'tools.path': 'Yol',
+ 'tools.version': 'Sürüm',
+ 'cron.title': 'Zamanlanmış Görevler',
+ 'cron.add': 'Görev Ekle',
+ 'cron.scheduled_tasks': 'Zamanlanmış Görevler',
+ 'cron.add_cron_job': 'Cron Görevi Ekle',
+ 'cron.name_optional': 'Ad (isteğe bağlı)',
+ 'cron.schedule_required_command_required': 'Zamanlama ve komut gereklidir.',
+ 'cron.adding': 'Ekleniyor...',
+ 'cron.no_tasks_configured': 'Zamanlanmış görev yapılandırılmamış.',
+ 'cron.load_failed': 'Cron görevleri yüklenemedi',
+ 'cron.failed_add': 'Görev eklenemedi',
+ 'cron.failed_delete': 'Görev silinemedi',
+ 'cron.delete_prompt': 'Silinsin mi?',
+ 'cron.disabled': 'Devre Dışı',
+ 'integrations.title': 'Entegrasyonlar',
+ 'integrations.available': 'Mevcut',
+ 'integrations.active': 'Aktif',
+ 'integrations.coming_soon': 'Yakında',
+ 'integrations.empty': 'Entegrasyon bulunamadı.',
+ 'integrations.load_failed': 'Entegrasyonlar yüklenemedi',
+ 'memory.title': 'Hafıza Deposu',
+ 'memory.add_memory': 'Hafıza Ekle',
+ 'memory.search_entries': 'Hafıza girdilerinde ara...',
+ 'memory.all_categories': 'Tüm Kategoriler',
+ 'memory.search_button': 'Ara',
+ 'memory.load_failed': 'Hafıza yüklenemedi',
+ 'memory.key_content_required': 'Anahtar ve içerik gereklidir.',
+ 'memory.failed_store': 'Hafıza kaydedilemedi',
+ 'memory.failed_delete': 'Hafıza silinemedi',
+ 'memory.category_optional': 'Kategori (isteğe bağlı)',
+ 'memory.key_placeholder': 'örn. kullanici_tercihleri',
+ 'memory.content_placeholder': 'Hafıza içeriği...',
+ 'memory.category_placeholder': 'örn. tercihler, bağlam, gerçekler',
+ 'memory.saving': 'Kaydediliyor...',
+ 'memory.delete_prompt': 'Silinsin mi?',
+ 'config.title': 'Yapılandırma',
+ 'config.save': 'Kaydet',
+ 'config.saved': 'Yapılandırma başarıyla kaydedildi.',
+ 'config.saving': 'Kaydediliyor...',
+ 'config.masked_title': 'Hassas alanlar maskelendi',
+ 'config.masked_description': 'Güvenlik için API anahtarları, belirteçler ve parolalar gizlenir. Maskelenmiş bir alanı güncellemek için tüm maskeli değeri yeni değerinizle değiştirin.',
+ 'config.toml_configuration': 'TOML Yapılandırması',
+ 'config.lines': 'satır',
+ 'cost.title': 'Maliyet Takibi',
+ 'cost.session': 'Oturum Maliyeti',
+ 'cost.daily': 'Günlük Maliyet',
+ 'cost.monthly': 'Aylık Maliyet',
+ 'cost.total_requests': 'Toplam İstek',
+ 'cost.token_statistics': 'Belirteç İstatistikleri',
+ 'cost.avg_tokens_per_request': 'İstek Başına Ort. Belirteç',
+ 'cost.cost_per_1k_tokens': '1K Belirteç Başına Maliyet',
+ 'cost.model_breakdown': 'Model Dağılımı',
+ 'cost.no_model_data': 'Model verisi yok.',
+ 'cost.share': 'Pay',
+ 'cost.load_failed': 'Maliyet verisi yüklenemedi',
+ 'logs.title': 'Canlı Kayıtlar',
+ 'logs.pause': 'Duraklat',
+ 'logs.resume': 'Sürdür',
+ 'logs.events': 'olay',
+ 'logs.jump_to_bottom': 'Alta git',
+ 'logs.filter_label': 'Filtre:',
+ 'logs.paused_stream': 'Kayıt akışı duraklatıldı.',
+ 'logs.waiting_for_events': 'Olaylar bekleniyor...',
+ 'doctor.title': 'Sistem Teşhisleri',
+ 'doctor.run': 'Teşhisleri Çalıştır',
+ 'doctor.running': 'Teşhisler çalıştırılıyor...',
+ 'doctor.running_short': 'Çalışıyor...',
+ 'doctor.running_hint': 'Bu birkaç saniye sürebilir.',
+ 'doctor.warn': 'Uyarı',
+ 'doctor.issues_found': 'Sorunlar Bulundu',
+ 'doctor.warnings': 'Uyarılar',
+ 'doctor.all_clear': 'Temiz',
+ 'doctor.instructions': 'ZeroClaw kurulumunuzu kontrol etmek için "Teşhisleri Çalıştır" düğmesine tıklayın.',
+ 'auth.pair': 'Cihazı Eşle',
+ 'auth.pair_button': 'Eşle',
+ 'auth.logout': 'Çıkış Yap',
+ 'auth.enter_code': 'Terminalinizdeki tek kullanımlık eşleştirme kodunu girin',
+ 'auth.code_placeholder': '6 haneli kod',
+ 'auth.pairing_progress': 'Eşleştiriliyor...',
+ 'common.languages': 'Diller',
+ 'common.select_language': 'Dil seçin',
+ 'common.connecting': 'Bağlanıyor...',
+ 'header.dashboard_tagline': 'ZeroClaw paneli',
+ 'sidebar.gateway_dashboard': 'Ağ Geçidi + Panel',
+ 'sidebar.runtime_mode': 'Çalışma Modu',
+ 'navigation.open': 'Gezinmeyi aç',
+ 'navigation.close': 'Gezinmeyi kapat',
+ 'navigation.expand': 'Gezinmeyi genişlet',
+ 'navigation.collapse': 'Gezinmeyi daralt',
+};
+
+export default tr;
diff --git a/web/src/lib/i18n/locales/uk.ts b/web/src/lib/i18n/locales/uk.ts
new file mode 100644
index 000000000..9da36ebe9
--- /dev/null
+++ b/web/src/lib/i18n/locales/uk.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const uk: Partial = {
+ 'nav.dashboard': 'Панель',
+ 'nav.agent': 'Агент',
+ 'nav.tools': 'Інструменти',
+ 'nav.cron': 'Заплановані завдання',
+ 'nav.integrations': 'Інтеграції',
+ 'nav.memory': 'Пам\u2019ять',
+ 'nav.config': 'Конфігурація',
+ 'nav.cost': 'Витрати',
+ 'nav.logs': 'Журнали',
+ 'nav.doctor': 'Діагностика',
+ 'dashboard.hero_title': 'Електрична панель runtime',
+ 'agent.placeholder': 'Введіть повідомлення…',
+ 'tools.search': 'Пошук інструментів…',
+ 'cron.add': 'Додати завдання',
+ 'memory.add_memory': 'Додати пам\u2019ять',
+ 'config.save': 'Зберегти',
+ 'cost.token_statistics': 'Статистика токенів',
+ 'logs.title': 'Живі журнали',
+ 'doctor.title': 'Діагностика системи',
+ 'auth.pair_button': 'З\u2019єднати',
+ 'auth.enter_code': 'Введіть одноразовий код з\u2019єднання з термінала',
+ 'auth.code_placeholder': '6-значний код',
+ 'auth.pairing_progress': 'З\u2019єднання…',
+ 'auth.logout': 'Вийти',
+ 'common.languages': 'Мови',
+ 'common.select_language': 'Оберіть мову',
+ 'header.dashboard_tagline': 'Панель ZeroClaw',
+};
+
+export default uk;
diff --git a/web/src/lib/i18n/locales/ur.ts b/web/src/lib/i18n/locales/ur.ts
new file mode 100644
index 000000000..541625e50
--- /dev/null
+++ b/web/src/lib/i18n/locales/ur.ts
@@ -0,0 +1,33 @@
+import type { TranslationKeys } from './en';
+
+const ur: Partial = {
+ 'nav.dashboard': 'ڈیش بورڈ',
+ 'nav.agent': 'ایجنٹ',
+ 'nav.tools': 'ٹولز',
+ 'nav.cron': 'شیڈول شدہ کام',
+ 'nav.integrations': 'انضمامات',
+ 'nav.memory': 'میموری',
+ 'nav.config': 'ترتیبات',
+ 'nav.cost': 'لاگت',
+ 'nav.logs': 'لاگز',
+ 'nav.doctor': 'تشخیص',
+ 'dashboard.hero_title': 'الیکٹرک رن ٹائم ڈیش بورڈ',
+ 'agent.placeholder': 'پیغام لکھیں…',
+ 'tools.search': 'ٹولز تلاش کریں…',
+ 'cron.add': 'کام شامل کریں',
+ 'memory.add_memory': 'میموری شامل کریں',
+ 'config.save': 'محفوظ کریں',
+ 'cost.token_statistics': 'ٹوکن کے اعدادوشمار',
+ 'logs.title': 'لائیو لاگز',
+ 'doctor.title': 'سسٹم تشخیص',
+ 'auth.pair_button': 'جوڑیں',
+ 'auth.enter_code': 'ٹرمینل سے ایک بار استعمال ہونے والا پیئرنگ کوڈ درج کریں',
+ 'auth.code_placeholder': '6 ہندسوں کا کوڈ',
+ 'auth.pairing_progress': 'جوڑا جا رہا ہے…',
+ 'auth.logout': 'لاگ آؤٹ',
+ 'common.languages': 'زبانیں',
+ 'common.select_language': 'زبان منتخب کریں',
+ 'header.dashboard_tagline': 'ZeroClaw ڈیش بورڈ',
+};
+
+export default ur;
diff --git a/web/src/lib/i18n/locales/vi.ts b/web/src/lib/i18n/locales/vi.ts
new file mode 100644
index 000000000..63b8140e5
--- /dev/null
+++ b/web/src/lib/i18n/locales/vi.ts
@@ -0,0 +1,51 @@
+import type { TranslationKeys } from './en';
+
+const vi: Partial = {
+ 'nav.dashboard': 'Bảng điều khiển',
+ 'nav.agent': 'Tác tử',
+ 'nav.tools': 'Công cụ',
+ 'nav.cron': 'Lịch tác vụ',
+ 'nav.integrations': 'Tích hợp',
+ 'nav.memory': 'Bộ nhớ',
+ 'nav.config': 'Cấu hình',
+ 'nav.cost': 'Chi phí',
+ 'nav.logs': 'Nhật ký',
+ 'nav.doctor': 'Chẩn đoán',
+ 'dashboard.hero_title': 'Bảng điều khiển runtime điện xanh',
+ 'dashboard.live_gateway': 'Cổng hoạt động',
+ 'dashboard.unpaired': 'Chưa ghép đôi',
+ 'agent.title': 'Trò chuyện với tác tử',
+ 'agent.placeholder': 'Nhập tin nhắn…',
+ 'agent.connecting': 'Đang kết nối…',
+ 'agent.connected': 'Đã kết nối',
+ 'agent.disconnected': 'Đã ngắt kết nối',
+ 'tools.search': 'Tìm công cụ…',
+ 'tools.agent_tools': 'Công cụ tác tử',
+ 'tools.cli_tools': 'Công cụ CLI',
+ 'cron.add': 'Thêm tác vụ',
+ 'cron.scheduled_tasks': 'Tác vụ đã lên lịch',
+ 'integrations.title': 'Tích hợp',
+ 'memory.add_memory': 'Thêm bộ nhớ',
+ 'memory.search_entries': 'Tìm trong bộ nhớ…',
+ 'config.save': 'Lưu',
+ 'config.saving': 'Đang lưu…',
+ 'cost.session': 'Chi phí phiên',
+ 'cost.daily': 'Chi phí ngày',
+ 'cost.monthly': 'Chi phí tháng',
+ 'logs.title': 'Nhật ký trực tiếp',
+ 'logs.pause': 'Tạm dừng',
+ 'logs.resume': 'Tiếp tục',
+ 'doctor.title': 'Chẩn đoán hệ thống',
+ 'doctor.run': 'Chạy chẩn đoán',
+ 'doctor.running_short': 'Đang chạy…',
+ 'auth.pair_button': 'Ghép đôi',
+ 'auth.enter_code': 'Nhập mã ghép đôi một lần từ terminal',
+ 'auth.code_placeholder': 'Mã 6 chữ số',
+ 'auth.pairing_progress': 'Đang ghép đôi…',
+ 'auth.logout': 'Đăng xuất',
+ 'common.languages': 'Ngôn ngữ',
+ 'common.select_language': 'Chọn ngôn ngữ',
+ 'header.dashboard_tagline': 'Bảng điều khiển ZeroClaw',
+};
+
+export default vi;
diff --git a/web/src/lib/i18n/locales/zh-CN.ts b/web/src/lib/i18n/locales/zh-CN.ts
new file mode 100644
index 000000000..f4dfff9d2
--- /dev/null
+++ b/web/src/lib/i18n/locales/zh-CN.ts
@@ -0,0 +1,51 @@
+import type { TranslationKeys } from './en';
+
+const zhCN: Partial = {
+ 'nav.dashboard': '仪表盘',
+ 'nav.agent': '代理',
+ 'nav.tools': '工具',
+ 'nav.cron': '定时任务',
+ 'nav.integrations': '集成',
+ 'nav.memory': '记忆',
+ 'nav.config': '配置',
+ 'nav.cost': '成本跟踪',
+ 'nav.logs': '日志',
+ 'nav.doctor': '诊断',
+ 'dashboard.hero_title': '电光运行仪表盘',
+ 'dashboard.live_gateway': '在线网关',
+ 'dashboard.unpaired': '未配对',
+ 'agent.title': '代理聊天',
+ 'agent.placeholder': '输入消息…',
+ 'agent.connecting': '正在连接…',
+ 'agent.connected': '已连接',
+ 'agent.disconnected': '已断开',
+ 'tools.search': '搜索工具…',
+ 'tools.agent_tools': '代理工具',
+ 'tools.cli_tools': 'CLI 工具',
+ 'cron.add': '添加任务',
+ 'cron.scheduled_tasks': '定时任务',
+ 'integrations.title': '集成',
+ 'memory.add_memory': '添加记忆',
+ 'memory.search_entries': '搜索记忆条目…',
+ 'config.save': '保存',
+ 'config.saving': '正在保存…',
+ 'cost.session': '会话成本',
+ 'cost.daily': '每日成本',
+ 'cost.monthly': '每月成本',
+ 'logs.title': '实时日志',
+ 'logs.pause': '暂停',
+ 'logs.resume': '继续',
+ 'doctor.title': '系统诊断',
+ 'doctor.run': '运行诊断',
+ 'doctor.running_short': '运行中…',
+ 'auth.pair_button': '配对',
+ 'auth.enter_code': '输入终端中的一次性配对码',
+ 'auth.code_placeholder': '6 位代码',
+ 'auth.pairing_progress': '正在配对…',
+ 'auth.logout': '退出',
+ 'common.languages': '语言',
+ 'common.select_language': '选择语言',
+ 'header.dashboard_tagline': 'ZeroClaw 仪表盘',
+};
+
+export default zhCN;
diff --git a/web/src/lib/i18n/translate.ts b/web/src/lib/i18n/translate.ts
new file mode 100644
index 000000000..2aa7c9ee4
--- /dev/null
+++ b/web/src/lib/i18n/translate.ts
@@ -0,0 +1,75 @@
+import type { Locale, LocaleDocumentTarget } from './types';
+import { getLocaleDirection } from './languages';
+import { translations } from './locales';
+
+const LOCALE_PREFIX_MAP = new Map([
+ ['zh', 'zh-CN'],
+ ['ja', 'ja'],
+ ['ko', 'ko'],
+ ['vi', 'vi'],
+ ['tl', 'tl'],
+ ['es', 'es'],
+ ['pt', 'pt'],
+ ['it', 'it'],
+ ['de', 'de'],
+ ['fr', 'fr'],
+ ['ar', 'ar'],
+ ['hi', 'hi'],
+ ['ru', 'ru'],
+ ['bn', 'bn'],
+ ['iw', 'he'],
+ ['he', 'he'],
+ ['pl', 'pl'],
+ ['cs', 'cs'],
+ ['nl', 'nl'],
+ ['tr', 'tr'],
+ ['uk', 'uk'],
+ ['id', 'id'],
+ ['th', 'th'],
+ ['ur', 'ur'],
+ ['ro', 'ro'],
+ ['sv', 'sv'],
+ ['el', 'el'],
+ ['hu', 'hu'],
+ ['fi', 'fi'],
+ ['da', 'da'],
+ ['nb', 'nb'],
+ ['no', 'nb'],
+]);
+
+export function coerceLocale(locale: string | undefined): Locale {
+ if (!locale) return 'en';
+ const prefix = locale.toLowerCase().split(/[-_]/)[0];
+ return LOCALE_PREFIX_MAP.get(prefix) ?? 'en';
+}
+
+let currentLocale: Locale = 'en';
+
+export function getLocale(): Locale {
+ return currentLocale;
+}
+
+export function setLocale(locale: Locale): void {
+ currentLocale = locale;
+}
+
+export function t(key: string): string {
+ return translations[currentLocale]?.[key] ?? translations.en[key] ?? key;
+}
+
+export function tLocale(key: string, locale: Locale): string {
+ return translations[locale]?.[key] ?? translations.en[key] ?? key;
+}
+
+export function applyLocaleToDocument(locale: Locale, target: LocaleDocumentTarget): void {
+ const direction = getLocaleDirection(locale);
+
+ if (target.documentElement) {
+ target.documentElement.lang = locale;
+ target.documentElement.dir = direction;
+ }
+
+ if (target.body) {
+ target.body.dir = direction;
+ }
+}
diff --git a/web/src/lib/i18n/types.ts b/web/src/lib/i18n/types.ts
new file mode 100644
index 000000000..6c5284087
--- /dev/null
+++ b/web/src/lib/i18n/types.ts
@@ -0,0 +1,46 @@
+export type Locale =
+ | 'en'
+ | 'zh-CN'
+ | 'ja'
+ | 'ko'
+ | 'vi'
+ | 'tl'
+ | 'es'
+ | 'pt'
+ | 'it'
+ | 'de'
+ | 'fr'
+ | 'ar'
+ | 'hi'
+ | 'ru'
+ | 'bn'
+ | 'he'
+ | 'pl'
+ | 'cs'
+ | 'nl'
+ | 'tr'
+ | 'uk'
+ | 'id'
+ | 'th'
+ | 'ur'
+ | 'ro'
+ | 'sv'
+ | 'el'
+ | 'hu'
+ | 'fi'
+ | 'da'
+ | 'nb';
+
+export type LocaleDirection = 'ltr' | 'rtl';
+
+export interface LanguageOption {
+ value: Locale;
+ label: string;
+ flag: string;
+ direction: LocaleDirection;
+}
+
+export interface LocaleDocumentTarget {
+ documentElement?: { lang?: string; dir?: string };
+ body?: { dir?: string } | null;
+}