1558 lines
60 KiB
TypeScript
1558 lines
60 KiB
TypeScript
/**
|
||
* Lightweight reactive i18n — no external deps.
|
||
*
|
||
* Locale priority: localStorage > VITE_LOCALE > navigator.language > 'en'
|
||
* Changing locale at runtime triggers subscribed React components to re-render.
|
||
*/
|
||
|
||
const STORAGE_KEY = 'pinchchat-locale';
|
||
|
||
const en = {
|
||
// Login screen
|
||
'login.title': 'PinchChat',
|
||
'login.subtitle': 'Connect to your OpenClaw gateway',
|
||
'login.gatewayUrl': 'Gateway URL',
|
||
'login.token': 'Token',
|
||
'login.tokenPlaceholder': 'Enter your gateway token',
|
||
'login.authToken': 'Token',
|
||
'login.authPassword': 'Password',
|
||
'login.password': 'Password',
|
||
'login.passwordPlaceholder': 'Enter your gateway password',
|
||
'login.connect': 'Connect',
|
||
'login.connecting': 'Connecting…',
|
||
'login.showToken': 'Show token',
|
||
'login.hideToken': 'Hide token',
|
||
'login.storedLocally': 'Credentials are stored locally in your browser',
|
||
'login.wsHint': 'URL must start with ws:// or wss://',
|
||
'login.advanced': 'Advanced',
|
||
'login.clientId': 'Client ID',
|
||
'login.clientIdHint': 'Sent in the WebSocket connect frame. Default: webchat',
|
||
|
||
// Header
|
||
'header.title': 'PinchChat',
|
||
'header.connected': 'Connected',
|
||
'header.disconnected': 'Disconnected',
|
||
'header.logout': 'Logout',
|
||
'header.toggleSidebar': 'Toggle sidebar',
|
||
'header.changeLanguage': 'Change language',
|
||
'header.soundOn': 'Enable notification sound',
|
||
'header.soundOff': 'Disable notification sound',
|
||
|
||
// Chat
|
||
'chat.welcome': 'PinchChat',
|
||
'chat.welcomeSub': 'Send a message to get started',
|
||
'chat.suggestions': 'Try asking...',
|
||
'chat.suggestion1': 'Summarize my recent emails',
|
||
'chat.suggestion2': "What's on my calendar today?",
|
||
'chat.suggestion3': 'Search the web for latest news',
|
||
'chat.suggestion4': 'Help me write a script',
|
||
'chat.loadingHistory': 'Loading messages…',
|
||
'chat.inputPlaceholder': 'Type a message…',
|
||
'chat.inputLabel': 'Message',
|
||
'chat.attachFile': 'Attach file',
|
||
'chat.send': 'Send',
|
||
'chat.stop': 'Stop',
|
||
'chat.showPreview': 'Preview markdown',
|
||
'chat.hidePreview': 'Hide preview',
|
||
'chat.scrollToBottom': 'New messages',
|
||
'chat.scrollDown': 'Scroll to bottom',
|
||
'chat.collapseTools': 'Collapse all tools',
|
||
'chat.expandTools': 'Expand all tools',
|
||
'chat.messages': 'Chat messages',
|
||
'chat.thinking': 'Thinking…',
|
||
|
||
// Sidebar
|
||
'sidebar.title': 'Sessions',
|
||
'sidebar.empty': 'No sessions',
|
||
'sidebar.search': 'Search sessions…',
|
||
'sidebar.noResults': 'No matching sessions',
|
||
'sidebar.pin': 'Pin session',
|
||
'sidebar.unpin': 'Unpin session',
|
||
'sidebar.pinned': 'Pinned',
|
||
'sidebar.delete': 'Delete session',
|
||
'sidebar.rename': 'Rename session',
|
||
'sidebar.deleteConfirm': 'Delete this session? This cannot be undone.',
|
||
'sidebar.deleteCancel': 'Cancel',
|
||
'sidebar.openSplit': 'Open in split view',
|
||
'sidebar.close': 'Close sidebar',
|
||
'sidebar.clearSearch': 'Clear search',
|
||
'sidebar.filterAll': 'All',
|
||
'sidebar.filterActive': 'Active',
|
||
'split.close': 'Close split view',
|
||
'app.mainChat': 'Main chat',
|
||
'app.splitPane': 'Split pane',
|
||
'app.skipToChat': 'Skip to chat input',
|
||
|
||
// Thinking
|
||
'thinking.label': 'Thinking',
|
||
'thinking.reasoning': 'Reasoning…',
|
||
|
||
// Tool call
|
||
'tool.parameters': 'Parameters',
|
||
'tool.result': 'Result',
|
||
|
||
// Connection banner
|
||
'connection.reconnecting': 'Connection lost — reconnecting…',
|
||
'connection.reconnected': 'Reconnected!',
|
||
'connection.pairing': 'Device pairing pending — run `openclaw devices approve` on your gateway',
|
||
|
||
// Message actions
|
||
'message.copy': 'Copy message',
|
||
'message.copied': 'Copied!',
|
||
'message.retry': 'Resend message',
|
||
'message.showMore': 'Show more',
|
||
'message.showLess': 'Show less',
|
||
'message.metadata': 'Message details',
|
||
'message.rawJson': 'Raw JSON',
|
||
'message.hideRawJson': 'Hide raw JSON',
|
||
|
||
// Timestamps
|
||
'time.yesterday': 'Yesterday',
|
||
'time.today': 'Today',
|
||
|
||
// Keyboard shortcuts
|
||
'shortcuts.title': 'Keyboard Shortcuts',
|
||
'shortcuts.send': 'Send message',
|
||
'shortcuts.newline': 'New line',
|
||
'shortcuts.search': 'Search sessions',
|
||
'shortcuts.switchSession': 'Previous / next session',
|
||
'shortcuts.closeSidebar': 'Close sidebar / search',
|
||
'shortcuts.stop': 'Stop generation',
|
||
'shortcuts.help': 'Show shortcuts',
|
||
'shortcuts.close': 'Close',
|
||
'shortcuts.chatSection': 'Chat',
|
||
|
||
// Error boundary
|
||
'error.title': 'Something went wrong',
|
||
'error.description': 'An unexpected error occurred while rendering the interface. You can try again or reload the page.',
|
||
'error.retry': 'Try again',
|
||
'error.reload': 'Reload page',
|
||
'shortcuts.navigationSection': 'Navigation',
|
||
'shortcuts.generalSection': 'General',
|
||
|
||
// Export
|
||
'header.export': 'Export conversation as Markdown',
|
||
'header.compact': 'Compact',
|
||
'header.compacting': 'Compacting…',
|
||
'header.sessionInfo': 'Session Info',
|
||
'sessionInfo.sessionKey': 'Session Key',
|
||
'sessionInfo.channel': 'Channel',
|
||
'sessionInfo.kind': 'Kind',
|
||
'sessionInfo.model': 'Model',
|
||
'sessionInfo.agent': 'Agent',
|
||
'sessionInfo.messages': 'Messages',
|
||
'sessionInfo.totalTokens': 'Total Tokens',
|
||
'sessionInfo.inputTokens': 'Input',
|
||
'sessionInfo.outputTokens': 'Output',
|
||
'sessionInfo.contextWindow': 'Context',
|
||
'sessionInfo.lastActive': 'Last Active',
|
||
|
||
// Theme
|
||
'theme.title': 'Theme',
|
||
'theme.mode': 'Mode',
|
||
'theme.accent': 'Accent',
|
||
'theme.system': 'System',
|
||
'theme.dark': 'Dark',
|
||
'theme.light': 'Light',
|
||
'theme.oled': 'OLED',
|
||
|
||
// Message search
|
||
'search.placeholder': 'Search messages…',
|
||
'search.noResults': '0 results',
|
||
'search.prev': 'Previous match',
|
||
'search.next': 'Next match',
|
||
'shortcuts.searchMessages': 'Search messages',
|
||
|
||
// Send shortcut setting
|
||
'settings.title': 'Settings',
|
||
'settings.appearance': 'Appearance',
|
||
'settings.typography': 'Typography',
|
||
'settings.chat': 'Chat',
|
||
'settings.notifications': 'Notifications',
|
||
'settings.notificationSound': 'Notification sound',
|
||
'settings.language': 'Language',
|
||
'settings.sendShortcut': 'Send with',
|
||
'settings.sendEnter': 'Enter',
|
||
'settings.sendCtrlEnter': 'Ctrl+Enter',
|
||
'settings.tab.appearance': 'Appearance',
|
||
'settings.tab.typography': 'Typography',
|
||
'settings.tab.chat': 'Chat',
|
||
'settings.tab.notifications': 'Notifications',
|
||
'settings.fontUi': 'UI font',
|
||
'settings.fontMono': 'Code font',
|
||
'settings.fontSize': 'UI font size',
|
||
'settings.fontMonoSize': 'Code font size',
|
||
'settings.preview': 'Preview',
|
||
'settings.previewText': 'The quick brown fox jumps over the lazy dog — 1234567890',
|
||
'settings.fontNote': 'Inter / JetBrains / Fira load automatically; Cascadia and SF use your system if installed.',
|
||
|
||
// Bookmarks
|
||
'message.bookmark': 'Bookmark message',
|
||
'message.removeBookmark': 'Remove bookmark',
|
||
'message.reply': 'Reply',
|
||
'chat.replyingTo': 'Replying to',
|
||
'chat.bookmarks': 'Bookmarks',
|
||
'chat.export': 'Export conversation',
|
||
'chat.contextCompacted': 'Context compacted — older messages cached locally',
|
||
'slash.commands': 'Commands',
|
||
'slash.status': 'Show session status & usage',
|
||
'slash.reasoning': 'Toggle reasoning mode',
|
||
'slash.verbose': 'Toggle verbose output',
|
||
'slash.model': 'Switch model for this session',
|
||
'slash.compact': 'Compact conversation context',
|
||
'slash.reset': 'Reset the session',
|
||
'slash.new': 'Create a new chat session',
|
||
'slash.help': 'Show available commands',
|
||
} as const;
|
||
|
||
const fr: Record<keyof typeof en, string> = {
|
||
'login.title': 'PinchChat',
|
||
'login.subtitle': 'Connectez-vous à votre gateway OpenClaw',
|
||
'login.gatewayUrl': 'URL de la gateway',
|
||
'login.token': 'Token',
|
||
'login.tokenPlaceholder': 'Entrez votre token gateway',
|
||
'login.authToken': 'Token',
|
||
'login.authPassword': 'Mot de passe',
|
||
'login.password': 'Mot de passe',
|
||
'login.passwordPlaceholder': 'Entrez votre mot de passe gateway',
|
||
'login.connect': 'Connexion',
|
||
'login.connecting': 'Connexion…',
|
||
'login.showToken': 'Afficher le token',
|
||
'login.hideToken': 'Masquer le token',
|
||
'login.storedLocally': 'Les identifiants sont stockés localement dans votre navigateur',
|
||
'login.wsHint': 'L\'URL doit commencer par ws:// ou wss://',
|
||
'login.advanced': 'Avancé',
|
||
'login.clientId': 'ID client',
|
||
'login.clientIdHint': 'Envoyé dans la trame de connexion WebSocket. Par défaut : webchat',
|
||
|
||
'header.title': 'PinchChat',
|
||
'header.connected': 'Connecté',
|
||
'header.disconnected': 'Déconnecté',
|
||
'header.logout': 'Déconnexion',
|
||
'header.toggleSidebar': 'Afficher/masquer la barre latérale',
|
||
'header.changeLanguage': 'Changer de langue',
|
||
'header.soundOn': 'Activer le son de notification',
|
||
'header.soundOff': 'Désactiver le son de notification',
|
||
|
||
'chat.welcome': 'PinchChat',
|
||
'chat.welcomeSub': 'Envoyez un message pour commencer',
|
||
'chat.suggestions': 'Essayez par exemple...',
|
||
'chat.suggestion1': 'Résume mes derniers emails',
|
||
'chat.suggestion2': "Qu'est-ce que j'ai au calendrier aujourd'hui ?",
|
||
'chat.suggestion3': 'Cherche sur le web les dernières actus',
|
||
'chat.suggestion4': "Aide-moi à écrire un script",
|
||
'chat.loadingHistory': 'Chargement des messages…',
|
||
'chat.inputPlaceholder': 'Tapez un message…',
|
||
'chat.inputLabel': 'Message',
|
||
'chat.attachFile': 'Joindre un fichier',
|
||
'chat.send': 'Envoyer',
|
||
'chat.stop': 'Arrêter',
|
||
'chat.showPreview': 'Aperçu markdown',
|
||
'chat.hidePreview': 'Masquer l\'aperçu',
|
||
'chat.scrollToBottom': 'Nouveaux messages',
|
||
'chat.scrollDown': 'Défiler en bas',
|
||
'chat.collapseTools': 'Replier tous les outils',
|
||
'chat.expandTools': 'Déplier tous les outils',
|
||
'chat.messages': 'Messages du chat',
|
||
'chat.thinking': 'Réflexion…',
|
||
|
||
'sidebar.title': 'Sessions',
|
||
'sidebar.empty': 'Aucune session',
|
||
'sidebar.search': 'Rechercher…',
|
||
'sidebar.noResults': 'Aucun résultat',
|
||
'sidebar.pin': 'Épingler la session',
|
||
'sidebar.unpin': 'Désépingler la session',
|
||
'sidebar.pinned': 'Épinglées',
|
||
'sidebar.delete': 'Supprimer la session',
|
||
'sidebar.rename': 'Renommer la session',
|
||
'sidebar.deleteConfirm': 'Supprimer cette session ? Cette action est irréversible.',
|
||
'sidebar.deleteCancel': 'Annuler',
|
||
'sidebar.openSplit': 'Ouvrir en vue scindée',
|
||
'sidebar.close': 'Fermer la barre latérale',
|
||
'sidebar.clearSearch': 'Effacer la recherche',
|
||
'sidebar.filterAll': 'Tout',
|
||
'sidebar.filterActive': 'Actives',
|
||
'split.close': 'Fermer la vue scindée',
|
||
'app.mainChat': 'Chat principal',
|
||
'app.splitPane': 'Volet scindé',
|
||
'app.skipToChat': 'Aller au champ de saisie',
|
||
|
||
'thinking.label': 'Réflexion',
|
||
'thinking.reasoning': 'Réflexion…',
|
||
|
||
'tool.parameters': 'Paramètres',
|
||
'tool.result': 'Résultat',
|
||
|
||
'connection.reconnecting': 'Connexion perdue — reconnexion…',
|
||
'connection.reconnected': 'Reconnecté !',
|
||
'connection.pairing': 'Appairage en attente — exécutez `openclaw devices approve` sur votre gateway',
|
||
|
||
'message.copy': 'Copier le message',
|
||
'message.copied': 'Copié !',
|
||
'message.retry': 'Renvoyer le message',
|
||
'message.showMore': 'Afficher plus',
|
||
'message.showLess': 'Afficher moins',
|
||
'message.metadata': 'Détails du message',
|
||
'message.rawJson': 'JSON brut',
|
||
'message.hideRawJson': 'Masquer le JSON brut',
|
||
|
||
'time.yesterday': 'Hier',
|
||
'time.today': "Aujourd'hui",
|
||
|
||
'shortcuts.title': 'Raccourcis clavier',
|
||
'shortcuts.send': 'Envoyer le message',
|
||
'shortcuts.newline': 'Nouvelle ligne',
|
||
'shortcuts.search': 'Rechercher des sessions',
|
||
'shortcuts.switchSession': 'Session précédente / suivante',
|
||
'shortcuts.closeSidebar': 'Fermer la barre / recherche',
|
||
'shortcuts.stop': 'Arrêter la génération',
|
||
'shortcuts.help': 'Afficher les raccourcis',
|
||
'shortcuts.close': 'Fermer',
|
||
'shortcuts.chatSection': 'Chat',
|
||
|
||
'error.title': 'Quelque chose s\'est mal passé',
|
||
'error.description': 'Une erreur inattendue est survenue lors de l\'affichage. Vous pouvez réessayer ou recharger la page.',
|
||
'error.retry': 'Réessayer',
|
||
'error.reload': 'Recharger',
|
||
'shortcuts.navigationSection': 'Navigation',
|
||
'shortcuts.generalSection': 'Général',
|
||
|
||
'header.export': 'Exporter la conversation en Markdown',
|
||
'header.compact': 'Compacter',
|
||
'header.compacting': 'Compaction…',
|
||
'header.sessionInfo': 'Infos session',
|
||
'sessionInfo.sessionKey': 'Clé session',
|
||
'sessionInfo.channel': 'Canal',
|
||
'sessionInfo.kind': 'Type',
|
||
'sessionInfo.model': 'Modèle',
|
||
'sessionInfo.agent': 'Agent',
|
||
'sessionInfo.messages': 'Messages',
|
||
'sessionInfo.totalTokens': 'Tokens total',
|
||
'sessionInfo.inputTokens': 'Entrée',
|
||
'sessionInfo.outputTokens': 'Sortie',
|
||
'sessionInfo.contextWindow': 'Contexte',
|
||
'sessionInfo.lastActive': 'Dernière activité',
|
||
|
||
'theme.title': 'Thème',
|
||
'theme.mode': 'Mode',
|
||
'theme.accent': 'Accent',
|
||
'theme.system': 'Système',
|
||
'theme.dark': 'Sombre',
|
||
'theme.light': 'Clair',
|
||
'theme.oled': 'OLED',
|
||
|
||
'search.placeholder': 'Rechercher dans les messages…',
|
||
'search.noResults': '0 résultat',
|
||
'search.prev': 'Résultat précédent',
|
||
'search.next': 'Résultat suivant',
|
||
'shortcuts.searchMessages': 'Rechercher dans les messages',
|
||
|
||
'settings.title': 'Paramètres',
|
||
'settings.appearance': 'Apparence',
|
||
'settings.typography': 'Typographie',
|
||
'settings.chat': 'Chat',
|
||
'settings.notifications': 'Notifications',
|
||
'settings.notificationSound': 'Son de notification',
|
||
'settings.language': 'Langue',
|
||
'settings.sendShortcut': 'Envoyer avec',
|
||
'settings.sendEnter': 'Entrée',
|
||
'settings.sendCtrlEnter': 'Ctrl+Entrée',
|
||
'settings.tab.appearance': 'Apparence',
|
||
'settings.tab.typography': 'Typographie',
|
||
'settings.tab.chat': 'Chat',
|
||
'settings.tab.notifications': 'Notifications',
|
||
'settings.fontUi': 'Police UI',
|
||
'settings.fontMono': 'Police code',
|
||
'settings.fontSize': 'Taille police UI',
|
||
'settings.fontMonoSize': 'Taille police code',
|
||
'settings.preview': 'Aperçu',
|
||
'settings.previewText': 'Le vif renard brun saute par-dessus le chien paresseux — 1234567890',
|
||
'settings.fontNote': 'Inter / JetBrains / Fira se chargent automatiquement ; Cascadia et SF dépendent des polices installées.',
|
||
|
||
'message.bookmark': 'Marquer le message',
|
||
'message.removeBookmark': 'Retirer le marque-page',
|
||
'message.reply': 'Répondre',
|
||
'chat.replyingTo': 'En réponse à',
|
||
'chat.bookmarks': 'Marque-pages',
|
||
'chat.export': 'Exporter la conversation',
|
||
'chat.contextCompacted': 'Contexte compacté — anciens messages en cache local',
|
||
'slash.commands': 'Commandes',
|
||
'slash.status': 'Afficher le statut et l\'utilisation',
|
||
'slash.reasoning': 'Activer/désactiver le raisonnement',
|
||
'slash.verbose': 'Activer/désactiver le mode verbeux',
|
||
'slash.model': 'Changer de modèle pour cette session',
|
||
'slash.compact': 'Compacter le contexte',
|
||
'slash.reset': 'Réinitialiser la session',
|
||
'slash.new': 'Créer une nouvelle session de chat',
|
||
'slash.help': 'Afficher les commandes disponibles',
|
||
};
|
||
|
||
const es: Record<keyof typeof en, string> = {
|
||
'login.title': 'PinchChat',
|
||
'login.subtitle': 'Conéctate a tu gateway OpenClaw',
|
||
'login.gatewayUrl': 'URL del gateway',
|
||
'login.token': 'Token',
|
||
'login.tokenPlaceholder': 'Introduce tu token de gateway',
|
||
'login.authToken': 'Token',
|
||
'login.authPassword': 'Contraseña',
|
||
'login.password': 'Contraseña',
|
||
'login.passwordPlaceholder': 'Introduce tu contraseña de gateway',
|
||
'login.connect': 'Conectar',
|
||
'login.connecting': 'Conectando…',
|
||
'login.showToken': 'Mostrar token',
|
||
'login.hideToken': 'Ocultar token',
|
||
'login.storedLocally': 'Las credenciales se guardan localmente en tu navegador',
|
||
'login.wsHint': 'La URL debe empezar con ws:// o wss://',
|
||
'login.advanced': 'Avanzado',
|
||
'login.clientId': 'ID de cliente',
|
||
'login.clientIdHint': 'Enviado en la trama de conexión WebSocket. Por defecto: webchat',
|
||
|
||
'header.title': 'PinchChat',
|
||
'header.connected': 'Conectado',
|
||
'header.disconnected': 'Desconectado',
|
||
'header.logout': 'Cerrar sesión',
|
||
'header.toggleSidebar': 'Mostrar/ocultar barra lateral',
|
||
'header.changeLanguage': 'Cambiar idioma',
|
||
'header.soundOn': 'Activar sonido de notificación',
|
||
'header.soundOff': 'Desactivar sonido de notificación',
|
||
|
||
'chat.welcome': 'PinchChat',
|
||
'chat.welcomeSub': 'Envía un mensaje para comenzar',
|
||
'chat.suggestions': 'Prueba a preguntar...',
|
||
'chat.suggestion1': 'Resume mis últimos correos',
|
||
'chat.suggestion2': '¿Qué tengo en el calendario hoy?',
|
||
'chat.suggestion3': 'Busca en la web las últimas noticias',
|
||
'chat.suggestion4': 'Ayúdame a escribir un script',
|
||
'chat.loadingHistory': 'Cargando mensajes…',
|
||
'chat.inputPlaceholder': 'Escribe un mensaje…',
|
||
'chat.inputLabel': 'Mensaje',
|
||
'chat.attachFile': 'Adjuntar archivo',
|
||
'chat.send': 'Enviar',
|
||
'chat.stop': 'Detener',
|
||
'chat.showPreview': 'Vista previa markdown',
|
||
'chat.hidePreview': 'Ocultar vista previa',
|
||
'chat.scrollToBottom': 'Nuevos mensajes',
|
||
'chat.scrollDown': 'Ir al final',
|
||
'chat.collapseTools': 'Contraer todas las herramientas',
|
||
'chat.expandTools': 'Expandir todas las herramientas',
|
||
'chat.messages': 'Mensajes del chat',
|
||
'chat.thinking': 'Pensando…',
|
||
|
||
'sidebar.title': 'Sesiones',
|
||
'sidebar.empty': 'Sin sesiones',
|
||
'sidebar.search': 'Buscar sesiones…',
|
||
'sidebar.noResults': 'Sin resultados',
|
||
'sidebar.pin': 'Fijar sesión',
|
||
'sidebar.unpin': 'Desfijar sesión',
|
||
'sidebar.pinned': 'Fijadas',
|
||
'sidebar.delete': 'Eliminar sesión',
|
||
'sidebar.rename': 'Renombrar sesión',
|
||
'sidebar.deleteConfirm': '¿Eliminar esta sesión? Esta acción no se puede deshacer.',
|
||
'sidebar.deleteCancel': 'Cancelar',
|
||
'sidebar.openSplit': 'Abrir en vista dividida',
|
||
'sidebar.close': 'Cerrar barra lateral',
|
||
'sidebar.clearSearch': 'Limpiar búsqueda',
|
||
'sidebar.filterAll': 'Todas',
|
||
'sidebar.filterActive': 'Activas',
|
||
'split.close': 'Cerrar vista dividida',
|
||
'app.mainChat': 'Chat principal',
|
||
'app.splitPane': 'Panel dividido',
|
||
'app.skipToChat': 'Ir al campo de entrada',
|
||
|
||
'thinking.label': 'Pensamiento',
|
||
'thinking.reasoning': 'Razonando…',
|
||
|
||
'tool.parameters': 'Parámetros',
|
||
'tool.result': 'Resultado',
|
||
|
||
'connection.reconnecting': 'Conexión perdida — reconectando…',
|
||
'connection.reconnected': '¡Reconectado!',
|
||
'connection.pairing': 'Emparejamiento pendiente — ejecute `openclaw devices approve` en su gateway',
|
||
|
||
'message.copy': 'Copiar mensaje',
|
||
'message.copied': '¡Copiado!',
|
||
'message.retry': 'Reenviar mensaje',
|
||
'message.showMore': 'Ver más',
|
||
'message.showLess': 'Ver menos',
|
||
'message.metadata': 'Detalles del mensaje',
|
||
'message.rawJson': 'JSON sin formato',
|
||
'message.hideRawJson': 'Ocultar JSON sin formato',
|
||
|
||
'time.yesterday': 'Ayer',
|
||
'time.today': 'Hoy',
|
||
|
||
'shortcuts.title': 'Atajos de teclado',
|
||
'shortcuts.send': 'Enviar mensaje',
|
||
'shortcuts.newline': 'Nueva línea',
|
||
'shortcuts.search': 'Buscar sesiones',
|
||
'shortcuts.switchSession': 'Sesión anterior / siguiente',
|
||
'shortcuts.closeSidebar': 'Cerrar barra / búsqueda',
|
||
'shortcuts.stop': 'Detener generación',
|
||
'shortcuts.help': 'Mostrar atajos',
|
||
'shortcuts.close': 'Cerrar',
|
||
'shortcuts.chatSection': 'Chat',
|
||
|
||
'error.title': 'Algo salió mal',
|
||
'error.description': 'Ocurrió un error inesperado al mostrar la interfaz. Puedes intentar de nuevo o recargar la página.',
|
||
'error.retry': 'Reintentar',
|
||
'error.reload': 'Recargar página',
|
||
'shortcuts.navigationSection': 'Navegación',
|
||
'shortcuts.generalSection': 'General',
|
||
|
||
'header.export': 'Exportar conversación como Markdown',
|
||
'header.compact': 'Compactar',
|
||
'header.compacting': 'Compactando…',
|
||
'header.sessionInfo': 'Info de sesión',
|
||
'sessionInfo.sessionKey': 'Clave de sesión',
|
||
'sessionInfo.channel': 'Canal',
|
||
'sessionInfo.kind': 'Tipo',
|
||
'sessionInfo.model': 'Modelo',
|
||
'sessionInfo.agent': 'Agente',
|
||
'sessionInfo.messages': 'Mensajes',
|
||
'sessionInfo.totalTokens': 'Tokens totales',
|
||
'sessionInfo.inputTokens': 'Entrada',
|
||
'sessionInfo.outputTokens': 'Salida',
|
||
'sessionInfo.contextWindow': 'Contexto',
|
||
'sessionInfo.lastActive': 'Última actividad',
|
||
|
||
'theme.title': 'Tema',
|
||
'theme.mode': 'Modo',
|
||
'theme.accent': 'Acento',
|
||
'theme.system': 'Sistema',
|
||
'theme.dark': 'Oscuro',
|
||
'theme.light': 'Claro',
|
||
'theme.oled': 'OLED',
|
||
|
||
'search.placeholder': 'Buscar en mensajes…',
|
||
'search.noResults': '0 resultados',
|
||
'search.prev': 'Resultado anterior',
|
||
'search.next': 'Resultado siguiente',
|
||
'shortcuts.searchMessages': 'Buscar en mensajes',
|
||
|
||
'settings.title': 'Ajustes',
|
||
'settings.appearance': 'Apariencia',
|
||
'settings.typography': 'Tipografía',
|
||
'settings.chat': 'Chat',
|
||
'settings.notifications': 'Notificaciones',
|
||
'settings.notificationSound': 'Sonido de notificación',
|
||
'settings.language': 'Idioma',
|
||
'settings.sendShortcut': 'Enviar con',
|
||
'settings.sendEnter': 'Enter',
|
||
'settings.sendCtrlEnter': 'Ctrl+Enter',
|
||
'settings.tab.appearance': 'Apariencia',
|
||
'settings.tab.typography': 'Tipografía',
|
||
'settings.tab.chat': 'Chat',
|
||
'settings.tab.notifications': 'Notificaciones',
|
||
'settings.fontUi': 'Fuente UI',
|
||
'settings.fontMono': 'Fuente de código',
|
||
'settings.fontSize': 'Tamaño fuente UI',
|
||
'settings.fontMonoSize': 'Tamaño fuente código',
|
||
'settings.preview': 'Vista previa',
|
||
'settings.previewText': 'El veloz zorro marrón salta sobre el perro perezoso — 1234567890',
|
||
'settings.fontNote': 'Inter / JetBrains / Fira se cargan automáticamente; Cascadia y SF dependen de que estén instaladas.',
|
||
|
||
'message.bookmark': 'Marcar mensaje',
|
||
'message.removeBookmark': 'Quitar marcador',
|
||
'message.reply': 'Responder',
|
||
'chat.replyingTo': 'Respondiendo a',
|
||
'chat.bookmarks': 'Marcadores',
|
||
'chat.export': 'Exportar conversación',
|
||
'chat.contextCompacted': 'Contexto compactado — mensajes anteriores en caché local',
|
||
'slash.commands': 'Comandos',
|
||
'slash.status': 'Mostrar estado y uso de la sesión',
|
||
'slash.reasoning': 'Activar/desactivar razonamiento',
|
||
'slash.verbose': 'Activar/desactivar modo detallado',
|
||
'slash.model': 'Cambiar modelo para esta sesión',
|
||
'slash.compact': 'Compactar contexto de conversación',
|
||
'slash.reset': 'Reiniciar la sesión',
|
||
'slash.new': 'Crear una nueva sesión de chat',
|
||
'slash.help': 'Mostrar comandos disponibles',
|
||
};
|
||
|
||
export type TranslationKey = keyof typeof en;
|
||
|
||
const de: Record<keyof typeof en, string> = {
|
||
'login.title': 'PinchChat',
|
||
'login.subtitle': 'Mit deinem OpenClaw-Gateway verbinden',
|
||
'login.gatewayUrl': 'Gateway-URL',
|
||
'login.token': 'Token',
|
||
'login.tokenPlaceholder': 'Gateway-Token eingeben',
|
||
'login.authToken': 'Token',
|
||
'login.authPassword': 'Passwort',
|
||
'login.password': 'Passwort',
|
||
'login.passwordPlaceholder': 'Gateway-Passwort eingeben',
|
||
'login.connect': 'Verbinden',
|
||
'login.connecting': 'Verbinde…',
|
||
'login.showToken': 'Token anzeigen',
|
||
'login.hideToken': 'Token verbergen',
|
||
'login.storedLocally': 'Zugangsdaten werden lokal in deinem Browser gespeichert',
|
||
'login.wsHint': 'URL muss mit ws:// oder wss:// beginnen',
|
||
'login.advanced': 'Erweitert',
|
||
'login.clientId': 'Client-ID',
|
||
'login.clientIdHint': 'Wird im WebSocket-Connect-Frame gesendet. Standard: webchat',
|
||
|
||
'header.title': 'PinchChat',
|
||
'header.connected': 'Verbunden',
|
||
'header.disconnected': 'Getrennt',
|
||
'header.logout': 'Abmelden',
|
||
'header.toggleSidebar': 'Seitenleiste ein-/ausblenden',
|
||
'header.changeLanguage': 'Sprache ändern',
|
||
'header.soundOn': 'Benachrichtigungston aktivieren',
|
||
'header.soundOff': 'Benachrichtigungston deaktivieren',
|
||
|
||
'chat.welcome': 'PinchChat',
|
||
'chat.welcomeSub': 'Sende eine Nachricht, um zu beginnen',
|
||
'chat.suggestions': 'Probiere z.\u00a0B. …',
|
||
'chat.suggestion1': 'Fasse meine letzten E-Mails zusammen',
|
||
'chat.suggestion2': 'Was steht heute in meinem Kalender?',
|
||
'chat.suggestion3': 'Suche im Web nach aktuellen Nachrichten',
|
||
'chat.suggestion4': 'Hilf mir, ein Skript zu schreiben',
|
||
'chat.loadingHistory': 'Nachrichten werden geladen…',
|
||
'chat.inputPlaceholder': 'Nachricht eingeben…',
|
||
'chat.inputLabel': 'Nachricht',
|
||
'chat.attachFile': 'Datei anhängen',
|
||
'chat.send': 'Senden',
|
||
'chat.stop': 'Stoppen',
|
||
'chat.showPreview': 'Markdown-Vorschau',
|
||
'chat.hidePreview': 'Vorschau ausblenden',
|
||
'chat.scrollToBottom': 'Neue Nachrichten',
|
||
'chat.scrollDown': 'Nach unten scrollen',
|
||
'chat.collapseTools': 'Alle Tools einklappen',
|
||
'chat.expandTools': 'Alle Tools ausklappen',
|
||
'chat.messages': 'Chat-Nachrichten',
|
||
'chat.thinking': 'Denkt nach…',
|
||
|
||
'sidebar.title': 'Sitzungen',
|
||
'sidebar.empty': 'Keine Sitzungen',
|
||
'sidebar.search': 'Sitzungen suchen…',
|
||
'sidebar.noResults': 'Keine Treffer',
|
||
'sidebar.pin': 'Sitzung anheften',
|
||
'sidebar.unpin': 'Sitzung lösen',
|
||
'sidebar.pinned': 'Angeheftet',
|
||
'sidebar.delete': 'Sitzung löschen',
|
||
'sidebar.rename': 'Sitzung umbenennen',
|
||
'sidebar.deleteConfirm': 'Diese Sitzung löschen? Dies kann nicht rückgängig gemacht werden.',
|
||
'sidebar.deleteCancel': 'Abbrechen',
|
||
'sidebar.openSplit': 'In geteilter Ansicht öffnen',
|
||
'sidebar.close': 'Seitenleiste schließen',
|
||
'sidebar.clearSearch': 'Suche leeren',
|
||
'sidebar.filterAll': 'Alle',
|
||
'sidebar.filterActive': 'Aktive',
|
||
'split.close': 'Geteilte Ansicht schließen',
|
||
'app.mainChat': 'Haupt-Chat',
|
||
'app.splitPane': 'Geteiltes Fenster',
|
||
'app.skipToChat': 'Zum Eingabefeld springen',
|
||
|
||
'thinking.label': 'Nachdenken',
|
||
'thinking.reasoning': 'Denkt nach…',
|
||
|
||
'tool.parameters': 'Parameter',
|
||
'tool.result': 'Ergebnis',
|
||
|
||
'connection.reconnecting': 'Verbindung verloren — wird wiederhergestellt…',
|
||
'connection.reconnected': 'Wieder verbunden!',
|
||
'connection.pairing': 'Gerätekopplung ausstehend — führen Sie `openclaw devices approve` auf Ihrem Gateway aus',
|
||
|
||
'message.copy': 'Nachricht kopieren',
|
||
'message.copied': 'Kopiert!',
|
||
'message.retry': 'Nachricht erneut senden',
|
||
'message.showMore': 'Mehr anzeigen',
|
||
'message.showLess': 'Weniger anzeigen',
|
||
'message.metadata': 'Nachrichtendetails',
|
||
'message.rawJson': 'Roh-JSON',
|
||
'message.hideRawJson': 'Roh-JSON ausblenden',
|
||
|
||
'time.yesterday': 'Gestern',
|
||
'time.today': 'Heute',
|
||
|
||
'shortcuts.title': 'Tastenkürzel',
|
||
'shortcuts.send': 'Nachricht senden',
|
||
'shortcuts.newline': 'Neue Zeile',
|
||
'shortcuts.search': 'Sitzungen suchen',
|
||
'shortcuts.switchSession': 'Vorherige / nächste Sitzung',
|
||
'shortcuts.closeSidebar': 'Seitenleiste / Suche schließen',
|
||
'shortcuts.stop': 'Generierung stoppen',
|
||
'shortcuts.help': 'Tastenkürzel anzeigen',
|
||
'shortcuts.close': 'Schließen',
|
||
'shortcuts.chatSection': 'Chat',
|
||
|
||
'error.title': 'Etwas ist schiefgelaufen',
|
||
'error.description': 'Beim Rendern der Oberfläche ist ein unerwarteter Fehler aufgetreten. Du kannst es erneut versuchen oder die Seite neu laden.',
|
||
'error.retry': 'Erneut versuchen',
|
||
'error.reload': 'Seite neu laden',
|
||
'shortcuts.navigationSection': 'Navigation',
|
||
'shortcuts.generalSection': 'Allgemein',
|
||
|
||
'header.export': 'Unterhaltung als Markdown exportieren',
|
||
'header.compact': 'Kompaktieren',
|
||
'header.compacting': 'Kompaktiere…',
|
||
'header.sessionInfo': 'Sitzungsinfo',
|
||
'sessionInfo.sessionKey': 'Sitzungsschlüssel',
|
||
'sessionInfo.channel': 'Kanal',
|
||
'sessionInfo.kind': 'Typ',
|
||
'sessionInfo.model': 'Modell',
|
||
'sessionInfo.agent': 'Agent',
|
||
'sessionInfo.messages': 'Nachrichten',
|
||
'sessionInfo.totalTokens': 'Tokens gesamt',
|
||
'sessionInfo.inputTokens': 'Eingabe',
|
||
'sessionInfo.outputTokens': 'Ausgabe',
|
||
'sessionInfo.contextWindow': 'Kontext',
|
||
'sessionInfo.lastActive': 'Letzte Aktivität',
|
||
|
||
'theme.title': 'Design',
|
||
'theme.mode': 'Modus',
|
||
'theme.accent': 'Akzent',
|
||
'theme.system': 'System',
|
||
'theme.dark': 'Dunkel',
|
||
'theme.light': 'Hell',
|
||
'theme.oled': 'OLED',
|
||
|
||
'search.placeholder': 'In Nachrichten suchen…',
|
||
'search.noResults': '0 Ergebnisse',
|
||
'search.prev': 'Vorheriger Treffer',
|
||
'search.next': 'Nächster Treffer',
|
||
'shortcuts.searchMessages': 'In Nachrichten suchen',
|
||
|
||
'settings.title': 'Einstellungen',
|
||
'settings.appearance': 'Darstellung',
|
||
'settings.typography': 'Typografie',
|
||
'settings.chat': 'Chat',
|
||
'settings.notifications': 'Benachrichtigungen',
|
||
'settings.notificationSound': 'Benachrichtigungston',
|
||
'settings.language': 'Sprache',
|
||
'settings.sendShortcut': 'Senden mit',
|
||
'settings.sendEnter': 'Enter',
|
||
'settings.sendCtrlEnter': 'Strg+Enter',
|
||
'settings.tab.appearance': 'Darstellung',
|
||
'settings.tab.typography': 'Typografie',
|
||
'settings.tab.chat': 'Chat',
|
||
'settings.tab.notifications': 'Benachrichtigungen',
|
||
'settings.fontUi': 'UI-Schriftart',
|
||
'settings.fontMono': 'Code-Schriftart',
|
||
'settings.fontSize': 'UI-Schriftgröße',
|
||
'settings.fontMonoSize': 'Code-Schriftgröße',
|
||
'settings.preview': 'Vorschau',
|
||
'settings.previewText': 'Falsches Üben von Xylophonmusik quält jeden größeren Zwerg — 1234567890',
|
||
'settings.fontNote': 'Inter / JetBrains / Fira werden automatisch geladen; Cascadia und SF erfordern Systeminstallation.',
|
||
|
||
'message.bookmark': 'Nachricht markieren',
|
||
'message.reply': 'Antworten',
|
||
'chat.replyingTo': 'Antwort auf',
|
||
'message.removeBookmark': 'Lesezeichen entfernen',
|
||
'chat.bookmarks': 'Lesezeichen',
|
||
'chat.export': 'Unterhaltung exportieren',
|
||
'chat.contextCompacted': 'Kontext kompaktiert — ältere Nachrichten lokal zwischengespeichert',
|
||
'slash.commands': 'Befehle',
|
||
'slash.status': 'Sitzungsstatus und Nutzung anzeigen',
|
||
'slash.reasoning': 'Reasoning-Modus umschalten',
|
||
'slash.verbose': 'Ausführliche Ausgabe umschalten',
|
||
'slash.model': 'Modell für diese Sitzung wechseln',
|
||
'slash.compact': 'Gesprächskontext kompaktieren',
|
||
'slash.reset': 'Sitzung zurücksetzen',
|
||
'slash.new': 'Neue Chat-Sitzung erstellen',
|
||
'slash.help': 'Verfügbare Befehle anzeigen',
|
||
};
|
||
|
||
const ja: Record<keyof typeof en, string> = {
|
||
'login.title': 'PinchChat',
|
||
'login.subtitle': 'OpenClawゲートウェイに接続',
|
||
'login.gatewayUrl': 'ゲートウェイURL',
|
||
'login.token': 'トークン',
|
||
'login.tokenPlaceholder': 'ゲートウェイトークンを入力',
|
||
'login.authToken': 'トークン',
|
||
'login.authPassword': 'パスワード',
|
||
'login.password': 'パスワード',
|
||
'login.passwordPlaceholder': 'ゲートウェイパスワードを入力',
|
||
'login.connect': '接続',
|
||
'login.connecting': '接続中…',
|
||
'login.showToken': 'トークンを表示',
|
||
'login.hideToken': 'トークンを非表示',
|
||
'login.storedLocally': '認証情報はブラウザにローカル保存されます',
|
||
'login.wsHint': 'URLはws://またはwss://で始まる必要があります',
|
||
'login.advanced': '詳細設定',
|
||
'login.clientId': 'クライアントID',
|
||
'login.clientIdHint': 'WebSocket接続フレームで送信されます。デフォルト: webchat',
|
||
|
||
'header.title': 'PinchChat',
|
||
'header.connected': '接続済み',
|
||
'header.disconnected': '切断',
|
||
'header.logout': 'ログアウト',
|
||
'header.toggleSidebar': 'サイドバーの表示切替',
|
||
'header.changeLanguage': '言語を変更',
|
||
'header.soundOn': '通知音を有効にする',
|
||
'header.soundOff': '通知音を無効にする',
|
||
|
||
'chat.welcome': 'PinchChat',
|
||
'chat.welcomeSub': 'メッセージを送信して始めましょう',
|
||
'chat.suggestions': '例えば…',
|
||
'chat.suggestion1': '最近のメールをまとめて',
|
||
'chat.suggestion2': '今日のカレンダーは?',
|
||
'chat.suggestion3': '最新ニュースをウェブで検索して',
|
||
'chat.suggestion4': 'スクリプトを書くのを手伝って',
|
||
'chat.loadingHistory': 'メッセージを読み込み中…',
|
||
'chat.inputPlaceholder': 'メッセージを入力…',
|
||
'chat.inputLabel': 'メッセージ',
|
||
'chat.attachFile': 'ファイルを添付',
|
||
'chat.send': '送信',
|
||
'chat.stop': '停止',
|
||
'chat.showPreview': 'Markdownプレビュー',
|
||
'chat.hidePreview': 'プレビューを非表示',
|
||
'chat.scrollToBottom': '新しいメッセージ',
|
||
'chat.scrollDown': '一番下へスクロール',
|
||
'chat.collapseTools': 'すべてのツールを折りたたむ',
|
||
'chat.expandTools': 'すべてのツールを展開',
|
||
'chat.messages': 'チャットメッセージ',
|
||
'chat.thinking': '思考中…',
|
||
|
||
'sidebar.title': 'セッション',
|
||
'sidebar.empty': 'セッションなし',
|
||
'sidebar.search': 'セッションを検索…',
|
||
'sidebar.noResults': '結果なし',
|
||
'sidebar.pin': 'セッションをピン留め',
|
||
'sidebar.unpin': 'ピン留めを解除',
|
||
'sidebar.pinned': 'ピン留め',
|
||
'sidebar.delete': 'セッションを削除',
|
||
'sidebar.rename': 'セッション名変更',
|
||
'sidebar.deleteConfirm': 'このセッションを削除しますか?元に戻せません。',
|
||
'sidebar.deleteCancel': 'キャンセル',
|
||
'sidebar.openSplit': '分割ビューで開く',
|
||
'sidebar.close': 'サイドバーを閉じる',
|
||
'sidebar.clearSearch': '検索をクリア',
|
||
'sidebar.filterAll': 'すべて',
|
||
'sidebar.filterActive': 'アクティブ',
|
||
'split.close': '分割ビューを閉じる',
|
||
'app.mainChat': 'メインチャット',
|
||
'app.splitPane': '分割ペイン',
|
||
'app.skipToChat': '入力欄へ移動',
|
||
|
||
'thinking.label': '思考',
|
||
'thinking.reasoning': '推論中…',
|
||
|
||
'tool.parameters': 'パラメータ',
|
||
'tool.result': '結果',
|
||
|
||
'connection.reconnecting': '接続が切断されました — 再接続中…',
|
||
'connection.reconnected': '再接続しました!',
|
||
'connection.pairing': 'デバイスペアリング保留中 — ゲートウェイで `openclaw devices approve` を実行してください',
|
||
|
||
'message.copy': 'メッセージをコピー',
|
||
'message.copied': 'コピーしました!',
|
||
'message.retry': 'メッセージを再送信',
|
||
'message.showMore': 'もっと見る',
|
||
'message.showLess': '折りたたむ',
|
||
'message.metadata': 'メッセージの詳細',
|
||
'message.rawJson': '生JSON',
|
||
'message.hideRawJson': '生JSONを非表示',
|
||
|
||
'time.yesterday': '昨日',
|
||
'time.today': '今日',
|
||
|
||
'shortcuts.title': 'キーボードショートカット',
|
||
'shortcuts.send': 'メッセージを送信',
|
||
'shortcuts.newline': '改行',
|
||
'shortcuts.search': 'セッションを検索',
|
||
'shortcuts.switchSession': '前 / 次のセッション',
|
||
'shortcuts.closeSidebar': 'サイドバー / 検索を閉じる',
|
||
'shortcuts.stop': '生成を停止',
|
||
'shortcuts.help': 'ショートカットを表示',
|
||
'shortcuts.close': '閉じる',
|
||
'shortcuts.chatSection': 'チャット',
|
||
|
||
'error.title': 'エラーが発生しました',
|
||
'error.description': 'インターフェースの表示中に予期しないエラーが発生しました。再試行するかページをリロードしてください。',
|
||
'error.retry': '再試行',
|
||
'error.reload': 'ページをリロード',
|
||
'shortcuts.navigationSection': 'ナビゲーション',
|
||
'shortcuts.generalSection': '全般',
|
||
|
||
'header.export': '会話をMarkdownでエクスポート',
|
||
'header.compact': 'コンパクト化',
|
||
'header.compacting': 'コンパクト化中…',
|
||
'header.sessionInfo': 'セッション情報',
|
||
'sessionInfo.sessionKey': 'セッションキー',
|
||
'sessionInfo.channel': 'チャンネル',
|
||
'sessionInfo.kind': '種類',
|
||
'sessionInfo.model': 'モデル',
|
||
'sessionInfo.agent': 'エージェント',
|
||
'sessionInfo.messages': 'メッセージ',
|
||
'sessionInfo.totalTokens': '合計トークン',
|
||
'sessionInfo.inputTokens': '入力',
|
||
'sessionInfo.outputTokens': '出力',
|
||
'sessionInfo.contextWindow': 'コンテキスト',
|
||
'sessionInfo.lastActive': '最終アクティブ',
|
||
|
||
'theme.title': 'テーマ',
|
||
'theme.mode': 'モード',
|
||
'theme.accent': 'アクセント',
|
||
'theme.system': 'システム',
|
||
'theme.dark': 'ダーク',
|
||
'theme.light': 'ライト',
|
||
'theme.oled': 'OLED',
|
||
|
||
'search.placeholder': 'メッセージを検索…',
|
||
'search.noResults': '0件',
|
||
'search.prev': '前の結果',
|
||
'search.next': '次の結果',
|
||
'shortcuts.searchMessages': 'メッセージを検索',
|
||
|
||
'settings.title': '設定',
|
||
'settings.appearance': '外観',
|
||
'settings.typography': 'タイポグラフィ',
|
||
'settings.chat': 'チャット',
|
||
'settings.notifications': '通知',
|
||
'settings.notificationSound': '通知音',
|
||
'settings.language': '言語',
|
||
'settings.sendShortcut': '送信キー',
|
||
'settings.sendEnter': 'Enter',
|
||
'settings.sendCtrlEnter': 'Ctrl+Enter',
|
||
'settings.tab.appearance': '外観',
|
||
'settings.tab.typography': 'タイポグラフィ',
|
||
'settings.tab.chat': 'チャット',
|
||
'settings.tab.notifications': '通知',
|
||
'settings.fontUi': 'UIフォント',
|
||
'settings.fontMono': 'コードフォント',
|
||
'settings.fontSize': 'UIフォントサイズ',
|
||
'settings.fontMonoSize': 'コードフォントサイズ',
|
||
'settings.preview': 'プレビュー',
|
||
'settings.previewText': '素早い茶色の狐はのんびり犬を飛び越える — 1234567890',
|
||
'settings.fontNote': 'Inter / JetBrains / Fira は自動読み込み。Cascadia と SF はシステムにある場合のみ使用。',
|
||
|
||
'message.bookmark': 'メッセージをブックマーク',
|
||
'message.reply': '返信',
|
||
'chat.replyingTo': '返信先',
|
||
'message.removeBookmark': 'ブックマークを削除',
|
||
'chat.bookmarks': 'ブックマーク',
|
||
'chat.export': '会話をエクスポート',
|
||
'chat.contextCompacted': 'コンテキストがコンパクト化されました — 古いメッセージはローカルキャッシュに保存',
|
||
'slash.commands': 'コマンド',
|
||
'slash.status': 'セッションのステータスと使用量を表示',
|
||
'slash.reasoning': '推論モードの切替',
|
||
'slash.verbose': '詳細出力の切替',
|
||
'slash.model': 'このセッションのモデルを変更',
|
||
'slash.compact': '会話コンテキストをコンパクト化',
|
||
'slash.reset': 'セッションをリセット',
|
||
'slash.new': '新しいチャットセッションを作成',
|
||
'slash.help': '利用可能なコマンドを表示',
|
||
};
|
||
|
||
const pt: Record<keyof typeof en, string> = {
|
||
'login.title': 'PinchChat',
|
||
'login.subtitle': 'Conectar ao seu gateway OpenClaw',
|
||
'login.gatewayUrl': 'URL do Gateway',
|
||
'login.token': 'Token',
|
||
'login.tokenPlaceholder': 'Insira o token do gateway',
|
||
'login.authToken': 'Token',
|
||
'login.authPassword': 'Senha',
|
||
'login.password': 'Senha',
|
||
'login.passwordPlaceholder': 'Insira a senha do gateway',
|
||
'login.connect': 'Conectar',
|
||
'login.connecting': 'Conectando…',
|
||
'login.showToken': 'Mostrar token',
|
||
'login.hideToken': 'Ocultar token',
|
||
'login.storedLocally': 'As credenciais são armazenadas localmente no navegador',
|
||
'login.wsHint': 'A URL deve começar com ws:// ou wss://',
|
||
'login.advanced': 'Avançado',
|
||
'login.clientId': 'ID do cliente',
|
||
'login.clientIdHint': 'Enviado no frame de conexão WebSocket. Padrão: webchat',
|
||
|
||
'header.title': 'PinchChat',
|
||
'header.connected': 'Conectado',
|
||
'header.disconnected': 'Desconectado',
|
||
'header.logout': 'Sair',
|
||
'header.toggleSidebar': 'Alternar barra lateral',
|
||
'header.changeLanguage': 'Alterar idioma',
|
||
'header.soundOn': 'Ativar som de notificação',
|
||
'header.soundOff': 'Desativar som de notificação',
|
||
|
||
'chat.welcome': 'PinchChat',
|
||
'chat.welcomeSub': 'Envie uma mensagem para começar',
|
||
'chat.suggestions': 'Tente perguntar…',
|
||
'chat.suggestion1': 'Resuma meus e-mails recentes',
|
||
'chat.suggestion2': 'O que há na minha agenda hoje?',
|
||
'chat.suggestion3': 'Pesquise na web as últimas notícias',
|
||
'chat.suggestion4': 'Ajude-me a escrever um script',
|
||
'chat.loadingHistory': 'Carregando mensagens…',
|
||
'chat.inputPlaceholder': 'Digite uma mensagem…',
|
||
'chat.inputLabel': 'Mensagem',
|
||
'chat.attachFile': 'Anexar arquivo',
|
||
'chat.send': 'Enviar',
|
||
'chat.stop': 'Parar',
|
||
'chat.showPreview': 'Pré-visualizar markdown',
|
||
'chat.hidePreview': 'Ocultar pré-visualização',
|
||
'chat.scrollToBottom': 'Novas mensagens',
|
||
'chat.scrollDown': 'Rolar para baixo',
|
||
'chat.collapseTools': 'Recolher todas as ferramentas',
|
||
'chat.expandTools': 'Expandir todas as ferramentas',
|
||
'chat.messages': 'Mensagens do chat',
|
||
'chat.thinking': 'Pensando…',
|
||
|
||
'sidebar.title': 'Sessões',
|
||
'sidebar.empty': 'Nenhuma sessão',
|
||
'sidebar.search': 'Pesquisar sessões…',
|
||
'sidebar.noResults': 'Nenhuma sessão encontrada',
|
||
'sidebar.pin': 'Fixar sessão',
|
||
'sidebar.unpin': 'Desafixar sessão',
|
||
'sidebar.pinned': 'Fixada',
|
||
'sidebar.delete': 'Excluir sessão',
|
||
'sidebar.rename': 'Renomear sessão',
|
||
'sidebar.deleteConfirm': 'Excluir esta sessão? Esta ação não pode ser desfeita.',
|
||
'sidebar.deleteCancel': 'Cancelar',
|
||
'sidebar.openSplit': 'Abrir em visualização dividida',
|
||
'sidebar.close': 'Fechar barra lateral',
|
||
'sidebar.clearSearch': 'Limpar pesquisa',
|
||
'sidebar.filterAll': 'Todas',
|
||
'sidebar.filterActive': 'Ativas',
|
||
'split.close': 'Fechar visualização dividida',
|
||
'app.mainChat': 'Chat principal',
|
||
'app.splitPane': 'Painel dividido',
|
||
'app.skipToChat': 'Ir para o campo de entrada',
|
||
|
||
'thinking.label': 'Pensamento',
|
||
'thinking.reasoning': 'Raciocinando…',
|
||
|
||
'tool.parameters': 'Parâmetros',
|
||
'tool.result': 'Resultado',
|
||
|
||
'connection.reconnecting': 'Conexão perdida — reconectando…',
|
||
'connection.reconnected': 'Reconectado!',
|
||
'connection.pairing': 'Emparelhamento pendente — execute `openclaw devices approve` no seu gateway',
|
||
|
||
'message.copy': 'Copiar mensagem',
|
||
'message.copied': 'Copiado!',
|
||
'message.retry': 'Reenviar mensagem',
|
||
'message.showMore': 'Ver mais',
|
||
'message.showLess': 'Ver menos',
|
||
'message.metadata': 'Detalhes da mensagem',
|
||
'message.rawJson': 'JSON bruto',
|
||
'message.hideRawJson': 'Ocultar JSON bruto',
|
||
|
||
'time.yesterday': 'Ontem',
|
||
'time.today': 'Hoje',
|
||
|
||
'shortcuts.title': 'Atalhos de teclado',
|
||
'shortcuts.send': 'Enviar mensagem',
|
||
'shortcuts.newline': 'Nova linha',
|
||
'shortcuts.search': 'Pesquisar sessões',
|
||
'shortcuts.switchSession': 'Sessão anterior / próxima',
|
||
'shortcuts.closeSidebar': 'Fechar barra lateral / pesquisa',
|
||
'shortcuts.stop': 'Parar geração',
|
||
'shortcuts.help': 'Mostrar atalhos',
|
||
'shortcuts.close': 'Fechar',
|
||
'shortcuts.chatSection': 'Chat',
|
||
|
||
'error.title': 'Algo deu errado',
|
||
'error.description': 'Ocorreu um erro inesperado ao renderizar a interface. Tente novamente ou recarregue a página.',
|
||
'error.retry': 'Tentar novamente',
|
||
'error.reload': 'Recarregar página',
|
||
'shortcuts.navigationSection': 'Navegação',
|
||
'shortcuts.generalSection': 'Geral',
|
||
|
||
'header.export': 'Exportar conversa em Markdown',
|
||
'header.compact': 'Compactar',
|
||
'header.compacting': 'Compactando…',
|
||
'header.sessionInfo': 'Informações da sessão',
|
||
'sessionInfo.sessionKey': 'Chave da sessão',
|
||
'sessionInfo.channel': 'Canal',
|
||
'sessionInfo.kind': 'Tipo',
|
||
'sessionInfo.model': 'Modelo',
|
||
'sessionInfo.agent': 'Agente',
|
||
'sessionInfo.messages': 'Mensagens',
|
||
'sessionInfo.totalTokens': 'Total de tokens',
|
||
'sessionInfo.inputTokens': 'Entrada',
|
||
'sessionInfo.outputTokens': 'Saída',
|
||
'sessionInfo.contextWindow': 'Contexto',
|
||
'sessionInfo.lastActive': 'Última atividade',
|
||
|
||
'theme.title': 'Tema',
|
||
'theme.mode': 'Modo',
|
||
'theme.accent': 'Cor de destaque',
|
||
'theme.system': 'Sistema',
|
||
'theme.dark': 'Escuro',
|
||
'theme.light': 'Claro',
|
||
'theme.oled': 'OLED',
|
||
|
||
'search.placeholder': 'Pesquisar mensagens…',
|
||
'search.noResults': '0 resultados',
|
||
'search.prev': 'Resultado anterior',
|
||
'search.next': 'Próximo resultado',
|
||
'shortcuts.searchMessages': 'Pesquisar mensagens',
|
||
|
||
'settings.title': 'Configurações',
|
||
'settings.appearance': 'Aparência',
|
||
'settings.typography': 'Tipografia',
|
||
'settings.chat': 'Chat',
|
||
'settings.notifications': 'Notificações',
|
||
'settings.notificationSound': 'Som de notificação',
|
||
'settings.language': 'Idioma',
|
||
'settings.sendShortcut': 'Tecla de envio',
|
||
'settings.sendEnter': 'Enter',
|
||
'settings.sendCtrlEnter': 'Ctrl+Enter',
|
||
'settings.tab.appearance': 'Aparência',
|
||
'settings.tab.typography': 'Tipografia',
|
||
'settings.tab.chat': 'Chat',
|
||
'settings.tab.notifications': 'Notificações',
|
||
'settings.fontUi': 'Fonte da UI',
|
||
'settings.fontMono': 'Fonte de código',
|
||
'settings.fontSize': 'Tamanho da fonte UI',
|
||
'settings.fontMonoSize': 'Tamanho da fonte de código',
|
||
'settings.preview': 'Pré-visualização',
|
||
'settings.previewText': 'A rápida raposa marrom pula sobre o cão preguiçoso — 1234567890',
|
||
'settings.fontNote': 'Inter / JetBrains / Fira carregam automaticamente; Cascadia e SF dependem de estarem instaladas.',
|
||
|
||
'message.bookmark': 'Marcar mensagem',
|
||
'message.reply': 'Responder',
|
||
'chat.replyingTo': 'Respondendo a',
|
||
'message.removeBookmark': 'Remover marcador',
|
||
'chat.bookmarks': 'Marcadores',
|
||
'chat.export': 'Exportar conversa',
|
||
'chat.contextCompacted': 'Contexto compactado — mensagens antigas salvas no cache local',
|
||
'slash.commands': 'Comandos',
|
||
'slash.status': 'Mostrar status e uso da sessão',
|
||
'slash.reasoning': 'Alternar modo de raciocínio',
|
||
'slash.verbose': 'Alternar saída detalhada',
|
||
'slash.model': 'Alterar modelo desta sessão',
|
||
'slash.compact': 'Compactar contexto da conversa',
|
||
'slash.reset': 'Redefinir sessão',
|
||
'slash.new': 'Criar uma nova sessão de chat',
|
||
'slash.help': 'Mostrar comandos disponíveis',
|
||
};
|
||
|
||
const zh: Record<keyof typeof en, string> = {
|
||
'login.title': 'PinchChat',
|
||
'login.subtitle': '连接到您的 OpenClaw 网关',
|
||
'login.gatewayUrl': '网关地址',
|
||
'login.token': '令牌',
|
||
'login.tokenPlaceholder': '输入网关令牌',
|
||
'login.authToken': '令牌',
|
||
'login.authPassword': '密码',
|
||
'login.password': '密码',
|
||
'login.passwordPlaceholder': '输入网关密码',
|
||
'login.connect': '连接',
|
||
'login.connecting': '连接中…',
|
||
'login.showToken': '显示令牌',
|
||
'login.hideToken': '隐藏令牌',
|
||
'login.storedLocally': '凭据仅存储在浏览器本地',
|
||
'login.wsHint': '地址必须以 ws:// 或 wss:// 开头',
|
||
'login.advanced': '高级',
|
||
'login.clientId': '客户端 ID',
|
||
'login.clientIdHint': '在 WebSocket 连接帧中发送。默认值:webchat',
|
||
|
||
'header.title': 'PinchChat',
|
||
'header.connected': '已连接',
|
||
'header.disconnected': '未连接',
|
||
'header.logout': '退出',
|
||
'header.toggleSidebar': '切换侧边栏',
|
||
'header.changeLanguage': '切换语言',
|
||
'header.soundOn': '开启通知音',
|
||
'header.soundOff': '关闭通知音',
|
||
|
||
'chat.welcome': 'PinchChat',
|
||
'chat.welcomeSub': '发送消息开始对话',
|
||
'chat.suggestions': '试试问…',
|
||
'chat.suggestion1': '总结我最近的邮件',
|
||
'chat.suggestion2': '今天的日程安排是什么?',
|
||
'chat.suggestion3': '搜索最新新闻',
|
||
'chat.suggestion4': '帮我写一个脚本',
|
||
'chat.loadingHistory': '加载消息中…',
|
||
'chat.inputPlaceholder': '输入消息…',
|
||
'chat.inputLabel': '消息',
|
||
'chat.attachFile': '添加附件',
|
||
'chat.send': '发送',
|
||
'chat.stop': '停止',
|
||
'chat.showPreview': '预览 Markdown',
|
||
'chat.hidePreview': '隐藏预览',
|
||
'chat.scrollToBottom': '新消息',
|
||
'chat.scrollDown': '滚动到底部',
|
||
'chat.collapseTools': '折叠所有工具',
|
||
'chat.expandTools': '展开所有工具',
|
||
'chat.messages': '聊天消息',
|
||
'chat.thinking': '思考中…',
|
||
|
||
'sidebar.title': '会话',
|
||
'sidebar.empty': '没有会话',
|
||
'sidebar.search': '搜索会话…',
|
||
'sidebar.noResults': '未找到匹配会话',
|
||
'sidebar.pin': '置顶会话',
|
||
'sidebar.unpin': '取消置顶',
|
||
'sidebar.pinned': '已置顶',
|
||
'sidebar.delete': '删除会话',
|
||
'sidebar.rename': '重命名会话',
|
||
'sidebar.deleteConfirm': '删除此会话?此操作无法撤消。',
|
||
'sidebar.deleteCancel': '取消',
|
||
'sidebar.openSplit': '在分屏中打开',
|
||
'sidebar.close': '关闭侧边栏',
|
||
'sidebar.clearSearch': '清除搜索',
|
||
'sidebar.filterAll': '全部',
|
||
'sidebar.filterActive': '活跃',
|
||
'split.close': '关闭分屏',
|
||
'app.mainChat': '主聊天',
|
||
'app.splitPane': '分屏面板',
|
||
'app.skipToChat': '跳转到输入框',
|
||
|
||
'thinking.label': '思考',
|
||
'thinking.reasoning': '推理中…',
|
||
|
||
'tool.parameters': '参数',
|
||
'tool.result': '结果',
|
||
|
||
'connection.reconnecting': '连接中断 — 正在重连…',
|
||
'connection.reconnected': '已重新连接!',
|
||
'connection.pairing': '设备配对待处理 — 在网关上运行 `openclaw devices approve`',
|
||
|
||
'message.copy': '复制消息',
|
||
'message.copied': '已复制!',
|
||
'message.retry': '重新发送',
|
||
'message.showMore': '展开更多',
|
||
'message.showLess': '收起',
|
||
'message.metadata': '消息详情',
|
||
'message.rawJson': '原始 JSON',
|
||
'message.hideRawJson': '隐藏原始 JSON',
|
||
|
||
'time.yesterday': '昨天',
|
||
'time.today': '今天',
|
||
|
||
'shortcuts.title': '键盘快捷键',
|
||
'shortcuts.send': '发送消息',
|
||
'shortcuts.newline': '换行',
|
||
'shortcuts.search': '搜索会话',
|
||
'shortcuts.switchSession': '上一个 / 下一个会话',
|
||
'shortcuts.closeSidebar': '关闭侧边栏 / 搜索',
|
||
'shortcuts.stop': '停止生成',
|
||
'shortcuts.help': '显示快捷键',
|
||
'shortcuts.close': '关闭',
|
||
'shortcuts.chatSection': '聊天',
|
||
|
||
'error.title': '出错了',
|
||
'error.description': '渲染界面时发生意外错误。您可以重试或刷新页面。',
|
||
'error.retry': '重试',
|
||
'error.reload': '刷新页面',
|
||
'shortcuts.navigationSection': '导航',
|
||
'shortcuts.generalSection': '通用',
|
||
|
||
'header.export': '导出会话为 Markdown',
|
||
'header.compact': '压缩',
|
||
'header.compacting': '压缩中…',
|
||
'header.sessionInfo': '会话信息',
|
||
'sessionInfo.sessionKey': '会话密钥',
|
||
'sessionInfo.channel': '频道',
|
||
'sessionInfo.kind': '类型',
|
||
'sessionInfo.model': '模型',
|
||
'sessionInfo.agent': '智能体',
|
||
'sessionInfo.messages': '消息数',
|
||
'sessionInfo.totalTokens': '总令牌数',
|
||
'sessionInfo.inputTokens': '输入',
|
||
'sessionInfo.outputTokens': '输出',
|
||
'sessionInfo.contextWindow': '上下文',
|
||
'sessionInfo.lastActive': '最后活跃',
|
||
|
||
'theme.title': '主题',
|
||
'theme.mode': '模式',
|
||
'theme.accent': '强调色',
|
||
'theme.system': '跟随系统',
|
||
'theme.dark': '深色',
|
||
'theme.light': '浅色',
|
||
'theme.oled': 'OLED',
|
||
|
||
'search.placeholder': '搜索消息…',
|
||
'search.noResults': '无结果',
|
||
'search.prev': '上一个',
|
||
'search.next': '下一个',
|
||
'shortcuts.searchMessages': '搜索消息',
|
||
|
||
'settings.title': '设置',
|
||
'settings.appearance': '外观',
|
||
'settings.typography': '排版',
|
||
'settings.chat': '聊天',
|
||
'settings.notifications': '通知',
|
||
'settings.notificationSound': '通知声音',
|
||
'settings.language': '语言',
|
||
'settings.sendShortcut': '发送方式',
|
||
'settings.sendEnter': 'Enter',
|
||
'settings.sendCtrlEnter': 'Ctrl+Enter',
|
||
'settings.tab.appearance': '外观',
|
||
'settings.tab.typography': '排版',
|
||
'settings.tab.chat': '聊天',
|
||
'settings.tab.notifications': '通知',
|
||
'settings.fontUi': '界面字体',
|
||
'settings.fontMono': '代码字体',
|
||
'settings.fontSize': '界面字号',
|
||
'settings.fontMonoSize': '代码字号',
|
||
'settings.preview': '预览',
|
||
'settings.previewText': '敏捷的棕狐跳过懒狗 — 1234567890',
|
||
'settings.fontNote': 'Inter / JetBrains / Fira 自动加载;Cascadia 和 SF 依赖系统已安装字体。',
|
||
|
||
'message.bookmark': '收藏消息',
|
||
'message.reply': '回复',
|
||
'chat.replyingTo': '回复',
|
||
'message.removeBookmark': '取消收藏',
|
||
'chat.bookmarks': '收藏',
|
||
'chat.export': '导出会话',
|
||
'chat.contextCompacted': '上下文已压缩 — 旧消息已缓存到本地',
|
||
'slash.commands': '命令',
|
||
'slash.status': '显示会话状态和用量',
|
||
'slash.reasoning': '切换推理模式',
|
||
'slash.verbose': '切换详细输出',
|
||
'slash.model': '切换当前会话模型',
|
||
'slash.compact': '压缩会话上下文',
|
||
'slash.reset': '重置会话',
|
||
'slash.new': '创建新的聊天会话',
|
||
'slash.help': '显示可用命令',
|
||
};
|
||
|
||
const it: Record<keyof typeof en, string> = {
|
||
'login.title': 'PinchChat',
|
||
'login.subtitle': 'Connettiti al tuo gateway OpenClaw',
|
||
'login.gatewayUrl': 'URL del Gateway',
|
||
'login.token': 'Token',
|
||
'login.tokenPlaceholder': 'Inserisci il token del gateway',
|
||
'login.authToken': 'Token',
|
||
'login.authPassword': 'Password',
|
||
'login.password': 'Password',
|
||
'login.passwordPlaceholder': 'Inserisci la password del gateway',
|
||
'login.connect': 'Connetti',
|
||
'login.connecting': 'Connessione…',
|
||
'login.showToken': 'Mostra token',
|
||
'login.hideToken': 'Nascondi token',
|
||
'login.storedLocally': 'Le credenziali vengono salvate localmente nel browser',
|
||
'login.wsHint': 'L\'URL deve iniziare con ws:// o wss://',
|
||
'login.advanced': 'Avanzate',
|
||
'login.clientId': 'ID client',
|
||
'login.clientIdHint': 'Inviato nel frame di connessione WebSocket. Predefinito: webchat',
|
||
|
||
'header.title': 'PinchChat',
|
||
'header.connected': 'Connesso',
|
||
'header.disconnected': 'Disconnesso',
|
||
'header.logout': 'Esci',
|
||
'header.toggleSidebar': 'Mostra/nascondi barra laterale',
|
||
'header.changeLanguage': 'Cambia lingua',
|
||
'header.soundOn': 'Attiva suono notifiche',
|
||
'header.soundOff': 'Disattiva suono notifiche',
|
||
|
||
'chat.welcome': 'PinchChat',
|
||
'chat.welcomeSub': 'Invia un messaggio per iniziare',
|
||
'chat.suggestions': 'Prova a chiedere…',
|
||
'chat.suggestion1': 'Riassumi le mie ultime email',
|
||
'chat.suggestion2': 'Cosa c\'è nel mio calendario oggi?',
|
||
'chat.suggestion3': 'Cerca sul web le ultime notizie',
|
||
'chat.suggestion4': 'Aiutami a scrivere uno script',
|
||
'chat.loadingHistory': 'Caricamento messaggi…',
|
||
'chat.inputPlaceholder': 'Scrivi un messaggio…',
|
||
'chat.inputLabel': 'Messaggio',
|
||
'chat.attachFile': 'Allega file',
|
||
'chat.send': 'Invia',
|
||
'chat.stop': 'Ferma',
|
||
'chat.showPreview': 'Anteprima markdown',
|
||
'chat.hidePreview': 'Nascondi anteprima',
|
||
'chat.scrollToBottom': 'Nuovi messaggi',
|
||
'chat.scrollDown': 'Scorri in fondo',
|
||
'chat.collapseTools': 'Comprimi tutti gli strumenti',
|
||
'chat.expandTools': 'Espandi tutti gli strumenti',
|
||
'chat.messages': 'Messaggi della chat',
|
||
'chat.thinking': 'Sto pensando…',
|
||
|
||
'sidebar.title': 'Sessioni',
|
||
'sidebar.empty': 'Nessuna sessione',
|
||
'sidebar.search': 'Cerca sessioni…',
|
||
'sidebar.noResults': 'Nessun risultato',
|
||
'sidebar.pin': 'Fissa sessione',
|
||
'sidebar.unpin': 'Sgancia sessione',
|
||
'sidebar.pinned': 'Fissate',
|
||
'sidebar.delete': 'Elimina sessione',
|
||
'sidebar.rename': 'Rinomina sessione',
|
||
'sidebar.deleteConfirm': 'Eliminare questa sessione? L\'azione è irreversibile.',
|
||
'sidebar.deleteCancel': 'Annulla',
|
||
'sidebar.openSplit': 'Apri in vista divisa',
|
||
'sidebar.close': 'Chiudi barra laterale',
|
||
'sidebar.clearSearch': 'Cancella ricerca',
|
||
'sidebar.filterAll': 'Tutte',
|
||
'sidebar.filterActive': 'Attive',
|
||
'split.close': 'Chiudi vista divisa',
|
||
'app.mainChat': 'Chat principale',
|
||
'app.splitPane': 'Pannello diviso',
|
||
'app.skipToChat': 'Vai al campo di input',
|
||
|
||
'thinking.label': 'Pensiero',
|
||
'thinking.reasoning': 'Ragionamento…',
|
||
|
||
'tool.parameters': 'Parametri',
|
||
'tool.result': 'Risultato',
|
||
|
||
'connection.reconnecting': 'Connessione persa — riconnessione…',
|
||
'connection.reconnected': 'Riconnesso!',
|
||
'connection.pairing': 'Accoppiamento dispositivo in attesa — esegui `openclaw devices approve` sul tuo gateway',
|
||
|
||
'message.copy': 'Copia messaggio',
|
||
'message.copied': 'Copiato!',
|
||
'message.retry': 'Reinvia messaggio',
|
||
'message.showMore': 'Mostra di più',
|
||
'message.showLess': 'Mostra meno',
|
||
'message.metadata': 'Dettagli messaggio',
|
||
'message.rawJson': 'JSON grezzo',
|
||
'message.hideRawJson': 'Nascondi JSON grezzo',
|
||
|
||
'time.yesterday': 'Ieri',
|
||
'time.today': 'Oggi',
|
||
|
||
'shortcuts.title': 'Scorciatoie da tastiera',
|
||
'shortcuts.send': 'Invia messaggio',
|
||
'shortcuts.newline': 'Nuova riga',
|
||
'shortcuts.search': 'Cerca sessioni',
|
||
'shortcuts.switchSession': 'Sessione precedente / successiva',
|
||
'shortcuts.closeSidebar': 'Chiudi barra laterale / ricerca',
|
||
'shortcuts.stop': 'Ferma generazione',
|
||
'shortcuts.help': 'Mostra scorciatoie',
|
||
'shortcuts.close': 'Chiudi',
|
||
'shortcuts.chatSection': 'Chat',
|
||
|
||
'error.title': 'Qualcosa è andato storto',
|
||
'error.description': 'Si è verificato un errore imprevisto durante il rendering dell\'interfaccia. Puoi riprovare o ricaricare la pagina.',
|
||
'error.retry': 'Riprova',
|
||
'error.reload': 'Ricarica pagina',
|
||
'shortcuts.navigationSection': 'Navigazione',
|
||
'shortcuts.generalSection': 'Generale',
|
||
|
||
'header.export': 'Esporta conversazione in Markdown',
|
||
'header.compact': 'Compatta',
|
||
'header.compacting': 'Compattamento…',
|
||
'header.sessionInfo': 'Info sessione',
|
||
'sessionInfo.sessionKey': 'Chiave sessione',
|
||
'sessionInfo.channel': 'Canale',
|
||
'sessionInfo.kind': 'Tipo',
|
||
'sessionInfo.model': 'Modello',
|
||
'sessionInfo.agent': 'Agente',
|
||
'sessionInfo.messages': 'Messaggi',
|
||
'sessionInfo.totalTokens': 'Token totali',
|
||
'sessionInfo.inputTokens': 'Input',
|
||
'sessionInfo.outputTokens': 'Output',
|
||
'sessionInfo.contextWindow': 'Contesto',
|
||
'sessionInfo.lastActive': 'Ultima attività',
|
||
|
||
'theme.title': 'Tema',
|
||
'theme.mode': 'Modalità',
|
||
'theme.accent': 'Accento',
|
||
'theme.system': 'Sistema',
|
||
'theme.dark': 'Scuro',
|
||
'theme.light': 'Chiaro',
|
||
'theme.oled': 'OLED',
|
||
|
||
'search.placeholder': 'Cerca nei messaggi…',
|
||
'search.noResults': '0 risultati',
|
||
'search.prev': 'Risultato precedente',
|
||
'search.next': 'Risultato successivo',
|
||
'shortcuts.searchMessages': 'Cerca nei messaggi',
|
||
|
||
'settings.title': 'Impostazioni',
|
||
'settings.appearance': 'Aspetto',
|
||
'settings.typography': 'Tipografia',
|
||
'settings.chat': 'Chat',
|
||
'settings.notifications': 'Notifiche',
|
||
'settings.notificationSound': 'Suono di notifica',
|
||
'settings.language': 'Lingua',
|
||
'settings.sendShortcut': 'Invia con',
|
||
'settings.sendEnter': 'Invio',
|
||
'settings.sendCtrlEnter': 'Ctrl+Invio',
|
||
'settings.tab.appearance': 'Aspetto',
|
||
'settings.tab.typography': 'Tipografia',
|
||
'settings.tab.chat': 'Chat',
|
||
'settings.tab.notifications': 'Notifiche',
|
||
'settings.fontUi': 'Font UI',
|
||
'settings.fontMono': 'Font codice',
|
||
'settings.fontSize': 'Dimensione font UI',
|
||
'settings.fontMonoSize': 'Dimensione font codice',
|
||
'settings.preview': 'Anteprima',
|
||
'settings.previewText': 'Quel vitello jazz fonde sciolto whiskey e cioccolato — 1234567890',
|
||
'settings.fontNote': 'Inter / JetBrains / Fira si caricano automaticamente; Cascadia e SF richiedono font di sistema.',
|
||
|
||
'message.bookmark': 'Aggiungi ai segnalibri',
|
||
'message.reply': 'Rispondi',
|
||
'chat.replyingTo': 'In risposta a',
|
||
'message.removeBookmark': 'Rimuovi segnalibro',
|
||
'chat.bookmarks': 'Segnalibri',
|
||
'chat.export': 'Esporta conversazione',
|
||
'chat.contextCompacted': 'Contesto compattato — messaggi precedenti nella cache locale',
|
||
'slash.commands': 'Comandi',
|
||
'slash.status': 'Mostra stato e utilizzo della sessione',
|
||
'slash.reasoning': 'Attiva/disattiva ragionamento',
|
||
'slash.verbose': 'Attiva/disattiva output dettagliato',
|
||
'slash.model': 'Cambia modello per questa sessione',
|
||
'slash.compact': 'Compatta il contesto della conversazione',
|
||
'slash.reset': 'Reimposta sessione',
|
||
'slash.new': 'Crea una nuova sessione chat',
|
||
'slash.help': 'Mostra comandi disponibili',
|
||
};
|
||
|
||
const messages: Record<string, Record<string, string>> = { en, fr, es, de, ja, pt, zh, it };
|
||
|
||
export const supportedLocales = Object.keys(messages) as string[];
|
||
|
||
/** Labels shown in the language selector */
|
||
export const localeLabels: Record<string, string> = {
|
||
en: 'EN',
|
||
fr: 'FR',
|
||
es: 'ES',
|
||
de: 'DE',
|
||
ja: 'JA',
|
||
pt: 'PT',
|
||
zh: '中文',
|
||
it: 'IT',
|
||
};
|
||
|
||
function resolveInitialLocale(): string {
|
||
// 1. localStorage
|
||
try {
|
||
const stored = localStorage.getItem(STORAGE_KEY);
|
||
if (stored && messages[stored]) return stored;
|
||
} catch { /* SSR or blocked storage */ }
|
||
|
||
// 2. VITE_LOCALE env var
|
||
const envLocale = (import.meta.env.VITE_LOCALE as string) || '';
|
||
if (envLocale && messages[envLocale]) return envLocale;
|
||
|
||
// 3. navigator.language
|
||
if (typeof navigator !== 'undefined') {
|
||
const navLang = navigator.language?.split('-')[0];
|
||
if (navLang && messages[navLang]) return navLang;
|
||
}
|
||
|
||
// 4. fallback
|
||
return 'en';
|
||
}
|
||
|
||
let currentLocale = resolveInitialLocale();
|
||
let dict = messages[currentLocale] || messages.en;
|
||
|
||
// Sync <html lang> on initial load
|
||
try { document.documentElement.lang = currentLocale; } catch { /* SSR */ }
|
||
|
||
type Listener = () => void;
|
||
const listeners = new Set<Listener>();
|
||
|
||
/** Subscribe to locale changes. Returns unsubscribe function. */
|
||
export function onLocaleChange(fn: Listener): () => void {
|
||
listeners.add(fn);
|
||
return () => listeners.delete(fn);
|
||
}
|
||
|
||
/** Get the current locale code */
|
||
export function getLocale(): string {
|
||
return currentLocale;
|
||
}
|
||
|
||
/** Switch locale at runtime. Persists to localStorage and notifies subscribers. */
|
||
export function setLocale(loc: string): void {
|
||
if (!messages[loc] || loc === currentLocale) return;
|
||
currentLocale = loc;
|
||
dict = messages[loc];
|
||
try { localStorage.setItem(STORAGE_KEY, loc); } catch { /* noop */ }
|
||
try { document.documentElement.lang = loc; } catch { /* SSR */ }
|
||
listeners.forEach((fn) => fn());
|
||
}
|
||
|
||
/** Return the translated string for the given key, falling back to English. */
|
||
export function t(key: TranslationKey): string {
|
||
return dict[key] ?? (messages.en as Record<string, string>)[key] ?? key;
|
||
}
|
||
|
||
// Keep backward-compat named export
|
||
export { currentLocale as locale };
|