refactor(web): decompose i18n module into smaller focused files

Split the monolithic i18n.ts (~1700 lines) into separate modules:
- types.ts: type definitions
- languages.ts: language options and helpers
- translate.ts: locale get/set and translation logic
- locales/: one file per locale
- index.ts: re-exports for backward-compatible imports

Update LanguageSelector to use option.label directly and remove
unused getLanguageOptionLabel import and id attribute.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Simian Astronaut 7 2026-03-10 03:41:23 -04:00
parent 149165fa45
commit ac63a4d16a
39 changed files with 1734 additions and 1709 deletions

View File

@ -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 (
<div ref={containerRef} className="relative" dir={localeDirection}>
<button
id="locale-selector-trigger"
type="button"
data-testid="locale-select"
aria-label={ariaLabel}
@ -75,7 +73,7 @@ export default function LanguageSelector({
>
{activeLanguage.flag}
</span>
<span dir={localeDirection} className="min-w-0 truncate text-start">{getLanguageOptionLabel(activeLanguage)}</span>
<span dir={localeDirection} className="min-w-0 truncate text-start">{activeLanguage.label}</span>
<ChevronDown className={`h-4 w-4 shrink-0 transition ${open ? 'rotate-180' : ''}`} />
</button>
@ -115,7 +113,7 @@ export default function LanguageSelector({
{option.flag}
</span>
<span dir={option.direction} className="min-w-0 flex-1 truncate text-start">
{getLanguageOptionLabel(option)}
{option.label}
</span>
{selected ? <Check className="h-4 w-4 shrink-0 text-[#8cc2ff]" /> : null}
</button>

File diff suppressed because it is too large Load Diff

View File

@ -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);
}
});

View File

@ -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';

View File

@ -0,0 +1,58 @@
import type { LanguageOption, Locale, LocaleDirection } from './types';
export const LANGUAGE_OPTIONS: ReadonlyArray<LanguageOption> = [
{ 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<Locale> =
LANGUAGE_OPTIONS.map((option) => option.value);
const RTL_LOCALES = new Set<Locale>(['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;
}

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const ar: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const bn: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const cs: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const da: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const de: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const el: Partial<TranslationKeys> = {
'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;

View File

@ -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<string, string>;
export type TranslationKeys = typeof en;
export default en;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const es: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const fi: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,51 @@
import type { TranslationKeys } from './en';
const fr: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const he: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const hi: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const hu: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const id: Partial<TranslationKeys> = {
'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;

View File

@ -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<typeof en>): Record<string, string> {
return { ...en, ...overrides };
}
export const translations: Record<Locale, Record<string, string>> = {
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),
};

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const it: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,51 @@
import type { TranslationKeys } from './en';
const ja: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const ko: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const nb: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const nl: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const pl: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const pt: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const ro: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,51 @@
import type { TranslationKeys } from './en';
const ru: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const sv: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const th: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const tl: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,157 @@
import type { TranslationKeys } from './en';
const tr: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const uk: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,33 @@
import type { TranslationKeys } from './en';
const ur: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,51 @@
import type { TranslationKeys } from './en';
const vi: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,51 @@
import type { TranslationKeys } from './en';
const zhCN: Partial<TranslationKeys> = {
'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;

View File

@ -0,0 +1,75 @@
import type { Locale, LocaleDocumentTarget } from './types';
import { getLocaleDirection } from './languages';
import { translations } from './locales';
const LOCALE_PREFIX_MAP = new Map<string, Locale>([
['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;
}
}

46
web/src/lib/i18n/types.ts Normal file
View File

@ -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;
}