diff --git a/web/messages/de.json b/web/messages/de.json index 5e9bf845..7292e829 100644 --- a/web/messages/de.json +++ b/web/messages/de.json @@ -1002,8 +1002,148 @@ "wifi": "WLAN", "quotes": "Zitate", "rotation": "Drehung" + }, + "on": "An", + "off": "Aus", + "toggleServiceAriaLabel": "{name} umschalten" + }, + "accountSection": { + "signedIn": { + "title": "Angemeldet", + "description": "Du bist derzeit als {username} angemeldet." + }, + "changeUsername": { + "title": "Benutzernamen ändern", + "description": "Wähle einen neuen Anmeldenamen. Erfordert dein aktuelles Passwort.", + "formAriaLabel": "Benutzernamen ändern", + "newUsernameLabel": "Neuer Benutzername", + "currentPasswordLabel": "Aktuelles Passwort", + "submit": "Benutzernamen speichern", + "submitting": "Wird gespeichert…", + "success": "Benutzername aktualisiert", + "failure": "Ändern des Benutzernamens fehlgeschlagen" + }, + "changePassword": { + "title": "Passwort ändern", + "description": "Ändere dein Passwort. Alle anderen mit dem alten Passwort angemeldeten Sitzungen werden abgemeldet.", + "formAriaLabel": "Passwort ändern", + "currentPasswordLabel": "Aktuelles Passwort", + "newPasswordLabel": "Neues Passwort", + "newPasswordHint": "Mindestens 8 Zeichen.", + "confirmPasswordLabel": "Neues Passwort bestätigen", + "submit": "Passwort speichern", + "submitting": "Wird gespeichert…", + "success": "Passwort aktualisiert", + "failure": "Ändern des Passworts fehlgeschlagen", + "tooShort": "Das neue Passwort muss mindestens 8 Zeichen lang sein.", + "mismatch": "Die Passwörter stimmen nicht überein." + }, + "signOut": { + "title": "Abmelden", + "description": "Beende deine aktuelle Sitzung. Du wirst zur Anmeldeseite zurückgeleitet.", + "button": "Abmelden" + }, + "disableLogin": { + "title": "Anmeldung deaktivieren", + "description": "Authentifizierung vollständig deaktivieren. Jeder, der dieses FiestaBoard im Netzwerk erreichen kann, kann dann Einstellungen ändern und API-Schlüssel lesen. Nicht empfohlen, es sei denn, dieses Gerät befindet sich in einem vollständig vertrauenswürdigen privaten Netzwerk.", + "button": "Anmeldung deaktivieren", + "dialogTitle": "Anmeldung für dieses FiestaBoard deaktivieren?", + "dialogBody1": "Durch das Deaktivieren der Anmeldung wird das Konto {username} entfernt und dieses FiestaBoard für jeden im Netzwerk geöffnet — diese können dann deine API-Schlüssel lesen, deine Board-Konfiguration ändern und alle Einstellungen anpassen.", + "dialogBody2": "Tue dies nur, wenn sich dieses Gerät in einem vollständig vertrauenswürdigen privaten Netzwerk befindet (keine Mitbewohner, keine Gäste, keine Smart-Home-Geräte, die du nicht kontrollierst). Dringend nicht empfohlen, wenn dieses FiestaBoard aus dem Internet erreichbar ist.", + "dialogBody3": "Dein Board zeigt in beiden Fällen weiter normal an — dies steuert nur, wer sich anmelden kann, um Einstellungen zu ändern.", + "confirmPasswordLabel": "Bestätige dein aktuelles Passwort, um fortzufahren", + "confirm": "Ja, Anmeldung deaktivieren", + "confirming": "Wird deaktiviert…", + "success": "Authentifizierung deaktiviert", + "failure": "Authentifizierung konnte nicht deaktiviert werden" + }, + "enableLogin": { + "title": "Anmeldung aktivieren", + "description": "Die Anmeldung ist derzeit aus. Jeder, der dieses FiestaBoard im Netzwerk erreichen kann, kann deine API-Schlüssel lesen, deine Board-Konfiguration ändern und alle Einstellungen anpassen.", + "body": "Dringend empfohlen, wenn du WLAN mit Personen teilst, denen du nicht vollständig vertraust (Mitbewohner, Gäste, Smart-Home-Geräte), oder wenn dieses FiestaBoard aus dem Internet erreichbar ist. Dein Board zeigt in beiden Fällen weiter normal an — die Anmeldung steuert nur, wer sich anmelden kann, um Einstellungen zu ändern.", + "button": "Benutzernamen & Passwort einrichten", + "submitting": "Wird aktiviert…", + "failure": "Anmeldung konnte nicht aktiviert werden" + } + }, + "aiActionConfirmation": { + "deny": "Ablehnen", + "allow": "Zulassen", + "working": "Wird ausgeführt…", + "done": "Fertig", + "denied": "Abgelehnt", + "noChanges": "keine Änderungen", + "noValues": "keine Werte", + "noChangesSpecified": "Keine Änderungen angegeben.", + "openEnd": "offen", + "label": { + "installPlugin": "Plugin installieren: {id}", + "updatePluginConfig": "Plugin konfigurieren: {id}", + "updatePlugin": "Plugin aktualisieren: {id}", + "enablePlugin": "Plugin aktivieren: {id}", + "disablePlugin": "Plugin deaktivieren: {id}", + "uninstallPlugin": "Plugin deinstallieren: {id}", + "updateSetting": "Einstellung ändern: {category}", + "createCollection": "Sammlung erstellen: \"{name}\"", + "updateCollection": "Sammlung aktualisieren", + "createSchedule": "Zeitplan erstellen", + "updateSchedule": "Zeitplan aktualisieren", + "deleteSchedule": "Zeitplan löschen", + "triggerSystemUpdate": "Systemaktualisierung" + }, + "description": { + "installPlugin": "Installiert \"{id}\" aus der offiziellen Registry.", + "installPluginEnable": "Installiert \"{id}\" aus der offiziellen Registry und aktiviert es.", + "updatePluginConfig": "Aktualisiert die Konfiguration von \"{id}\": {keys}.", + "updatePlugin": "Lädt die neueste Registry-Version von \"{id}\" herunter und installiert sie.", + "enablePlugin": "Aktiviert \"{id}\", damit es Daten für deine Boards bereitstellen kann.", + "disablePlugin": "Deaktiviert \"{id}\", ohne es zu entfernen. Es kann später wieder aktiviert werden.", + "uninstallPlugin": "Entfernt \"{id}\" dauerhaft. Dies kann nicht rückgängig gemacht werden.", + "updateSetting": "Setzt {values} in den {category}-Einstellungen.", + "createCollection": "Erstellt eine Sammlung mit {count, plural, one {# Seite} other {# Seiten}}, die alle {interval}s wechselt.", + "createSchedule": "Zeigt Seite \"{page}\" von {time} an {days}-Tagen.", + "deleteSchedule": "Entfernt den Zeitplan \"{id}\" dauerhaft. Dies kann nicht rückgängig gemacht werden.", + "triggerSystemUpdate": "Lädt die neueste FiestaBoard-Aktualisierung herunter und installiert sie. Das System startet kurz neu." + }, + "change": { + "rename": "umbenennen in \"{name}\"", + "setPages": "{count, plural, one {# Seite} other {# Seiten}} festlegen", + "interval": "Intervall → {interval}s", + "page": "Seite → {page}", + "start": "Start → {start}", + "end": "Ende → {end}", + "days": "Tage → {days}", + "enable": "aktivieren", + "disable": "deaktivieren" + } + }, + "chainingModePicker": { + "menuTitle": "KI-Verkettungsmodus", + "triggerAriaLabel": "KI-Verkettungsmodus: {mode}", + "modes": { + "manual": { + "label": "Manuell", + "description": "Ich frage nach jeder Aktion erneut nach" + }, + "autoContinue": { + "label": "Auto-Fortsetzung", + "description": "Aktionen verketten, jeden Schritt bestätigen" + }, + "autonomous": { + "label": "Autonom", + "description": "Bis zum Abschluss ausführen, Bestätigungen überspringen" + } } }, + "bootGate": { + "waiting": "Warten auf den Start…", + "errorHeading": "Verbindung zu FiestaBoard fehlgeschlagen", + "errorDescription": "Prüfe, ob die App läuft, und versuche, die Seite neu zu laden.", + "refreshPage": "Seite neu laden" + }, + "globalAiChatDrawer": { + "panelAriaLabel": "FiestaBot-KI-Chat" + }, "plainTextEditor": { "placeholder": "Vorlagentext eingeben...", "lineCount": "{current} / {total} Zeilen", @@ -1212,7 +1352,8 @@ "change": "Ändern", "selectAttribute": "Attribut auswählen", "valueLabel": "Wert", - "insert": "Einfügen" + "insert": "Einfügen", + "searchAriaLabel": "Entitäten suchen" }, "pluginSettings": { "title": "Plugin-Updates", @@ -1510,10 +1651,10 @@ "importWithMissingPlugins": "Einige Plugins sind noch nicht aktiviert: {plugins}. Du kannst trotzdem importieren und sie später aktivieren." }, "aiChatPanel": { + "messagesAriaLabel": "Chat-Nachrichten", + "taskStatusAriaLabel": "Aufgabenfortschritt", + "taskProgressAriaLabel": "Fortschritt der KI-Aufgaben", "clearConversationAriaLabel": "Konversation löschen", "closePanelAriaLabel": "FiestaBot (Beta) schließen" - }, - "aiChat": { - "taskProgressAriaLabel": "Fortschritt der KI-Aufgaben" } } diff --git a/web/messages/en.json b/web/messages/en.json index 68ad436e..64e35148 100644 --- a/web/messages/en.json +++ b/web/messages/en.json @@ -959,8 +959,148 @@ "wifi": "WiFi", "quotes": "Quotes", "rotation": "Rotation" + }, + "on": "On", + "off": "Off", + "toggleServiceAriaLabel": "Toggle {name}" + }, + "accountSection": { + "signedIn": { + "title": "Signed in", + "description": "You're currently signed in as {username}." + }, + "changeUsername": { + "title": "Change username", + "description": "Pick a new sign-in name. Requires your current password.", + "formAriaLabel": "Change username", + "newUsernameLabel": "New username", + "currentPasswordLabel": "Current password", + "submit": "Save username", + "submitting": "Saving…", + "success": "Username updated", + "failure": "Username change failed" + }, + "changePassword": { + "title": "Change password", + "description": "Rotate your password. Any other sessions signed in with the old password will be signed out.", + "formAriaLabel": "Change password", + "currentPasswordLabel": "Current password", + "newPasswordLabel": "New password", + "newPasswordHint": "At least 8 characters.", + "confirmPasswordLabel": "Confirm new password", + "submit": "Save password", + "submitting": "Saving…", + "success": "Password updated", + "failure": "Password change failed", + "tooShort": "New password must be at least 8 characters.", + "mismatch": "Passwords do not match." + }, + "signOut": { + "title": "Sign out", + "description": "End your current session. You'll be sent back to the sign-in page.", + "button": "Sign out" + }, + "disableLogin": { + "title": "Disable login", + "description": "Turn off authentication entirely. Anyone who can reach this FiestaBoard on the network will be able to change settings and read API keys. Not recommended unless this device is on a fully trusted private network.", + "button": "Disable login", + "dialogTitle": "Disable login for this FiestaBoard?", + "dialogBody1": "Turning off login removes the {username} account and opens this FiestaBoard up to anyone who can reach it on the network — they'll be able to read your API keys, change your board configuration, and modify any settings.", + "dialogBody2": "Only do this if this device is on a fully trusted private network (no roommates, no guests, no smart-home devices you don't control). Strongly not recommended if this FiestaBoard is reachable from the internet.", + "dialogBody3": "Your board keeps displaying as normal either way — this only controls who can sign in to change settings.", + "confirmPasswordLabel": "Confirm your current password to continue", + "confirm": "Yes, disable login", + "confirming": "Disabling…", + "success": "Authentication disabled", + "failure": "Failed to disable auth" + }, + "enableLogin": { + "title": "Turn on login", + "description": "Login is currently off. Anyone who can reach this FiestaBoard on the network can read your API keys, change your board configuration, and modify any settings.", + "body": "Strongly recommended if you share Wi-Fi with people you don't fully trust (roommates, guests, smart-home devices), or if this FiestaBoard is reachable from the internet. Your board keeps displaying as normal either way — login only controls who can sign in to change settings.", + "button": "Set up a username & password", + "submitting": "Enabling…", + "failure": "Could not enable login" } }, + "aiActionConfirmation": { + "deny": "Deny", + "allow": "Allow", + "working": "Working…", + "done": "Done", + "denied": "Denied", + "noChanges": "no changes", + "noValues": "no values", + "noChangesSpecified": "No changes specified.", + "openEnd": "open", + "label": { + "installPlugin": "Install plugin: {id}", + "updatePluginConfig": "Configure plugin: {id}", + "updatePlugin": "Update plugin: {id}", + "enablePlugin": "Enable plugin: {id}", + "disablePlugin": "Disable plugin: {id}", + "uninstallPlugin": "Uninstall plugin: {id}", + "updateSetting": "Change setting: {category}", + "createCollection": "Create collection: \"{name}\"", + "updateCollection": "Update collection", + "createSchedule": "Create schedule", + "updateSchedule": "Update schedule", + "deleteSchedule": "Delete schedule", + "triggerSystemUpdate": "System update" + }, + "description": { + "installPlugin": "Installs \"{id}\" from the official registry.", + "installPluginEnable": "Installs \"{id}\" from the official registry and enables it.", + "updatePluginConfig": "Updates configuration for \"{id}\": {keys}.", + "updatePlugin": "Downloads and installs the latest registry version of \"{id}\".", + "enablePlugin": "Enables \"{id}\" so it can provide data to your boards.", + "disablePlugin": "Disables \"{id}\" without removing it. It can be re-enabled later.", + "uninstallPlugin": "Permanently removes \"{id}\". This cannot be undone.", + "updateSetting": "Sets {values} in {category} settings.", + "createCollection": "Creates a collection with {count, plural, one {# page} other {# pages}}, rotating every {interval}s.", + "createSchedule": "Shows page \"{page}\" from {time} on {days} days.", + "deleteSchedule": "Permanently removes schedule \"{id}\". This cannot be undone.", + "triggerSystemUpdate": "Downloads and installs the latest FiestaBoard update. The system will restart briefly." + }, + "change": { + "rename": "rename to \"{name}\"", + "setPages": "set {count, plural, one {# page} other {# pages}}", + "interval": "interval → {interval}s", + "page": "page → {page}", + "start": "start → {start}", + "end": "end → {end}", + "days": "days → {days}", + "enable": "enable", + "disable": "disable" + } + }, + "chainingModePicker": { + "menuTitle": "AI chaining mode", + "triggerAriaLabel": "AI chaining mode: {mode}", + "modes": { + "manual": { + "label": "Manual", + "description": "I'll re-prompt after each action" + }, + "autoContinue": { + "label": "Auto-continue", + "description": "Chain actions, confirm each step" + }, + "autonomous": { + "label": "Autonomous", + "description": "Run to completion, skip confirmations" + } + } + }, + "bootGate": { + "waiting": "Waiting to start…", + "errorHeading": "Couldn't connect to FiestaBoard", + "errorDescription": "Check that the app is running and try refreshing the page.", + "refreshPage": "Refresh page" + }, + "globalAiChatDrawer": { + "panelAriaLabel": "FiestaBot AI chat" + }, "plainTextEditor": { "placeholder": "Type your template text...", "lineCount": "{current} / {total} lines", @@ -1169,7 +1309,8 @@ "change": "Change", "selectAttribute": "Select Attribute", "valueLabel": "Value", - "insert": "Insert" + "insert": "Insert", + "searchAriaLabel": "Search entities" }, "pluginSettings": { "title": "Plugin Updates", @@ -1510,10 +1651,10 @@ "importWithMissingPlugins": "Some plugins aren't enabled yet: {plugins}. You can still import and enable them later." }, "aiChatPanel": { + "messagesAriaLabel": "Chat messages", + "taskStatusAriaLabel": "Task progress", + "taskProgressAriaLabel": "AI task progress", "clearConversationAriaLabel": "Clear conversation", "closePanelAriaLabel": "Close FiestaBot (Beta)" - }, - "aiChat": { - "taskProgressAriaLabel": "AI task progress" } } diff --git a/web/messages/es.json b/web/messages/es.json index 8abf716b..98eb8eb3 100644 --- a/web/messages/es.json +++ b/web/messages/es.json @@ -1002,8 +1002,148 @@ "wifi": "WiFi", "quotes": "Frases", "rotation": "Rotación" + }, + "on": "Activado", + "off": "Desactivado", + "toggleServiceAriaLabel": "Alternar {name}" + }, + "accountSection": { + "signedIn": { + "title": "Sesión iniciada", + "description": "Actualmente tienes la sesión iniciada como {username}." + }, + "changeUsername": { + "title": "Cambiar nombre de usuario", + "description": "Elige un nuevo nombre de inicio de sesión. Requiere tu contraseña actual.", + "formAriaLabel": "Cambiar nombre de usuario", + "newUsernameLabel": "Nuevo nombre de usuario", + "currentPasswordLabel": "Contraseña actual", + "submit": "Guardar nombre de usuario", + "submitting": "Guardando…", + "success": "Nombre de usuario actualizado", + "failure": "No se pudo cambiar el nombre de usuario" + }, + "changePassword": { + "title": "Cambiar contraseña", + "description": "Cambia tu contraseña. Cualquier otra sesión iniciada con la contraseña anterior se cerrará.", + "formAriaLabel": "Cambiar contraseña", + "currentPasswordLabel": "Contraseña actual", + "newPasswordLabel": "Nueva contraseña", + "newPasswordHint": "Al menos 8 caracteres.", + "confirmPasswordLabel": "Confirmar nueva contraseña", + "submit": "Guardar contraseña", + "submitting": "Guardando…", + "success": "Contraseña actualizada", + "failure": "No se pudo cambiar la contraseña", + "tooShort": "La nueva contraseña debe tener al menos 8 caracteres.", + "mismatch": "Las contraseñas no coinciden." + }, + "signOut": { + "title": "Cerrar sesión", + "description": "Finaliza tu sesión actual. Volverás a la página de inicio de sesión.", + "button": "Cerrar sesión" + }, + "disableLogin": { + "title": "Desactivar inicio de sesión", + "description": "Desactiva la autenticación por completo. Cualquiera que pueda acceder a este FiestaBoard en la red podrá cambiar la configuración y leer las claves de API. No se recomienda a menos que este dispositivo esté en una red privada totalmente confiable.", + "button": "Desactivar inicio de sesión", + "dialogTitle": "¿Desactivar el inicio de sesión de este FiestaBoard?", + "dialogBody1": "Desactivar el inicio de sesión elimina la cuenta {username} y abre este FiestaBoard a cualquiera que pueda acceder a él en la red — podrán leer tus claves de API, cambiar la configuración de tu tablero y modificar cualquier ajuste.", + "dialogBody2": "Hazlo solo si este dispositivo está en una red privada totalmente confiable (sin compañeros de piso, sin invitados, sin dispositivos de domótica que no controles). Muy poco recomendable si este FiestaBoard es accesible desde internet.", + "dialogBody3": "Tu tablero seguirá mostrándose con normalidad en cualquier caso — esto solo controla quién puede iniciar sesión para cambiar la configuración.", + "confirmPasswordLabel": "Confirma tu contraseña actual para continuar", + "confirm": "Sí, desactivar inicio de sesión", + "confirming": "Desactivando…", + "success": "Autenticación desactivada", + "failure": "No se pudo desactivar la autenticación" + }, + "enableLogin": { + "title": "Activar inicio de sesión", + "description": "El inicio de sesión está actualmente desactivado. Cualquiera que pueda acceder a este FiestaBoard en la red puede leer tus claves de API, cambiar la configuración de tu tablero y modificar cualquier ajuste.", + "body": "Muy recomendable si compartes la Wi-Fi con personas en las que no confías plenamente (compañeros de piso, invitados, dispositivos de domótica), o si este FiestaBoard es accesible desde internet. Tu tablero seguirá mostrándose con normalidad en cualquier caso — el inicio de sesión solo controla quién puede iniciar sesión para cambiar la configuración.", + "button": "Configurar un nombre de usuario y contraseña", + "submitting": "Activando…", + "failure": "No se pudo activar el inicio de sesión" } }, + "aiActionConfirmation": { + "deny": "Denegar", + "allow": "Permitir", + "working": "Trabajando…", + "done": "Hecho", + "denied": "Denegado", + "noChanges": "sin cambios", + "noValues": "sin valores", + "noChangesSpecified": "No se especificaron cambios.", + "openEnd": "abierto", + "label": { + "installPlugin": "Instalar complemento: {id}", + "updatePluginConfig": "Configurar complemento: {id}", + "updatePlugin": "Actualizar complemento: {id}", + "enablePlugin": "Activar complemento: {id}", + "disablePlugin": "Desactivar complemento: {id}", + "uninstallPlugin": "Desinstalar complemento: {id}", + "updateSetting": "Cambiar ajuste: {category}", + "createCollection": "Crear colección: \"{name}\"", + "updateCollection": "Actualizar colección", + "createSchedule": "Crear programación", + "updateSchedule": "Actualizar programación", + "deleteSchedule": "Eliminar programación", + "triggerSystemUpdate": "Actualización del sistema" + }, + "description": { + "installPlugin": "Instala \"{id}\" desde el registro oficial.", + "installPluginEnable": "Instala \"{id}\" desde el registro oficial y lo activa.", + "updatePluginConfig": "Actualiza la configuración de \"{id}\": {keys}.", + "updatePlugin": "Descarga e instala la última versión del registro de \"{id}\".", + "enablePlugin": "Activa \"{id}\" para que pueda proporcionar datos a tus tableros.", + "disablePlugin": "Desactiva \"{id}\" sin eliminarlo. Se puede volver a activar más tarde.", + "uninstallPlugin": "Elimina \"{id}\" de forma permanente. Esto no se puede deshacer.", + "updateSetting": "Establece {values} en los ajustes de {category}.", + "createCollection": "Crea una colección con {count, plural, one {# página} other {# páginas}}, rotando cada {interval}s.", + "createSchedule": "Muestra la página \"{page}\" de {time} los días {days}.", + "deleteSchedule": "Elimina permanentemente la programación \"{id}\". Esto no se puede deshacer.", + "triggerSystemUpdate": "Descarga e instala la última actualización de FiestaBoard. El sistema se reiniciará brevemente." + }, + "change": { + "rename": "renombrar a \"{name}\"", + "setPages": "establecer {count, plural, one {# página} other {# páginas}}", + "interval": "intervalo → {interval}s", + "page": "página → {page}", + "start": "inicio → {start}", + "end": "fin → {end}", + "days": "días → {days}", + "enable": "activar", + "disable": "desactivar" + } + }, + "chainingModePicker": { + "menuTitle": "Modo de encadenamiento de IA", + "triggerAriaLabel": "Modo de encadenamiento de IA: {mode}", + "modes": { + "manual": { + "label": "Manual", + "description": "Te volveré a preguntar después de cada acción" + }, + "autoContinue": { + "label": "Continuación automática", + "description": "Encadena acciones, confirma cada paso" + }, + "autonomous": { + "label": "Autónomo", + "description": "Ejecuta hasta el final, omite confirmaciones" + } + } + }, + "bootGate": { + "waiting": "Esperando para iniciar…", + "errorHeading": "No se pudo conectar con FiestaBoard", + "errorDescription": "Comprueba que la aplicación está en ejecución e intenta recargar la página.", + "refreshPage": "Recargar página" + }, + "globalAiChatDrawer": { + "panelAriaLabel": "Chat de IA de FiestaBot" + }, "plainTextEditor": { "placeholder": "Escribe el texto de tu plantilla...", "lineCount": "{current} / {total} líneas", @@ -1212,7 +1352,8 @@ "change": "Cambiar", "selectAttribute": "Seleccionar atributo", "valueLabel": "Valor", - "insert": "Insertar" + "insert": "Insertar", + "searchAriaLabel": "Buscar entidades" }, "pluginSettings": { "title": "Actualizaciones de plugins", @@ -1510,10 +1651,10 @@ "importWithMissingPlugins": "Algunos plugins aún no están activados: {plugins}. Aún puedes importar y activarlos más tarde." }, "aiChatPanel": { + "messagesAriaLabel": "Mensajes del chat", + "taskStatusAriaLabel": "Progreso de tareas", + "taskProgressAriaLabel": "Progreso de tareas de IA", "clearConversationAriaLabel": "Borrar conversación", "closePanelAriaLabel": "Cerrar FiestaBot (Beta)" - }, - "aiChat": { - "taskProgressAriaLabel": "Progreso de tareas de IA" } } diff --git a/web/messages/fr.json b/web/messages/fr.json index 56b93bfc..7e0bd48a 100644 --- a/web/messages/fr.json +++ b/web/messages/fr.json @@ -1002,8 +1002,148 @@ "wifi": "WiFi", "quotes": "Citations", "rotation": "Rotation" + }, + "on": "Activé", + "off": "Désactivé", + "toggleServiceAriaLabel": "Basculer {name}" + }, + "accountSection": { + "signedIn": { + "title": "Connecté", + "description": "Vous êtes actuellement connecté en tant que {username}." + }, + "changeUsername": { + "title": "Changer le nom d'utilisateur", + "description": "Choisissez un nouveau nom de connexion. Nécessite votre mot de passe actuel.", + "formAriaLabel": "Changer le nom d'utilisateur", + "newUsernameLabel": "Nouveau nom d'utilisateur", + "currentPasswordLabel": "Mot de passe actuel", + "submit": "Enregistrer le nom d'utilisateur", + "submitting": "Enregistrement…", + "success": "Nom d'utilisateur mis à jour", + "failure": "Échec du changement de nom d'utilisateur" + }, + "changePassword": { + "title": "Changer le mot de passe", + "description": "Changez votre mot de passe. Toutes les autres sessions connectées avec l'ancien mot de passe seront déconnectées.", + "formAriaLabel": "Changer le mot de passe", + "currentPasswordLabel": "Mot de passe actuel", + "newPasswordLabel": "Nouveau mot de passe", + "newPasswordHint": "Au moins 8 caractères.", + "confirmPasswordLabel": "Confirmer le nouveau mot de passe", + "submit": "Enregistrer le mot de passe", + "submitting": "Enregistrement…", + "success": "Mot de passe mis à jour", + "failure": "Échec du changement de mot de passe", + "tooShort": "Le nouveau mot de passe doit comporter au moins 8 caractères.", + "mismatch": "Les mots de passe ne correspondent pas." + }, + "signOut": { + "title": "Se déconnecter", + "description": "Mettez fin à votre session actuelle. Vous serez renvoyé vers la page de connexion.", + "button": "Se déconnecter" + }, + "disableLogin": { + "title": "Désactiver la connexion", + "description": "Désactiver entièrement l'authentification. Toute personne pouvant atteindre ce FiestaBoard sur le réseau pourra modifier les paramètres et lire les clés API. Non recommandé sauf si cet appareil se trouve sur un réseau privé entièrement fiable.", + "button": "Désactiver la connexion", + "dialogTitle": "Désactiver la connexion pour ce FiestaBoard ?", + "dialogBody1": "Désactiver la connexion supprime le compte {username} et ouvre ce FiestaBoard à toute personne pouvant l'atteindre sur le réseau — elle pourra lire vos clés API, modifier la configuration de votre tableau et changer tous les paramètres.", + "dialogBody2": "Ne le faites que si cet appareil se trouve sur un réseau privé entièrement fiable (pas de colocataires, pas d'invités, pas d'appareils domotiques que vous ne contrôlez pas). Fortement déconseillé si ce FiestaBoard est accessible depuis internet.", + "dialogBody3": "Votre tableau continue de s'afficher normalement dans tous les cas — cela contrôle uniquement qui peut se connecter pour modifier les paramètres.", + "confirmPasswordLabel": "Confirmez votre mot de passe actuel pour continuer", + "confirm": "Oui, désactiver la connexion", + "confirming": "Désactivation…", + "success": "Authentification désactivée", + "failure": "Échec de la désactivation de l'authentification" + }, + "enableLogin": { + "title": "Activer la connexion", + "description": "La connexion est actuellement désactivée. Toute personne pouvant atteindre ce FiestaBoard sur le réseau peut lire vos clés API, modifier la configuration de votre tableau et changer tous les paramètres.", + "body": "Fortement recommandé si vous partagez le Wi-Fi avec des personnes en qui vous n'avez pas entièrement confiance (colocataires, invités, appareils domotiques), ou si ce FiestaBoard est accessible depuis internet. Votre tableau continue de s'afficher normalement dans tous les cas — la connexion contrôle uniquement qui peut se connecter pour modifier les paramètres.", + "button": "Configurer un nom d'utilisateur et un mot de passe", + "submitting": "Activation…", + "failure": "Impossible d'activer la connexion" } }, + "aiActionConfirmation": { + "deny": "Refuser", + "allow": "Autoriser", + "working": "En cours…", + "done": "Terminé", + "denied": "Refusé", + "noChanges": "aucun changement", + "noValues": "aucune valeur", + "noChangesSpecified": "Aucun changement spécifié.", + "openEnd": "ouvert", + "label": { + "installPlugin": "Installer le module : {id}", + "updatePluginConfig": "Configurer le module : {id}", + "updatePlugin": "Mettre à jour le module : {id}", + "enablePlugin": "Activer le module : {id}", + "disablePlugin": "Désactiver le module : {id}", + "uninstallPlugin": "Désinstaller le module : {id}", + "updateSetting": "Modifier le paramètre : {category}", + "createCollection": "Créer une collection : \"{name}\"", + "updateCollection": "Mettre à jour la collection", + "createSchedule": "Créer une programmation", + "updateSchedule": "Mettre à jour la programmation", + "deleteSchedule": "Supprimer la programmation", + "triggerSystemUpdate": "Mise à jour du système" + }, + "description": { + "installPlugin": "Installe \"{id}\" depuis le registre officiel.", + "installPluginEnable": "Installe \"{id}\" depuis le registre officiel et l'active.", + "updatePluginConfig": "Met à jour la configuration de \"{id}\" : {keys}.", + "updatePlugin": "Télécharge et installe la dernière version du registre de \"{id}\".", + "enablePlugin": "Active \"{id}\" pour qu'il puisse fournir des données à vos tableaux.", + "disablePlugin": "Désactive \"{id}\" sans le supprimer. Il peut être réactivé plus tard.", + "uninstallPlugin": "Supprime définitivement \"{id}\". Cette action est irréversible.", + "updateSetting": "Définit {values} dans les paramètres {category}.", + "createCollection": "Crée une collection avec {count, plural, one {# page} other {# pages}}, en alternant toutes les {interval}s.", + "createSchedule": "Affiche la page \"{page}\" de {time} les jours {days}.", + "deleteSchedule": "Supprime définitivement la programmation \"{id}\". Cette action est irréversible.", + "triggerSystemUpdate": "Télécharge et installe la dernière mise à jour de FiestaBoard. Le système redémarrera brièvement." + }, + "change": { + "rename": "renommer en \"{name}\"", + "setPages": "définir {count, plural, one {# page} other {# pages}}", + "interval": "intervalle → {interval}s", + "page": "page → {page}", + "start": "début → {start}", + "end": "fin → {end}", + "days": "jours → {days}", + "enable": "activer", + "disable": "désactiver" + } + }, + "chainingModePicker": { + "menuTitle": "Mode de chaînage IA", + "triggerAriaLabel": "Mode de chaînage IA : {mode}", + "modes": { + "manual": { + "label": "Manuel", + "description": "Je redemanderai après chaque action" + }, + "autoContinue": { + "label": "Continuation auto", + "description": "Enchaîne les actions, confirme chaque étape" + }, + "autonomous": { + "label": "Autonome", + "description": "Exécute jusqu'au bout, ignore les confirmations" + } + } + }, + "bootGate": { + "waiting": "En attente de démarrage…", + "errorHeading": "Impossible de se connecter à FiestaBoard", + "errorDescription": "Vérifiez que l'application est en cours d'exécution et essayez de recharger la page.", + "refreshPage": "Recharger la page" + }, + "globalAiChatDrawer": { + "panelAriaLabel": "Chat IA FiestaBot" + }, "plainTextEditor": { "placeholder": "Tapez votre texte de modèle...", "lineCount": "{current} / {total} lignes", @@ -1212,7 +1352,8 @@ "change": "Modifier", "selectAttribute": "Sélectionner un attribut", "valueLabel": "Valeur", - "insert": "Insérer" + "insert": "Insérer", + "searchAriaLabel": "Rechercher des entités" }, "pluginSettings": { "title": "Mises à jour des plugins", @@ -1510,10 +1651,10 @@ "importWithMissingPlugins": "Certains plugins ne sont pas encore activés : {plugins}. Vous pouvez quand même importer et les activer plus tard." }, "aiChatPanel": { + "messagesAriaLabel": "Messages du chat", + "taskStatusAriaLabel": "Progression des tâches", + "taskProgressAriaLabel": "Progression des tâches IA", "clearConversationAriaLabel": "Effacer la conversation", "closePanelAriaLabel": "Fermer FiestaBot (Beta)" - }, - "aiChat": { - "taskProgressAriaLabel": "Progression des tâches IA" } } diff --git a/web/messages/it.json b/web/messages/it.json index f22fa79c..39fad758 100644 --- a/web/messages/it.json +++ b/web/messages/it.json @@ -1002,8 +1002,148 @@ "wifi": "WiFi", "quotes": "Citazioni", "rotation": "Rotazione" + }, + "on": "Attivo", + "off": "Disattivo", + "toggleServiceAriaLabel": "Attiva/disattiva {name}" + }, + "accountSection": { + "signedIn": { + "title": "Accesso effettuato", + "description": "Hai effettuato l'accesso come {username}." + }, + "changeUsername": { + "title": "Cambia nome utente", + "description": "Scegli un nuovo nome di accesso. Richiede la password attuale.", + "formAriaLabel": "Cambia nome utente", + "newUsernameLabel": "Nuovo nome utente", + "currentPasswordLabel": "Password attuale", + "submit": "Salva nome utente", + "submitting": "Salvataggio…", + "success": "Nome utente aggiornato", + "failure": "Modifica del nome utente non riuscita" + }, + "changePassword": { + "title": "Cambia password", + "description": "Cambia la tua password. Tutte le altre sessioni connesse con la vecchia password verranno disconnesse.", + "formAriaLabel": "Cambia password", + "currentPasswordLabel": "Password attuale", + "newPasswordLabel": "Nuova password", + "newPasswordHint": "Almeno 8 caratteri.", + "confirmPasswordLabel": "Conferma nuova password", + "submit": "Salva password", + "submitting": "Salvataggio…", + "success": "Password aggiornata", + "failure": "Modifica della password non riuscita", + "tooShort": "La nuova password deve contenere almeno 8 caratteri.", + "mismatch": "Le password non corrispondono." + }, + "signOut": { + "title": "Esci", + "description": "Termina la sessione corrente. Tornerai alla pagina di accesso.", + "button": "Esci" + }, + "disableLogin": { + "title": "Disabilita l'accesso", + "description": "Disabilita completamente l'autenticazione. Chiunque possa raggiungere questo FiestaBoard sulla rete potrà modificare le impostazioni e leggere le chiavi API. Sconsigliato a meno che questo dispositivo non si trovi su una rete privata completamente affidabile.", + "button": "Disabilita l'accesso", + "dialogTitle": "Disabilitare l'accesso per questo FiestaBoard?", + "dialogBody1": "Disabilitare l'accesso rimuove l'account {username} e apre questo FiestaBoard a chiunque possa raggiungerlo sulla rete — potranno leggere le tue chiavi API, modificare la configurazione del tuo tabellone e cambiare qualsiasi impostazione.", + "dialogBody2": "Fallo solo se questo dispositivo si trova su una rete privata completamente affidabile (nessun coinquilino, nessun ospite, nessun dispositivo smart-home che non controlli). Fortemente sconsigliato se questo FiestaBoard è raggiungibile da internet.", + "dialogBody3": "Il tuo tabellone continua a funzionare normalmente in entrambi i casi — questo controlla solo chi può accedere per modificare le impostazioni.", + "confirmPasswordLabel": "Conferma la tua password attuale per continuare", + "confirm": "Sì, disabilita l'accesso", + "confirming": "Disabilitazione…", + "success": "Autenticazione disabilitata", + "failure": "Impossibile disabilitare l'autenticazione" + }, + "enableLogin": { + "title": "Attiva l'accesso", + "description": "L'accesso è attualmente disattivato. Chiunque possa raggiungere questo FiestaBoard sulla rete può leggere le tue chiavi API, modificare la configurazione del tuo tabellone e cambiare qualsiasi impostazione.", + "body": "Fortemente consigliato se condividi il Wi-Fi con persone di cui non ti fidi completamente (coinquilini, ospiti, dispositivi smart-home), o se questo FiestaBoard è raggiungibile da internet. Il tuo tabellone continua a funzionare normalmente in entrambi i casi — l'accesso controlla solo chi può accedere per modificare le impostazioni.", + "button": "Configura un nome utente e una password", + "submitting": "Attivazione…", + "failure": "Impossibile attivare l'accesso" } }, + "aiActionConfirmation": { + "deny": "Nega", + "allow": "Consenti", + "working": "In corso…", + "done": "Fatto", + "denied": "Negato", + "noChanges": "nessuna modifica", + "noValues": "nessun valore", + "noChangesSpecified": "Nessuna modifica specificata.", + "openEnd": "aperto", + "label": { + "installPlugin": "Installa plugin: {id}", + "updatePluginConfig": "Configura plugin: {id}", + "updatePlugin": "Aggiorna plugin: {id}", + "enablePlugin": "Abilita plugin: {id}", + "disablePlugin": "Disabilita plugin: {id}", + "uninstallPlugin": "Disinstalla plugin: {id}", + "updateSetting": "Cambia impostazione: {category}", + "createCollection": "Crea collezione: \"{name}\"", + "updateCollection": "Aggiorna collezione", + "createSchedule": "Crea pianificazione", + "updateSchedule": "Aggiorna pianificazione", + "deleteSchedule": "Elimina pianificazione", + "triggerSystemUpdate": "Aggiornamento di sistema" + }, + "description": { + "installPlugin": "Installa \"{id}\" dal registro ufficiale.", + "installPluginEnable": "Installa \"{id}\" dal registro ufficiale e lo abilita.", + "updatePluginConfig": "Aggiorna la configurazione di \"{id}\": {keys}.", + "updatePlugin": "Scarica e installa l'ultima versione del registro di \"{id}\".", + "enablePlugin": "Abilita \"{id}\" affinché possa fornire dati alle tue board.", + "disablePlugin": "Disabilita \"{id}\" senza rimuoverlo. Può essere riabilitato in seguito.", + "uninstallPlugin": "Rimuove definitivamente \"{id}\". Questa azione non può essere annullata.", + "updateSetting": "Imposta {values} nelle impostazioni {category}.", + "createCollection": "Crea una collezione con {count, plural, one {# pagina} other {# pagine}}, alternando ogni {interval}s.", + "createSchedule": "Mostra la pagina \"{page}\" dalle {time} nei giorni {days}.", + "deleteSchedule": "Rimuove definitivamente la pianificazione \"{id}\". Questa azione non può essere annullata.", + "triggerSystemUpdate": "Scarica e installa l'ultimo aggiornamento di FiestaBoard. Il sistema si riavvierà brevemente." + }, + "change": { + "rename": "rinomina in \"{name}\"", + "setPages": "imposta {count, plural, one {# pagina} other {# pagine}}", + "interval": "intervallo → {interval}s", + "page": "pagina → {page}", + "start": "inizio → {start}", + "end": "fine → {end}", + "days": "giorni → {days}", + "enable": "abilita", + "disable": "disabilita" + } + }, + "chainingModePicker": { + "menuTitle": "Modalità di concatenamento IA", + "triggerAriaLabel": "Modalità di concatenamento IA: {mode}", + "modes": { + "manual": { + "label": "Manuale", + "description": "Ti chiederò di nuovo dopo ogni azione" + }, + "autoContinue": { + "label": "Continuazione automatica", + "description": "Concatena le azioni, conferma ogni passaggio" + }, + "autonomous": { + "label": "Autonomo", + "description": "Esegue fino al completamento, salta le conferme" + } + } + }, + "bootGate": { + "waiting": "In attesa di avvio…", + "errorHeading": "Impossibile connettersi a FiestaBoard", + "errorDescription": "Verifica che l'app sia in esecuzione e prova a ricaricare la pagina.", + "refreshPage": "Ricarica la pagina" + }, + "globalAiChatDrawer": { + "panelAriaLabel": "Chat IA di FiestaBot" + }, "plainTextEditor": { "placeholder": "Scrivi il testo del template...", "lineCount": "{current} / {total} righe", @@ -1212,7 +1352,8 @@ "change": "Cambia", "selectAttribute": "Seleziona attributo", "valueLabel": "Valore", - "insert": "Inserisci" + "insert": "Inserisci", + "searchAriaLabel": "Cerca entità" }, "pluginSettings": { "title": "Aggiornamenti plugin", @@ -1510,10 +1651,10 @@ "importWithMissingPlugins": "Alcuni plugin non sono ancora attivi: {plugins}. Puoi comunque importare e attivarli più tardi." }, "aiChatPanel": { + "messagesAriaLabel": "Messaggi della chat", + "taskStatusAriaLabel": "Avanzamento delle attività", + "taskProgressAriaLabel": "Avanzamento attività IA", "clearConversationAriaLabel": "Cancella conversazione", "closePanelAriaLabel": "Chiudi FiestaBot (Beta)" - }, - "aiChat": { - "taskProgressAriaLabel": "Avanzamento attività IA" } } diff --git a/web/messages/ja.json b/web/messages/ja.json index 6256b62f..e7348760 100644 --- a/web/messages/ja.json +++ b/web/messages/ja.json @@ -1002,8 +1002,148 @@ "wifi": "WiFi", "quotes": "名言", "rotation": "ローテーション" + }, + "on": "オン", + "off": "オフ", + "toggleServiceAriaLabel": "{name}を切り替え" + }, + "accountSection": { + "signedIn": { + "title": "サインイン中", + "description": "現在 {username} としてサインインしています。" + }, + "changeUsername": { + "title": "ユーザー名を変更", + "description": "新しいサインイン名を選択します。現在のパスワードが必要です。", + "formAriaLabel": "ユーザー名を変更", + "newUsernameLabel": "新しいユーザー名", + "currentPasswordLabel": "現在のパスワード", + "submit": "ユーザー名を保存", + "submitting": "保存中…", + "success": "ユーザー名を更新しました", + "failure": "ユーザー名の変更に失敗しました" + }, + "changePassword": { + "title": "パスワードを変更", + "description": "パスワードを変更します。古いパスワードでサインインしている他のセッションはすべてサインアウトされます。", + "formAriaLabel": "パスワードを変更", + "currentPasswordLabel": "現在のパスワード", + "newPasswordLabel": "新しいパスワード", + "newPasswordHint": "8文字以上。", + "confirmPasswordLabel": "新しいパスワードを確認", + "submit": "パスワードを保存", + "submitting": "保存中…", + "success": "パスワードを更新しました", + "failure": "パスワードの変更に失敗しました", + "tooShort": "新しいパスワードは8文字以上にしてください。", + "mismatch": "パスワードが一致しません。" + }, + "signOut": { + "title": "サインアウト", + "description": "現在のセッションを終了します。サインインページに戻ります。", + "button": "サインアウト" + }, + "disableLogin": { + "title": "ログインを無効化", + "description": "認証を完全に無効にします。ネットワーク上でこの FiestaBoard にアクセスできる人は誰でも設定を変更し、API キーを読み取れるようになります。このデバイスが完全に信頼できるプライベートネットワーク上にある場合を除き、おすすめしません。", + "button": "ログインを無効化", + "dialogTitle": "この FiestaBoard のログインを無効にしますか?", + "dialogBody1": "ログインを無効にすると {username} アカウントが削除され、ネットワーク上でアクセスできる人全員にこの FiestaBoard が開かれます。彼らは API キーを読み取り、ボードの構成を変更し、あらゆる設定を変更できるようになります。", + "dialogBody2": "このデバイスが完全に信頼できるプライベートネットワーク上にある場合(ルームメイト、ゲスト、管理外のスマートホーム機器がない場合)にのみ実行してください。この FiestaBoard がインターネットから到達可能な場合は強くおすすめしません。", + "dialogBody3": "いずれの場合もボードは通常どおり表示され続けます。これは設定を変更するためにサインインできる人を制御するだけです。", + "confirmPasswordLabel": "続行するには現在のパスワードを確認してください", + "confirm": "はい、ログインを無効化します", + "confirming": "無効化中…", + "success": "認証を無効化しました", + "failure": "認証の無効化に失敗しました" + }, + "enableLogin": { + "title": "ログインを有効化", + "description": "ログインは現在オフです。ネットワーク上でこの FiestaBoard にアクセスできる人は誰でも API キーを読み取り、ボードの構成を変更し、あらゆる設定を変更できます。", + "body": "完全には信頼していない人(ルームメイト、ゲスト、スマートホーム機器)と Wi-Fi を共有している場合、またはこの FiestaBoard がインターネットから到達可能な場合は強くおすすめします。いずれの場合もボードは通常どおり表示され続けます。ログインは設定を変更するためにサインインできる人を制御するだけです。", + "button": "ユーザー名とパスワードを設定", + "submitting": "有効化中…", + "failure": "ログインを有効化できませんでした" } }, + "aiActionConfirmation": { + "deny": "拒否", + "allow": "許可", + "working": "実行中…", + "done": "完了", + "denied": "拒否しました", + "noChanges": "変更なし", + "noValues": "値なし", + "noChangesSpecified": "変更が指定されていません。", + "openEnd": "未指定", + "label": { + "installPlugin": "プラグインをインストール: {id}", + "updatePluginConfig": "プラグインを設定: {id}", + "updatePlugin": "プラグインを更新: {id}", + "enablePlugin": "プラグインを有効化: {id}", + "disablePlugin": "プラグインを無効化: {id}", + "uninstallPlugin": "プラグインをアンインストール: {id}", + "updateSetting": "設定を変更: {category}", + "createCollection": "コレクションを作成: \"{name}\"", + "updateCollection": "コレクションを更新", + "createSchedule": "スケジュールを作成", + "updateSchedule": "スケジュールを更新", + "deleteSchedule": "スケジュールを削除", + "triggerSystemUpdate": "システム更新" + }, + "description": { + "installPlugin": "公式レジストリから「{id}」をインストールします。", + "installPluginEnable": "公式レジストリから「{id}」をインストールして有効化します。", + "updatePluginConfig": "「{id}」の設定を更新します: {keys}。", + "updatePlugin": "「{id}」の最新のレジストリ版をダウンロードしてインストールします。", + "enablePlugin": "「{id}」を有効にして、ボードにデータを提供できるようにします。", + "disablePlugin": "「{id}」を削除せずに無効化します。後で再び有効化できます。", + "uninstallPlugin": "「{id}」を完全に削除します。この操作は元に戻せません。", + "updateSetting": "{category} 設定に {values} を設定します。", + "createCollection": "{count, plural, other {# ページ}}のコレクションを作成し、{interval}秒ごとに切り替えます。", + "createSchedule": "「{page}」ページを {days} の日に {time} に表示します。", + "deleteSchedule": "スケジュール「{id}」を完全に削除します。この操作は元に戻せません。", + "triggerSystemUpdate": "最新の FiestaBoard アップデートをダウンロードしてインストールします。システムは短時間再起動します。" + }, + "change": { + "rename": "「{name}」に名前を変更", + "setPages": "{count, plural, other {# ページ}}を設定", + "interval": "間隔 → {interval}秒", + "page": "ページ → {page}", + "start": "開始 → {start}", + "end": "終了 → {end}", + "days": "曜日 → {days}", + "enable": "有効化", + "disable": "無効化" + } + }, + "chainingModePicker": { + "menuTitle": "AI チェーンモード", + "triggerAriaLabel": "AI チェーンモード: {mode}", + "modes": { + "manual": { + "label": "手動", + "description": "各操作のあとに再確認します" + }, + "autoContinue": { + "label": "自動継続", + "description": "操作を連鎖し、各ステップを確認します" + }, + "autonomous": { + "label": "自律", + "description": "完了まで実行し、確認をスキップします" + } + } + }, + "bootGate": { + "waiting": "起動を待機中…", + "errorHeading": "FiestaBoard に接続できませんでした", + "errorDescription": "アプリが起動していることを確認し、ページを再読み込みしてください。", + "refreshPage": "ページを再読み込み" + }, + "globalAiChatDrawer": { + "panelAriaLabel": "FiestaBot AI チャット" + }, "plainTextEditor": { "placeholder": "テンプレートテキストを入力...", "lineCount": "{current} / {total} 行", @@ -1212,7 +1352,8 @@ "change": "変更", "selectAttribute": "属性を選択", "valueLabel": "値", - "insert": "挿入" + "insert": "挿入", + "searchAriaLabel": "エンティティを検索" }, "pluginSettings": { "title": "プラグイン更新", @@ -1510,10 +1651,10 @@ "importWithMissingPlugins": "一部のプラグインがまだ有効化されていません: {plugins}。インポートして後で有効化することもできます。" }, "aiChatPanel": { + "messagesAriaLabel": "チャットメッセージ", + "taskStatusAriaLabel": "タスクの進捗", + "taskProgressAriaLabel": "AI タスクの進行状況", "clearConversationAriaLabel": "会話をクリア", "closePanelAriaLabel": "FiestaBot (Beta) を閉じる" - }, - "aiChat": { - "taskProgressAriaLabel": "AI タスクの進行状況" } } diff --git a/web/messages/ko.json b/web/messages/ko.json index 9f2db059..fffb1b57 100644 --- a/web/messages/ko.json +++ b/web/messages/ko.json @@ -1002,8 +1002,148 @@ "wifi": "WiFi", "quotes": "명언", "rotation": "회전" + }, + "on": "켜짐", + "off": "꺼짐", + "toggleServiceAriaLabel": "{name} 전환" + }, + "accountSection": { + "signedIn": { + "title": "로그인됨", + "description": "현재 {username}(으)로 로그인되어 있습니다." + }, + "changeUsername": { + "title": "사용자 이름 변경", + "description": "새 로그인 이름을 선택하세요. 현재 비밀번호가 필요합니다.", + "formAriaLabel": "사용자 이름 변경", + "newUsernameLabel": "새 사용자 이름", + "currentPasswordLabel": "현재 비밀번호", + "submit": "사용자 이름 저장", + "submitting": "저장 중…", + "success": "사용자 이름이 업데이트되었습니다", + "failure": "사용자 이름 변경에 실패했습니다" + }, + "changePassword": { + "title": "비밀번호 변경", + "description": "비밀번호를 변경합니다. 이전 비밀번호로 로그인된 다른 모든 세션은 로그아웃됩니다.", + "formAriaLabel": "비밀번호 변경", + "currentPasswordLabel": "현재 비밀번호", + "newPasswordLabel": "새 비밀번호", + "newPasswordHint": "최소 8자.", + "confirmPasswordLabel": "새 비밀번호 확인", + "submit": "비밀번호 저장", + "submitting": "저장 중…", + "success": "비밀번호가 업데이트되었습니다", + "failure": "비밀번호 변경에 실패했습니다", + "tooShort": "새 비밀번호는 최소 8자 이상이어야 합니다.", + "mismatch": "비밀번호가 일치하지 않습니다." + }, + "signOut": { + "title": "로그아웃", + "description": "현재 세션을 종료합니다. 로그인 페이지로 돌아갑니다.", + "button": "로그아웃" + }, + "disableLogin": { + "title": "로그인 비활성화", + "description": "인증을 완전히 끕니다. 네트워크에서 이 FiestaBoard에 접근할 수 있는 사람은 누구나 설정을 변경하고 API 키를 읽을 수 있게 됩니다. 이 기기가 완전히 신뢰할 수 있는 사설 네트워크에 있지 않다면 권장하지 않습니다.", + "button": "로그인 비활성화", + "dialogTitle": "이 FiestaBoard의 로그인을 비활성화하시겠습니까?", + "dialogBody1": "로그인을 비활성화하면 {username} 계정이 제거되고 네트워크에서 접근할 수 있는 모든 사람에게 이 FiestaBoard가 열립니다. 그들은 API 키를 읽고, 보드 구성을 변경하고, 모든 설정을 수정할 수 있게 됩니다.", + "dialogBody2": "이 기기가 완전히 신뢰할 수 있는 사설 네트워크에 있는 경우(룸메이트, 손님, 제어할 수 없는 스마트홈 기기가 없는 경우)에만 수행하세요. 이 FiestaBoard가 인터넷에서 접근 가능한 경우 강력히 권장하지 않습니다.", + "dialogBody3": "어느 경우든 보드는 평소처럼 계속 표시됩니다. 이것은 설정을 변경하기 위해 로그인할 수 있는 사람만 제어합니다.", + "confirmPasswordLabel": "계속하려면 현재 비밀번호를 확인하세요", + "confirm": "예, 로그인을 비활성화합니다", + "confirming": "비활성화 중…", + "success": "인증이 비활성화되었습니다", + "failure": "인증을 비활성화하지 못했습니다" + }, + "enableLogin": { + "title": "로그인 활성화", + "description": "로그인이 현재 꺼져 있습니다. 네트워크에서 이 FiestaBoard에 접근할 수 있는 사람은 누구나 API 키를 읽고, 보드 구성을 변경하고, 모든 설정을 수정할 수 있습니다.", + "body": "완전히 신뢰하지 않는 사람들(룸메이트, 손님, 스마트홈 기기)과 Wi-Fi를 공유하거나, 이 FiestaBoard가 인터넷에서 접근 가능한 경우 강력히 권장합니다. 어느 경우든 보드는 평소처럼 계속 표시됩니다. 로그인은 설정을 변경하기 위해 로그인할 수 있는 사람만 제어합니다.", + "button": "사용자 이름과 비밀번호 설정", + "submitting": "활성화 중…", + "failure": "로그인을 활성화할 수 없습니다" } }, + "aiActionConfirmation": { + "deny": "거부", + "allow": "허용", + "working": "처리 중…", + "done": "완료", + "denied": "거부됨", + "noChanges": "변경 없음", + "noValues": "값 없음", + "noChangesSpecified": "지정된 변경 사항이 없습니다.", + "openEnd": "미지정", + "label": { + "installPlugin": "플러그인 설치: {id}", + "updatePluginConfig": "플러그인 구성: {id}", + "updatePlugin": "플러그인 업데이트: {id}", + "enablePlugin": "플러그인 활성화: {id}", + "disablePlugin": "플러그인 비활성화: {id}", + "uninstallPlugin": "플러그인 제거: {id}", + "updateSetting": "설정 변경: {category}", + "createCollection": "컬렉션 만들기: \"{name}\"", + "updateCollection": "컬렉션 업데이트", + "createSchedule": "일정 만들기", + "updateSchedule": "일정 업데이트", + "deleteSchedule": "일정 삭제", + "triggerSystemUpdate": "시스템 업데이트" + }, + "description": { + "installPlugin": "공식 레지스트리에서 \"{id}\"을(를) 설치합니다.", + "installPluginEnable": "공식 레지스트리에서 \"{id}\"을(를) 설치하고 활성화합니다.", + "updatePluginConfig": "\"{id}\"의 구성을 업데이트합니다: {keys}.", + "updatePlugin": "\"{id}\"의 최신 레지스트리 버전을 다운로드하여 설치합니다.", + "enablePlugin": "\"{id}\"을(를) 활성화하여 보드에 데이터를 제공할 수 있도록 합니다.", + "disablePlugin": "\"{id}\"을(를) 제거하지 않고 비활성화합니다. 나중에 다시 활성화할 수 있습니다.", + "uninstallPlugin": "\"{id}\"을(를) 영구적으로 제거합니다. 이 작업은 취소할 수 없습니다.", + "updateSetting": "{category} 설정에서 {values}을(를) 설정합니다.", + "createCollection": "{count, plural, other {# 페이지}}로 컬렉션을 만들고 {interval}초마다 전환합니다.", + "createSchedule": "\"{page}\" 페이지를 {days} 요일에 {time}에 표시합니다.", + "deleteSchedule": "일정 \"{id}\"을(를) 영구적으로 제거합니다. 이 작업은 취소할 수 없습니다.", + "triggerSystemUpdate": "최신 FiestaBoard 업데이트를 다운로드하여 설치합니다. 시스템이 잠시 다시 시작됩니다." + }, + "change": { + "rename": "\"{name}\"(으)로 이름 변경", + "setPages": "{count, plural, other {# 페이지}} 설정", + "interval": "간격 → {interval}초", + "page": "페이지 → {page}", + "start": "시작 → {start}", + "end": "종료 → {end}", + "days": "요일 → {days}", + "enable": "활성화", + "disable": "비활성화" + } + }, + "chainingModePicker": { + "menuTitle": "AI 체이닝 모드", + "triggerAriaLabel": "AI 체이닝 모드: {mode}", + "modes": { + "manual": { + "label": "수동", + "description": "각 작업 후에 다시 확인합니다" + }, + "autoContinue": { + "label": "자동 계속", + "description": "작업을 연결하고 각 단계를 확인합니다" + }, + "autonomous": { + "label": "자율", + "description": "완료될 때까지 실행하며 확인을 건너뜁니다" + } + } + }, + "bootGate": { + "waiting": "시작을 기다리는 중…", + "errorHeading": "FiestaBoard에 연결할 수 없습니다", + "errorDescription": "앱이 실행 중인지 확인하고 페이지를 새로 고쳐 보세요.", + "refreshPage": "페이지 새로 고침" + }, + "globalAiChatDrawer": { + "panelAriaLabel": "FiestaBot AI 채팅" + }, "plainTextEditor": { "placeholder": "템플릿 텍스트를 입력하세요...", "lineCount": "{current} / {total} 줄", @@ -1212,7 +1352,8 @@ "change": "변경", "selectAttribute": "속성 선택", "valueLabel": "값", - "insert": "삽입" + "insert": "삽입", + "searchAriaLabel": "엔터티 검색" }, "pluginSettings": { "title": "플러그인 업데이트", @@ -1510,10 +1651,10 @@ "importWithMissingPlugins": "일부 플러그인이 아직 활성화되지 않았습니다: {plugins}. 가져온 후 나중에 활성화할 수 있습니다." }, "aiChatPanel": { + "messagesAriaLabel": "채팅 메시지", + "taskStatusAriaLabel": "작업 진행 상황", + "taskProgressAriaLabel": "AI 작업 진행률", "clearConversationAriaLabel": "대화 지우기", "closePanelAriaLabel": "FiestaBot (Beta) 닫기" - }, - "aiChat": { - "taskProgressAriaLabel": "AI 작업 진행률" } } diff --git a/web/messages/nl.json b/web/messages/nl.json index 4436f371..185772c1 100644 --- a/web/messages/nl.json +++ b/web/messages/nl.json @@ -1002,8 +1002,148 @@ "wifi": "WiFi", "quotes": "Citaten", "rotation": "Rotatie" + }, + "on": "Aan", + "off": "Uit", + "toggleServiceAriaLabel": "{name} in-/uitschakelen" + }, + "accountSection": { + "signedIn": { + "title": "Aangemeld", + "description": "Je bent momenteel aangemeld als {username}." + }, + "changeUsername": { + "title": "Gebruikersnaam wijzigen", + "description": "Kies een nieuwe aanmeldnaam. Vereist je huidige wachtwoord.", + "formAriaLabel": "Gebruikersnaam wijzigen", + "newUsernameLabel": "Nieuwe gebruikersnaam", + "currentPasswordLabel": "Huidig wachtwoord", + "submit": "Gebruikersnaam opslaan", + "submitting": "Opslaan…", + "success": "Gebruikersnaam bijgewerkt", + "failure": "Wijzigen van gebruikersnaam mislukt" + }, + "changePassword": { + "title": "Wachtwoord wijzigen", + "description": "Wijzig je wachtwoord. Alle andere sessies die met het oude wachtwoord zijn aangemeld, worden afgemeld.", + "formAriaLabel": "Wachtwoord wijzigen", + "currentPasswordLabel": "Huidig wachtwoord", + "newPasswordLabel": "Nieuw wachtwoord", + "newPasswordHint": "Minstens 8 tekens.", + "confirmPasswordLabel": "Nieuw wachtwoord bevestigen", + "submit": "Wachtwoord opslaan", + "submitting": "Opslaan…", + "success": "Wachtwoord bijgewerkt", + "failure": "Wijzigen van wachtwoord mislukt", + "tooShort": "Het nieuwe wachtwoord moet minstens 8 tekens bevatten.", + "mismatch": "De wachtwoorden komen niet overeen." + }, + "signOut": { + "title": "Afmelden", + "description": "Beëindig je huidige sessie. Je wordt teruggestuurd naar de aanmeldpagina.", + "button": "Afmelden" + }, + "disableLogin": { + "title": "Aanmelden uitschakelen", + "description": "Schakel authenticatie volledig uit. Iedereen die dit FiestaBoard op het netwerk kan bereiken, kan dan instellingen wijzigen en API-sleutels lezen. Niet aanbevolen, tenzij dit apparaat zich op een volledig vertrouwd privénetwerk bevindt.", + "button": "Aanmelden uitschakelen", + "dialogTitle": "Aanmelden voor dit FiestaBoard uitschakelen?", + "dialogBody1": "Het uitschakelen van aanmelden verwijdert het account {username} en stelt dit FiestaBoard open voor iedereen die het op het netwerk kan bereiken — zij kunnen je API-sleutels lezen, je bordconfiguratie wijzigen en alle instellingen aanpassen.", + "dialogBody2": "Doe dit alleen als dit apparaat zich op een volledig vertrouwd privénetwerk bevindt (geen huisgenoten, geen gasten, geen smarthome-apparaten die je niet beheert). Sterk afgeraden als dit FiestaBoard bereikbaar is vanaf internet.", + "dialogBody3": "Je bord blijft in beide gevallen normaal weergeven — dit bepaalt alleen wie zich kan aanmelden om instellingen te wijzigen.", + "confirmPasswordLabel": "Bevestig je huidige wachtwoord om door te gaan", + "confirm": "Ja, aanmelden uitschakelen", + "confirming": "Uitschakelen…", + "success": "Authenticatie uitgeschakeld", + "failure": "Authenticatie uitschakelen mislukt" + }, + "enableLogin": { + "title": "Aanmelden inschakelen", + "description": "Aanmelden staat momenteel uit. Iedereen die dit FiestaBoard op het netwerk kan bereiken, kan je API-sleutels lezen, je bordconfiguratie wijzigen en alle instellingen aanpassen.", + "body": "Sterk aanbevolen als je wifi deelt met mensen die je niet volledig vertrouwt (huisgenoten, gasten, smarthome-apparaten), of als dit FiestaBoard bereikbaar is vanaf internet. Je bord blijft in beide gevallen normaal weergeven — aanmelden bepaalt alleen wie zich kan aanmelden om instellingen te wijzigen.", + "button": "Een gebruikersnaam en wachtwoord instellen", + "submitting": "Inschakelen…", + "failure": "Kon aanmelden niet inschakelen" + } + }, + "aiActionConfirmation": { + "deny": "Weigeren", + "allow": "Toestaan", + "working": "Bezig…", + "done": "Klaar", + "denied": "Geweigerd", + "noChanges": "geen wijzigingen", + "noValues": "geen waarden", + "noChangesSpecified": "Geen wijzigingen opgegeven.", + "openEnd": "open", + "label": { + "installPlugin": "Plug-in installeren: {id}", + "updatePluginConfig": "Plug-in configureren: {id}", + "updatePlugin": "Plug-in bijwerken: {id}", + "enablePlugin": "Plug-in inschakelen: {id}", + "disablePlugin": "Plug-in uitschakelen: {id}", + "uninstallPlugin": "Plug-in verwijderen: {id}", + "updateSetting": "Instelling wijzigen: {category}", + "createCollection": "Collectie maken: \"{name}\"", + "updateCollection": "Collectie bijwerken", + "createSchedule": "Planning maken", + "updateSchedule": "Planning bijwerken", + "deleteSchedule": "Planning verwijderen", + "triggerSystemUpdate": "Systeemupdate" + }, + "description": { + "installPlugin": "Installeert \"{id}\" uit het officiële register.", + "installPluginEnable": "Installeert \"{id}\" uit het officiële register en schakelt het in.", + "updatePluginConfig": "Werkt de configuratie van \"{id}\" bij: {keys}.", + "updatePlugin": "Downloadt en installeert de nieuwste registerversie van \"{id}\".", + "enablePlugin": "Schakelt \"{id}\" in zodat het gegevens aan je borden kan leveren.", + "disablePlugin": "Schakelt \"{id}\" uit zonder het te verwijderen. Het kan later opnieuw worden ingeschakeld.", + "uninstallPlugin": "Verwijdert \"{id}\" definitief. Dit kan niet ongedaan worden gemaakt.", + "updateSetting": "Stelt {values} in bij de instellingen voor {category}.", + "createCollection": "Maakt een collectie met {count, plural, one {# pagina} other {# pagina's}}, die elke {interval}s wisselt.", + "createSchedule": "Toont pagina \"{page}\" vanaf {time} op {days}-dagen.", + "deleteSchedule": "Verwijdert planning \"{id}\" definitief. Dit kan niet ongedaan worden gemaakt.", + "triggerSystemUpdate": "Downloadt en installeert de nieuwste FiestaBoard-update. Het systeem start kort opnieuw op." + }, + "change": { + "rename": "hernoemen naar \"{name}\"", + "setPages": "{count, plural, one {# pagina} other {# pagina's}} instellen", + "interval": "interval → {interval}s", + "page": "pagina → {page}", + "start": "begin → {start}", + "end": "einde → {end}", + "days": "dagen → {days}", + "enable": "inschakelen", + "disable": "uitschakelen" + } + }, + "chainingModePicker": { + "menuTitle": "AI-koppelingsmodus", + "triggerAriaLabel": "AI-koppelingsmodus: {mode}", + "modes": { + "manual": { + "label": "Handmatig", + "description": "Ik vraag het na elke actie opnieuw" + }, + "autoContinue": { + "label": "Automatisch doorgaan", + "description": "Koppel acties, bevestig elke stap" + }, + "autonomous": { + "label": "Autonoom", + "description": "Voer tot het einde uit, sla bevestigingen over" + } } }, + "bootGate": { + "waiting": "Wachten op opstarten…", + "errorHeading": "Kan geen verbinding maken met FiestaBoard", + "errorDescription": "Controleer of de app draait en probeer de pagina opnieuw te laden.", + "refreshPage": "Pagina vernieuwen" + }, + "globalAiChatDrawer": { + "panelAriaLabel": "FiestaBot AI-chat" + }, "plainTextEditor": { "placeholder": "Typ je sjabloontekst...", "lineCount": "{current} / {total} regels", @@ -1212,7 +1352,8 @@ "change": "Wijzigen", "selectAttribute": "Selecteer attribuut", "valueLabel": "Waarde", - "insert": "Invoegen" + "insert": "Invoegen", + "searchAriaLabel": "Entiteiten zoeken" }, "pluginSettings": { "title": "Plugin-updates", @@ -1510,10 +1651,10 @@ "importWithMissingPlugins": "Sommige plugins zijn nog niet ingeschakeld: {plugins}. Je kunt nog steeds importeren en ze later inschakelen." }, "aiChatPanel": { + "messagesAriaLabel": "Chatberichten", + "taskStatusAriaLabel": "Taakvoortgang", + "taskProgressAriaLabel": "Voortgang AI-taken", "clearConversationAriaLabel": "Gesprek wissen", "closePanelAriaLabel": "FiestaBot (Beta) sluiten" - }, - "aiChat": { - "taskProgressAriaLabel": "Voortgang AI-taken" } } diff --git a/web/messages/pl.json b/web/messages/pl.json index e5884dfe..8ac1ff0e 100644 --- a/web/messages/pl.json +++ b/web/messages/pl.json @@ -1002,8 +1002,148 @@ "wifi": "WiFi", "quotes": "Cytaty", "rotation": "Rotacja" + }, + "on": "Wł.", + "off": "Wył.", + "toggleServiceAriaLabel": "Przełącz {name}" + }, + "accountSection": { + "signedIn": { + "title": "Zalogowano", + "description": "Jesteś obecnie zalogowany jako {username}." + }, + "changeUsername": { + "title": "Zmień nazwę użytkownika", + "description": "Wybierz nową nazwę logowania. Wymaga obecnego hasła.", + "formAriaLabel": "Zmień nazwę użytkownika", + "newUsernameLabel": "Nowa nazwa użytkownika", + "currentPasswordLabel": "Obecne hasło", + "submit": "Zapisz nazwę użytkownika", + "submitting": "Zapisywanie…", + "success": "Zaktualizowano nazwę użytkownika", + "failure": "Zmiana nazwy użytkownika nie powiodła się" + }, + "changePassword": { + "title": "Zmień hasło", + "description": "Zmień swoje hasło. Wszystkie inne sesje zalogowane przy użyciu starego hasła zostaną wylogowane.", + "formAriaLabel": "Zmień hasło", + "currentPasswordLabel": "Obecne hasło", + "newPasswordLabel": "Nowe hasło", + "newPasswordHint": "Co najmniej 8 znaków.", + "confirmPasswordLabel": "Potwierdź nowe hasło", + "submit": "Zapisz hasło", + "submitting": "Zapisywanie…", + "success": "Zaktualizowano hasło", + "failure": "Zmiana hasła nie powiodła się", + "tooShort": "Nowe hasło musi mieć co najmniej 8 znaków.", + "mismatch": "Hasła nie są zgodne." + }, + "signOut": { + "title": "Wyloguj się", + "description": "Zakończ bieżącą sesję. Zostaniesz przekierowany z powrotem na stronę logowania.", + "button": "Wyloguj się" + }, + "disableLogin": { + "title": "Wyłącz logowanie", + "description": "Całkowicie wyłącz uwierzytelnianie. Każdy, kto może uzyskać dostęp do tego FiestaBoard w sieci, będzie mógł zmieniać ustawienia i odczytywać klucze API. Niezalecane, chyba że to urządzenie znajduje się w pełni zaufanej sieci prywatnej.", + "button": "Wyłącz logowanie", + "dialogTitle": "Wyłączyć logowanie dla tego FiestaBoard?", + "dialogBody1": "Wyłączenie logowania usuwa konto {username} i otwiera ten FiestaBoard dla każdego, kto może uzyskać do niego dostęp w sieci — będą mogli odczytywać Twoje klucze API, zmieniać konfigurację tablicy i modyfikować dowolne ustawienia.", + "dialogBody2": "Zrób to tylko wtedy, gdy to urządzenie znajduje się w pełni zaufanej sieci prywatnej (bez współlokatorów, bez gości, bez urządzeń smart home, których nie kontrolujesz). Zdecydowanie niezalecane, jeśli ten FiestaBoard jest dostępny z internetu.", + "dialogBody3": "Twoja tablica nadal wyświetla się normalnie w obu przypadkach — kontroluje to tylko, kto może się zalogować, aby zmienić ustawienia.", + "confirmPasswordLabel": "Potwierdź swoje obecne hasło, aby kontynuować", + "confirm": "Tak, wyłącz logowanie", + "confirming": "Wyłączanie…", + "success": "Uwierzytelnianie wyłączone", + "failure": "Nie udało się wyłączyć uwierzytelniania" + }, + "enableLogin": { + "title": "Włącz logowanie", + "description": "Logowanie jest obecnie wyłączone. Każdy, kto może uzyskać dostęp do tego FiestaBoard w sieci, może odczytywać Twoje klucze API, zmieniać konfigurację tablicy i modyfikować dowolne ustawienia.", + "body": "Zdecydowanie zalecane, jeśli dzielisz Wi-Fi z osobami, którym nie do końca ufasz (współlokatorzy, goście, urządzenia smart home), lub jeśli ten FiestaBoard jest dostępny z internetu. Twoja tablica nadal wyświetla się normalnie w obu przypadkach — logowanie kontroluje tylko, kto może się zalogować, aby zmienić ustawienia.", + "button": "Skonfiguruj nazwę użytkownika i hasło", + "submitting": "Włączanie…", + "failure": "Nie udało się włączyć logowania" } }, + "aiActionConfirmation": { + "deny": "Odmów", + "allow": "Zezwól", + "working": "Trwa…", + "done": "Gotowe", + "denied": "Odmówiono", + "noChanges": "brak zmian", + "noValues": "brak wartości", + "noChangesSpecified": "Nie określono zmian.", + "openEnd": "otwarte", + "label": { + "installPlugin": "Zainstaluj wtyczkę: {id}", + "updatePluginConfig": "Skonfiguruj wtyczkę: {id}", + "updatePlugin": "Zaktualizuj wtyczkę: {id}", + "enablePlugin": "Włącz wtyczkę: {id}", + "disablePlugin": "Wyłącz wtyczkę: {id}", + "uninstallPlugin": "Odinstaluj wtyczkę: {id}", + "updateSetting": "Zmień ustawienie: {category}", + "createCollection": "Utwórz kolekcję: \"{name}\"", + "updateCollection": "Zaktualizuj kolekcję", + "createSchedule": "Utwórz harmonogram", + "updateSchedule": "Zaktualizuj harmonogram", + "deleteSchedule": "Usuń harmonogram", + "triggerSystemUpdate": "Aktualizacja systemu" + }, + "description": { + "installPlugin": "Instaluje \"{id}\" z oficjalnego rejestru.", + "installPluginEnable": "Instaluje \"{id}\" z oficjalnego rejestru i włącza ją.", + "updatePluginConfig": "Aktualizuje konfigurację \"{id}\": {keys}.", + "updatePlugin": "Pobiera i instaluje najnowszą wersję \"{id}\" z rejestru.", + "enablePlugin": "Włącza \"{id}\", aby mogła dostarczać dane do Twoich tablic.", + "disablePlugin": "Wyłącza \"{id}\" bez usuwania. Można ją później ponownie włączyć.", + "uninstallPlugin": "Trwale usuwa \"{id}\". Tej operacji nie można cofnąć.", + "updateSetting": "Ustawia {values} w ustawieniach {category}.", + "createCollection": "Tworzy kolekcję z {count, plural, one {# stroną} other {# stronami}}, zmieniając co {interval}s.", + "createSchedule": "Pokazuje stronę \"{page}\" od {time} w dni {days}.", + "deleteSchedule": "Trwale usuwa harmonogram \"{id}\". Tej operacji nie można cofnąć.", + "triggerSystemUpdate": "Pobiera i instaluje najnowszą aktualizację FiestaBoard. System na chwilę uruchomi się ponownie." + }, + "change": { + "rename": "zmień nazwę na \"{name}\"", + "setPages": "ustaw {count, plural, one {# stronę} other {# stron}}", + "interval": "interwał → {interval}s", + "page": "strona → {page}", + "start": "początek → {start}", + "end": "koniec → {end}", + "days": "dni → {days}", + "enable": "włącz", + "disable": "wyłącz" + } + }, + "chainingModePicker": { + "menuTitle": "Tryb łączenia AI", + "triggerAriaLabel": "Tryb łączenia AI: {mode}", + "modes": { + "manual": { + "label": "Ręczny", + "description": "Zapytam ponownie po każdej akcji" + }, + "autoContinue": { + "label": "Automatyczna kontynuacja", + "description": "Łączy akcje, potwierdza każdy krok" + }, + "autonomous": { + "label": "Autonomiczny", + "description": "Wykonuje do końca, pomija potwierdzenia" + } + } + }, + "bootGate": { + "waiting": "Oczekiwanie na uruchomienie…", + "errorHeading": "Nie można połączyć się z FiestaBoard", + "errorDescription": "Sprawdź, czy aplikacja działa, i spróbuj odświeżyć stronę.", + "refreshPage": "Odśwież stronę" + }, + "globalAiChatDrawer": { + "panelAriaLabel": "Czat AI FiestaBot" + }, "plainTextEditor": { "placeholder": "Wpisz tekst szablonu...", "lineCount": "{current} / {total} linii", @@ -1212,7 +1352,8 @@ "change": "Zmień", "selectAttribute": "Wybierz atrybut", "valueLabel": "Wartość", - "insert": "Wstaw" + "insert": "Wstaw", + "searchAriaLabel": "Szukaj encji" }, "pluginSettings": { "title": "Aktualizacje wtyczek", @@ -1510,10 +1651,10 @@ "importWithMissingPlugins": "Niektóre wtyczki nie są jeszcze włączone: {plugins}. Możesz wciąż zaimportować i włączyć je później." }, "aiChatPanel": { + "messagesAriaLabel": "Wiadomości czatu", + "taskStatusAriaLabel": "Postęp zadań", + "taskProgressAriaLabel": "Postęp zadań AI", "clearConversationAriaLabel": "Wyczyść rozmowę", "closePanelAriaLabel": "Zamknij FiestaBot (Beta)" - }, - "aiChat": { - "taskProgressAriaLabel": "Postęp zadań AI" } } diff --git a/web/messages/pt.json b/web/messages/pt.json index b411a65b..6cbc050c 100644 --- a/web/messages/pt.json +++ b/web/messages/pt.json @@ -1002,8 +1002,148 @@ "wifi": "WiFi", "quotes": "Citações", "rotation": "Rotação" + }, + "on": "Ligado", + "off": "Desligado", + "toggleServiceAriaLabel": "Alternar {name}" + }, + "accountSection": { + "signedIn": { + "title": "Sessão iniciada", + "description": "Atualmente tem a sessão iniciada como {username}." + }, + "changeUsername": { + "title": "Alterar nome de utilizador", + "description": "Escolha um novo nome de início de sessão. Requer a sua palavra-passe atual.", + "formAriaLabel": "Alterar nome de utilizador", + "newUsernameLabel": "Novo nome de utilizador", + "currentPasswordLabel": "Palavra-passe atual", + "submit": "Guardar nome de utilizador", + "submitting": "A guardar…", + "success": "Nome de utilizador atualizado", + "failure": "Não foi possível alterar o nome de utilizador" + }, + "changePassword": { + "title": "Alterar palavra-passe", + "description": "Altere a sua palavra-passe. Todas as outras sessões iniciadas com a palavra-passe antiga serão terminadas.", + "formAriaLabel": "Alterar palavra-passe", + "currentPasswordLabel": "Palavra-passe atual", + "newPasswordLabel": "Nova palavra-passe", + "newPasswordHint": "Pelo menos 8 caracteres.", + "confirmPasswordLabel": "Confirmar nova palavra-passe", + "submit": "Guardar palavra-passe", + "submitting": "A guardar…", + "success": "Palavra-passe atualizada", + "failure": "Não foi possível alterar a palavra-passe", + "tooShort": "A nova palavra-passe deve ter pelo menos 8 caracteres.", + "mismatch": "As palavras-passe não coincidem." + }, + "signOut": { + "title": "Terminar sessão", + "description": "Termine a sua sessão atual. Será reencaminhado para a página de início de sessão.", + "button": "Terminar sessão" + }, + "disableLogin": { + "title": "Desativar início de sessão", + "description": "Desativar a autenticação por completo. Qualquer pessoa que consiga aceder a este FiestaBoard na rede poderá alterar definições e ler chaves de API. Não recomendado, a menos que este dispositivo esteja numa rede privada totalmente fiável.", + "button": "Desativar início de sessão", + "dialogTitle": "Desativar o início de sessão para este FiestaBoard?", + "dialogBody1": "Desativar o início de sessão remove a conta {username} e abre este FiestaBoard a qualquer pessoa que consiga aceder-lhe na rede — poderão ler as suas chaves de API, alterar a configuração do seu quadro e modificar quaisquer definições.", + "dialogBody2": "Faça-o apenas se este dispositivo estiver numa rede privada totalmente fiável (sem colegas de casa, sem convidados, sem dispositivos domésticos inteligentes que não controla). Fortemente desaconselhado se este FiestaBoard for acessível a partir da internet.", + "dialogBody3": "O seu quadro continua a apresentar normalmente em qualquer dos casos — isto controla apenas quem pode iniciar sessão para alterar definições.", + "confirmPasswordLabel": "Confirme a sua palavra-passe atual para continuar", + "confirm": "Sim, desativar início de sessão", + "confirming": "A desativar…", + "success": "Autenticação desativada", + "failure": "Não foi possível desativar a autenticação" + }, + "enableLogin": { + "title": "Ativar início de sessão", + "description": "O início de sessão está atualmente desativado. Qualquer pessoa que consiga aceder a este FiestaBoard na rede pode ler as suas chaves de API, alterar a configuração do seu quadro e modificar quaisquer definições.", + "body": "Fortemente recomendado se partilha o Wi-Fi com pessoas em quem não confia totalmente (colegas de casa, convidados, dispositivos domésticos inteligentes), ou se este FiestaBoard for acessível a partir da internet. O seu quadro continua a apresentar normalmente em qualquer dos casos — o início de sessão controla apenas quem pode iniciar sessão para alterar definições.", + "button": "Configurar um nome de utilizador e palavra-passe", + "submitting": "A ativar…", + "failure": "Não foi possível ativar o início de sessão" } }, + "aiActionConfirmation": { + "deny": "Negar", + "allow": "Permitir", + "working": "A processar…", + "done": "Concluído", + "denied": "Negado", + "noChanges": "sem alterações", + "noValues": "sem valores", + "noChangesSpecified": "Nenhuma alteração especificada.", + "openEnd": "aberto", + "label": { + "installPlugin": "Instalar plugin: {id}", + "updatePluginConfig": "Configurar plugin: {id}", + "updatePlugin": "Atualizar plugin: {id}", + "enablePlugin": "Ativar plugin: {id}", + "disablePlugin": "Desativar plugin: {id}", + "uninstallPlugin": "Desinstalar plugin: {id}", + "updateSetting": "Alterar definição: {category}", + "createCollection": "Criar coleção: \"{name}\"", + "updateCollection": "Atualizar coleção", + "createSchedule": "Criar agendamento", + "updateSchedule": "Atualizar agendamento", + "deleteSchedule": "Eliminar agendamento", + "triggerSystemUpdate": "Atualização do sistema" + }, + "description": { + "installPlugin": "Instala \"{id}\" a partir do registo oficial.", + "installPluginEnable": "Instala \"{id}\" a partir do registo oficial e ativa-o.", + "updatePluginConfig": "Atualiza a configuração de \"{id}\": {keys}.", + "updatePlugin": "Transfere e instala a versão mais recente do registo de \"{id}\".", + "enablePlugin": "Ativa \"{id}\" para que possa fornecer dados aos teus quadros.", + "disablePlugin": "Desativa \"{id}\" sem o remover. Pode ser reativado mais tarde.", + "uninstallPlugin": "Remove permanentemente \"{id}\". Esta ação não pode ser anulada.", + "updateSetting": "Define {values} nas definições de {category}.", + "createCollection": "Cria uma coleção com {count, plural, one {# página} other {# páginas}}, alternando a cada {interval}s.", + "createSchedule": "Mostra a página \"{page}\" das {time} nos dias {days}.", + "deleteSchedule": "Remove permanentemente o agendamento \"{id}\". Esta ação não pode ser anulada.", + "triggerSystemUpdate": "Transfere e instala a atualização mais recente do FiestaBoard. O sistema reiniciará brevemente." + }, + "change": { + "rename": "renomear para \"{name}\"", + "setPages": "definir {count, plural, one {# página} other {# páginas}}", + "interval": "intervalo → {interval}s", + "page": "página → {page}", + "start": "início → {start}", + "end": "fim → {end}", + "days": "dias → {days}", + "enable": "ativar", + "disable": "desativar" + } + }, + "chainingModePicker": { + "menuTitle": "Modo de encadeamento de IA", + "triggerAriaLabel": "Modo de encadeamento de IA: {mode}", + "modes": { + "manual": { + "label": "Manual", + "description": "Vou perguntar de novo após cada ação" + }, + "autoContinue": { + "label": "Continuação automática", + "description": "Encadeia ações, confirma cada passo" + }, + "autonomous": { + "label": "Autónomo", + "description": "Executa até ao fim, ignora confirmações" + } + } + }, + "bootGate": { + "waiting": "A aguardar o início…", + "errorHeading": "Não foi possível ligar ao FiestaBoard", + "errorDescription": "Verifica se a aplicação está em execução e tenta recarregar a página.", + "refreshPage": "Recarregar página" + }, + "globalAiChatDrawer": { + "panelAriaLabel": "Chat de IA do FiestaBot" + }, "plainTextEditor": { "placeholder": "Digite o texto do seu template...", "lineCount": "{current} / {total} linhas", @@ -1212,7 +1352,8 @@ "change": "Alterar", "selectAttribute": "Selecionar atributo", "valueLabel": "Valor", - "insert": "Inserir" + "insert": "Inserir", + "searchAriaLabel": "Pesquisar entidades" }, "pluginSettings": { "title": "Atualizações de plugins", @@ -1510,10 +1651,10 @@ "importWithMissingPlugins": "Alguns plugins ainda não estão ativados: {plugins}. Pode importar e ativá-los mais tarde." }, "aiChatPanel": { + "messagesAriaLabel": "Mensagens do chat", + "taskStatusAriaLabel": "Progresso das tarefas", + "taskProgressAriaLabel": "Progresso das tarefas de IA", "clearConversationAriaLabel": "Limpar conversa", "closePanelAriaLabel": "Fechar FiestaBot (Beta)" - }, - "aiChat": { - "taskProgressAriaLabel": "Progresso das tarefas de IA" } } diff --git a/web/messages/ru.json b/web/messages/ru.json index b36fdcd5..cedb0069 100644 --- a/web/messages/ru.json +++ b/web/messages/ru.json @@ -1002,8 +1002,148 @@ "wifi": "WiFi", "quotes": "Цитаты", "rotation": "Ротация" + }, + "on": "Вкл.", + "off": "Выкл.", + "toggleServiceAriaLabel": "Переключить {name}" + }, + "accountSection": { + "signedIn": { + "title": "Выполнен вход", + "description": "Вы вошли как {username}." + }, + "changeUsername": { + "title": "Изменить имя пользователя", + "description": "Выберите новое имя для входа. Требуется ваш текущий пароль.", + "formAriaLabel": "Изменить имя пользователя", + "newUsernameLabel": "Новое имя пользователя", + "currentPasswordLabel": "Текущий пароль", + "submit": "Сохранить имя пользователя", + "submitting": "Сохранение…", + "success": "Имя пользователя обновлено", + "failure": "Не удалось изменить имя пользователя" + }, + "changePassword": { + "title": "Изменить пароль", + "description": "Измените свой пароль. Все остальные сеансы, вошедшие со старым паролем, будут завершены.", + "formAriaLabel": "Изменить пароль", + "currentPasswordLabel": "Текущий пароль", + "newPasswordLabel": "Новый пароль", + "newPasswordHint": "Не менее 8 символов.", + "confirmPasswordLabel": "Подтвердите новый пароль", + "submit": "Сохранить пароль", + "submitting": "Сохранение…", + "success": "Пароль обновлён", + "failure": "Не удалось изменить пароль", + "tooShort": "Новый пароль должен содержать не менее 8 символов.", + "mismatch": "Пароли не совпадают." + }, + "signOut": { + "title": "Выйти", + "description": "Завершите текущий сеанс. Вы будете возвращены на страницу входа.", + "button": "Выйти" + }, + "disableLogin": { + "title": "Отключить вход", + "description": "Полностью отключить аутентификацию. Любой, кто сможет получить доступ к этому FiestaBoard в сети, сможет изменять настройки и читать ключи API. Не рекомендуется, если только это устройство не находится в полностью доверенной частной сети.", + "button": "Отключить вход", + "dialogTitle": "Отключить вход для этого FiestaBoard?", + "dialogBody1": "Отключение входа удаляет учётную запись {username} и открывает этот FiestaBoard для любого, кто сможет получить к нему доступ в сети — они смогут читать ваши ключи API, изменять конфигурацию доски и менять любые настройки.", + "dialogBody2": "Делайте это только если это устройство находится в полностью доверенной частной сети (без соседей по квартире, без гостей, без устройств умного дома, которые вы не контролируете). Настоятельно не рекомендуется, если этот FiestaBoard доступен из интернета.", + "dialogBody3": "Ваша доска в любом случае продолжает отображаться как обычно — это контролирует только то, кто может войти для изменения настроек.", + "confirmPasswordLabel": "Подтвердите текущий пароль, чтобы продолжить", + "confirm": "Да, отключить вход", + "confirming": "Отключение…", + "success": "Аутентификация отключена", + "failure": "Не удалось отключить аутентификацию" + }, + "enableLogin": { + "title": "Включить вход", + "description": "Вход сейчас отключён. Любой, кто сможет получить доступ к этому FiestaBoard в сети, может читать ваши ключи API, изменять конфигурацию доски и менять любые настройки.", + "body": "Настоятельно рекомендуется, если вы используете общий Wi-Fi с людьми, которым не полностью доверяете (соседи по квартире, гости, устройства умного дома), или если этот FiestaBoard доступен из интернета. Ваша доска в любом случае продолжает отображаться как обычно — вход контролирует только то, кто может войти для изменения настроек.", + "button": "Настроить имя пользователя и пароль", + "submitting": "Включение…", + "failure": "Не удалось включить вход" } }, + "aiActionConfirmation": { + "deny": "Отклонить", + "allow": "Разрешить", + "working": "Выполняется…", + "done": "Готово", + "denied": "Отклонено", + "noChanges": "без изменений", + "noValues": "без значений", + "noChangesSpecified": "Изменения не указаны.", + "openEnd": "открыто", + "label": { + "installPlugin": "Установить плагин: {id}", + "updatePluginConfig": "Настроить плагин: {id}", + "updatePlugin": "Обновить плагин: {id}", + "enablePlugin": "Включить плагин: {id}", + "disablePlugin": "Отключить плагин: {id}", + "uninstallPlugin": "Удалить плагин: {id}", + "updateSetting": "Изменить настройку: {category}", + "createCollection": "Создать коллекцию: \"{name}\"", + "updateCollection": "Обновить коллекцию", + "createSchedule": "Создать расписание", + "updateSchedule": "Обновить расписание", + "deleteSchedule": "Удалить расписание", + "triggerSystemUpdate": "Обновление системы" + }, + "description": { + "installPlugin": "Устанавливает \"{id}\" из официального реестра.", + "installPluginEnable": "Устанавливает \"{id}\" из официального реестра и включает его.", + "updatePluginConfig": "Обновляет конфигурацию \"{id}\": {keys}.", + "updatePlugin": "Загружает и устанавливает последнюю версию \"{id}\" из реестра.", + "enablePlugin": "Включает \"{id}\", чтобы он мог предоставлять данные для ваших досок.", + "disablePlugin": "Отключает \"{id}\" без удаления. Его можно снова включить позже.", + "uninstallPlugin": "Безвозвратно удаляет \"{id}\". Это действие нельзя отменить.", + "updateSetting": "Устанавливает {values} в настройках {category}.", + "createCollection": "Создаёт коллекцию из {count, plural, one {# страницы} other {# страниц}}, чередуя каждые {interval}с.", + "createSchedule": "Показывает страницу \"{page}\" с {time} по дням: {days}.", + "deleteSchedule": "Безвозвратно удаляет расписание \"{id}\". Это действие нельзя отменить.", + "triggerSystemUpdate": "Загружает и устанавливает последнее обновление FiestaBoard. Система ненадолго перезапустится." + }, + "change": { + "rename": "переименовать в \"{name}\"", + "setPages": "задать {count, plural, one {# страницу} other {# страниц}}", + "interval": "интервал → {interval}с", + "page": "страница → {page}", + "start": "начало → {start}", + "end": "конец → {end}", + "days": "дни → {days}", + "enable": "включить", + "disable": "отключить" + } + }, + "chainingModePicker": { + "menuTitle": "Режим цепочки ИИ", + "triggerAriaLabel": "Режим цепочки ИИ: {mode}", + "modes": { + "manual": { + "label": "Ручной", + "description": "Буду переспрашивать после каждого действия" + }, + "autoContinue": { + "label": "Автопродолжение", + "description": "Связывает действия, подтверждает каждый шаг" + }, + "autonomous": { + "label": "Автономный", + "description": "Выполняет до конца, пропускает подтверждения" + } + } + }, + "bootGate": { + "waiting": "Ожидание запуска…", + "errorHeading": "Не удалось подключиться к FiestaBoard", + "errorDescription": "Убедитесь, что приложение запущено, и попробуйте обновить страницу.", + "refreshPage": "Обновить страницу" + }, + "globalAiChatDrawer": { + "panelAriaLabel": "ИИ-чат FiestaBot" + }, "plainTextEditor": { "placeholder": "Введите текст шаблона...", "lineCount": "{current} / {total} строк", @@ -1212,7 +1352,8 @@ "change": "Изменить", "selectAttribute": "Выбрать атрибут", "valueLabel": "Значение", - "insert": "Вставить" + "insert": "Вставить", + "searchAriaLabel": "Поиск сущностей" }, "pluginSettings": { "title": "Обновления плагинов", @@ -1510,10 +1651,10 @@ "importWithMissingPlugins": "Некоторые плагины ещё не включены: {plugins}. Вы можете импортировать и включить их позже." }, "aiChatPanel": { + "messagesAriaLabel": "Сообщения чата", + "taskStatusAriaLabel": "Ход выполнения задач", + "taskProgressAriaLabel": "Прогресс задач ИИ", "clearConversationAriaLabel": "Очистить разговор", "closePanelAriaLabel": "Закрыть FiestaBot (Beta)" - }, - "aiChat": { - "taskProgressAriaLabel": "Прогресс задач ИИ" } } diff --git a/web/messages/sv.json b/web/messages/sv.json index 70209c95..49ef6433 100644 --- a/web/messages/sv.json +++ b/web/messages/sv.json @@ -1002,8 +1002,148 @@ "wifi": "WiFi", "quotes": "Citat", "rotation": "Rotation" + }, + "on": "På", + "off": "Av", + "toggleServiceAriaLabel": "Växla {name}" + }, + "accountSection": { + "signedIn": { + "title": "Inloggad", + "description": "Du är för närvarande inloggad som {username}." + }, + "changeUsername": { + "title": "Ändra användarnamn", + "description": "Välj ett nytt inloggningsnamn. Kräver ditt nuvarande lösenord.", + "formAriaLabel": "Ändra användarnamn", + "newUsernameLabel": "Nytt användarnamn", + "currentPasswordLabel": "Nuvarande lösenord", + "submit": "Spara användarnamn", + "submitting": "Sparar…", + "success": "Användarnamn uppdaterat", + "failure": "Det gick inte att ändra användarnamnet" + }, + "changePassword": { + "title": "Ändra lösenord", + "description": "Byt ditt lösenord. Alla andra sessioner som är inloggade med det gamla lösenordet loggas ut.", + "formAriaLabel": "Ändra lösenord", + "currentPasswordLabel": "Nuvarande lösenord", + "newPasswordLabel": "Nytt lösenord", + "newPasswordHint": "Minst 8 tecken.", + "confirmPasswordLabel": "Bekräfta nytt lösenord", + "submit": "Spara lösenord", + "submitting": "Sparar…", + "success": "Lösenord uppdaterat", + "failure": "Det gick inte att ändra lösenordet", + "tooShort": "Det nya lösenordet måste vara minst 8 tecken.", + "mismatch": "Lösenorden matchar inte." + }, + "signOut": { + "title": "Logga ut", + "description": "Avsluta din nuvarande session. Du skickas tillbaka till inloggningssidan.", + "button": "Logga ut" + }, + "disableLogin": { + "title": "Inaktivera inloggning", + "description": "Stäng av autentisering helt. Alla som kan nå detta FiestaBoard i nätverket kan då ändra inställningar och läsa API-nycklar. Rekommenderas inte om inte denna enhet finns i ett helt betrott privat nätverk.", + "button": "Inaktivera inloggning", + "dialogTitle": "Inaktivera inloggning för detta FiestaBoard?", + "dialogBody1": "Att stänga av inloggningen tar bort kontot {username} och öppnar detta FiestaBoard för alla som kan nå det i nätverket — de kan läsa dina API-nycklar, ändra din tavelkonfiguration och ändra alla inställningar.", + "dialogBody2": "Gör detta endast om denna enhet finns i ett helt betrott privat nätverk (inga rumskamrater, inga gäster, inga smarta hem-enheter som du inte kontrollerar). Avråds starkt om detta FiestaBoard är nåbart från internet.", + "dialogBody3": "Din tavla fortsätter att visas som vanligt oavsett — detta styr bara vem som kan logga in för att ändra inställningar.", + "confirmPasswordLabel": "Bekräfta ditt nuvarande lösenord för att fortsätta", + "confirm": "Ja, inaktivera inloggning", + "confirming": "Inaktiverar…", + "success": "Autentisering inaktiverad", + "failure": "Det gick inte att inaktivera autentiseringen" + }, + "enableLogin": { + "title": "Aktivera inloggning", + "description": "Inloggning är för närvarande av. Alla som kan nå detta FiestaBoard i nätverket kan läsa dina API-nycklar, ändra din tavelkonfiguration och ändra alla inställningar.", + "body": "Rekommenderas starkt om du delar Wi-Fi med personer du inte helt litar på (rumskamrater, gäster, smarta hem-enheter), eller om detta FiestaBoard är nåbart från internet. Din tavla fortsätter att visas som vanligt oavsett — inloggning styr bara vem som kan logga in för att ändra inställningar.", + "button": "Konfigurera ett användarnamn och lösenord", + "submitting": "Aktiverar…", + "failure": "Det gick inte att aktivera inloggning" } }, + "aiActionConfirmation": { + "deny": "Neka", + "allow": "Tillåt", + "working": "Arbetar…", + "done": "Klar", + "denied": "Nekad", + "noChanges": "inga ändringar", + "noValues": "inga värden", + "noChangesSpecified": "Inga ändringar angivna.", + "openEnd": "öppet", + "label": { + "installPlugin": "Installera plugin: {id}", + "updatePluginConfig": "Konfigurera plugin: {id}", + "updatePlugin": "Uppdatera plugin: {id}", + "enablePlugin": "Aktivera plugin: {id}", + "disablePlugin": "Inaktivera plugin: {id}", + "uninstallPlugin": "Avinstallera plugin: {id}", + "updateSetting": "Ändra inställning: {category}", + "createCollection": "Skapa samling: \"{name}\"", + "updateCollection": "Uppdatera samling", + "createSchedule": "Skapa schema", + "updateSchedule": "Uppdatera schema", + "deleteSchedule": "Ta bort schema", + "triggerSystemUpdate": "Systemuppdatering" + }, + "description": { + "installPlugin": "Installerar \"{id}\" från det officiella registret.", + "installPluginEnable": "Installerar \"{id}\" från det officiella registret och aktiverar det.", + "updatePluginConfig": "Uppdaterar konfigurationen för \"{id}\": {keys}.", + "updatePlugin": "Laddar ner och installerar den senaste registerversionen av \"{id}\".", + "enablePlugin": "Aktiverar \"{id}\" så att det kan leverera data till dina tavlor.", + "disablePlugin": "Inaktiverar \"{id}\" utan att ta bort det. Det kan aktiveras igen senare.", + "uninstallPlugin": "Tar bort \"{id}\" permanent. Detta kan inte ångras.", + "updateSetting": "Ställer in {values} i inställningarna för {category}.", + "createCollection": "Skapar en samling med {count, plural, one {# sida} other {# sidor}}, som växlar var {interval}:e sekund.", + "createSchedule": "Visar sidan \"{page}\" från {time} på {days}-dagar.", + "deleteSchedule": "Tar bort schemat \"{id}\" permanent. Detta kan inte ångras.", + "triggerSystemUpdate": "Laddar ner och installerar den senaste FiestaBoard-uppdateringen. Systemet startar om en kort stund." + }, + "change": { + "rename": "byt namn till \"{name}\"", + "setPages": "ange {count, plural, one {# sida} other {# sidor}}", + "interval": "intervall → {interval}s", + "page": "sida → {page}", + "start": "start → {start}", + "end": "slut → {end}", + "days": "dagar → {days}", + "enable": "aktivera", + "disable": "inaktivera" + } + }, + "chainingModePicker": { + "menuTitle": "AI-kedjeläge", + "triggerAriaLabel": "AI-kedjeläge: {mode}", + "modes": { + "manual": { + "label": "Manuell", + "description": "Jag frågar igen efter varje åtgärd" + }, + "autoContinue": { + "label": "Fortsätt automatiskt", + "description": "Kedjar åtgärder, bekräftar varje steg" + }, + "autonomous": { + "label": "Autonom", + "description": "Kör till slutet, hoppar över bekräftelser" + } + } + }, + "bootGate": { + "waiting": "Väntar på start…", + "errorHeading": "Det gick inte att ansluta till FiestaBoard", + "errorDescription": "Kontrollera att appen körs och försök ladda om sidan.", + "refreshPage": "Ladda om sidan" + }, + "globalAiChatDrawer": { + "panelAriaLabel": "FiestaBot AI-chatt" + }, "plainTextEditor": { "placeholder": "Skriv din malltext...", "lineCount": "{current} / {total} rader", @@ -1212,7 +1352,8 @@ "change": "Ändra", "selectAttribute": "Välj attribut", "valueLabel": "Värde", - "insert": "Infoga" + "insert": "Infoga", + "searchAriaLabel": "Sök entiteter" }, "pluginSettings": { "title": "Plugin-uppdateringar", @@ -1510,10 +1651,10 @@ "importWithMissingPlugins": "Vissa plugins är inte aktiverade än: {plugins}. Du kan ändå importera och aktivera dem senare." }, "aiChatPanel": { + "messagesAriaLabel": "Chattmeddelanden", + "taskStatusAriaLabel": "Uppgiftsförlopp", + "taskProgressAriaLabel": "AI-uppgifters förlopp", "clearConversationAriaLabel": "Rensa konversation", "closePanelAriaLabel": "Stäng FiestaBot (Beta)" - }, - "aiChat": { - "taskProgressAriaLabel": "AI-uppgifters förlopp" } } diff --git a/web/messages/tr.json b/web/messages/tr.json index b63383ef..55acadee 100644 --- a/web/messages/tr.json +++ b/web/messages/tr.json @@ -1002,8 +1002,148 @@ "wifi": "WiFi", "quotes": "Alıntılar", "rotation": "Rotasyon" + }, + "on": "Açık", + "off": "Kapalı", + "toggleServiceAriaLabel": "{name} aç/kapat" + }, + "accountSection": { + "signedIn": { + "title": "Oturum açıldı", + "description": "Şu anda {username} olarak oturum açtınız." + }, + "changeUsername": { + "title": "Kullanıcı adını değiştir", + "description": "Yeni bir oturum açma adı seçin. Mevcut parolanızı gerektirir.", + "formAriaLabel": "Kullanıcı adını değiştir", + "newUsernameLabel": "Yeni kullanıcı adı", + "currentPasswordLabel": "Mevcut parola", + "submit": "Kullanıcı adını kaydet", + "submitting": "Kaydediliyor…", + "success": "Kullanıcı adı güncellendi", + "failure": "Kullanıcı adı değiştirilemedi" + }, + "changePassword": { + "title": "Parolayı değiştir", + "description": "Parolanızı değiştirin. Eski parolayla oturum açmış diğer tüm oturumların oturumu kapatılır.", + "formAriaLabel": "Parolayı değiştir", + "currentPasswordLabel": "Mevcut parola", + "newPasswordLabel": "Yeni parola", + "newPasswordHint": "En az 8 karakter.", + "confirmPasswordLabel": "Yeni parolayı onayla", + "submit": "Parolayı kaydet", + "submitting": "Kaydediliyor…", + "success": "Parola güncellendi", + "failure": "Parola değiştirilemedi", + "tooShort": "Yeni parola en az 8 karakter olmalıdır.", + "mismatch": "Parolalar eşleşmiyor." + }, + "signOut": { + "title": "Oturumu kapat", + "description": "Mevcut oturumunuzu sonlandırın. Oturum açma sayfasına geri gönderileceksiniz.", + "button": "Oturumu kapat" + }, + "disableLogin": { + "title": "Oturum açmayı devre dışı bırak", + "description": "Kimlik doğrulamayı tamamen kapatın. Bu FiestaBoard'a ağ üzerinden erişebilen herkes ayarları değiştirebilir ve API anahtarlarını okuyabilir. Bu cihaz tamamen güvenilir bir özel ağda değilse önerilmez.", + "button": "Oturum açmayı devre dışı bırak", + "dialogTitle": "Bu FiestaBoard için oturum açma devre dışı bırakılsın mı?", + "dialogBody1": "Oturum açmayı devre dışı bırakmak {username} hesabını kaldırır ve bu FiestaBoard'ı ağ üzerinden erişebilen herkese açar — API anahtarlarınızı okuyabilir, pano yapılandırmanızı değiştirebilir ve tüm ayarları düzenleyebilirler.", + "dialogBody2": "Bunu yalnızca bu cihaz tamamen güvenilir bir özel ağdaysa yapın (ev arkadaşı yok, misafir yok, kontrol etmediğiniz akıllı ev cihazları yok). Bu FiestaBoard internetten erişilebiliyorsa kesinlikle önerilmez.", + "dialogBody3": "Panonuz her iki durumda da normal şekilde görüntülenmeye devam eder — bu yalnızca ayarları değiştirmek için kimin oturum açabileceğini kontrol eder.", + "confirmPasswordLabel": "Devam etmek için mevcut parolanızı onaylayın", + "confirm": "Evet, oturum açmayı devre dışı bırak", + "confirming": "Devre dışı bırakılıyor…", + "success": "Kimlik doğrulama devre dışı bırakıldı", + "failure": "Kimlik doğrulama devre dışı bırakılamadı" + }, + "enableLogin": { + "title": "Oturum açmayı etkinleştir", + "description": "Oturum açma şu anda kapalı. Bu FiestaBoard'a ağ üzerinden erişebilen herkes API anahtarlarınızı okuyabilir, pano yapılandırmanızı değiştirebilir ve tüm ayarları düzenleyebilir.", + "body": "Tam olarak güvenmediğiniz kişilerle (ev arkadaşları, misafirler, akıllı ev cihazları) Wi-Fi paylaşıyorsanız veya bu FiestaBoard internetten erişilebiliyorsa kesinlikle önerilir. Panonuz her iki durumda da normal şekilde görüntülenmeye devam eder — oturum açma yalnızca ayarları değiştirmek için kimin oturum açabileceğini kontrol eder.", + "button": "Bir kullanıcı adı ve parola ayarla", + "submitting": "Etkinleştiriliyor…", + "failure": "Oturum açma etkinleştirilemedi" } }, + "aiActionConfirmation": { + "deny": "Reddet", + "allow": "İzin ver", + "working": "Çalışıyor…", + "done": "Tamam", + "denied": "Reddedildi", + "noChanges": "değişiklik yok", + "noValues": "değer yok", + "noChangesSpecified": "Değişiklik belirtilmedi.", + "openEnd": "açık", + "label": { + "installPlugin": "Eklenti yükle: {id}", + "updatePluginConfig": "Eklentiyi yapılandır: {id}", + "updatePlugin": "Eklentiyi güncelle: {id}", + "enablePlugin": "Eklentiyi etkinleştir: {id}", + "disablePlugin": "Eklentiyi devre dışı bırak: {id}", + "uninstallPlugin": "Eklentiyi kaldır: {id}", + "updateSetting": "Ayarı değiştir: {category}", + "createCollection": "Koleksiyon oluştur: \"{name}\"", + "updateCollection": "Koleksiyonu güncelle", + "createSchedule": "Zamanlama oluştur", + "updateSchedule": "Zamanlamayı güncelle", + "deleteSchedule": "Zamanlamayı sil", + "triggerSystemUpdate": "Sistem güncellemesi" + }, + "description": { + "installPlugin": "\"{id}\" eklentisini resmi kayıttan yükler.", + "installPluginEnable": "\"{id}\" eklentisini resmi kayıttan yükler ve etkinleştirir.", + "updatePluginConfig": "\"{id}\" yapılandırmasını günceller: {keys}.", + "updatePlugin": "\"{id}\" eklentisinin en son kayıt sürümünü indirir ve yükler.", + "enablePlugin": "\"{id}\" eklentisini panolarınıza veri sağlayabilmesi için etkinleştirir.", + "disablePlugin": "\"{id}\" eklentisini kaldırmadan devre dışı bırakır. Daha sonra tekrar etkinleştirilebilir.", + "uninstallPlugin": "\"{id}\" eklentisini kalıcı olarak kaldırır. Bu işlem geri alınamaz.", + "updateSetting": "{category} ayarlarında {values} değerini ayarlar.", + "createCollection": "{count, plural, one {# sayfa} other {# sayfa}} içeren bir koleksiyon oluşturur, her {interval}s'de bir döner.", + "createSchedule": "\"{page}\" sayfasını {days} günlerinde {time} arasında gösterir.", + "deleteSchedule": "\"{id}\" zamanlamasını kalıcı olarak kaldırır. Bu işlem geri alınamaz.", + "triggerSystemUpdate": "En son FiestaBoard güncellemesini indirir ve yükler. Sistem kısa süreliğine yeniden başlar." + }, + "change": { + "rename": "\"{name}\" olarak yeniden adlandır", + "setPages": "{count, plural, one {# sayfa} other {# sayfa}} ayarla", + "interval": "aralık → {interval}s", + "page": "sayfa → {page}", + "start": "başlangıç → {start}", + "end": "bitiş → {end}", + "days": "günler → {days}", + "enable": "etkinleştir", + "disable": "devre dışı bırak" + } + }, + "chainingModePicker": { + "menuTitle": "Yapay zeka zincirleme modu", + "triggerAriaLabel": "Yapay zeka zincirleme modu: {mode}", + "modes": { + "manual": { + "label": "Manuel", + "description": "Her işlemden sonra tekrar soracağım" + }, + "autoContinue": { + "label": "Otomatik devam", + "description": "İşlemleri zincirler, her adımı onaylar" + }, + "autonomous": { + "label": "Otonom", + "description": "Tamamlanana kadar çalışır, onayları atlar" + } + } + }, + "bootGate": { + "waiting": "Başlatılması bekleniyor…", + "errorHeading": "FiestaBoard'a bağlanılamadı", + "errorDescription": "Uygulamanın çalıştığından emin olun ve sayfayı yenilemeyi deneyin.", + "refreshPage": "Sayfayı yenile" + }, + "globalAiChatDrawer": { + "panelAriaLabel": "FiestaBot yapay zeka sohbeti" + }, "plainTextEditor": { "placeholder": "Şablon metninizi yazın...", "lineCount": "{current} / {total} satır", @@ -1212,7 +1352,8 @@ "change": "Değiştir", "selectAttribute": "Öznitelik Seç", "valueLabel": "Değer", - "insert": "Ekle" + "insert": "Ekle", + "searchAriaLabel": "Varlıkları ara" }, "pluginSettings": { "title": "Eklenti Güncellemeleri", @@ -1510,10 +1651,10 @@ "importWithMissingPlugins": "Bazı eklentiler henüz etkin değil: {plugins}. Yine de içe aktarıp daha sonra etkinleştirebilirsiniz." }, "aiChatPanel": { + "messagesAriaLabel": "Sohbet mesajları", + "taskStatusAriaLabel": "Görev ilerlemesi", + "taskProgressAriaLabel": "AI görev ilerlemesi", "clearConversationAriaLabel": "Konuşmayı temizle", "closePanelAriaLabel": "FiestaBot (Beta)'yı kapat" - }, - "aiChat": { - "taskProgressAriaLabel": "AI görev ilerlemesi" } } diff --git a/web/messages/zh.json b/web/messages/zh.json index 30d1dab2..ea9d636a 100644 --- a/web/messages/zh.json +++ b/web/messages/zh.json @@ -1002,8 +1002,148 @@ "wifi": "WiFi", "quotes": "名言", "rotation": "轮换" + }, + "on": "开", + "off": "关", + "toggleServiceAriaLabel": "切换{name}" + }, + "accountSection": { + "signedIn": { + "title": "已登录", + "description": "您当前以 {username} 身份登录。" + }, + "changeUsername": { + "title": "更改用户名", + "description": "选择一个新的登录名。需要您当前的密码。", + "formAriaLabel": "更改用户名", + "newUsernameLabel": "新用户名", + "currentPasswordLabel": "当前密码", + "submit": "保存用户名", + "submitting": "正在保存…", + "success": "用户名已更新", + "failure": "更改用户名失败" + }, + "changePassword": { + "title": "更改密码", + "description": "更改您的密码。使用旧密码登录的所有其他会话都将被注销。", + "formAriaLabel": "更改密码", + "currentPasswordLabel": "当前密码", + "newPasswordLabel": "新密码", + "newPasswordHint": "至少 8 个字符。", + "confirmPasswordLabel": "确认新密码", + "submit": "保存密码", + "submitting": "正在保存…", + "success": "密码已更新", + "failure": "更改密码失败", + "tooShort": "新密码至少需要 8 个字符。", + "mismatch": "两次密码不一致。" + }, + "signOut": { + "title": "退出登录", + "description": "结束您当前的会话。您将被送回登录页面。", + "button": "退出登录" + }, + "disableLogin": { + "title": "禁用登录", + "description": "完全关闭身份验证。任何能在网络中访问此 FiestaBoard 的人都将能够更改设置并读取 API 密钥。除非此设备位于完全受信任的专用网络中,否则不建议这样做。", + "button": "禁用登录", + "dialogTitle": "禁用此 FiestaBoard 的登录?", + "dialogBody1": "禁用登录会删除 {username} 账户,并将此 FiestaBoard 开放给任何能在网络中访问它的人——他们将能够读取您的 API 密钥、更改您的看板配置以及修改任何设置。", + "dialogBody2": "仅当此设备位于完全受信任的专用网络中(没有室友、没有访客、没有您无法控制的智能家居设备)时才执行此操作。如果此 FiestaBoard 可从互联网访问,则强烈不建议这样做。", + "dialogBody3": "无论哪种方式,您的看板都会照常显示——这只控制谁可以登录以更改设置。", + "confirmPasswordLabel": "确认您当前的密码以继续", + "confirm": "是的,禁用登录", + "confirming": "正在禁用…", + "success": "身份验证已禁用", + "failure": "禁用身份验证失败" + }, + "enableLogin": { + "title": "开启登录", + "description": "登录目前为关闭状态。任何能在网络中访问此 FiestaBoard 的人都可以读取您的 API 密钥、更改您的看板配置以及修改任何设置。", + "body": "如果您与并非完全信任的人(室友、访客、智能家居设备)共享 Wi-Fi,或者此 FiestaBoard 可从互联网访问,则强烈建议开启。无论哪种方式,您的看板都会照常显示——登录只控制谁可以登录以更改设置。", + "button": "设置用户名和密码", + "submitting": "正在开启…", + "failure": "无法开启登录" } }, + "aiActionConfirmation": { + "deny": "拒绝", + "allow": "允许", + "working": "处理中…", + "done": "完成", + "denied": "已拒绝", + "noChanges": "无更改", + "noValues": "无值", + "noChangesSpecified": "未指定更改。", + "openEnd": "未设定", + "label": { + "installPlugin": "安装插件:{id}", + "updatePluginConfig": "配置插件:{id}", + "updatePlugin": "更新插件:{id}", + "enablePlugin": "启用插件:{id}", + "disablePlugin": "禁用插件:{id}", + "uninstallPlugin": "卸载插件:{id}", + "updateSetting": "更改设置:{category}", + "createCollection": "创建合集:\"{name}\"", + "updateCollection": "更新合集", + "createSchedule": "创建日程", + "updateSchedule": "更新日程", + "deleteSchedule": "删除日程", + "triggerSystemUpdate": "系统更新" + }, + "description": { + "installPlugin": "从官方注册表安装“{id}”。", + "installPluginEnable": "从官方注册表安装“{id}”并启用它。", + "updatePluginConfig": "更新“{id}”的配置:{keys}。", + "updatePlugin": "下载并安装“{id}”的最新注册表版本。", + "enablePlugin": "启用“{id}”,使其能够向你的看板提供数据。", + "disablePlugin": "禁用“{id}”但不移除它。稍后可重新启用。", + "uninstallPlugin": "永久移除“{id}”。此操作无法撤销。", + "updateSetting": "在 {category} 设置中设置 {values}。", + "createCollection": "创建一个包含 {count, plural, other {# 个页面}} 的合集,每 {interval} 秒轮换一次。", + "createSchedule": "在 {days} 的 {time} 显示页面“{page}”。", + "deleteSchedule": "永久移除日程“{id}”。此操作无法撤销。", + "triggerSystemUpdate": "下载并安装最新的 FiestaBoard 更新。系统将短暂重启。" + }, + "change": { + "rename": "重命名为“{name}”", + "setPages": "设置 {count, plural, other {# 个页面}}", + "interval": "间隔 → {interval}秒", + "page": "页面 → {page}", + "start": "开始 → {start}", + "end": "结束 → {end}", + "days": "日期 → {days}", + "enable": "启用", + "disable": "禁用" + } + }, + "chainingModePicker": { + "menuTitle": "AI 链式模式", + "triggerAriaLabel": "AI 链式模式:{mode}", + "modes": { + "manual": { + "label": "手动", + "description": "每次操作后我会再次询问" + }, + "autoContinue": { + "label": "自动继续", + "description": "串联操作,逐步确认" + }, + "autonomous": { + "label": "自主", + "description": "运行至完成,跳过确认" + } + } + }, + "bootGate": { + "waiting": "正在等待启动…", + "errorHeading": "无法连接到 FiestaBoard", + "errorDescription": "请确认应用正在运行,然后尝试刷新页面。", + "refreshPage": "刷新页面" + }, + "globalAiChatDrawer": { + "panelAriaLabel": "FiestaBot AI 聊天" + }, "plainTextEditor": { "placeholder": "输入您的模板文本...", "lineCount": "{current} / {total} 行", @@ -1212,7 +1352,8 @@ "change": "更改", "selectAttribute": "选择属性", "valueLabel": "值", - "insert": "插入" + "insert": "插入", + "searchAriaLabel": "搜索实体" }, "pluginSettings": { "title": "插件更新", @@ -1510,10 +1651,10 @@ "importWithMissingPlugins": "某些插件尚未启用:{plugins}。您仍然可以导入并稍后启用它们。" }, "aiChatPanel": { + "messagesAriaLabel": "聊天消息", + "taskStatusAriaLabel": "任务进度", + "taskProgressAriaLabel": "AI 任务进度", "clearConversationAriaLabel": "清除对话", "closePanelAriaLabel": "关闭 FiestaBot (Beta)" - }, - "aiChat": { - "taskProgressAriaLabel": "AI 任务进度" } } diff --git a/web/src/__tests__/ai-chat-panel.test.tsx b/web/src/__tests__/ai-chat-panel.test.tsx index a202a03a..9a45cc1d 100644 --- a/web/src/__tests__/ai-chat-panel.test.tsx +++ b/web/src/__tests__/ai-chat-panel.test.tsx @@ -312,8 +312,10 @@ describe("AiChatPanel", () => { render(, { wrapper: Wrapper, }); - // ChainingModePicker renders a button with the mode name - expect(await screen.findByTitle(/ai mode: manual/i)).toBeInTheDocument(); + // ChainingModePicker exposes the current mode through the trigger's + // accessible name (aria-label), which stays present even when the + // visible label is hidden at narrow widths. + expect(await screen.findByRole("button", { name: /ai chaining mode: manual/i })).toBeInTheDocument(); }); it("header buttons resolve their aria-label through next-intl (no hardcoded English)", async () => { diff --git a/web/src/components/account-section.tsx b/web/src/components/account-section.tsx index 9f76eb57..45dbba92 100644 --- a/web/src/components/account-section.tsx +++ b/web/src/components/account-section.tsx @@ -16,7 +16,7 @@ import { useQuery, useQueryClient } from "@tanstack/react-query"; import { KeyRound, LogOut, ShieldAlert, ShieldCheck, ShieldOff, UserCircle2, UserCog } from "lucide-react"; -import { type FormEvent, useState } from "react"; +import { type FormEvent, type ReactNode, useState } from "react"; import { toast } from "sonner"; import { @@ -34,9 +34,11 @@ import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Skeleton } from "@/components/ui/skeleton"; import { useRouter } from "@/hooks/use-router"; +import { useTranslations } from "@/i18n/translations"; import { api } from "@/lib/api"; export function AccountSection() { + const t = useTranslations("accountSection"); const router = useRouter(); const queryClient = useQueryClient(); @@ -94,10 +96,12 @@ export function AccountSection() { - Signed in + {t("signedIn.title")} - You're currently signed in as {username}. + {t.rich("signedIn.description", { + name: () => {username}, + })} @@ -106,9 +110,9 @@ export function AccountSection() { - Change username + {t("changeUsername.title")} - Pick a new sign-in name. Requires your current password. + {t("changeUsername.description")} @@ -119,11 +123,9 @@ export function AccountSection() { - Change password + {t("changePassword.title")} - - Rotate your password. Any other sessions signed in with the old password will be signed out. - + {t("changePassword.description")} @@ -134,13 +136,13 @@ export function AccountSection() { - Sign out + {t("signOut.title")} - End your current session. You'll be sent back to the sign-in page. + {t("signOut.description")} @@ -149,12 +151,9 @@ export function AccountSection() { - Disable login + {t("disableLogin.title")} - - Turn off authentication entirely. Anyone who can reach this FiestaBoard on the network will be able to - change settings and read API keys. Not recommended unless this device is on a fully trusted private network. - + {t("disableLogin.description")} @@ -165,6 +164,7 @@ export function AccountSection() { } function ChangeUsernameForm({ currentUsername }: { currentUsername: string }) { + const t = useTranslations("accountSection"); const queryClient = useQueryClient(); const [newUsername, setNewUsername] = useState(currentUsername); const [password, setPassword] = useState(""); @@ -177,10 +177,10 @@ function ChangeUsernameForm({ currentUsername }: { currentUsername: string }) { try { await api.changeUsername(password, newUsername.trim()); setPassword(""); - toast.success("Username updated"); + toast.success(t("changeUsername.success")); queryClient.invalidateQueries({ queryKey: ["auth-status"] }); } catch (err) { - toast.error(err instanceof Error ? err.message : "Username change failed"); + toast.error(err instanceof Error ? err.message : t("changeUsername.failure")); } finally { setSubmitting(false); } @@ -189,9 +189,9 @@ function ChangeUsernameForm({ currentUsername }: { currentUsername: string }) { const unchanged = newUsername.trim() === currentUsername; return ( -
+
- +
- +
); } function ChangePasswordForm() { + const t = useTranslations("accountSection"); const [currentPassword, setCurrentPassword] = useState(""); const [newPassword, setNewPassword] = useState(""); const [confirm, setConfirm] = useState(""); @@ -232,11 +233,11 @@ function ChangePasswordForm() { e.preventDefault(); setError(null); if (newPassword.length < 8) { - setError("New password must be at least 8 characters."); + setError(t("changePassword.tooShort")); return; } if (newPassword !== confirm) { - setError("Passwords do not match."); + setError(t("changePassword.mismatch")); return; } setSubmitting(true); @@ -245,18 +246,18 @@ function ChangePasswordForm() { setCurrentPassword(""); setNewPassword(""); setConfirm(""); - toast.success("Password updated"); + toast.success(t("changePassword.success")); } catch (err) { - setError(err instanceof Error ? err.message : "Password change failed"); + setError(err instanceof Error ? err.message : t("changePassword.failure")); } finally { setSubmitting(false); } }; return ( -
+
- +
- + -

At least 8 characters.

+

{t("changePassword.newPasswordHint")}

- + )} ); } function DisableAuthDialog({ username }: { username: string }) { + const t = useTranslations("accountSection"); + const tCommon = useTranslations("common"); const router = useRouter(); const queryClient = useQueryClient(); const [open, setOpen] = useState(false); @@ -321,7 +324,7 @@ function DisableAuthDialog({ username }: { username: string }) { setSubmitting(true); try { await api.disableAuth(password); - toast.success("Authentication disabled"); + toast.success(t("disableLogin.success")); setPassword(""); setOpen(false); // The install is now wide open — drop cached auth state and @@ -329,7 +332,7 @@ function DisableAuthDialog({ username }: { username: string }) { queryClient.removeQueries({ queryKey: ["auth-status"] }); router.replace("/"); } catch (err) { - setError(err instanceof Error ? err.message : "Failed to disable auth"); + setError(err instanceof Error ? err.message : t("disableLogin.failure")); } finally { setSubmitting(false); } @@ -348,37 +351,34 @@ function DisableAuthDialog({ username }: { username: string }) { > - Disable login for this FiestaBoard? + {t("disableLogin.dialogTitle")}

- Turning off login removes the {username} account and opens this - FiestaBoard up to anyone who can reach it on the network — they'll be able to read your API keys, - change your board configuration, and modify any settings. + {t.rich("disableLogin.dialogBody1", { + name: () => {username}, + })}

- Only do this if this device is on a fully trusted private network (no roommates, no guests, no - smart-home devices you don't control). Strongly not recommended if this - FiestaBoard is reachable from the internet. -

-

- Your board keeps displaying as normal either way — this only controls who can sign in to change - settings. + {t.rich("disableLogin.dialogBody2", { + strong: (chunks: ReactNode) => {chunks}, + })}

+

{t("disableLogin.dialogBody3")}

- + setOpen(false)}> - Cancel + {tCommon("cancel")} @@ -413,6 +413,7 @@ function DisableAuthDialog({ username }: { username: string }) { } function EnableLoginCard() { + const t = useTranslations("accountSection"); const router = useRouter(); const queryClient = useQueryClient(); const [submitting, setSubmitting] = useState(false); @@ -427,7 +428,7 @@ function EnableLoginCard() { queryClient.removeQueries({ queryKey: ["auth-status"] }); router.push("/login"); } catch (err) { - toast.error(err instanceof Error ? err.message : "Could not enable login"); + toast.error(err instanceof Error ? err.message : t("enableLogin.failure")); setSubmitting(false); } }; @@ -437,22 +438,19 @@ function EnableLoginCard() { - Turn on login + {t("enableLogin.title")} - Login is currently off. Anyone who can reach this FiestaBoard on the network can read your - API keys, change your board configuration, and modify any settings. + {t.rich("enableLogin.description", { + strong: (chunks: ReactNode) => {chunks}, + })} -

- Strongly recommended if you share Wi-Fi with people you don't fully trust (roommates, guests, smart-home - devices), or if this FiestaBoard is reachable from the internet. Your board keeps displaying as normal either - way — login only controls who can sign in to change settings. -

+

{t("enableLogin.body")}

diff --git a/web/src/components/ai-action-confirmation.tsx b/web/src/components/ai-action-confirmation.tsx index cb4a40a4..3f65a694 100644 --- a/web/src/components/ai-action-confirmation.tsx +++ b/web/src/components/ai-action-confirmation.tsx @@ -17,6 +17,7 @@ import { useEffect, useRef, useState } from "react"; import { Button } from "@/components/ui/button"; import { Card } from "@/components/ui/card"; +import { useTranslations } from "@/i18n/translations"; import type { CreateCollectionArgs, CreateScheduleArgs, @@ -49,102 +50,106 @@ interface AiActionConfirmationProps { autoAllow?: boolean; } -function actionLabel(call: AiActionConfirmationProps["call"]): string { +type TranslateFn = (key: string, params?: Record) => string; + +function actionLabel(call: AiActionConfirmationProps["call"], t: TranslateFn): string { switch (call.op) { case "install_plugin": - return `Install plugin: ${(call.args as InstallPluginArgs).plugin_id}`; + return t("label.installPlugin", { id: (call.args as InstallPluginArgs).plugin_id }); case "update_plugin_config": - return `Configure plugin: ${(call.args as UpdatePluginConfigArgs).plugin_id}`; + return t("label.updatePluginConfig", { id: (call.args as UpdatePluginConfigArgs).plugin_id }); case "update_plugin": - return `Update plugin: ${(call.args as UpdatePluginArgs).plugin_id}`; + return t("label.updatePlugin", { id: (call.args as UpdatePluginArgs).plugin_id }); case "enable_plugin": - return `Enable plugin: ${(call.args as EnablePluginArgs).plugin_id}`; + return t("label.enablePlugin", { id: (call.args as EnablePluginArgs).plugin_id }); case "disable_plugin": - return `Disable plugin: ${(call.args as DisablePluginArgs).plugin_id}`; + return t("label.disablePlugin", { id: (call.args as DisablePluginArgs).plugin_id }); case "uninstall_plugin": - return `Uninstall plugin: ${(call.args as UninstallPluginArgs).plugin_id}`; + return t("label.uninstallPlugin", { id: (call.args as UninstallPluginArgs).plugin_id }); case "update_setting": - return `Change setting: ${(call.args as UpdateSettingArgs).category}`; + return t("label.updateSetting", { category: (call.args as UpdateSettingArgs).category }); case "create_collection": - return `Create collection: "${(call.args as CreateCollectionArgs).name}"`; + return t("label.createCollection", { name: (call.args as CreateCollectionArgs).name }); case "update_collection": - return `Update collection`; + return t("label.updateCollection"); case "create_schedule": - return `Create schedule`; + return t("label.createSchedule"); case "update_schedule": - return `Update schedule`; + return t("label.updateSchedule"); case "delete_schedule": - return `Delete schedule`; + return t("label.deleteSchedule"); case "trigger_system_update": - return `System update`; + return t("label.triggerSystemUpdate"); } } -function actionDescription(call: AiActionConfirmationProps["call"]): string { +function actionDescription(call: AiActionConfirmationProps["call"], t: TranslateFn): string { switch (call.op) { case "install_plugin": { const a = call.args as InstallPluginArgs; - return `Installs "${a.plugin_id}" from the official registry${a.auto_enable !== false ? " and enables it" : ""}.`; + return a.auto_enable !== false + ? t("description.installPluginEnable", { id: a.plugin_id }) + : t("description.installPlugin", { id: a.plugin_id }); } case "update_plugin_config": { const a = call.args as UpdatePluginConfigArgs; const keys = Object.keys(a.config).join(", "); - return `Updates configuration for "${a.plugin_id}": ${keys || "no changes"}.`; + return t("description.updatePluginConfig", { id: a.plugin_id, keys: keys || t("noChanges") }); } case "update_plugin": { const a = call.args as UpdatePluginArgs; - return `Downloads and installs the latest registry version of "${a.plugin_id}".`; + return t("description.updatePlugin", { id: a.plugin_id }); } case "enable_plugin": { const a = call.args as EnablePluginArgs; - return `Enables "${a.plugin_id}" so it can provide data to your boards.`; + return t("description.enablePlugin", { id: a.plugin_id }); } case "disable_plugin": { const a = call.args as DisablePluginArgs; - return `Disables "${a.plugin_id}" without removing it. It can be re-enabled later.`; + return t("description.disablePlugin", { id: a.plugin_id }); } case "uninstall_plugin": { const a = call.args as UninstallPluginArgs; - return `Permanently removes "${a.plugin_id}". This cannot be undone.`; + return t("description.uninstallPlugin", { id: a.plugin_id }); } case "update_setting": { const a = call.args as UpdateSettingArgs; const entries = Object.entries(a.values) .map(([k, v]) => `${k}: ${JSON.stringify(v)}`) .join(", "); - return `Sets ${entries || "no values"} in ${a.category} settings.`; + return t("description.updateSetting", { values: entries || t("noValues"), category: a.category }); } case "create_collection": { const a = call.args as CreateCollectionArgs; - return `Creates a collection with ${a.page_ids.length} page(s), rotating every ${a.interval_seconds}s.`; + return t("description.createCollection", { count: a.page_ids.length, interval: a.interval_seconds }); } case "update_collection": { const a = call.args as UpdateCollectionArgs; const changes: string[] = []; - if (a.name != null) changes.push(`rename to "${a.name}"`); - if (a.page_ids != null) changes.push(`set ${a.page_ids.length} page(s)`); - if (a.interval_seconds != null) changes.push(`interval → ${a.interval_seconds}s`); - return changes.length ? changes.join(", ") + "." : "No changes specified."; + if (a.name != null) changes.push(t("change.rename", { name: a.name })); + if (a.page_ids != null) changes.push(t("change.setPages", { count: a.page_ids.length })); + if (a.interval_seconds != null) changes.push(t("change.interval", { interval: a.interval_seconds })); + return changes.length ? changes.join(", ") + "." : t("noChangesSpecified"); } case "create_schedule": { const a = call.args as CreateScheduleArgs; const time = `${a.start_time}${a.end_time ? `–${a.end_time}` : "+"}`; - return `Shows page "${a.page_id}" from ${time} on ${a.day_pattern} days.`; + return t("description.createSchedule", { page: a.page_id, time, days: a.day_pattern }); } case "update_schedule": { const a = call.args as UpdateScheduleArgs; const changes: string[] = []; - if (a.page_id != null) changes.push(`page → ${a.page_id}`); - if (a.start_time != null) changes.push(`start → ${a.start_time}`); - if (a.end_time !== undefined) changes.push(`end → ${a.end_time ?? "open"}`); - if (a.day_pattern != null) changes.push(`days → ${a.day_pattern}`); - if (a.enabled != null) changes.push(a.enabled ? "enable" : "disable"); - return changes.length ? changes.join(", ") + "." : "No changes specified."; + if (a.page_id != null) changes.push(t("change.page", { page: a.page_id })); + if (a.start_time != null) changes.push(t("change.start", { start: a.start_time })); + if (a.end_time !== undefined) changes.push(t("change.end", { end: a.end_time ?? t("openEnd") })); + if (a.day_pattern != null) changes.push(t("change.days", { days: a.day_pattern })); + if (a.enabled != null) changes.push(a.enabled ? t("change.enable") : t("change.disable")); + return changes.length ? changes.join(", ") + "." : t("noChangesSpecified"); } case "delete_schedule": - return `Permanently removes schedule "${(call.args as DeleteScheduleArgs).schedule_id}". This cannot be undone.`; + return t("description.deleteSchedule", { id: (call.args as DeleteScheduleArgs).schedule_id }); case "trigger_system_update": - return "Downloads and installs the latest FiestaBoard update. The system will restart briefly."; + return t("description.triggerSystemUpdate"); } } @@ -152,32 +157,33 @@ function ActionIcon({ op }: { op: ConfirmableOp }) { const cls = "h-4 w-4 shrink-0 text-muted-foreground"; switch (op) { case "install_plugin": - return ; + return
)} {state === "done" && (
- - Done +
)} {state === "denied" && (
- - Denied +
)} diff --git a/web/src/components/ai-chat-panel.tsx b/web/src/components/ai-chat-panel.tsx index f1f6c3b0..007b1d6a 100644 --- a/web/src/components/ai-chat-panel.tsx +++ b/web/src/components/ai-chat-panel.tsx @@ -219,9 +219,18 @@ export function AiChatPanel({ {/* Task list panel — shown when the AI has an active task list */} {(taskList?.length ?? 0) > 0 && } - {/* Messages — scrollable middle section */} + {/* Messages — scrollable middle section. The list is an + aria-live region so streamed assistant replies are announced + to screen-reader users as they arrive (additions + text + changes), without re-reading the entire transcript. */} -
+
{messages.length === 0 && } {messages.map((m, i) => ( 0 && tasks.every((t) => t.status === "done" || t.status === "failed"); - const doneCount = tasks.filter((t) => t.status === "done").length; + const t = useTranslations("aiChatPanel"); + const allDone = tasks.length > 0 && tasks.every((task) => task.status === "done" || task.status === "failed"); + const doneCount = tasks.filter((task) => task.status === "done").length; const [visible, setVisible] = useState(true); useEffect(() => { @@ -353,7 +362,13 @@ function TaskListPanel({ tasks }: { tasks: TaskItem[] }) { const pct = tasks.length > 0 ? (doneCount / tasks.length) * 100 : 0; return ( -
+
Tasks ({doneCount}/{tasks.length}) diff --git a/web/src/components/boot-gate.tsx b/web/src/components/boot-gate.tsx index 0a2577a6..b320a3f1 100644 --- a/web/src/components/boot-gate.tsx +++ b/web/src/components/boot-gate.tsx @@ -5,6 +5,7 @@ import { WifiOff } from "lucide-react"; import { useEffect, useState } from "react"; import { FiestaLogo } from "@/components/fiesta-logo"; +import { useTranslations } from "@/i18n/translations"; /** How long to wait before showing the splash (avoids a flash for fast startups). */ const SHOW_SPLASH_DELAY_MS = 600; @@ -22,6 +23,7 @@ const ERROR_TIMEOUT_MS = 30_000; * A brief connection hiccup during normal use never re-shows the splash. */ export function BootGate({ children }: { children: React.ReactNode }) { + const t = useTranslations("bootGate"); const [hasConnected, setHasConnected] = useState(false); const [showSplash, setShowSplash] = useState(false); const [timedOut, setTimedOut] = useState(false); @@ -72,7 +74,12 @@ export function BootGate({ children }: { children: React.ReactNode }) { return (
-
+
{/* Branding */}
@@ -82,25 +89,26 @@ export function BootGate({ children }: { children: React.ReactNode }) { {timedOut ? ( /* ── Error state ── */ <> - +