From 20121981a0fcdfa60263a1fa8ca8b353636a1847 Mon Sep 17 00:00:00 2001 From: Rune Olsen Date: Fri, 19 Jun 2026 11:17:36 +0200 Subject: [PATCH 01/10] Add French localization and catch up nb/sv/da/de translations French (fr) added as a 5th supported language; full catalog translated. Also caught up nb/sv/da/de for ~300 strings added since the last localization pass (Jarvis, Anytype, model categories, reasoning effort, Combine Conversations) plus Button/Toggle/Menu/CommandMenu titles and custom sectionHeader/row helpers in Settings that were never extracted by prior tooling, leaving Settings and the View menu English-only regardless of locale. Co-Authored-By: Claude Sonnet 4.6 --- oAI.xcodeproj/project.pbxproj | 1 + oAI/Localizable.xcstrings | 11076 +++++++++++++++++++++++++++++++- 2 files changed, 11037 insertions(+), 40 deletions(-) diff --git a/oAI.xcodeproj/project.pbxproj b/oAI.xcodeproj/project.pbxproj index a2ee833..be3380f 100644 --- a/oAI.xcodeproj/project.pbxproj +++ b/oAI.xcodeproj/project.pbxproj @@ -104,6 +104,7 @@ da, de, sv, + fr, ); mainGroup = A550A6592F3B72EA00136F2B; minimizedProjectReferenceProxies = 1; diff --git a/oAI/Localizable.xcstrings b/oAI/Localizable.xcstrings index 46e7901..2577421 100644 --- a/oAI/Localizable.xcstrings +++ b/oAI/Localizable.xcstrings @@ -3,10 +3,73 @@ "strings" : { "·" : { "comment" : "A separator between the message count and the date.", - "isCommentAutoGenerated" : true + "isCommentAutoGenerated" : true, + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "·" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "·" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "·" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "·" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "·" + } + } + } }, "· %@" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "· %@" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "· %@" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "· %@" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "· %@" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "· %@" + } + } + } }, "(always used)" : { "localizations" : { @@ -22,6 +85,12 @@ "value" : "(immer verwendet)" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "(toujours utilisé)" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -50,6 +119,12 @@ "value" : "(optional)" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "(facultatif)" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -80,6 +155,12 @@ "value" : "[GNU Affero General Public License v3.0](https://www.gnu.org/licenses/agpl-3.0.html)" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "[GNU Affero General Public License v3.0](https://www.gnu.org/licenses/agpl-3.0.html)" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -108,6 +189,12 @@ "value" : "# When reviewing code, always:\n- Check for security vulnerabilities\n- Verify error handling\n- Suggest tests for edge cases" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "# When reviewing code, always:\n- Check for security vulnerabilities\n- Verify error handling\n- Suggest tests for edge cases" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -136,6 +223,12 @@ "value" : "%@" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -166,6 +259,12 @@ "value" : "%@ aktiv — in jedes Gespräch eingefügt" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ actif — injecté dans chaque conversation" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -196,6 +295,12 @@ "value" : "%@ Zeichen" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ caractères" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -224,6 +329,12 @@ "value" : "%@ min" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ min" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -254,6 +365,12 @@ "value" : "%@ pt" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ pt" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -282,6 +399,12 @@ "value" : "%@s" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@s" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -312,6 +435,12 @@ "value" : "•" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "•" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -340,6 +469,12 @@ "value" : "• Öffentlichen Schlüssel beim Git-Anbieter hinzufügen" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "• Ajouter la clé publique à ton fournisseur Git" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -368,6 +503,12 @@ "value" : "• Keine Zugangsdaten in oAI erforderlich" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "• Aucun identifiant requis dans oAI" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -396,6 +537,12 @@ "value" : "• Verwendet deine System-SSH-Schlüssel (~/.ssh/id_ed25519)" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "• Utilise les clés SSH de ton système (~/.ssh/id_ed25519)" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -426,6 +573,12 @@ "value" : "^[%@ Eintrag](inflect: true)" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ entrée](inflect: true)" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -441,10 +594,72 @@ } }, "^[%@ message](inflect: true)" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ besked](inflect: true)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ Nachricht](inflect: true)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ message](inflect: true)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ melding](inflect: true)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ meddelande](inflect: true)" + } + } + } }, "^[%@ token](inflect: true)" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ token](inflect: true)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ token](inflect: true)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ token](inflect: true)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ token](inflect: true)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ token](inflect: true)" + } + } + } }, "© 2026 [Rune Olsen](https://blog.rune.pm)" : { "comment" : "A copyright notice with the copyright holder's name.", @@ -462,6 +677,12 @@ "value" : "© 2026 [Rune Olsen](https://blog.rune.pm)" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "© 2026 [Rune Olsen](https://blog.rune.pm)" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -490,6 +711,12 @@ "value" : "↑↓ navigate ↩ open" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "↑↓ navigate ↩ open" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -518,6 +745,12 @@ "value" : "~750 Tokens ≈ 500 Wörter. Online-Modus ermöglicht Websuche in Antworten." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "~750 tokens ≈ 500 mots. Le mode en ligne permet la recherche web dans les réponses." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -549,6 +782,12 @@ "value" : "⌘N New • ⌘M Model • ⌘S Save" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "⌘N New • ⌘M Model • ⌘S Save" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -565,7 +804,39 @@ }, "⚠️ Beta — Paperless integration is under active development. Some features may be incomplete or behave unexpectedly." : { "comment" : "A warning displayed in the settings view.", - "isCommentAutoGenerated" : true + "isCommentAutoGenerated" : true, + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ Beta — Paperless-integrationen er under aktiv udvikling. Nogle funktioner kan være ufuldstændige eller fungere uventet." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ Beta — Die Paperless-Integration befindet sich in aktiver Entwicklung. Einige Funktionen können unvollständig sein oder sich unerwartet verhalten." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ Bêta — L'intégration Paperless est en développement actif. Certaines fonctionnalités peuvent être incomplètes ou se comporter de façon inattendue." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ Beta — Paperless-integrasjonen er under aktiv utvikling. Noen funksjoner kan være ufullstendige eller fungere uventet." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ Beta — Paperless-integrationen är under aktiv utveckling. Vissa funktioner kan vara ofullständiga eller bete sig oväntat." + } + } + } }, "⚠️ Custom prompt active — only this prompt will be sent to the model." : { "localizations" : { @@ -581,6 +852,12 @@ "value" : "⚠️ Benutzerdefinierter Prompt aktiv — nur dieser Prompt wird an das Modell gesendet." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ Prompt personnalisé actif — seul ce prompt sera envoyé au modèle." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -611,6 +888,12 @@ "value" : "⚠️ unterbrochen" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ interrompu" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -639,6 +922,12 @@ "value" : "⚠️ Viele Anbieter (GitHub) unterstützen keine Passwort-Authentifizierung mehr. Stattdessen Access Token verwenden." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ De nombreux fournisseurs (GitHub) ne prennent plus en charge l'authentification par mot de passe. Utilise un Access Token à la place." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -667,6 +956,12 @@ "value" : "⚠️ Keine Embedding-Anbieter verfügbar. Konfiguriere einen API-Schlüssel für OpenAI, OpenRouter oder Google auf der Registerkarte „Allgemein“." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ Aucun fournisseur d'embeddings disponible. Configure une clé API pour OpenAI, OpenRouter ou Google dans l'onglet Général." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -695,6 +990,12 @@ "value" : "⚠️ Einmaliger Vorgang — generiert Embeddings für alle Nachrichten. Geschätzte Kosten: ~$0,04 für 10.000 Nachrichten." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ Opération unique — génère des embeddings pour tous les messages. Coût estimé : ~0,04 $ pour 10 000 messages." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -723,6 +1024,12 @@ "value" : "⚠️ Das sind erweiterte Einstellungen" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ Ce sont des réglages avancés" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -753,6 +1060,12 @@ "value" : "🌐" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "🌐" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -783,6 +1096,12 @@ "value" : "🎨" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "🎨" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -813,6 +1132,12 @@ "value" : "👁️" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "👁️" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -841,6 +1166,12 @@ "value" : "💡 Für Gmail ein App-Passwort verwenden. Google-Konto > Sicherheit > 2-Schritt-Verifizierung > App-Passwörter." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "💡 Pour Gmail, utilise un mot de passe d'application. Compte Google > Sécurité > Validation en deux étapes > Mots de passe d'application." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -869,6 +1200,12 @@ "value" : "💡 HTTPS-URL verwenden (z.B. https://gitlab.pm/user/repo.git) — funktioniert mit allen Authentifizierungsmethoden." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "💡 Utilise une URL HTTPS (ex. https://gitlab.pm/user/repo.git) — fonctionne avec toutes les méthodes d'authentification." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -899,6 +1236,12 @@ "value" : "🔧" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "🔧" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -914,10 +1257,72 @@ } }, "🧠" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "🧠" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "🧠" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "🧠" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "🧠" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "🧠" + } + } + } }, "1. Open Anytype → Settings → Integrations" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "1. Åbn Anytype → Indstillinger → Integrationer" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "1. Anytype öffnen → Einstellungen → Integrationen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "1. Ouvrir Anytype → Réglages → Intégrations" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "1. Åpne Anytype → Innstillinger → Integrasjoner" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "1. Öppna Anytype → Inställningar → Integrationer" + } + } + } }, "1. Open Paperless-NGX → Settings → API Tokens" : { "comment" : "A step in the process of getting a Paperless-NGX API token.", @@ -935,6 +1340,12 @@ "value" : "1. Paperless-NGX öffnen → Einstellungen → API-Tokens" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "1. Ouvrir Paperless-NGX → Réglages → Tokens API" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -951,7 +1362,39 @@ }, "2. Create a new API key" : { "comment" : "A step in the process of getting an API key from Anytype.", - "isCommentAutoGenerated" : true + "isCommentAutoGenerated" : true, + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "2. Opret en ny API-nøgle" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "2. Neuen API-Schlüssel erstellen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "2. Créer une nouvelle clé API" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "2. Opprett en ny API-nøkkel" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "2. Skapa en ny API-nyckel" + } + } + } }, "2. Create or copy your token" : { "comment" : "A step in the process of getting a Paperless-NGX API token.", @@ -969,6 +1412,12 @@ "value" : "2. Token erstellen oder kopieren" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "2. Créer ou copier ton token" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -999,6 +1448,12 @@ "value" : "3. Oben einfügen" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "3. Coller ci-dessus" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1013,6 +1468,40 @@ } } }, + "A model reads all the source messages and rewrites them into one coherent, de-duplicated conversation." : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "En model læser alle kildebeskederne og omskriver dem til én sammenhængende samtale uden dubletter." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ein Modell liest alle Quellnachrichten und schreibt sie zu einem zusammenhängenden, duplikatfreien Gespräch um." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Un modèle lit tous les messages source et les réécrit en une conversation cohérente et dédupliquée." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "En modell leser alle kildemeldingene og skriver dem om til én sammenhengende samtale uten duplikater." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "En modell läser alla källmeddelanden och skriver om dem till en sammanhängande konversation utan dubbletter." + } + } + } + }, "A shortcut with command %@ already exists." : { "comment" : "A warning message that appears when a user tries to import a shortcut that already exists in their settings. The argument is the command of the conflicting shortcut.", "isCommentAutoGenerated" : true, @@ -1029,6 +1518,12 @@ "value" : "Eine Verknüpfung mit dem Befehl %@ existiert bereits." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Un raccourci avec la commande %@ existe déjà." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1057,6 +1552,12 @@ "value" : "Access Token" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Access Token" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1087,6 +1588,12 @@ "value" : "aktiv" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "actif" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1117,6 +1624,12 @@ "value" : "Aktiv" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Actif" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1147,6 +1660,12 @@ "value" : "Aktive Skills werden an den System-Prompt angehängt. Schalte sie einzeln ein oder aus, um zu steuern, was die KI weiß." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Les skills actifs sont ajoutés au prompt système. Active ou désactive-les individuellement pour contrôler ce que l'IA sait." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1162,7 +1681,38 @@ } }, "Agent" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agent" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agent" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agent" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agent" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agent" + } + } + } }, "Agent Skills" : { "localizations" : { @@ -1178,6 +1728,12 @@ "value" : "Agent-Skills" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agent Skills" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1193,7 +1749,72 @@ } }, "Agents" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agenter" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agenten" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agents" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agenter" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agenter" + } + } + } + }, + "AI-Assisted Merge" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "AI-assisteret sammenlægning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "KI-unterstützte Zusammenführung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fusion assistée par IA" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "KI-assistert sammenslåing" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "AI-assisterad sammanslagning" + } + } + } }, "Allow Shell Command?" : { "comment" : "A title for a modal that asks the user if they want to allow a shell command.", @@ -1211,6 +1832,12 @@ "value" : "Shell-Befehl erlauben?" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Autoriser la commande shell ?" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1239,6 +1866,12 @@ "value" : "Erlaube der KI, Shell-Befehle auf deinem Rechner auszuführen. Befehle werden über /bin/zsh ausgeführt. Aktiviere den Genehmigungsmodus, um jeden Befehl vor der Ausführung zu prüfen." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Autorise l'IA à exécuter des commandes shell sur ta machine. Les commandes sont exécutées via /bin/zsh. Active le mode d'approbation pour examiner chaque commande avant son exécution." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1269,6 +1902,12 @@ "value" : "Anthropic Balance" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anthropic Balance" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1299,6 +1938,12 @@ "value" : "API-Schlüssel und Zugangsdaten sind **nicht** in der Sicherung enthalten. Du musst sie nach der Wiederherstellung auf einem neuen Gerät erneut eingeben." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Les clés API et les identifiants ne sont **pas** inclus dans la sauvegarde. Tu devras les saisir à nouveau après la restauration sur une nouvelle machine." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1327,6 +1972,12 @@ "value" : "Automatischer Ausführungsmodus: Befehle werden ohne Genehmigung ausgeführt. Mit Vorsicht verwenden." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mode d'exécution automatique : les commandes s'exécutent sans approbation. À utiliser avec prudence." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1355,6 +2006,12 @@ "value" : "Die automatische Synchronisierung kann zu Konflikten führen, wenn sie auf mehreren Geräten gleichzeitig läuft." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "La synchronisation automatique peut provoquer des conflits si elle s'exécute simultanément sur plusieurs machines." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1383,6 +2040,12 @@ "value" : "Relevante Nachrichten automatisch auswählen statt die gesamte Historie zu senden. Reduziert den Token-Verbrauch bei langen Gesprächen." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sélectionne automatiquement les messages pertinents au lieu d'envoyer tout l'historique. Réduit la consommation de tokens pour les longues conversations." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1411,6 +2074,12 @@ "value" : "Ältere Teile langer Gespräche automatisch zusammenfassen, um Tokens zu sparen und die Kontexteffizienz zu verbessern." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Résume automatiquement les anciennes parties des longues conversations pour économiser des tokens et améliorer l'efficacité du contexte." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1441,6 +2110,12 @@ "value" : "Jetzt sichern" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sauvegarder maintenant" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1471,6 +2146,12 @@ "value" : "Sicherungsort:" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Emplacement de la sauvegarde :" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1499,6 +2180,12 @@ "value" : "Bash Execution" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bash Execution" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1527,6 +2214,12 @@ "value" : "Branch: %@" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Branch: %@" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1557,6 +2250,12 @@ "value" : "Built with SwiftUI" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Built with SwiftUI" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1587,6 +2286,12 @@ "value" : "Fähigkeiten" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Capacités" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1602,7 +2307,38 @@ } }, "Category" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kategori" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kategorie" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Catégorie" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kategori" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kategori" + } + } + } }, "Changing these values affects how the AI generates responses. The defaults work well for most use cases." : { "localizations" : { @@ -1618,6 +2354,12 @@ "value" : "Das Ändern dieser Werte beeinflusst, wie die KI Antworten generiert. Die Standardwerte funktionieren für die meisten Anwendungsfälle gut." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modifier ces valeurs affecte la façon dont l'IA génère ses réponses. Les valeurs par défaut conviennent à la plupart des cas d'usage." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1648,6 +2390,12 @@ "value" : "Guthaben prüfen unter:" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vérifie ton solde sur :" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1678,6 +2426,12 @@ "value" : "Nutzung prüfen unter:" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vérifie ta consommation sur :" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1693,7 +2447,38 @@ } }, "Choose an agent from the list to view details and run history" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vælg en agent fra listen for at se detaljer og kørehistorik" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wähle einen Agenten aus der Liste, um Details und Verlauf anzuzeigen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Choisis un agent dans la liste pour voir ses détails et son historique d'exécution" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Velg en agent fra listen for å se detaljer og kjørehistorikk" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Välj en agent från listan för att se detaljer och körhistorik" + } + } + } }, "Clear All" : { "comment" : "A button to clear all email activity logs.", @@ -1711,6 +2496,12 @@ "value" : "Alle löschen" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tout effacer" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1739,6 +2530,12 @@ "value" : "Klicke unten auf „Ordner hinzufügen“ oder ziehe Ordner aus dem Finder hierher" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Clique sur « Ajouter un dossier » ci-dessous ou fais glisser des dossiers depuis le Finder" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1753,6 +2550,142 @@ } } }, + "Combine (%@)" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sammenlæg (%@)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zusammenführen (%@)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fusionner (%@)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slå sammen (%@)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slå samman (%@)" + } + } + } + }, + "Combine Conversations" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sammenlæg samtaler" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gespräche zusammenführen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fusionner les conversations" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slå sammen samtaler" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slå samman konversationer" + } + } + } + }, + "Combining %@ conversations" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sammenlægger %@ samtaler" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ Gespräche werden zusammengeführt" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fusion de %@ conversations" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slår sammen %@ samtaler" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slår samman %@ konversationer" + } + } + } + }, + "Combining…" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sammenlægger…" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wird zusammengeführt…" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fusion en cours…" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slår sammen…" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slår samman…" + } + } + } + }, "Command" : { "comment" : "A label displayed above the command field.", "isCommentAutoGenerated" : true, @@ -1769,6 +2702,12 @@ "value" : "Befehl" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Commande" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1799,6 +2738,12 @@ "value" : "BEFEHL" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "COMMANDE" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1829,6 +2774,12 @@ "value" : "Befehlshistorie" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Historique des commandes" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1859,6 +2810,12 @@ "value" : "Inhalt (Markdown)" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Contenu (Markdown)" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1887,6 +2844,12 @@ "value" : "Steuert, welche Nachrichten in ~/Library/Logs/oAI.log geschrieben werden" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Contrôle quels messages sont écrits dans ~/Library/Logs/oAI.log" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1915,6 +2878,12 @@ "value" : "Gespräche" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Conversations" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1945,6 +2914,12 @@ "value" : "Kopiert!" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Copié !" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -1960,7 +2935,38 @@ } }, "Cost" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Omkostning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kosten" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Coût" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kostnad" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kostnad" + } + } + } }, "Cost Examples" : { "comment" : "A heading for the cost examples of a model.", @@ -1978,6 +2984,12 @@ "value" : "Kostenbeispiele" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exemples de coûts" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2006,6 +3018,12 @@ "value" : "Erstelle ein dediziertes E-Mail-Konto speziell für die KI-Bearbeitung. Verwende NICHT deine persönliche E-Mail-Adresse." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Crée un compte e-mail dédié spécifiquement à la gestion par l'IA. N'utilise PAS ton adresse e-mail personnelle." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2036,6 +3054,12 @@ "value" : "Erstelle eine Verknüpfung, um eine wiederverwendbare Prompt-Vorlage zu speichern, die über das /-Befehlsmenü zugänglich ist." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Crée un raccourci pour enregistrer un modèle de prompt réutilisable, accessible depuis le menu de commandes /." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2064,6 +3088,12 @@ "value" : "Standard-Prompt" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prompt par défaut" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2092,6 +3122,12 @@ "value" : "Löschen (%@)" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Supprimer (%@)" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2122,6 +3158,12 @@ "value" : "Beschreibung" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Description" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2137,7 +3179,38 @@ } }, "Disabled" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Deaktiveret" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Deaktiviert" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Désactivé" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Deaktivert" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inaktiverad" + } + } + } }, "Each command will require your approval before running." : { "localizations" : { @@ -2153,6 +3226,12 @@ "value" : "Jeder Befehl erfordert deine Genehmigung, bevor er ausgeführt wird." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Chaque commande nécessitera ton approbation avant son exécution." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2183,6 +3262,12 @@ "value" : "Bearbeiten" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modifier" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2213,6 +3298,12 @@ "value" : "E-Mail-Aktivitätsprotokoll" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Journal d'activité e-mail" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2241,6 +3332,12 @@ "value" : "System-Prompt für E-Mail-Handler" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prompt système du gestionnaire d'e-mails" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2269,6 +3366,12 @@ "value" : "Der E-Mail-Handler verwendet NUR seinen eigenen System-Prompt, vollständig isoliert von deinen Chat-Einstellungen. Ein benutzerdefinierter Prompt unten überschreibt die Standardeinstellungen." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Le gestionnaire d'e-mails utilise UNIQUEMENT son propre prompt système, complètement isolé de tes paramètres de chat principaux. Un prompt personnalisé ci-dessous remplacera les valeurs par défaut." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2297,6 +3400,12 @@ "value" : "E-Mail-Aufgaben haben NUR LESEZUGRIFF auf MCP-Ordner. Die KI kann beim Verarbeiten von E-Mails keine Dateien schreiben, löschen oder ändern." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Les tâches e-mail ont un accès EN LECTURE SEULE aux dossiers MCP. L'IA ne peut pas écrire, supprimer ou modifier de fichiers lors du traitement des e-mails." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2325,6 +3434,12 @@ "value" : "KI-gestützte semantische Suche mit %@-Embeddings aktivieren. Kosten: ~$0,02–0,15/1M Tokens." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Active la recherche sémantique par IA avec les embeddings %@. Coût : ~0,02–0,15 $/1M tokens." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2355,6 +3470,12 @@ "value" : "E-Mail-Handler in den Einstellungen aktivieren, um E-Mails zu überwachen" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Active le gestionnaire d'e-mails dans les Réglages pour commencer à surveiller les e-mails" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2385,6 +3506,12 @@ "value" : "Fehler: %@" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erreur : %@" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2415,6 +3542,12 @@ "value" : "Beispielstruktur:" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exemple de structure :" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2443,6 +3576,12 @@ "value" : "Example: oai-bot-x7k2m9p3@gmail.com" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exemple : oai-bot-x7k2m9p3@gmail.com" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2471,6 +3610,12 @@ "value" : "Dateizugriffsberechtigungen" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Autorisations d'accès aux fichiers" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2501,6 +3646,12 @@ "value" : "Dateien" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fichiers" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2516,10 +3667,72 @@ } }, "Filter by Category" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filtrer efter kategori" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nach Kategorie filtern" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filtrer par catégorie" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filtrer etter kategori" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filtrera efter kategori" + } + } + } }, "Generate an API key in your Jarvis settings and paste it above." : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Generer en API-nøgle i dine Jarvis-indstillinger og indsæt den ovenfor." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erstelle einen API-Schlüssel in deinen Jarvis-Einstellungen und füge ihn oben ein." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Génère une clé API dans tes réglages Jarvis et colle-la ci-dessus." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Generer en API-nøkkel i Jarvis-innstillingene dine og lim den inn ovenfor." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Generera en API-nyckel i dina Jarvis-inställningar och klistra in den ovan." + } + } + } }, "Google (Gemini embedding)" : { "localizations" : { @@ -2535,6 +3748,12 @@ "value" : "Google (Gemini embedding)" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Google (Gemini embedding)" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2565,6 +3784,12 @@ "value" : "Hilfe" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aide" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2580,10 +3805,72 @@ } }, "High (~80%)" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Høj (~80%)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hoch (~80%)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Élevé (~80%)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Høy (~80%)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hög (~80%)" + } + } + } }, "How to get your API key:" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sådan får du din API-nøgle:" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "So erhältst du deinen API-Schlüssel:" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Comment obtenir ta clé API :" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slik får du API-nøkkelen din:" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Så här hämtar du din API-nyckel:" + } + } + } }, "How to get your API token:" : { "comment" : "A heading for a section that describes how to get your API token.", @@ -2601,6 +3888,12 @@ "value" : "So erhältst du deinen API-Token:" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Comment obtenir ton token API :" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2629,6 +3922,12 @@ "value" : "ℹ️ SSH-Schlüssel-Authentifizierung" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "ℹ️ Authentification par clé SSH" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2657,6 +3956,12 @@ "value" : "Repository initialisieren" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Initialiser le dépôt" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2685,6 +3990,12 @@ "value" : "In den System-Prompt jedes Gesprächs einfügen" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Injecter dans le prompt système de chaque conversation" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2700,7 +4011,38 @@ } }, "Input" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Input" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eingabe" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Entrée" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inndata" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Indata" + } + } + } }, "Large files inflate the system prompt and may hit token limits." : { "comment" : "A warning displayed when a user adds a large file to a skill.", @@ -2718,6 +4060,12 @@ "value" : "Große Dateien blähen den System-Prompt auf und können Token-Limits erreichen." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Les fichiers volumineux alourdissent le prompt système et peuvent atteindre les limites de tokens." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2746,6 +4094,12 @@ "value" : "Letzte Synchronisierung: %@" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dernière synchro : %@" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2774,6 +4128,12 @@ "value" : "Leer lassen, um den Standard-System-Prompt des E-Mail-Handlers zu verwenden." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Laisser vide pour utiliser le prompt système par défaut du gestionnaire d'e-mails." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2789,7 +4149,38 @@ } }, "Low (~20%)" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lav (~20%)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Niedrig (~20%)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Faible (~20%)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lav (~20%)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Låg (~20%)" + } + } + } }, "Lowercase letters, numbers, and hyphens only. No spaces." : { "comment" : "A description of the format of a shortcut's command.", @@ -2807,6 +4198,12 @@ "value" : "Nur Kleinbuchstaben, Zahlen und Bindestriche. Keine Leerzeichen." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lettres minuscules, chiffres et tirets uniquement. Pas d'espaces." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2837,6 +4234,12 @@ "value" : "Markdown-Anweisungsdateien, die in den System-Prompt eingefügt werden. Kompatibel mit SKILL.md-Format." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fichiers d'instructions Markdown injectés dans le prompt système. Compatible avec le format SKILL.md." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2865,6 +4268,12 @@ "value" : "Maximale Tokens: auf 0 setzen, um den Modell-Standard zu verwenden. Höhere Werte erlauben längere Antworten." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokens max : mettre à 0 pour utiliser la valeur par défaut du modèle. Des valeurs plus élevées permettent des réponses plus longues." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2893,6 +4302,12 @@ "value" : "MCP gibt der KI kontrollierten Zugriff, um Dateien auf deinem Computer zu lesen und optional zu schreiben. Die KI kann Dateien in erlaubten Ordnern suchen, lesen und analysieren, um bei Programmierung, Analyse und anderen Aufgaben zu helfen." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "MCP donne à l'IA un accès contrôlé pour lire et, optionnellement, écrire des fichiers sur ton ordinateur. L'IA peut rechercher, lire et analyser des fichiers dans les dossiers autorisés pour t'aider en programmation, en analyse et dans d'autres tâches." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2908,7 +4323,72 @@ } }, "Medium (~50%)" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mellem (~50%)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mittel (~50%)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Moyen (~50%)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Middels (~50%)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Medel (~50%)" + } + } + } + }, + "Merge method" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sammenlægningsmetode" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zusammenführungsmethode" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Méthode de fusion" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sammenslåingsmetode" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sammanslagningsmetod" + } + } + } }, "messages" : { "localizations" : { @@ -2924,6 +4404,12 @@ "value" : "Nachrichten" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "messages" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2938,8 +4424,73 @@ } } }, + "Messages from all selected conversations are combined in chronological order." : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Beskeder fra alle valgte samtaler sammenlægges i kronologisk rækkefølge." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nachrichten aus allen ausgewählten Gesprächen werden in chronologischer Reihenfolge zusammengeführt." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Les messages de toutes les conversations sélectionnées sont fusionnés par ordre chronologique." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Meldinger fra alle valgte samtaler slås sammen i kronologisk rekkefølge." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Meddelanden från alla valda konversationer slås samman i kronologisk ordning." + } + } + } + }, "Minimal (~10%)" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Minimal (~10%)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Minimal (~10%)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Minimal (~10%)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Minimal (~10%)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Minimal (~10%)" + } + } + } }, "Model Context Protocol" : { "localizations" : { @@ -2955,6 +4506,12 @@ "value" : "Model Context Protocol" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Model Context Protocol" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -2985,6 +4542,12 @@ "value" : "Modell-Info" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Infos du modèle" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3000,7 +4563,38 @@ } }, "Model thinks internally but reasoning is not shown in chat" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modellen tænker internt, men ræsonnementet vises ikke i chatten" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Das Modell denkt intern nach, aber die Überlegungen werden nicht im Chat angezeigt" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Le modèle réfléchit en interne mais le raisonnement n'est pas affiché dans le chat" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modellen tenker internt, men resonneringen vises ikke i chatten" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modellen tänker internt, men resonemanget visas inte i chatten" + } + } + } }, "Multi-provider AI chat client" : { "comment" : "A description of oAI.", @@ -3018,6 +4612,12 @@ "value" : "KI-Chat-Client mit mehreren Anbietern" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Client de chat IA multi-fournisseurs" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3048,6 +4648,12 @@ "value" : "Name" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nom" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3078,6 +4684,12 @@ "value" : "Nie" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jamais" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3093,7 +4705,72 @@ } }, "New Chat" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ny chat" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Neuer Chat" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nouveau chat" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ny chat" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ny chatt" + } + } + } + }, + "New conversation name" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nyt samtalenavn" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Neuer Gesprächsname" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nouveau nom de conversation" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nytt samtalenavn" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nytt konversationsnamn" + } + } + } }, "No credit data available" : { "comment" : "A message displayed when there is no credit data available.", @@ -3111,6 +4788,12 @@ "value" : "Keine Guthabendaten verfügbar" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aucune donnée de crédit disponible" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3141,6 +4824,12 @@ "value" : "Noch keine E-Mail-Aktivität" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aucune activité e-mail pour le moment" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3171,6 +4860,12 @@ "value" : "Keine Dateien angehängt. Füge JSON, YAML, CSV oder TXT-Dateien hinzu, um Daten zusammen mit diesem Skill in den System-Prompt einzufügen." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aucun fichier joint. Ajoute des fichiers JSON, YAML, CSV ou TXT pour injecter des données dans le prompt système avec ce skill." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3201,6 +4896,12 @@ "value" : "Kein Modell ausgewählt" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aucun modèle sélectionné" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3229,6 +4930,12 @@ "value" : "Keine Modelle verfügbar" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aucun modèle disponible" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3259,6 +4966,12 @@ "value" : "Keine Ergebnisse für „%@“" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aucun résultat pour « %@ »" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3274,7 +4987,38 @@ } }, "No runs yet" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ingen kørsler endnu" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Noch keine Durchläufe" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aucune exécution pour le moment" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ingen kjøringer ennå" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inga körningar ännu" + } + } + } }, "No shortcuts yet" : { "comment" : "A message displayed when a user has no shortcuts.", @@ -3292,6 +5036,12 @@ "value" : "Noch keine Verknüpfungen" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aucun raccourci pour le moment" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3322,6 +5072,12 @@ "value" : "Noch keine Verknüpfungen — klicke auf „Neue Verknüpfung“, um eine zu erstellen." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aucun raccourci pour le moment — clique sur « Nouveau raccourci » pour en créer un." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3352,6 +5108,12 @@ "value" : "Noch keine Skills" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aucun skill pour le moment" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3382,6 +5144,12 @@ "value" : "Noch keine Skills — klicke auf „Neuer Skill“ oder „Importieren“, um loszulegen." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aucun skill pour le moment — clique sur « Nouveau skill » ou « Importer » pour commencer." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3412,6 +5180,12 @@ "value" : "oAI" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "oAI" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3428,7 +5202,39 @@ }, "oAI v2.4 is the last version to support Intel Macs and Rosetta. Starting with macOS 28, oAI will require Apple Silicon. Consider upgrading your Mac to continue receiving updates." : { "comment" : "A warning that Intel Macs are no longer supported.", - "isCommentAutoGenerated" : true + "isCommentAutoGenerated" : true, + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "oAI v2.4 er den sidste version, der understøtter Intel-Mac og Rosetta. Fra macOS 28 vil oAI kræve Apple Silicon. Overvej at opgradere din Mac for at fortsætte med at få opdateringer." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "oAI v2.4 ist die letzte Version, die Intel-Macs und Rosetta unterstützt. Ab macOS 28 benötigt oAI Apple Silicon. Erwäge ein Upgrade deines Mac, um weiterhin Updates zu erhalten." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "oAI v2.4 est la dernière version à prendre en charge les Mac Intel et Rosetta. À partir de macOS 28, oAI nécessitera Apple Silicon. Envisage de mettre à niveau ton Mac pour continuer à recevoir des mises à jour." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "oAI v2.4 er den siste versjonen som støtter Intel-Mac og Rosetta. Fra macOS 28 vil oAI kreve Apple Silicon. Vurder å oppgradere Mac-en din for å fortsette å få oppdateringer." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "oAI v2.4 är den sista versionen som stöder Intel-Mac och Rosetta. Från macOS 28 kommer oAI att kräva Apple Silicon. Överväg att uppgradera din Mac för att fortsätta få uppdateringar." + } + } + } }, "Ollama (Local)" : { "comment" : "A label displayed above the credits information for the local Ollie.", @@ -3446,6 +5252,12 @@ "value" : "Ollama (Local)" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ollama (Local)" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3474,6 +5286,12 @@ "value" : "Nur E-Mails mit diesem Text in der Betreffzeile werden verarbeitet. Beispiel: „[OAIBOT] Wie ist das Wetter?“" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Seuls les e-mails contenant ce texte dans la ligne d'objet seront traités. Exemple : « [OAIBOT] Quel temps fait-il ? »" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3502,6 +5320,12 @@ "value" : "OpenAI (text-embedding-3-large)" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "OpenAI (text-embedding-3-large)" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3530,6 +5354,12 @@ "value" : "OpenAI (text-embedding-3-small)" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "OpenAI (text-embedding-3-small)" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3560,6 +5390,12 @@ "value" : "OpenAI Balance" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "OpenAI Balance" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3588,6 +5424,12 @@ "value" : "OpenRouter (OpenAI large)" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "OpenRouter (OpenAI large)" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3616,6 +5458,12 @@ "value" : "OpenRouter (OpenAI small)" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "OpenRouter (OpenAI small)" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3644,6 +5492,12 @@ "value" : "OpenRouter (Qwen 8B)" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "OpenRouter (Qwen 8B)" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3659,7 +5513,38 @@ } }, "OpenRouter Balance" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "OpenRouter Balance" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "OpenRouter Balance" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "OpenRouter Balance" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "OpenRouter Balance" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "OpenRouter Balance" + } + } + } }, "OpenRouter Credits" : { "comment" : "A heading for the user's OpenRouter credits.", @@ -3677,6 +5562,12 @@ "value" : "OpenRouter Credits" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "OpenRouter Credits" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3692,10 +5583,72 @@ } }, "Output" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Output" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ausgabe" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sortie" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Utdata" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Utdata" + } + } + } }, "Prompt" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prompt" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prompt" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prompt" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prompt" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prompt" + } + } + } }, "Read access (always enabled)" : { "localizations" : { @@ -3711,6 +5664,12 @@ "value" : "Lesezugriff (immer aktiviert)" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Accès en lecture (toujours activé)" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3726,7 +5685,38 @@ } }, "Reasoning" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ræsonnement" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Denkprozess" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Raisonnement" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Resonnering" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Resonemang" + } + } + } }, "Remote: %@" : { "localizations" : { @@ -3742,6 +5732,12 @@ "value" : "Remote: %@" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Remote: %@" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3772,6 +5768,12 @@ "value" : "Aus Datei wiederherstellen…" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Restaurer depuis un fichier…" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3787,10 +5789,72 @@ } }, "Run History" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kørehistorik" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Durchlaufverlauf" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Historique d'exécution" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kjørehistorikk" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Körhistorik" + } + } + } }, "Run some agents to see usage statistics" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kør nogle agenter for at se forbrugsstatistik" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Führe einige Agenten aus, um Nutzungsstatistiken zu sehen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exécute des agents pour voir les statistiques d'utilisation" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kjør noen agenter for å se forbruksstatistikk" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kör några agenter för att se användningsstatistik" + } + } + } }, "Running locally — no credits needed!" : { "comment" : "A message displayed when using an on-device LLM like the one provided by the `.ollama` provider.", @@ -3808,6 +5872,12 @@ "value" : "Läuft lokal — kein Guthaben benötigt!" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exécution locale — aucun crédit nécessaire !" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3824,7 +5894,39 @@ }, "Runs" : { "comment" : "A column header for the number of runs.", - "isCommentAutoGenerated" : true + "isCommentAutoGenerated" : true, + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kørsler" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Durchläufe" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exécutions" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kjøringer" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Körningar" + } + } + } }, "Security Recommendation" : { "localizations" : { @@ -3840,6 +5942,12 @@ "value" : "Sicherheitsempfehlung" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Recommandation de sécurité" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3870,6 +5978,12 @@ "value" : "Shell-Befehle haben vollen Zugriff auf dein System. Genehmige nur Befehle, die du verstehst und denen du vertraust." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Les commandes shell ont un accès complet à ton système. N'approuve que les commandes que tu comprends et en lesquelles tu as confiance." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3900,6 +6014,12 @@ "value" : "Textbeschriftungen unter Symbolleistensymbolen anzeigen (hilfreich für neue Benutzer)" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Afficher les libellés sous les icônes de la barre d'outils (utile pour les nouveaux utilisateurs)" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3914,6 +6034,40 @@ } } }, + "Simple Merge" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Enkel sammenlægning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Einfache Zusammenführung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fusion simple" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Enkel sammenslåing" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Enkel sammanslagning" + } + } + } + }, "SKILL.md format — write instructions in plain Markdown." : { "localizations" : { "da" : { @@ -3928,6 +6082,12 @@ "value" : "SKILL.md-Format — Anweisungen in einfachem Markdown schreiben." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Format SKILL.md — écris des instructions en Markdown simple." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3958,6 +6118,12 @@ "value" : "Skills sind Markdown-Anweisungsdateien, die der KI beibringen, wie sie sich verhalten soll. Aktive Skills werden automatisch in den System-Prompt eingefügt." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Les skills sont des fichiers d'instructions Markdown qui apprennent à l'IA comment se comporter. Les skills actifs sont automatiquement injectés dans le prompt système." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -3973,7 +6139,38 @@ } }, "Sort" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sorter" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sortieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Trier" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sorter" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sortera" + } + } + } }, "SSH Key" : { "localizations" : { @@ -3989,6 +6186,12 @@ "value" : "SSH Key" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "SSH Key" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4017,6 +6220,12 @@ "value" : "Antworten während der Generierung streamen. Deaktivieren für vollständige Einzelantworten." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Diffuse les réponses au fur et à mesure de leur génération. Désactive pour des réponses uniques et complètes." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4045,6 +6254,12 @@ "value" : "Gespräche und Einstellungen über mehrere Geräte hinweg mit Git synchronisieren." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Synchronise les conversations et les réglages entre plusieurs machines via Git." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4073,6 +6288,12 @@ "value" : "Jetzt synchronisieren" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Synchroniser maintenant" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4101,6 +6322,12 @@ "value" : "Temperatur: 0 = Modell-Standard · 0,0–0,7 = fokussiert · 0,8–2,0 = kreativ" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Température : 0 = défaut du modèle · 0,0–0,7 = précis · 0,8–2,0 = créatif" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4131,6 +6358,12 @@ "value" : "Vorlage" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modèle" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4159,6 +6392,12 @@ "value" : "Verbindung testen" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tester la connexion" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4189,6 +6428,12 @@ "value" : "Textdateien werden zusammen mit dem Skill in den System-Prompt eingefügt." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Les fichiers texte sont injectés dans le prompt système avec le skill." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4217,6 +6462,12 @@ "value" : "Die KI kann Dateien in erlaubten Ordnern lesen und durchsuchen" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "L'IA peut lire et rechercher des fichiers dans les dossiers autorisés" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4245,6 +6496,12 @@ "value" : "Die KI liest diesen Inhalt und entscheidet, wann sie ihn anwendet. Beschreibe **was** die KI tun soll und **wie** — sei spezifisch und prägnant." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "L'IA lit ce contenu et décide quand l'appliquer. Décris **quoi** l'IA doit faire et **comment** — sois précis et concis." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4275,6 +6532,12 @@ "value" : "Die KI möchte den folgenden Befehl ausführen" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "L'IA souhaite exécuter la commande suivante" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4290,7 +6553,38 @@ } }, "Thinking…" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tænker…" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Denkt nach…" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Réflexion…" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tenker…" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tänker…" + } + } + } }, "This default prompt is always included to ensure accurate, helpful responses." : { "localizations" : { @@ -4306,6 +6600,12 @@ "value" : "Dieser Standard-Prompt ist immer enthalten, um genaue und hilfreiche Antworten sicherzustellen." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ce prompt par défaut est toujours inclus pour garantir des réponses précises et utiles." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4336,6 +6636,12 @@ "value" : "Dadurch werden alle E-Mail-Aktivitätsprotokolle dauerhaft gelöscht. Diese Aktion kann nicht rückgängig gemacht werden." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cela supprimera définitivement tous les journaux d'activité e-mail. Cette action est irréversible." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4366,6 +6672,12 @@ "value" : "Token-Verteilung" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Répartition des tokens" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4394,6 +6706,12 @@ "value" : "tokens" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "tokens" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4409,13 +6727,106 @@ } }, "Total" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "I alt" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gesamt" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Total" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Totalt" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Totalt" + } + } + } }, "Total Credits" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Samlede kreditter" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gesamtguthaben" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Total des crédits" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Totale kreditter" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Totala krediter" + } + } + } }, "Total Used" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "I alt brugt" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Insgesamt verwendet" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Total utilisé" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Totalt brukt" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Totalt använt" + } + } + } }, "Try adjusting your search or filters" : { "comment" : "A description of the error that occurs when no models match the user's search.", @@ -4433,6 +6844,12 @@ "value" : "Suche oder Filter anpassen" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Essaie d'ajuster ta recherche ou tes filtres" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4463,6 +6880,12 @@ "value" : "/ im Eingabefeld eingeben, um Befehlsvorschläge zu sehen" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tape / dans le champ de saisie pour voir les suggestions de commandes" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4493,6 +6916,12 @@ "value" : "Nachricht eingeben oder / für Befehle..." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Écris un message ou / pour les commandes..." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4521,6 +6950,12 @@ "value" : "Nicht übernommene Änderungen: %@" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modifications non commitées : %@" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4551,6 +6986,12 @@ "value" : "Update verfügbar%@" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mise à jour disponible%@" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4566,7 +7007,38 @@ } }, "Usage" : { - + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Forbrug" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nutzung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Utilisation" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Forbruk" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Användning" + } + } + } }, "Use @filename to attach files to your message" : { "comment" : "A description of how to attach files to a message.", @@ -4584,6 +7056,12 @@ "value" : "@dateiname verwenden, um Dateien an die Nachricht anzuhängen" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Utilise @nomdefichier pour joindre des fichiers à ton message" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4614,6 +7092,12 @@ "value" : "Verwende **{{input}}** in der Vorlage, um einzufügen, was du nach dem Befehl tippst." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Utilise **{{input}}** dans le modèle pour insérer ce que tu tapes après la commande." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4644,6 +7128,12 @@ "value" : "Verwende **{{input}}**, um einzufügen, was du nach dem Befehl tippst." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Utilise **{{input}}** pour insérer ce que tu tapes après la commande." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4672,6 +7162,12 @@ "value" : "Username + Password" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Username + Password" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4703,6 +7199,12 @@ "value" : "v%@" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "v%@" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4739,6 +7241,12 @@ "value" : "Version %1$@ (%2$@)" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Version %1$@ (%2$@)" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4767,6 +7275,12 @@ "value" : "E-Mail-Protokoll anzeigen" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Voir le journal e-mail" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4795,6 +7309,12 @@ "value" : "Wenn aktiviert, werden gitignorierte Dateien beim Auflisten und Suchen übersprungen. Schreiboperationen ignorieren immer .gitignore." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lorsque activé, le listage et la recherche ignorent les fichiers gitignorés. Les opérations d'écriture ignorent toujours .gitignore." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4825,6 +7345,12 @@ "value" : "Arbeitsverzeichnis:" } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Répertoire de travail :" + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4855,6 +7381,12 @@ "value" : "Du kannst jede SKILL.md-Datei von skill0.io importieren oder deine eigene schreiben." } }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tu peux importer n'importe quel fichier SKILL.md depuis skill0.io ou écrire le tien." + } + }, "nb" : { "stringUnit" : { "state" : "translated", @@ -4871,7 +7403,8471 @@ }, "β" : { "comment" : "A beta badge.", - "isCommentAutoGenerated" : true + "isCommentAutoGenerated" : true, + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "β" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "β" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "β" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "β" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "β" + } + } + } + }, + "Cancel" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Annuller" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Abbrechen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Annuler" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Avbryt" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Avbryt" + } + } + } + }, + "Save" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gem" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Speichern" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Enregistrer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lagre" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Spara" + } + } + } + }, + "Done" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Færdig" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fertig" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Terminé" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ferdig" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Klar" + } + } + } + }, + "Delete" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slet" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Löschen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Supprimer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slett" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ta bort" + } + } + } + }, + "Rename" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Omdøb" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Umbenennen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Renommer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gi nytt navn" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Byt namn" + } + } + } + }, + "Export" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eksporter" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exportieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exporter" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eksporter" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exportera" + } + } + } + }, + "Import" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Importer" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Importieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Importer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Importer" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Importera" + } + } + } + }, + "Retry" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prøv igen" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erneut versuchen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Réessayer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prøv igjen" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Försök igen" + } + } + } + }, + "Refresh" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Opdater" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktualisieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Actualiser" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Oppdater" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Uppdatera" + } + } + } + }, + "Dismiss" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Luk" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Schließen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fermer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lukk" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stäng" + } + } + } + }, + "Select" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vælg" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auswählen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sélectionner" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Velg" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Välj" + } + } + } + }, + "Clear" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ryd" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Leeren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Effacer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tøm" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rensa" + } + } + } + }, + "Skip" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Spring over" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Überspringen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ignorer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hopp over" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hoppa över" + } + } + } + }, + "Replace" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erstat" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ersetzen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Remplacer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erstatt" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ersätt" + } + } + } + }, + "Keep Both" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Behold begge" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Beide behalten" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Garder les deux" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Behold begge" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Behåll båda" + } + } + } + }, + "Got It" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Forstået" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verstanden" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Compris" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skjønner" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Förstått" + } + } + } + }, + "Later" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Senere" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Später" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Plus tard" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Senere" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Senare" + } + } + } + }, + "OK" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "OK" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "OK" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "OK" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "OK" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "OK" + } + } + } + }, + "Release Page" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Udgivelsesside" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Release-Seite" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Page de version" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Utgivelsesside" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Utgivningssida" + } + } + } + }, + "Download v%@" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hent v%@" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "v%@ herunterladen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Télécharger v%@" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Last ned v%@" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ladda ner v%@" + } + } + } + }, + "Allow Once" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tillad denne gang" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Einmal erlauben" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Autoriser une fois" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tillat denne gangen" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tillåt denna gång" + } + } + } + }, + "Allow for Session" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tillad for sessionen" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Für Sitzung erlauben" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Autoriser pour la session" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tillat for sesjonen" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tillåt för sessionen" + } + } + } + }, + "Deny" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Afvis" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verweigern" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Refuser" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Avslå" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Neka" + } + } + } + }, + "Choose…" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vælg…" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auswählen…" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Choisir…" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Velg…" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Välj…" + } + } + } + }, + "Save to Downloads" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gem til Downloads" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "In Downloads speichern" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Enregistrer dans Téléchargements" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lagre til Nedlastinger" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Spara till Nedladdningar" + } + } + } + }, + "Copy Image" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kopiér billede" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bild kopieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Copier l'image" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kopier bilde" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kopiera bild" + } + } + } + }, + "Add File" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tilføj fil" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Datei hinzufügen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ajouter un fichier" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Legg til fil" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lägg till fil" + } + } + } + }, + "New Skill" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ny færdighed" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Neuer Skill" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nouveau skill" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ny ferdighet" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ny färdighet" + } + } + } + }, + "Export All" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eksporter alle" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Alle exportieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tout exporter" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eksporter alle" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exportera alla" + } + } + } + }, + "Your Shortcuts" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dine genveje" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Deine Verknüpfungen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tes raccourcis" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dine snarveier" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dina genvägar" + } + } + } + }, + "New Shortcut" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ny genvej" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Neue Verknüpfung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nouveau raccourci" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ny snarvei" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ny genväg" + } + } + } + }, + "needs input" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "kræver input" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "benötigt Eingabe" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "nécessite une saisie" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "krever input" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "kräver indata" + } + } + } + }, + "immediate" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "umiddelbar" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "sofort" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "immédiat" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "umiddelbar" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "omedelbar" + } + } + } + }, + "No default model configured — set one in Settings → General." : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ingen standardmodel konfigureret — angiv en i Indstillinger → Generelt." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kein Standardmodell konfiguriert — lege eines in Einstellungen → Allgemein fest." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aucun modèle par défaut configuré — définis-en un dans Réglages → Général." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ingen standardmodell konfigurert — sett en i Innstillinger → Generelt." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ingen standardmodell konfigurerad — ställ in en i Inställningar → Allmänt." + } + } + } + }, + "Delete original conversations after combining" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slet de oprindelige samtaler efter sammenlægning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ursprüngliche Gespräche nach dem Zusammenführen löschen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Supprimer les conversations d'origine après la fusion" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slett originalsamtalene etter sammenslåing" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ta bort originalkonversationerna efter sammanslagning" + } + } + } + }, + "Combine" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sammenlæg" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zusammenführen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fusionner" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slå sammen" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slå samman" + } + } + } + }, + "Semantic" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Semantisk" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Semantisch" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sémantique" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Semantisk" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Semantisk" + } + } + } + }, + "Keyboard Shortcuts" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tastaturgenveje" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tastenkombinationen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Raccourcis clavier" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tastatursnarveier" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tangentbordsgenvägar" + } + } + } + }, + "Jarvis" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jarvis" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jarvis" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jarvis" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jarvis" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jarvis" + } + } + } + }, + "New Agent" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ny agent" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Neuer Agent" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nouvel agent" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ny agent" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ny agent" + } + } + } + }, + "Paused" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pauset" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pausiert" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "En pause" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pauset" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pausad" + } + } + } + }, + "Idle" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inaktiv" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inaktiv" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inactif" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inaktiv" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inaktiv" + } + } + } + }, + "Add Folder…" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tilføj mappe…" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ordner hinzufügen…" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ajouter un dossier…" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Legg til mappe…" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lägg till mapp…" + } + } + } + }, + "Embed All Conversations" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Indlejr alle samtaler" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Alle Gespräche einbetten" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Intégrer toutes les conversations" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bygg inn alle samtaler" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bädda in alla konversationer" + } + } + } + }, + "Needs input — user types after the command" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kræver input — brugeren skriver efter kommandoen" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Benötigt Eingabe — Benutzer tippt nach dem Befehl" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nécessite une saisie — l'utilisateur tape après la commande" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Krever input — brukeren skriver etter kommandoen" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kräver indata — användaren skriver efter kommandot" + } + } + } + }, + "Executes immediately — no extra input needed" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Udføres umiddelbart — ingen ekstra input nødvendig" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wird sofort ausgeführt — keine zusätzliche Eingabe nötig" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "S'exécute immédiatement — aucune saisie supplémentaire nécessaire" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Utføres umiddelbart — ingen ekstra input nødvendig" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Körs omedelbart — ingen extra indata behövs" + } + } + } + }, + "About oAI" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Om oAI" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Über oAI" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "À propos d'oAI" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Om oAI" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Om oAI" + } + } + } + }, + "Settings…" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Indstillinger…" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Einstellungen…" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Réglages…" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Innstillinger…" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inställningar…" + } + } + } + }, + "Clear Chat" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ryd chat" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Chat leeren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Effacer la discussion" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tøm chat" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rensa chatt" + } + } + } + }, + "Open Chat…" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Åbn chat…" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Chat öffnen…" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ouvrir une discussion…" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Åpne chat…" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Öppna chatt…" + } + } + } + }, + "Search Conversations" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søg i samtaler" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gespräche durchsuchen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rechercher dans les conversations" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søk i samtaler" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sök i konversationer" + } + } + } + }, + "Save Chat" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gem chat" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Chat speichern" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Enregistrer la discussion" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lagre chat" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Spara chatt" + } + } + } + }, + "Save Chat As…" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gem chat som…" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Chat speichern als…" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Enregistrer la discussion sous…" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lagre chat som…" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Spara chatt som…" + } + } + } + }, + "Stats" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistik" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistik" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistiques" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistikk" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistik" + } + } + } + }, + "Export as Markdown…" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eksporter som Markdown…" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Als Markdown exportieren…" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exporter en Markdown…" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eksporter som Markdown…" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exportera som Markdown…" + } + } + } + }, + "View" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Visning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ansicht" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Affichage" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Visning" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Visning" + } + } + } + }, + "Select Model" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vælg model" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modell auswählen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sélectionner le modèle" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Velg modell" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Välj modell" + } + } + } + }, + "In-App Help" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hjælp i appen" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hilfe in der App" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aide dans l'app" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hjelp i appen" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hjälp i appen" + } + } + } + }, + "Credits" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kreditter" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Guthaben" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Crédits" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kreditter" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Krediter" + } + } + } + }, + "oAI Help" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "oAI-hjælp" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "oAI-Hilfe" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aide oAI" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "oAI-hjelp" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "oAI-hjälp" + } + } + } + }, + "%@ tokens" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ tokens" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ tokens" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ tokens" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ tokens" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ tokens" + } + } + } + }, + "^[%@ skill](inflect: true) imported" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ færdighed](inflect: true) importeret" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ Skill](inflect: true) importiert" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ skill](inflect: true) importé" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ ferdighet](inflect: true) importert" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ färdighet](inflect: true) importerad" + } + } + } + }, + "^[%@ skill](inflect: true) exported to Downloads" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ færdighed](inflect: true) eksporteret til Downloads" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ Skill](inflect: true) nach Downloads exportiert" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ skill](inflect: true) exporté vers Téléchargements" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ ferdighet](inflect: true) eksportert til Nedlastinger" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ färdighet](inflect: true) exporterad till Nedladdningar" + } + } + } + }, + "^[%@ file](inflect: true)" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ fil](inflect: true)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ Datei](inflect: true)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ fichier](inflect: true)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ fil](inflect: true)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ fil](inflect: true)" + } + } + } + }, + "^[%@ skill](inflect: true) active — appended to every system prompt" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ færdighed](inflect: true) aktiv — tilføjet til hver systemprompt" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ Skill](inflect: true) aktiv — an jeden System-Prompt angehängt" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ skill](inflect: true) actif — ajouté à chaque prompt système" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ ferdighet](inflect: true) aktiv — lagt til i hver systemprompt" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ färdighet](inflect: true) aktiv — lagd till i varje systemprompt" + } + } + } + }, + "^[%@ running](inflect: true)" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ kørende](inflect: true)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ laufend](inflect: true)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ en cours](inflect: true)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ kjørende](inflect: true)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ igång](inflect: true)" + } + } + } + }, + "Search conversations…" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søg i samtaler…" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gespräche durchsuchen…" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rechercher dans les conversations…" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søk i samtaler…" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sök i konversationer…" + } + } + } + }, + "e.g. Code Review, Test Writer, Security Auditor" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "f.eks. Kodegennemgang, Testskribent, Sikkerhedsrevisor" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "z. B. Code-Review, Test-Autor, Sicherheitsprüfer" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "ex. Revue de code, Rédacteur de tests, Auditeur sécurité" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "f.eks. Kodegjennomgang, Testskriving, Sikkerhetsrevisor" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "t.ex. Kodgranskning, Testskrivare, Säkerhetsgranskare" + } + } + } + }, + "Brief summary (optional — auto-extracted from content if left blank)" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kort resumé (valgfrit — udtrækkes automatisk fra indholdet, hvis det er tomt)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kurze Zusammenfassung (optional — wird automatisch aus dem Inhalt extrahiert, wenn leer)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Résumé bref (facultatif — extrait automatiquement du contenu si laissé vide)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kort sammendrag (valgfritt — hentes automatisk fra innholdet hvis tomt)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kort sammanfattning (valfritt — extraheras automatiskt från innehållet om tomt)" + } + } + } + }, + "Search conversations..." : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søg i samtaler..." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gespräche durchsuchen..." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rechercher dans les conversations..." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søk i samtaler..." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sök i konversationer..." + } + } + } + }, + "Loading..." : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Indlæser..." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wird geladen..." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Chargement..." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Laster..." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Laddar..." + } + } + } + }, + "Search by sender, subject, or content..." : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søg efter afsender, emne eller indhold..." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nach Absender, Betreff oder Inhalt suchen..." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rechercher par expéditeur, objet ou contenu..." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søk etter avsender, emne eller innhold..." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sök efter avsändare, ämne eller innehåll..." + } + } + } + }, + "Search commands, shortcuts, features..." : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søg i kommandoer, genveje, funktioner..." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Befehle, Verknüpfungen, Funktionen durchsuchen..." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rechercher des commandes, raccourcis, fonctionnalités..." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søk i kommandoer, snarveier, funksjoner..." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sök i kommandon, genvägar, funktioner..." + } + } + } + }, + "Search by text or date (dd.mm.yyyy)..." : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søg efter tekst eller dato (dd.mm.åååå)..." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nach Text oder Datum suchen (TT.MM.JJJJ)..." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rechercher par texte ou date (jj.mm.aaaa)..." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søk etter tekst eller dato (dd.mm.åååå)..." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sök efter text eller datum (dd.mm.åååå)..." + } + } + } + }, + "Loading usage…" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Indlæser forbrug…" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nutzung wird geladen…" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Chargement de l'utilisation…" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Laster forbruk…" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Laddar användning…" + } + } + } + }, + "Agent name" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agentnavn" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agentenname" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nom de l'agent" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agentnavn" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agentnamn" + } + } + } + }, + "Optional description" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Valgfri beskrivelse" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Optionale Beschreibung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Description facultative" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Valgfri beskrivelse" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Valfri beskrivning" + } + } + } + }, + "Cron expression (e.g. 0 * * * *)" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cron-udtryk (f.eks. 0 * * * *)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cron-Ausdruck (z. B. 0 * * * *)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Expression cron (ex. 0 * * * *)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cron-uttrykk (f.eks. 0 * * * *)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cron-uttryck (t.ex. 0 * * * *)" + } + } + } + }, + "Leave blank for default" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lad stå tomt for standard" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Leer lassen für Standard" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Laisser vide pour la valeur par défaut" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "La stå tomt for standard" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lämna tomt för standard" + } + } + } + }, + "Search models..." : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søg modeller..." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modelle durchsuchen..." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rechercher des modèles..." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søk modeller..." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sök modeller..." + } + } + } + }, + "username" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "brugernavn" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Benutzername" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "nom d'utilisateur" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "brukernavn" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "användarnamn" + } + } + } + }, + "Brief description shown in the command dropdown" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kort beskrivelse vist i kommando-rullemenuen" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kurze Beschreibung im Befehlsmenü" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Brève description affichée dans le menu de commandes" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kort beskrivelse vist i kommando-rullegardinmenyen" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kort beskrivning som visas i kommandomenyn" + } + } + } + }, + "Session Info" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sessionsinfo" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sitzungsinfo" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Infos de session" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sesjonsinfo" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sessionsinfo" + } + } + } + }, + "Token Usage" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokenforbrug" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Token-Nutzung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Utilisation des tokens" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokenbruk" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokenanvändning" + } + } + } + }, + "Costs" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Omkostninger" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kosten" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Coûts" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kostnader" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kostnader" + } + } + } + }, + "Model Details" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modeldetaljer" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modelldetails" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Détails du modèle" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modelldetaljer" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modelldetaljer" + } + } + } + }, + "Intel Mac Support Ending" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Intel Mac-support afsluttes" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Intel-Mac-Unterstützung endet" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fin du support Intel Mac" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Intel Mac-støtte avsluttes" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Intel Mac-support upphör" + } + } + } + }, + "Software Update" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Softwareopdatering" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Software-Update" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mise à jour logicielle" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Programvareoppdatering" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Programvaruuppdatering" + } + } + } + }, + "A new version is available — click to open the releases page" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "En ny version er tilgængelig — klik for at åbne udgivelsessiden" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eine neue Version ist verfügbar — klicke, um die Release-Seite zu öffnen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Une nouvelle version est disponible — clique pour ouvrir la page des versions" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "En ny versjon er tilgjengelig — klikk for å åpne utgivelsessiden" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "En ny version är tillgänglig — klicka för att öppna utgivningssidan" + } + } + } + }, + "Switch provider" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skift udbyder" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anbieter wechseln" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Changer de fournisseur" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bytt tilbyder" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Byt leverantör" + } + } + } + }, + "Select model" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vælg model" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modell auswählen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sélectionner le modèle" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Velg modell" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Välj modell" + } + } + } + }, + "Attach file" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vedhæft fil" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Datei anhängen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Joindre un fichier" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Legg til fil" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bifoga fil" + } + } + } + }, + "Stop generation" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stop generering" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Generierung stoppen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Arrêter la génération" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stopp generering" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stoppa generering" + } + } + } + }, + "Send message" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Send besked" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nachricht senden" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Envoyer le message" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Send melding" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skicka meddelande" + } + } + } + }, + "Star this message to always include it in context" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stjernemarkér denne besked for altid at inkludere den i konteksten" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Markiere diese Nachricht mit einem Stern, um sie immer in den Kontext einzubeziehen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Marque ce message d'une étoile pour toujours l'inclure dans le contexte" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stjernemerk denne meldingen for alltid å inkludere den i konteksten" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stjärnmärk detta meddelande för att alltid inkludera det i kontexten" + } + } + } + }, + "Advanced search — semantic search, bulk delete, export" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Avanceret søgning — semantisk søgning, massesletning, eksport" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erweiterte Suche — semantische Suche, Massenlöschung, Export" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Recherche avancée — recherche sémantique, suppression groupée, export" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Avansert søk — semantisk søk, massesletting, eksport" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Avancerad sökning — semantisk sökning, massradering, export" + } + } + } + }, + "Remove file" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fjern fil" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Datei entfernen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Supprimer le fichier" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fjern fil" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ta bort fil" + } + } + } + }, + "Delete skill" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slet færdighed" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skill löschen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Supprimer le skill" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slett ferdighet" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ta bort färdighet" + } + } + } + }, + "Use AI-powered semantic search instead of keyword matching" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Brug AI-drevet semantisk søgning i stedet for nøgleordssøgning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "KI-gestützte semantische Suche statt Schlüsselwortabgleich verwenden" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Utiliser la recherche sémantique par IA au lieu de la correspondance par mots-clés" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bruk KI-drevet semantisk søk i stedet for nøkkelordsøk" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Använd AI-driven semantisk sökning istället för nyckelordsmatchning" + } + } + } + }, + "Rename conversation" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Omdøb samtale" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gespräch umbenennen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Renommer la conversation" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gi samtalen nytt navn" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Byt namn på konversation" + } + } + } + }, + "Delete conversation" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slet samtale" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gespräch löschen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Supprimer la conversation" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slett samtale" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ta bort konversation" + } + } + } + }, + "Clear Email Log?" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ryd e-maillog?" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-Mail-Protokoll löschen?" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Effacer le journal e-mail ?" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tøm e-postlogg?" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rensa e-postlogg?" + } + } + } + }, + "Refresh agents" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Opdater agenter" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agenten aktualisieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Actualiser les agents" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Oppdater agenter" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Uppdatera agenter" + } + } + } + }, + "Stop agent" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stop agent" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agent stoppen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Arrêter l'agent" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stopp agent" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stoppa agent" + } + } + } + }, + "Run agent now" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kør agent nu" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agent jetzt ausführen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exécuter l'agent maintenant" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kjør agent nå" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kör agent nu" + } + } + } + }, + "Filter by category" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filtrer efter kategori" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nach Kategorie filtern" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filtrer par catégorie" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filtrer etter kategori" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filtrera efter kategori" + } + } + } + }, + "Show favorites only" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vis kun favoritter" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nur Favoriten anzeigen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Afficher seulement les favoris" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vis bare favoritter" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Visa endast favoriter" + } + } + } + }, + "Show model info" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vis modelinfo" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modellinfo anzeigen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Afficher les infos du modèle" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vis modellinfo" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Visa modellinfo" + } + } + } + }, + "Enter your Ollama server URL to enable the Ollama provider" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Indtast din Ollama-server-URL for at aktivere Ollama-udbyderen" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gib die URL deines Ollama-Servers ein, um den Ollama-Anbieter zu aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Saisis l'URL de ton serveur Ollama pour activer le fournisseur Ollama" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skriv inn Ollama-serverens URL for å aktivere Ollama-tilbyderen" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ange din Ollama-servers URL för att aktivera Ollama-leverantören" + } + } + } + }, + "Generate embeddings for all existing messages (one-time operation)" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Generer indlejringer for alle eksisterende beskeder (enkeltstående handling)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Embeddings für alle vorhandenen Nachrichten generieren (einmaliger Vorgang)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Générer des embeddings pour tous les messages existants (opération unique)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Generer innbygginger for alle eksisterende meldinger (engangsoperasjon)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Generera embeddings för alla befintliga meddelanden (engångsoperation)" + } + } + } + }, + "Duplicate Shortcut" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dupliker genvej" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verknüpfung duplizieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dupliquer le raccourci" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dupliser snarvei" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Duplicera genväg" + } + } + } + }, + "Export shortcut" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eksporter genvej" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verknüpfung exportieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exporter le raccourci" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eksporter snarvei" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exportera genväg" + } + } + } + }, + "Delete shortcut" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slet genvej" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verknüpfung löschen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Supprimer le raccourci" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slett snarvei" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ta bort genväg" + } + } + } + }, + "Statistics" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistik" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistiken" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistiques" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistikk" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistik" + } + } + } + }, + "Select model..." : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vælg model..." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modell auswählen..." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sélectionner le modèle..." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Velg modell..." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Välj modell..." + } + } + } + }, + "Hide" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skjul" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verbergen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Masquer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skjul" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dölj" + } + } + } + }, + "Show" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vis" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anzeigen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Afficher" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vis" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Visa" + } + } + } + }, + "Provider" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Udbyder" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anbieter" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fournisseur" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tilbyder" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Leverantör" + } + } + } + }, + "Default Provider" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standardudbyder" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standardanbieter" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fournisseur par défaut" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standardtilbyder" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standardleverantör" + } + } + } + }, + "API Keys" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-nøgler" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-Schlüssel" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Clés API" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-nøkler" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-nycklar" + } + } + } + }, + "Ollama URL" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ollama-URL" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ollama-URL" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL Ollama" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ollama-URL" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ollama-URL" + } + } + } + }, + "Features" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Funktioner" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Funktionen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fonctionnalités" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Funksjoner" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Funktioner" + } + } + } + }, + "Online Mode (Web Search)" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onlinetilstand (websøgning)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Online-Modus (Websuche)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mode en ligne (recherche web)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nettmodus (websøk)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onlineläge (webbsökning)" + } + } + } + }, + "Conversation Memory" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Samtalehukommelse" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gesprächsspeicher" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mémoire de conversation" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Samtaleminne" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Konversationsminne" + } + } + } + }, + "Reasoning (Thinking)" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ræsonnement (tænkning)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reasoning (Denkprozess)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Raisonnement (réflexion)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Resonnering (tenking)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Resonemang (tänkande)" + } + } + } + }, + "Reasoning Effort" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ræsonnementniveau" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reasoning-Aufwand" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Effort de raisonnement" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Resonneringsnivå" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Resonemangsnivå" + } + } + } + }, + "Hide Reasoning in Response" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skjul ræsonnement i svar" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reasoning in Antwort verbergen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Masquer le raisonnement dans la réponse" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skjul resonnering i svar" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dölj resonemang i svar" + } + } + } + }, + "Web Search" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Websøgning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Websuche" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Recherche web" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Websøk" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Webbsökning" + } + } + } + }, + "Search Provider" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søgeudbyder" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Suchanbieter" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fournisseur de recherche" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søketilbyder" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sökleverantör" + } + } + } + }, + "Google API Key" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Google API-nøgle" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Google-API-Schlüssel" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Clé API Google" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Google API-nøkkel" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Google API-nyckel" + } + } + } + }, + "Search Engine ID" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søgemaskine-ID" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Suchmaschinen-ID" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "ID du moteur de recherche" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søkemotor-ID" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sökmotor-ID" + } + } + } + }, + "Model Settings" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modelindstillinger" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modelleinstellungen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Réglages du modèle" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modellinnstillinger" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modellinställningar" + } + } + } + }, + "Default Model" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standardmodel" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standardmodell" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modèle par défaut" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standardmodell" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standardmodell" + } + } + } + }, + "Logging" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Logning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Protokollierung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Journalisation" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Logging" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Loggning" + } + } + } + }, + "Log Level" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Logniveau" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Protokollstufe" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Niveau de journalisation" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Loggnivå" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Loggnivå" + } + } + } + }, + "Status" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Status" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Status" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statut" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Status" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Status" + } + } + } + }, + "Enable MCP" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver MCP" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "MCP aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer MCP" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver MCP" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera MCP" + } + } + } + }, + "Allowed Folders" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tilladte mapper" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erlaubte Ordner" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dossiers autorisés" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tillatte mapper" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tillåtna mappar" + } + } + } + }, + "Permissions" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tilladelser" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Berechtigungen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Autorisations" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tillatelser" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Behörigheter" + } + } + } + }, + "Write & Edit Files" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skriv og rediger filer" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dateien schreiben und bearbeiten" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Écrire et modifier des fichiers" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skriv og rediger filer" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skriv och redigera filer" + } + } + } + }, + "Delete Files" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slet filer" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dateien löschen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Supprimer des fichiers" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slett filer" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ta bort filer" + } + } + } + }, + "Create Directories" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Opret mapper" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verzeichnisse erstellen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Créer des dossiers" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Opprett mapper" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skapa mappar" + } + } + } + }, + "Move & Copy Files" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Flyt og kopiér filer" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dateien verschieben und kopieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Déplacer et copier des fichiers" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Flytt og kopier filer" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Flytta och kopiera filer" + } + } + } + }, + "Filtering" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filtrering" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filterung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filtrage" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filtrering" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filtrering" + } + } + } + }, + "Respect .gitignore" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Respekter .gitignore" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : ".gitignore beachten" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Respecter .gitignore" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Respekter .gitignore" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Respektera .gitignore" + } + } + } + }, + "Enable Bash Execution" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver Bash-udførelse" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bash-Ausführung aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer l'exécution Bash" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver Bash-kjøring" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera Bash-körning" + } + } + } + }, + "Settings" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Indstillinger" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Einstellungen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Réglages" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Innstillinger" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inställningar" + } + } + } + }, + "Require Approval" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kræver godkendelse" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Genehmigung erforderlich" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Approbation requise" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Krever godkjenning" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kräver godkännande" + } + } + } + }, + "Working Directory" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Arbejdsmappe" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Arbeitsverzeichnis" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Répertoire de travail" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Arbeidsmappe" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Arbetskatalog" + } + } + } + }, + "Timeout (seconds)" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Timeout (sekunder)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Timeout (Sekunden)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Délai (secondes)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tidsavbrudd (sekunder)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tidsgräns (sekunder)" + } + } + } + }, + "Text Sizes" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tekststørrelser" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Textgrößen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tailles de texte" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tekststørrelser" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Textstorlekar" + } + } + } + }, + "GUI Text" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "GUI-tekst" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "GUI-Text" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Texte de l'interface" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "GUI-tekst" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "GUI-text" + } + } + } + }, + "Dialog Text" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dialogtekst" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dialogtext" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Texte des boîtes de dialogue" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dialogtekst" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dialogtext" + } + } + } + }, + "Input Text" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inputtekst" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eingabetext" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Texte de saisie" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inndatatekst" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inmatningstext" + } + } + } + }, + "Toolbar" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Værktøjslinje" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Symbolleiste" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Barre d'outils" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verktøylinje" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verktygsfält" + } + } + } + }, + "Icon Size" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ikonstørrelse" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Symbolgröße" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Taille des icônes" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ikonstørrelse" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ikonstorlek" + } + } + } + }, + "Show Icon Labels" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vis ikonetiketter" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Symbolbeschriftungen anzeigen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Afficher les libellés des icônes" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vis ikonetiketter" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Visa ikonetiketter" + } + } + } + }, + "Response Generation" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Svargenerering" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Antwortgenerierung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Génération de réponses" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Svargenerering" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Svarsgenerering" + } + } + } + }, + "Enable Streaming" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver streaming" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Streaming aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer le streaming" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver strømming" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera streaming" + } + } + } + }, + "Model Parameters" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modelparametre" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modellparameter" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Paramètres du modèle" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modellparametere" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modellparametrar" + } + } + } + }, + "Max Tokens" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maks tokens" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maximale Tokens" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokens max" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maks tokens" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Max tokens" + } + } + } + }, + "Temperature" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Temperatur" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Temperatur" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Température" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Temperatur" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Temperatur" + } + } + } + }, + "System Prompts" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Systemprompter" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "System-Prompts" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prompts système" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Systemprompter" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Systemprompter" + } + } + } + }, + "Use Only Your Prompt" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Brug kun din prompt" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nur deinen Prompt verwenden" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Utiliser uniquement ton prompt" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bruk bare din prompt" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Använd endast din prompt" + } + } + } + }, + "Memory & Context" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hukommelse og kontekst" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Speicher und Kontext" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mémoire et contexte" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Minne og kontekst" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Minne och kontext" + } + } + } + }, + "Smart Context Selection" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Smart kontekstvalg" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Intelligente Kontextauswahl" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sélection intelligente du contexte" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Smart kontekstvalg" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Smart kontextval" + } + } + } + }, + "Max Context Tokens" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maks konteksttokens" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maximale Kontext-Tokens" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokens de contexte max" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maks kontekst-tokens" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Max kontext-tokens" + } + } + } + }, + "Semantic Search" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Semantisk søgning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Semantische Suche" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Recherche sémantique" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Semantisk søk" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Semantisk sökning" + } + } + } + }, + "Enable Embeddings" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver indlejringer" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Embeddings aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer les embeddings" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver innbygginger" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera embeddings" + } + } + } + }, + "Model" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Model" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modell" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modèle" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modell" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modell" + } + } + } + }, + "Progressive Summarization" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Progressiv opsummering" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Progressive Zusammenfassung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Résumé progressif" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Progressiv sammendrag" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Progressiv sammanfattning" + } + } + } + }, + "Enable Summarization" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver opsummering" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zusammenfassung aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer le résumé" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver sammendrag" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera sammanfattning" + } + } + } + }, + "Message Threshold" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Beskedtærskel" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nachrichtenschwelle" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Seuil de messages" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Meldingsterskel" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Meddelandetröskel" + } + } + } + }, + "Git Sync" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Git-synkronisering" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Git-Synchronisierung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Synchronisation Git" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Git-synkronisering" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Git-synkronisering" + } + } + } + }, + "Enable Git Sync" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver Git-synkronisering" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Git-Synchronisierung aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer la synchronisation Git" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver Git-synkronisering" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera Git-synkronisering" + } + } + } + }, + "Connection" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Forbindelse" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verbindung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Connexion" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tilkobling" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anslutning" + } + } + } + }, + "URL" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL" + } + } + } + }, + "Local Path" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lokal sti" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lokaler Pfad" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Chemin local" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lokal bane" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lokal sökväg" + } + } + } + }, + "Authentication" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Godkendelse" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Authentifizierung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Authentification" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Autentisering" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Autentisering" + } + } + } + }, + "Method" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Metode" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Methode" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Méthode" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Metode" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Metod" + } + } + } + }, + "Username" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Brugernavn" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Benutzername" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nom d'utilisateur" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Brukernavn" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Användarnamn" + } + } + } + }, + "Password" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Adgangskode" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Passwort" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mot de passe" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Passord" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lösenord" + } + } + } + }, + "Token" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Token" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Token" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Token" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Token" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Token" + } + } + } + }, + "Sync Options" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Synkroniseringsindstillinger" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Synchronisierungsoptionen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Options de synchronisation" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Synkroniseringsalternativer" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Synkroniseringsalternativ" + } + } + } + }, + "Auto-export on save" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auto-eksporter ved gem" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Automatisch exportieren beim Speichern" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exporter automatiquement à l'enregistrement" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auto-eksporter ved lagring" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auto-exportera vid sparande" + } + } + } + }, + "Auto-pull on launch" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auto-hent ved start" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Automatisch abrufen beim Start" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Récupérer automatiquement au démarrage" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auto-hent ved oppstart" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auto-hämta vid start" + } + } + } + }, + "Auto-Save" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auto-gem" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Automatisches Speichern" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Enregistrement automatique" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auto-lagring" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auto-spara" + } + } + } + }, + "Enable Auto-Save" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver auto-gem" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Automatisches Speichern aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer l'enregistrement automatique" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver auto-lagring" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera auto-spara" + } + } + } + }, + "Min Messages" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Min. beskeder" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Min. Nachrichten" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Messages min." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Min. meldinger" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Min. meddelanden" + } + } + } + }, + "On model switch" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ved modelskift" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Beim Modellwechsel" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Au changement de modèle" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ved modellbytte" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vid modellbyte" + } + } + } + }, + "On app quit" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ved app-afslutning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Beim Beenden der App" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "À la fermeture de l'app" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ved avslutning av app" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vid app-avslut" + } + } + } + }, + "After idle timeout" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Efter inaktivitetstid" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nach Inaktivitäts-Timeout" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Après délai d'inactivité" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Etter inaktivitetstid" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Efter inaktivitetstid" + } + } + } + }, + "Idle Timeout" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inaktivitetstid" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inaktivitäts-Timeout" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Délai d'inactivité" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inaktivitetstid" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inaktivitetstid" + } + } + } + }, + "Manual Sync" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Manuel synkronisering" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Manuelle Synchronisierung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Synchronisation manuelle" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Manuell synkronisering" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Manuell synkronisering" + } + } + } + }, + "AI Email Handler" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "AI-e-mailbehandler" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "KI-E-Mail-Handler" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gestionnaire d'e-mails IA" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "KI-e-postbehandler" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "AI-e-posthanterare" + } + } + } + }, + "Enable Email Handler" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver e-mailbehandler" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-Mail-Handler aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer le gestionnaire d'e-mails" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver e-postbehandler" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera e-posthanterare" + } + } + } + }, + "AI Configuration" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "AI-konfiguration" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "KI-Konfiguration" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Configuration de l'IA" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "KI-konfigurasjon" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "AI-konfiguration" + } + } + } + }, + "AI Provider" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "AI-udbyder" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "KI-Anbieter" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fournisseur IA" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "KI-tilbyder" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "AI-leverantör" + } + } + } + }, + "AI Model" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "AI-model" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "KI-Modell" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modèle IA" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "KI-modell" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "AI-modell" + } + } + } + }, + "Email Server" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-mailserver" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-Mail-Server" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Serveur e-mail" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-postserver" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-postserver" + } + } + } + }, + "IMAP Host" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "IMAP-vært" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "IMAP-Host" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hôte IMAP" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "IMAP-vert" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "IMAP-värd" + } + } + } + }, + "SMTP Host" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "SMTP-vært" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "SMTP-Host" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hôte SMTP" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "SMTP-vert" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "SMTP-värd" + } + } + } + }, + "IMAP Port" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "IMAP-port" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "IMAP-Port" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Port IMAP" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "IMAP-port" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "IMAP-port" + } + } + } + }, + "SMTP Port" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "SMTP-port" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "SMTP-Port" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Port SMTP" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "SMTP-port" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "SMTP-port" + } + } + } + }, + "Email Trigger" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-mailudløser" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-Mail-Trigger" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Déclencheur e-mail" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-postutløser" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-postutlösare" + } + } + } + }, + "Subject Identifier" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Emneidentifikator" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Betreff-Kennung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Identifiant d'objet" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Emneidentifikator" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ämnesidentifierare" + } + } + } + }, + "Rate Limiting" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hastighedsbegrænsning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ratenbegrenzung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Limitation de débit" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Frekvensbegrensning" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hastighetsbegränsning" + } + } + } + }, + "Enable Rate Limit" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver hastighedsbegrænsning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ratenbegrenzung aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer la limitation de débit" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver frekvensbegrensning" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera hastighetsbegränsning" + } + } + } + }, + "Max Emails Per Hour" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maks e-mails pr. time" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Max. E-Mails pro Stunde" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-mails max par heure" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maks e-poster per time" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Max e-post per timme" + } + } + } + }, + "Response Settings" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Svarindstillinger" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Antworteinstellungen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Réglages de réponse" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Svarinnstillinger" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Svarsinställningar" + } + } + } + }, + "Max Response Tokens" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maks svartokens" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maximale Antwort-Tokens" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokens de réponse max" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maks svar-tokens" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Max svars-tokens" + } + } + } + }, + "Enable Online Mode" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver onlinetilstand" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Online-Modus aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer le mode en ligne" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver nettmodus" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera onlineläge" + } + } + } + }, + "System Prompt (Optional)" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Systemprompt (valgfri)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "System-Prompt (optional)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prompt système (facultatif)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Systemprompt (valgfri)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Systemprompt (valfri)" + } + } + } + }, + "Activity" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivitet" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivität" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activité" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivitet" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivitet" + } + } + } + }, + "Email Log" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-maillog" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-Mail-Protokoll" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Journal e-mail" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-postlogg" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-postlogg" + } + } + } + }, + "Enable Paperless" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver Paperless" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Paperless aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer Paperless" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver Paperless" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera Paperless" + } + } + } + }, + "Base URL" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Base-URL" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Basis-URL" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL de base" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Base-URL" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bas-URL" + } + } + } + }, + "API Token" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-token" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-Token" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Token API" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-token" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-token" + } + } + } + }, + "Enable Anytype" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver Anytype" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anytype aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer Anytype" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver Anytype" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera Anytype" + } + } + } + }, + "API URL" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-URL" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-URL" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL API" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-URL" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-URL" + } + } + } + }, + "API Key" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-nøgle" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-Schlüssel" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Clé API" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-nøkkel" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-nyckel" + } + } + } + }, + "Enable Jarvis" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver Jarvis" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jarvis aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer Jarvis" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver Jarvis" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera Jarvis" + } + } + } + }, + "Server URL" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Server-URL" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Server-URL" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL du serveur" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Server-URL" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Server-URL" + } + } + } + }, + "iCloud Drive Backup" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "iCloud Drive-sikkerhedskopi" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "iCloud-Drive-Sicherung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sauvegarde iCloud Drive" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "iCloud Drive-sikkerhetskopi" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "iCloud Drive-säkerhetskopia" + } + } + } + }, + "Last Backup" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Seneste sikkerhedskopi" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Letzte Sicherung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dernière sauvegarde" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Siste sikkerhetskopi" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Senaste säkerhetskopia" + } + } + } + }, + "Actions" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Handlinger" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktionen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Actions" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Handlinger" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Åtgärder" + } + } + } + }, + "Overview" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Overblik" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Übersicht" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aperçu" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Oversikt" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Översikt" + } + } + } + }, + "ID" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "ID" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "ID" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "ID" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "ID" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "ID" + } + } + } + }, + "Pricing" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Priser" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Preise" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tarification" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Priser" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Priser" + } + } + } + }, + "1K tokens" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "1K tokens" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "1K Tokens" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "1K tokens" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "1K tokens" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "1K tokens" + } + } + } + }, + "10K tokens" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "10K tokens" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "10K Tokens" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "10K tokens" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "10K tokens" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "10K tokens" + } + } + } + }, + "100K tokens" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "100K tokens" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "100K Tokens" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "100K tokens" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "100K tokens" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "100K tokens" + } + } + } + }, + "Context Window" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kontekstvindue" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kontextfenster" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fenêtre de contexte" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kontekstvindu" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kontextfönster" + } + } + } + }, + "Categories" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kategorier" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kategorien" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Catégories" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kategorier" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kategorier" + } + } + } + }, + "Architecture" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Arkitektur" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Architektur" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Architecture" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Arkitektur" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Arkitektur" + } + } + } + }, + "Modality" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modalitet" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modalität" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modalité" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modalitet" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modalitet" + } + } + } + }, + "Tokenizer" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokenizer" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokenizer" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokenizer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokenizer" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokenizer" + } + } + } + }, + "Instruct Type" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Instruktionstype" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anweisungstyp" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Type d'instruction" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Instruksjonstype" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Instruktionstyp" + } + } + } + }, + "Vision" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vision" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vision" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vision" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vision" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vision" + } + } + } + }, + "Tools" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Værktøjer" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Werkzeuge" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Outils" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verktøy" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verktyg" + } + } + } + }, + "Online" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Online" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Online" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "En ligne" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Online" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Online" + } + } + } + }, + "Image Gen" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Billedgenerering" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bildgenerierung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Génération d'images" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bildegenerering" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bildgenerering" + } + } + } + }, + "Thinking" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tænkning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Denken" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Réflexion" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tenking" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tänkande" + } + } + } + }, + "Schedule" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tidsplan" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zeitplan" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Planification" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tidsplan" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Schema" + } + } + } + }, + "Max Tool Calls" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maks værktøjskald" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Max. Tool-Aufrufe" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Appels d'outils max" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maks verktøykall" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Max verktygsanrop" + } + } + } + }, + "Enabled" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiveret" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiviert" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activé" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivert" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiverad" + } + } + } + }, + "Online Mode: On" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onlinetilstand: Til" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Online-Modus: An" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mode en ligne : activé" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nettmodus: På" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onlineläge: På" + } + } + } + }, + "Online Mode: Off" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onlinetilstand: Fra" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Online-Modus: Aus" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mode en ligne : désactivé" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nettmodus: Av" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onlineläge: Av" + } + } + } } }, "version" : "1.1" -- 2.52.0 From 66c9054bd510e1c42bdb876b68b809dbcb123c78 Mon Sep 17 00:00:00 2001 From: Rune Olsen Date: Mon, 22 Jun 2026 11:14:34 +0200 Subject: [PATCH 02/10] Update README with i18n disclosure and newly added features Document Jarvis integration, Combine Conversations, model category filter, sidebar navigation, prompt caching, and the 2nd Brain trust toggle. Clarify that localization is AI/machine-translated rather than reviewed by native speakers. Normalize all em-dashes to plain hyphens. --- README.md | 54 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index cc9ca76..e21cab8 100644 --- a/README.md +++ b/README.md @@ -8,15 +8,16 @@ A powerful native macOS AI chat application with support for multiple providers, ### 🤖 Multi-Provider Support - **OpenAI** - GPT models with native API support -- **Anthropic** - All Claude models +- **Anthropic** - All Claude models; prompt caching support (direct API and via OpenRouter) reduces cost on repeated system prompts/context - **OpenRouter** - Access to 300+ AI models from multiple providers - **Ollama** - Local model inference for privacy ### 💬 Core Chat Capabilities - **Streaming Responses** - Real-time token streaming for faster interactions - **Conversation Management** - Save, load, export, and search conversations +- **Combine Conversations** - Merge 2+ saved conversations, either by chronological concatenation or AI-assisted synthesis - **File Attachments** - Support for text files, images, and PDFs -- **Image Generation** - Create images with supported models (DALL-E, Flux, etc.) — renders inline in chat +- **Image Generation** - Create images with supported models (DALL-E, Flux, etc.) - renders inline in chat - **Reasoning / Thinking Tokens** - Stream live reasoning from thinking-capable models (DeepSeek R1, Claude 3.7+, o1/o3, Qwen); configurable effort level (High/Medium/Low/Minimal); collapsible block auto-expands while thinking and collapses when the answer arrives - **Online Mode** - DuckDuckGo and Google web search integration - **Session Statistics** - Track token usage, costs, and response times @@ -51,17 +52,25 @@ Seamless conversation backup and sync across devices: ### ⚡ Shortcuts & Agent Skills - **Shortcuts** - Personal slash commands that expand to prompt templates; optional `{{input}}` placeholder for inline input -- **Agent Skills (SKILL.md)** - Markdown instruction files injected into the system prompt; compatible with skill0.io, skillsmp.com, and other SKILL.md marketplaces; import as `.md` or `.zip` bundle with attached data files +- **Agent Skills (SKILL.md)** - Markdown instruction files injected into the system prompt; compatible with skill0.io, skillsmp.com, and other SKILL.md marketplaces; import as `.md` or `.zip` bundle with attached data files; a skill named exactly "2nd Brain" can be marked always-trusted, skipping the bash approval prompt for its helper-script calls ### 📚 Anytype Integration Connect oAI to your local [Anytype](https://anytype.io) knowledge base: -- **Search** — find objects by keyword across all spaces or within a specific one -- **Read** — open any object and read its full markdown content -- **Append** — add content to the end of an existing object without touching existing text or internal links (preferred over full update) -- **Create** — make new notes, tasks, or pages -- **Checkbox tools** — surgically toggle to-do checkboxes or set task done/undone via native relation +- **Search** - find objects by keyword across all spaces or within a specific one +- **Read** - open any object and read its full markdown content +- **Append** - add content to the end of an existing object without touching existing text or internal links (preferred over full update) +- **Create** - make new notes, tasks, or pages +- **Checkbox tools** - surgically toggle to-do checkboxes or set task done/undone via native relation - All data stays on your machine (local API, no cloud) +### 🛰️ Jarvis Integration +Connect oAI to a self-hosted [Jarvis](https://jarvis.pm) agent-automation server: +- **Agent Management** - List, create, edit, enable/disable, run, and stop agents +- **Run History** - Expandable per-run output with status and timing +- **Usage & Credits** - Per-agent usage stats and credits balance +- **Queue Control** - Pause/resume all agents +- `/jarvis` slash command opens the Jarvis panel directly + ### 🖥️ Power-User Features - **Bash Execution** - AI can run shell commands via `/bin/zsh` (opt-in, with per-command approval prompt) - **iCloud Backup** - One-click settings backup to iCloud Drive; restore on any Mac; API keys excluded for security @@ -85,9 +94,10 @@ Automated email responses powered by AI: - Footer stats display (messages, tokens, cost, sync status) - Header status indicators (MCP, Online mode, Git sync) - Responsive message layout with copy buttons -- **Model Selector (⌘M)** - Filter by capability (Vision / Tools / Online / Image Gen / Thinking 🧠), sort by price or context window, search by name or description, per-row ⓘ info button; ★ favourite any model — favourites float to the top and can be filtered in one click +- **Model Selector (⌘M)** - Filter by capability (Vision / Tools / Online / Image Gen / Thinking 🧠) or by category (Programming, Math, Medical, Translation, Roleplay, Creative, Science, Finance, Legal), sort by price or context window, search by name or description, per-row ⓘ info button; ★ favourite any model - favourites float to the top and can be filtered in one click - **Default Model** - Set a fixed startup model in Settings → General; switching models during a session does not overwrite it -- **Localization** - UI ~~fully translated~~ being translated into Norwegian Bokmål, Swedish, Danish, and German; follows macOS language preference automatically +- **Sidebar Navigation** - Collapsible sidebar for switching between conversations +- **Localization** - Fully localized into Norwegian Bokmål, Swedish, Danish, German, and French; follows macOS language preference automatically. Translations are AI-generated (machine translation), not reviewed by native speakers - if you spot an awkward or incorrect phrase, please [open an issue](https://gitlab.pm/rune/oai-swift/issues/new) ![Advanced Features](Screenshots/4.png) @@ -97,8 +107,8 @@ Automated email responses powered by AI: Download the latest release from the [Releases page](https://gitlab.pm/rune/oai-swift/releases). Two builds are available: -- **oAI-x.x.x-AppleSilicon.dmg** — for Macs with an Apple Silicon chip (M1 and later) -- **oAI-x.x.x-Universal.dmg** — runs natively on both Apple Silicon and Intel Macs +- **oAI-x.x.x-AppleSilicon.dmg** - for Macs with an Apple Silicon chip (M1 and later) +- **oAI-x.x.x-Universal.dmg** - runs natively on both Apple Silicon and Intel Macs ### Installing from DMG @@ -107,19 +117,19 @@ Download the latest release from the [Releases page](https://gitlab.pm/rune/oai- 3. Eject the DMG 4. Launch oAI from Applications or Spotlight -### First Launch — Gatekeeper Warning +### First Launch - Gatekeeper Warning -oAI is **signed by the developer** but has **not yet been notarized by Apple**. Notarization is Apple's automated malware scan — the app itself is safe, but macOS Gatekeeper may block it on first launch with a message saying the app "cannot be opened because the developer cannot be verified." +oAI is **signed by the developer** but has **not yet been notarized by Apple**. Notarization is Apple's automated malware scan - the app itself is safe, but macOS Gatekeeper may block it on first launch with a message saying the app "cannot be opened because the developer cannot be verified." To open the app, you have two options: -**Option A — Right-click to open (quickest):** +**Option A - Right-click to open (quickest):** 1. Right-click (or Control-click) `oAI.app` in Applications 2. Select **Open** from the context menu 3. Click **Open** in the dialog that appears 4. After doing this once, the app opens normally from then on -**Option B — Remove the quarantine flag via Terminal:** +**Option B - Remove the quarantine flag via Terminal:** ```bash xattr -dr com.apple.quarantine /Applications/oAI.app @@ -139,7 +149,7 @@ Add your API keys in Settings (⌘,) → General tab: - **Anthropic** - Get from [Anthropic Console](https://console.anthropic.com/) or use OAuth - **OpenRouter** - Get from [OpenRouter Keys](https://openrouter.ai/keys) - **Ollama** - Base URL (default: http://localhost:11434) -- **Google** - API key used for Google Custom Search (web search) and Google embeddings (semantic search) — not a chat provider +- **Google** - API key used for Google Custom Search (web search) and Google embeddings (semantic search) - not a chat provider ### Essential Settings @@ -313,12 +323,16 @@ AI-powered email auto-responder: - [x] Vector index for faster semantic search (sqlite-vss) - [x] Reasoning / thinking tokens (streamed live, collapsible) -- [x] Localization (Norwegian Bokmål, Swedish, Danish, German) +- [x] Localization (Norwegian Bokmål, Swedish, Danish, German, French) - [x] iCloud Backup (settings export/restore) - [x] Bash execution with per-command approval - [x] Anytype integration (read, append, create, checkbox tools) - [x] Model favourites (starred models, filter, float to top) -- [ ] SOUL.md / USER.md — living identity documents injected into system prompt +- [x] Jarvis integration (agent management, run history, usage/credits) +- [x] Model category filter (Programming, Math, Medical, etc.) +- [x] Combine saved conversations (concatenation or AI-assisted synthesis) +- [x] Sidebar navigation redesign +- [ ] SOUL.md / USER.md - living identity documents injected into system prompt - [ ] Parallel research agents (read-only, concurrent) - [ ] Local embeddings (sentence-transformers, $0 cost) - [ ] Multi-modal conversation export (PDF, HTML) @@ -346,7 +360,7 @@ See [LICENSE](LICENSE) for the full license text, or visit [gnu.org/licenses/agp ## Disclaimer -oAI takes real actions on your behalf — it can send emails, write files, make calendar changes, and post Telegram messages. Review your whitelist and permission settings carefully before use. Content you send is processed by your configured AI provider (Anthropic, OpenRouter, or OpenAI). oAI-Web is provided "as is" without warranty of any kind — the author accepts no responsibility for actions taken by the agent or any consequences thereof. See LICENSE for full terms. +oAI takes real actions on your behalf - it can send emails, write files, make calendar changes, and post Telegram messages. Review your whitelist and permission settings carefully before use. Content you send is processed by your configured AI provider (Anthropic, OpenRouter, or OpenAI). oAI-Web is provided "as is" without warranty of any kind - the author accepts no responsibility for actions taken by the agent or any consequences thereof. See LICENSE for full terms. --- -- 2.52.0 From 454cef419316ad674695c33dfcab23b891c520b6 Mon Sep 17 00:00:00 2001 From: Rune Olsen Date: Mon, 29 Jun 2026 14:04:27 +0200 Subject: [PATCH 03/10] Update AppLogo imageset Co-Authored-By: Claude Sonnet 4.6 --- oAI/Assets.xcassets/AppLogo.imageset/Contents.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/oAI/Assets.xcassets/AppLogo.imageset/Contents.json b/oAI/Assets.xcassets/AppLogo.imageset/Contents.json index b12e46b..a75bb54 100644 --- a/oAI/Assets.xcassets/AppLogo.imageset/Contents.json +++ b/oAI/Assets.xcassets/AppLogo.imageset/Contents.json @@ -4,6 +4,14 @@ "filename" : "AppLogo.png", "idiom" : "universal", "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" } ], "info" : { -- 2.52.0 From 40c5f25517da5588dec004f5170074e2a818acef Mon Sep 17 00:00:00 2001 From: Rune Olsen Date: Mon, 29 Jun 2026 14:04:47 +0200 Subject: [PATCH 04/10] Add personal data tools, 2nd Brain trust toggle, and research agents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Personal Data Tools: native Calendar, Reminders, Contacts (hidden pending Apple TCC fix in beta), and Location & Maps access via EventKit, Contacts framework, and MapKit. Write actions (create event/reminder, complete reminder) gate through an approval sheet. Four hardened-runtime entitlements added to oAI.entitlements; Info.plist usage strings added for all services. Personal Data section shows a β badge while Contacts is hidden. 2nd Brain always-trust: inline toggle on the Agent Skills row for the skill named "2nd Brain" skips the bash approval dialog when the command contains .brain_helper.py, gated by three runtime checks in MCPService. Research agents: spawn_research_agents tool runs up to 5 concurrent read-only sub-agents (read_file, list_directory, search_files, web_search — no write, no bash, no nesting). Bounded by maxConcurrentAgents setting (default 3) and a hard ceiling of 8 tasks. Added items field to Tool.Function.Parameters.Property for JSON Schema array support; wired into AnthropicProvider.convertParametersToDict. Co-Authored-By: Claude Sonnet 4.6 --- oAI.xcodeproj/project.pbxproj | 18 +- oAI/Localizable.xcstrings | 17485 ++++++++-------- oAI/Models/AgentSkill.swift | 6 + oAI/Providers/AIProvider.swift | 13 + oAI/Providers/AnthropicProvider.swift | 3 + oAI/Services/ContactsService.swift | 250 + oAI/Services/EventKitService.swift | 593 + oAI/Services/LocationMapsService.swift | 343 + oAI/Services/MCPService.swift | 275 +- oAI/Services/SettingsService.swift | 85 + oAI/ViewModels/ChatViewModel.swift | 18 +- oAI/Views/Main/ChatView.swift | 10 + oAI/Views/Screens/AgentSkillsView.swift | 18 +- .../Screens/PersonalDataApprovalSheet.swift | 97 + oAI/Views/Screens/SettingsView.swift | 214 + oAI/oAI-InfoPlist.xcstrings | 48 + oAI/oAI.entitlements | 8 + 17 files changed, 11041 insertions(+), 8443 deletions(-) create mode 100644 oAI/Services/ContactsService.swift create mode 100644 oAI/Services/EventKitService.swift create mode 100644 oAI/Services/LocationMapsService.swift create mode 100644 oAI/Views/Screens/PersonalDataApprovalSheet.swift diff --git a/oAI.xcodeproj/project.pbxproj b/oAI.xcodeproj/project.pbxproj index be3380f..3e2321f 100644 --- a/oAI.xcodeproj/project.pbxproj +++ b/oAI.xcodeproj/project.pbxproj @@ -270,6 +270,11 @@ ENABLE_PREVIEWS = YES; ENABLE_USER_SELECTED_FILES = readonly; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; + INFOPLIST_KEY_NSCalendarsFullAccessUsageDescription = "oAI can read and create calendar events when you ask it to, if you enable Calendar access in Settings."; + INFOPLIST_KEY_NSContactsUsageDescription = "oAI can search your contacts when you ask it to, if you enable Contacts access in Settings."; + INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "oAI can use your current location to answer questions, if you enable Location & Maps access in Settings."; + INFOPLIST_KEY_NSRemindersFullAccessUsageDescription = "oAI can read and create reminders when you ask it to, if you enable Reminders access in Settings."; "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; @@ -283,8 +288,8 @@ IPHONEOS_DEPLOYMENT_TARGET = 27.0; LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 27.0; - MARKETING_VERSION = 2.4.0; + MACOSX_DEPLOYMENT_TARGET = 26.2; + MARKETING_VERSION = 2.4.1; PRODUCT_BUNDLE_IDENTIFIER = com.oai.oAI; PRODUCT_NAME = "$(TARGET_NAME)"; REGISTER_APP_GROUPS = YES; @@ -314,6 +319,11 @@ ENABLE_PREVIEWS = YES; ENABLE_USER_SELECTED_FILES = readonly; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; + INFOPLIST_KEY_NSCalendarsFullAccessUsageDescription = "oAI can read and create calendar events when you ask it to, if you enable Calendar access in Settings."; + INFOPLIST_KEY_NSContactsUsageDescription = "oAI can search your contacts when you ask it to, if you enable Contacts access in Settings."; + INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "oAI can use your current location to answer questions, if you enable Location & Maps access in Settings."; + INFOPLIST_KEY_NSRemindersFullAccessUsageDescription = "oAI can read and create reminders when you ask it to, if you enable Reminders access in Settings."; "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; @@ -327,8 +337,8 @@ IPHONEOS_DEPLOYMENT_TARGET = 27.0; LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 27.0; - MARKETING_VERSION = 2.4.0; + MACOSX_DEPLOYMENT_TARGET = 26.2; + MARKETING_VERSION = 2.4.1; PRODUCT_BUNDLE_IDENTIFIER = com.oai.oAI; PRODUCT_NAME = "$(TARGET_NAME)"; REGISTER_APP_GROUPS = YES; diff --git a/oAI/Localizable.xcstrings b/oAI/Localizable.xcstrings index 2577421..99e92c5 100644 --- a/oAI/Localizable.xcstrings +++ b/oAI/Localizable.xcstrings @@ -385,6 +385,40 @@ } } }, + "%@ tokens" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ tokens" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ tokens" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ tokens" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ tokens" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ tokens" + } + } + } + }, "%@s" : { "localizations" : { "da" : { @@ -593,6 +627,40 @@ } } }, + "^[%@ file](inflect: true)" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ fil](inflect: true)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ Datei](inflect: true)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ fichier](inflect: true)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ fil](inflect: true)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ fil](inflect: true)" + } + } + } + }, "^[%@ message](inflect: true)" : { "localizations" : { "da" : { @@ -627,6 +695,142 @@ } } }, + "^[%@ running](inflect: true)" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ kørende](inflect: true)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ laufend](inflect: true)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ en cours](inflect: true)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ kjørende](inflect: true)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ igång](inflect: true)" + } + } + } + }, + "^[%@ skill](inflect: true) active — appended to every system prompt" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ færdighed](inflect: true) aktiv — tilføjet til hver systemprompt" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ Skill](inflect: true) aktiv — an jeden System-Prompt angehängt" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ skill](inflect: true) actif — ajouté à chaque prompt système" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ ferdighet](inflect: true) aktiv — lagt til i hver systemprompt" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ färdighet](inflect: true) aktiv — lagd till i varje systemprompt" + } + } + } + }, + "^[%@ skill](inflect: true) exported to Downloads" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ færdighed](inflect: true) eksporteret til Downloads" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ Skill](inflect: true) nach Downloads exportiert" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ skill](inflect: true) exporté vers Téléchargements" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ ferdighet](inflect: true) eksportert til Nedlastinger" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ färdighet](inflect: true) exporterad till Nedladdningar" + } + } + } + }, + "^[%@ skill](inflect: true) imported" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ færdighed](inflect: true) importeret" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ Skill](inflect: true) importiert" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ skill](inflect: true) importé" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ ferdighet](inflect: true) importert" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%@ färdighet](inflect: true) importerad" + } + } + } + }, "^[%@ token](inflect: true)" : { "localizations" : { "da" : { @@ -1360,6 +1564,40 @@ } } }, + "1K tokens" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "1K tokens" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "1K Tokens" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "1K tokens" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "1K tokens" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "1K tokens" + } + } + } + }, "2. Create a new API key" : { "comment" : "A step in the process of getting an API key from Anytype.", "isCommentAutoGenerated" : true, @@ -1468,6 +1706,74 @@ } } }, + "10K tokens" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "10K tokens" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "10K Tokens" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "10K tokens" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "10K tokens" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "10K tokens" + } + } + } + }, + "100K tokens" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "100K tokens" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "100K Tokens" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "100K tokens" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "100K tokens" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "100K tokens" + } + } + } + }, "A model reads all the source messages and rewrites them into one coherent, de-duplicated conversation." : { "localizations" : { "da" : { @@ -1502,6 +1808,40 @@ } } }, + "A new version is available — click to open the releases page" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "En ny version er tilgængelig — klik for at åbne udgivelsessiden" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eine neue Version ist verfügbar — klicke, um die Release-Seite zu öffnen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Une nouvelle version est disponible — clique pour ouvrir la page des versions" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "En ny versjon er tilgjengelig — klikk for å åpne utgivelsessiden" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "En ny version är tillgänglig — klicka för att öppna utgivningssidan" + } + } + } + }, "A shortcut with command %@ already exists." : { "comment" : "A warning message that appears when a user tries to import a shortcut that already exists in their settings. The argument is the command of the conflicting shortcut.", "isCommentAutoGenerated" : true, @@ -1538,6 +1878,142 @@ } } }, + "About oAI" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Om oAI" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Über oAI" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "À propos d'oAI" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Om oAI" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Om oAI" + } + } + } + }, + "Access denied — enable in System Settings" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Adgang nægtet — aktiver i Systemindstillinger" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zugriff verweigert — in den Systemeinstellungen aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Accès refusé — active-le dans Réglages Système" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tilgang avslått — aktiver i Systeminnstillinger" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Åtkomst nekad — aktivera i Systeminställningar" + } + } + } + }, + "Access granted" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Adgang givet" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zugriff gewährt" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Accès accordé" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tilgang gitt" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Åtkomst beviljad" + } + } + } + }, + "Access not granted" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Adgang ikke givet" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zugriff nicht gewährt" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Accès non accordé" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tilgang ikke gitt" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Åtkomst inte beviljad" + } + } + } + }, "Access Token" : { "localizations" : { "da" : { @@ -1572,6 +2048,74 @@ } } }, + "ACTION" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "HANDLING" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "AKTION" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "ACTION" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "HANDLING" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "ÅTGÄRD" + } + } + } + }, + "Actions" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Handlinger" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktionen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Actions" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Handlinger" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Åtgärder" + } + } + } + }, "active" : { "comment" : "A label for an active skill.", "isCommentAutoGenerated" : true, @@ -1680,6 +2224,176 @@ } } }, + "Activity" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivitet" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivität" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activité" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivitet" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivitet" + } + } + } + }, + "Add File" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tilføj fil" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Datei hinzufügen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ajouter un fichier" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Legg til fil" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lägg till fil" + } + } + } + }, + "Add Folder…" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tilføj mappe…" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ordner hinzufügen…" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ajouter un dossier…" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Legg til mappe…" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lägg till mapp…" + } + } + } + }, + "Advanced search — semantic search, bulk delete, export" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Avanceret søgning — semantisk søgning, massesletning, eksport" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erweiterte Suche — semantische Suche, Massenlöschung, Export" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Recherche avancée — recherche sémantique, suppression groupée, export" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Avansert søk — semantisk søk, massesletting, eksport" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Avancerad sökning — semantisk sökning, massradering, export" + } + } + } + }, + "After idle timeout" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Efter inaktivitetstid" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nach Inaktivitäts-Timeout" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Après délai d'inactivité" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Etter inaktivitetstid" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Efter inaktivitetstid" + } + } + } + }, "Agent" : { "localizations" : { "da" : { @@ -1714,6 +2428,40 @@ } } }, + "Agent name" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agentnavn" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agentenname" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nom de l'agent" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agentnavn" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agentnamn" + } + } + } + }, "Agent Skills" : { "localizations" : { "da" : { @@ -1782,6 +2530,142 @@ } } }, + "AI Configuration" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "AI-konfiguration" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "KI-Konfiguration" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Configuration de l'IA" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "KI-konfigurasjon" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "AI-konfiguration" + } + } + } + }, + "AI Email Handler" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "AI-e-mailbehandler" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "KI-E-Mail-Handler" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gestionnaire d'e-mails IA" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "KI-e-postbehandler" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "AI-e-posthanterare" + } + } + } + }, + "AI Model" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "AI-model" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "KI-Modell" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modèle IA" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "KI-modell" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "AI-modell" + } + } + } + }, + "AI Provider" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "AI-udbyder" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "KI-Anbieter" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fournisseur IA" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "KI-tilbyder" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "AI-leverantör" + } + } + } + }, "AI-Assisted Merge" : { "localizations" : { "da" : { @@ -1816,6 +2700,74 @@ } } }, + "Allow for Session" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tillad for sessionen" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Für Sitzung erlauben" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Autoriser pour la session" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tillat for sesjonen" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tillåt för sessionen" + } + } + } + }, + "Allow Once" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tillad denne gang" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Einmal erlauben" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Autoriser une fois" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tillat denne gangen" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tillåt denna gång" + } + } + } + }, "Allow Shell Command?" : { "comment" : "A title for a modal that asks the user if they want to allow a shell command.", "isCommentAutoGenerated" : true, @@ -1886,6 +2838,74 @@ } } }, + "Allow This Action?" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tillad denne handling?" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Diese Aktion zulassen?" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Autoriser cette action ?" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tillat denne handlingen?" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tillåt denna åtgärd?" + } + } + } + }, + "Allowed Folders" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tilladte mapper" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erlaubte Ordner" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dossiers autorisés" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tillatte mapper" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tillåtna mappar" + } + } + } + }, "Anthropic Balance" : { "comment" : "A label displayed above the user's balance on the Anthropic platform.", "isCommentAutoGenerated" : true, @@ -1922,6 +2942,74 @@ } } }, + "API Key" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-nøgle" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-Schlüssel" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Clé API" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-nøkkel" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-nyckel" + } + } + } + }, + "API Keys" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-nøgler" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-Schlüssel" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Clés API" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-nøkler" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-nycklar" + } + } + } + }, "API keys and credentials are **not** included in the backup. You will need to re-enter them after restoring on a new machine." : { "comment" : "A warning message displayed in the settings tab of the app.", "isCommentAutoGenerated" : true, @@ -1958,6 +3046,176 @@ } } }, + "API Token" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-token" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-Token" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Token API" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-token" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-token" + } + } + } + }, + "API URL" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-URL" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-URL" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL API" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-URL" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "API-URL" + } + } + } + }, + "Architecture" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Arkitektur" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Architektur" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Architecture" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Arkitektur" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Arkitektur" + } + } + } + }, + "Attach file" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vedhæft fil" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Datei anhängen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Joindre un fichier" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Legg til fil" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bifoga fil" + } + } + } + }, + "Authentication" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Godkendelse" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Authentifizierung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Authentification" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Autentisering" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Autentisering" + } + } + } + }, "Auto-execute mode: commands run without approval. Use with caution." : { "localizations" : { "da" : { @@ -1992,6 +3250,108 @@ } } }, + "Auto-export on save" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auto-eksporter ved gem" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Automatisch exportieren beim Speichern" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exporter automatiquement à l'enregistrement" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auto-eksporter ved lagring" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auto-exportera vid sparande" + } + } + } + }, + "Auto-pull on launch" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auto-hent ved start" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Automatisch abrufen beim Start" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Récupérer automatiquement au démarrage" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auto-hent ved oppstart" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auto-hämta vid start" + } + } + } + }, + "Auto-Save" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auto-gem" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Automatisches Speichern" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Enregistrement automatique" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auto-lagring" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auto-spara" + } + } + } + }, "Auto-sync can cause conflicts if running on multiple machines simultaneously." : { "localizations" : { "da" : { @@ -2166,6 +3526,40 @@ } } }, + "Base URL" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Base-URL" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Basis-URL" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL de base" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Base-URL" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bas-URL" + } + } + } + }, "Bash Execution" : { "localizations" : { "da" : { @@ -2234,6 +3628,74 @@ } } }, + "Brief description shown in the command dropdown" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kort beskrivelse vist i kommando-rullemenuen" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kurze Beschreibung im Befehlsmenü" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Brève description affichée dans le menu de commandes" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kort beskrivelse vist i kommando-rullegardinmenyen" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kort beskrivning som visas i kommandomenyn" + } + } + } + }, + "Brief summary (optional — auto-extracted from content if left blank)" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kort resumé (valgfrit — udtrækkes automatisk fra indholdet, hvis det er tomt)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kurze Zusammenfassung (optional — wird automatisch aus dem Inhalt extrahiert, wenn leer)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Résumé bref (facultatif — extrait automatiquement du contenu si laissé vide)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kort sammendrag (valgfritt — hentes automatisk fra innholdet hvis tomt)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kort sammanfattning (valfritt — extraheras automatiskt från innehållet om tomt)" + } + } + } + }, "Built with SwiftUI" : { "comment" : "A label that says that the app is built with SwiftUI.", "isCommentAutoGenerated" : true, @@ -2270,6 +3732,74 @@ } } }, + "Calendar" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kalender" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kalender" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Calendrier" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kalender" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kalender" + } + } + } + }, + "Cancel" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Annuller" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Abbrechen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Annuler" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Avbryt" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Avbryt" + } + } + } + }, "Capabilities" : { "comment" : "A label displayed under the list of capabilities of a model.", "isCommentAutoGenerated" : true, @@ -2306,6 +3836,40 @@ } } }, + "Categories" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kategorier" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kategorien" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Catégories" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kategorier" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kategorier" + } + } + } + }, "Category" : { "localizations" : { "da" : { @@ -2480,6 +4044,74 @@ } } }, + "Choose…" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vælg…" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auswählen…" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Choisir…" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Velg…" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Välj…" + } + } + } + }, + "Clear" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ryd" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Leeren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Effacer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tøm" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rensa" + } + } + } + }, "Clear All" : { "comment" : "A button to clear all email activity logs.", "isCommentAutoGenerated" : true, @@ -2516,6 +4148,74 @@ } } }, + "Clear Chat" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ryd chat" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Chat leeren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Effacer la discussion" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tøm chat" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rensa chatt" + } + } + } + }, + "Clear Email Log?" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ryd e-maillog?" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-Mail-Protokoll löschen?" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Effacer le journal e-mail ?" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tøm e-postlogg?" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rensa e-postlogg?" + } + } + } + }, "Click 'Add Folder' below or drag folders here from Finder" : { "localizations" : { "da" : { @@ -2550,6 +4250,40 @@ } } }, + "Combine" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sammenlæg" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zusammenführen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fusionner" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slå sammen" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slå samman" + } + } + } + }, "Combine (%@)" : { "localizations" : { "da" : { @@ -2794,6 +4528,74 @@ } } }, + "Connection" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Forbindelse" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verbindung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Connexion" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tilkobling" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anslutning" + } + } + } + }, + "Contacts" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kontakter" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kontakte" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Contacts" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kontakter" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kontakter" + } + } + } + }, "Content (Markdown)" : { "comment" : "A", "isCommentAutoGenerated" : true, @@ -2830,6 +4632,40 @@ } } }, + "Context Window" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kontekstvindue" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kontextfenster" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fenêtre de contexte" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kontekstvindu" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kontextfönster" + } + } + } + }, "Controls which messages are written to ~/Library/Logs/oAI.log" : { "localizations" : { "da" : { @@ -2864,6 +4700,40 @@ } } }, + "Conversation Memory" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Samtalehukommelse" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gesprächsspeicher" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mémoire de conversation" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Samtaleminne" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Konversationsminne" + } + } + } + }, "Conversations" : { "localizations" : { "da" : { @@ -2934,6 +4804,40 @@ } } }, + "Copy Image" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kopiér billede" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bild kopieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Copier l'image" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kopier bilde" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kopiera bild" + } + } + } + }, "Cost" : { "localizations" : { "da" : { @@ -3004,6 +4908,43 @@ } } }, + "Cost warning: each sub-agent runs its own full chain of model calls. A single request that spawns several agents can cost several times a normal reply. The AI is instructed to only use this for genuinely parallel research, but model behavior can vary — leave this off unless you want that tradeoff." : { + + }, + "Costs" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Omkostninger" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kosten" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Coûts" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kostnader" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kostnader" + } + } + } + }, "Create a dedicated email account specifically for AI handling. Do NOT use your personal email address." : { "localizations" : { "da" : { @@ -3074,6 +5015,176 @@ } } }, + "Create Directories" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Opret mapper" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verzeichnisse erstellen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Créer des dossiers" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Opprett mapper" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skapa mappar" + } + } + } + }, + "Creating calendar events or reminders, and completing reminders, will ask for your approval first." : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Oprettelse af kalenderbegivenheder eller påmindelser samt afslutning af påmindelser vil først bede om din godkendelse." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Das Erstellen von Kalenderereignissen oder Erinnerungen sowie das Abschließen von Erinnerungen fragt zuerst nach deiner Genehmigung." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "La création d'événements de calendrier ou de rappels, ainsi que la finalisation de rappels, demandera d'abord ton approbation." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Å opprette kalenderhendelser eller påminnelser, og å fullføre påminnelser, vil først be om din godkjenning." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Att skapa kalenderhändelser eller påminnelser, samt att slutföra påminnelser, kommer först att be om ditt godkännande." + } + } + } + }, + "Credits" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kreditter" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Guthaben" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Crédits" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kreditter" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Krediter" + } + } + } + }, + "Cron expression (e.g. 0 * * * *)" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cron-udtryk (f.eks. 0 * * * *)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cron-Ausdruck (z. B. 0 * * * *)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Expression cron (ex. 0 * * * *)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cron-uttrykk (f.eks. 0 * * * *)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cron-uttryck (t.ex. 0 * * * *)" + } + } + } + }, + "Default Model" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standardmodel" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standardmodell" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modèle par défaut" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standardmodell" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standardmodell" + } + } + } + }, "Default Prompt" : { "localizations" : { "da" : { @@ -3108,6 +5219,74 @@ } } }, + "Default Provider" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standardudbyder" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standardanbieter" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fournisseur par défaut" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standardtilbyder" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standardleverantör" + } + } + } + }, + "Delete" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slet" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Löschen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Supprimer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slett" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ta bort" + } + } + } + }, "Delete (%@)" : { "localizations" : { "da" : { @@ -3142,6 +5321,210 @@ } } }, + "Delete conversation" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slet samtale" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gespräch löschen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Supprimer la conversation" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slett samtale" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ta bort konversation" + } + } + } + }, + "Delete Files" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slet filer" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dateien löschen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Supprimer des fichiers" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slett filer" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ta bort filer" + } + } + } + }, + "Delete original conversations after combining" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slet de oprindelige samtaler efter sammenlægning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ursprüngliche Gespräche nach dem Zusammenführen löschen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Supprimer les conversations d'origine après la fusion" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slett originalsamtalene etter sammenslåing" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ta bort originalkonversationerna efter sammanslagning" + } + } + } + }, + "Delete shortcut" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slet genvej" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verknüpfung löschen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Supprimer le raccourci" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slett snarvei" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ta bort genväg" + } + } + } + }, + "Delete skill" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slet færdighed" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skill löschen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Supprimer le skill" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slett ferdighet" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ta bort färdighet" + } + } + } + }, + "Deny" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Afvis" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verweigern" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Refuser" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Avslå" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Neka" + } + } + } + }, "Description" : { "comment" : "A label", "isCommentAutoGenerated" : true, @@ -3178,6 +5561,40 @@ } } }, + "Dialog Text" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dialogtekst" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dialogtext" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Texte des boîtes de dialogue" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dialogtekst" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dialogtext" + } + } + } + }, "Disabled" : { "localizations" : { "da" : { @@ -3212,6 +5629,176 @@ } } }, + "Dismiss" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Luk" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Schließen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fermer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lukk" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stäng" + } + } + } + }, + "Done" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Færdig" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fertig" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Terminé" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ferdig" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Klar" + } + } + } + }, + "Download v%@" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hent v%@" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "v%@ herunterladen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Télécharger v%@" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Last ned v%@" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ladda ner v%@" + } + } + } + }, + "Duplicate Shortcut" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dupliker genvej" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verknüpfung duplizieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dupliquer le raccourci" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dupliser snarvei" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Duplicera genväg" + } + } + } + }, + "e.g. Code Review, Test Writer, Security Auditor" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "f.eks. Kodegennemgang, Testskribent, Sikkerhedsrevisor" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "z. B. Code-Review, Test-Autor, Sicherheitsprüfer" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "ex. Revue de code, Rédacteur de tests, Auditeur sécurité" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "f.eks. Kodegjennomgang, Testskriving, Sikkerhetsrevisor" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "t.ex. Kodgranskning, Testskrivare, Säkerhetsgranskare" + } + } + } + }, "Each command will require your approval before running." : { "localizations" : { "da" : { @@ -3386,6 +5973,74 @@ } } }, + "Email Log" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-maillog" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-Mail-Protokoll" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Journal e-mail" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-postlogg" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-postlogg" + } + } + } + }, + "Email Server" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-mailserver" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-Mail-Server" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Serveur e-mail" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-postserver" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-postserver" + } + } + } + }, "Email tasks have READ-ONLY access to MCP folders. The AI cannot write, delete, or modify files when processing emails." : { "localizations" : { "da" : { @@ -3420,6 +6075,74 @@ } } }, + "Email Trigger" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-mailudløser" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-Mail-Trigger" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Déclencheur e-mail" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-postutløser" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-postutlösare" + } + } + } + }, + "Embed All Conversations" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Indlejr alle samtaler" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Alle Gespräche einbetten" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Intégrer toutes les conversations" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bygg inn alle samtaler" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bädda in alla konversationer" + } + } + } + }, "Enable AI-powered semantic search using %@ embeddings. Cost: ~$0.02–0.15/1M tokens." : { "localizations" : { "da" : { @@ -3454,6 +6177,142 @@ } } }, + "Enable Anytype" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver Anytype" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anytype aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer Anytype" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver Anytype" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera Anytype" + } + } + } + }, + "Enable Auto-Save" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver auto-gem" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Automatisches Speichern aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer l'enregistrement automatique" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver auto-lagring" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera auto-spara" + } + } + } + }, + "Enable Bash Execution" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver Bash-udførelse" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bash-Ausführung aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer l'exécution Bash" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver Bash-kjøring" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera Bash-körning" + } + } + } + }, + "Enable Email Handler" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver e-mailbehandler" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-Mail-Handler aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer le gestionnaire d'e-mails" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver e-postbehandler" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera e-posthanterare" + } + } + } + }, "Enable email handler in Settings to start monitoring emails" : { "comment" : "A message displayed when the email handler is disabled.", "isCommentAutoGenerated" : true, @@ -3490,6 +6349,380 @@ } } }, + "Enable Embeddings" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver indlejringer" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Embeddings aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer les embeddings" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver innbygginger" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera embeddings" + } + } + } + }, + "Enable Git Sync" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver Git-synkronisering" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Git-Synchronisierung aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer la synchronisation Git" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver Git-synkronisering" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera Git-synkronisering" + } + } + } + }, + "Enable Jarvis" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver Jarvis" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jarvis aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer Jarvis" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver Jarvis" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera Jarvis" + } + } + } + }, + "Enable MCP" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver MCP" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "MCP aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer MCP" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver MCP" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera MCP" + } + } + } + }, + "Enable Online Mode" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver onlinetilstand" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Online-Modus aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer le mode en ligne" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver nettmodus" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera onlineläge" + } + } + } + }, + "Enable Paperless" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver Paperless" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Paperless aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer Paperless" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver Paperless" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera Paperless" + } + } + } + }, + "Enable Rate Limit" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver hastighedsbegrænsning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ratenbegrenzung aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer la limitation de débit" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver frekvensbegrensning" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera hastighetsbegränsning" + } + } + } + }, + "Enable Streaming" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver streaming" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Streaming aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer le streaming" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver strømming" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera streaming" + } + } + } + }, + "Enable Summarization" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver opsummering" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zusammenfassung aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activer le résumé" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiver sammendrag" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivera sammanfattning" + } + } + } + }, + "Enabled" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiveret" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiviert" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activé" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktivert" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktiverad" + } + } + } + }, + "Enter your Ollama server URL to enable the Ollama provider" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Indtast din Ollama-server-URL for at aktivere Ollama-udbyderen" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gib die URL deines Ollama-Servers ein, um den Ollama-Anbieter zu aktivieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Saisis l'URL de ton serveur Ollama pour activer le fournisseur Ollama" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skriv inn Ollama-serverens URL for å aktivere Ollama-tilbyderen" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ange din Ollama-servers URL för att aktivera Ollama-leverantören" + } + } + } + }, "Error: %@" : { "comment" : "A label displaying an error message in the checkout view.", "isCommentAutoGenerated" : true, @@ -3596,6 +6829,210 @@ } } }, + "Executes immediately — no extra input needed" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Udføres umiddelbart — ingen ekstra input nødvendig" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wird sofort ausgeführt — keine zusätzliche Eingabe nötig" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "S'exécute immédiatement — aucune saisie supplémentaire nécessaire" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Utføres umiddelbart — ingen ekstra input nødvendig" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Körs omedelbart — ingen extra indata behövs" + } + } + } + }, + "Export" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eksporter" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exportieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exporter" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eksporter" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exportera" + } + } + } + }, + "Export All" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eksporter alle" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Alle exportieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tout exporter" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eksporter alle" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exportera alla" + } + } + } + }, + "Export as Markdown…" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eksporter som Markdown…" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Als Markdown exportieren…" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exporter en Markdown…" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eksporter som Markdown…" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exportera som Markdown…" + } + } + } + }, + "Export shortcut" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eksporter genvej" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verknüpfung exportieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exporter le raccourci" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eksporter snarvei" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exportera genväg" + } + } + } + }, + "Features" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Funktioner" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Funktionen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fonctionnalités" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Funksjoner" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Funktioner" + } + } + } + }, "File Access Permissions" : { "localizations" : { "da" : { @@ -3666,6 +7103,40 @@ } } }, + "Filter by category" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filtrer efter kategori" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nach Kategorie filtern" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filtrer par catégorie" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filtrer etter kategori" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filtrera efter kategori" + } + } + } + }, "Filter by Category" : { "localizations" : { "da" : { @@ -3700,6 +7171,40 @@ } } }, + "Filtering" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filtrering" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filterung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filtrage" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filtrering" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filtrering" + } + } + } + }, "Generate an API key in your Jarvis settings and paste it above." : { "localizations" : { "da" : { @@ -3734,6 +7239,74 @@ } } }, + "Generate embeddings for all existing messages (one-time operation)" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Generer indlejringer for alle eksisterende beskeder (enkeltstående handling)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Embeddings für alle vorhandenen Nachrichten generieren (einmaliger Vorgang)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Générer des embeddings pour tous les messages existants (opération unique)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Generer innbygginger for alle eksisterende meldinger (engangsoperasjon)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Generera embeddings för alla befintliga meddelanden (engångsoperation)" + } + } + } + }, + "Git Sync" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Git-synkronisering" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Git-Synchronisierung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Synchronisation Git" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Git-synkronisering" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Git-synkronisering" + } + } + } + }, "Google (Gemini embedding)" : { "localizations" : { "da" : { @@ -3768,6 +7341,108 @@ } } }, + "Google API Key" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Google API-nøgle" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Google-API-Schlüssel" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Clé API Google" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Google API-nøkkel" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Google API-nyckel" + } + } + } + }, + "Got It" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Forstået" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verstanden" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Compris" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skjønner" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Förstått" + } + } + } + }, + "GUI Text" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "GUI-tekst" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "GUI-Text" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Texte de l'interface" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "GUI-tekst" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "GUI-text" + } + } + } + }, "Help" : { "comment" : "A heading for the help screen", "isCommentAutoGenerated" : true, @@ -3804,6 +7479,74 @@ } } }, + "Hide" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skjul" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verbergen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Masquer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skjul" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dölj" + } + } + } + }, + "Hide Reasoning in Response" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skjul ræsonnement i svar" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reasoning in Antwort verbergen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Masquer le raisonnement dans la réponse" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skjul resonnering i svar" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dölj resonemang i svar" + } + } + } + }, "High (~80%)" : { "localizations" : { "da" : { @@ -3942,6 +7685,380 @@ } } }, + "iCloud Drive Backup" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "iCloud Drive-sikkerhedskopi" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "iCloud-Drive-Sicherung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sauvegarde iCloud Drive" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "iCloud Drive-sikkerhetskopi" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "iCloud Drive-säkerhetskopia" + } + } + } + }, + "Icon Size" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ikonstørrelse" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Symbolgröße" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Taille des icônes" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ikonstørrelse" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ikonstorlek" + } + } + } + }, + "ID" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "ID" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "ID" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "ID" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "ID" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "ID" + } + } + } + }, + "Idle" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inaktiv" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inaktiv" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inactif" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inaktiv" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inaktiv" + } + } + } + }, + "Idle Timeout" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inaktivitetstid" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inaktivitäts-Timeout" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Délai d'inactivité" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inaktivitetstid" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inaktivitetstid" + } + } + } + }, + "Image Gen" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Billedgenerering" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bildgenerierung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Génération d'images" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bildegenerering" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bildgenerering" + } + } + } + }, + "IMAP Host" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "IMAP-vært" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "IMAP-Host" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hôte IMAP" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "IMAP-vert" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "IMAP-värd" + } + } + } + }, + "IMAP Port" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "IMAP-port" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "IMAP-Port" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Port IMAP" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "IMAP-port" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "IMAP-port" + } + } + } + }, + "immediate" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "umiddelbar" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "sofort" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "immédiat" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "umiddelbar" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "omedelbar" + } + } + } + }, + "Import" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Importer" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Importieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Importer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Importer" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Importera" + } + } + } + }, + "In-App Help" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hjælp i appen" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hilfe in der App" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aide dans l'app" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hjelp i appen" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hjälp i appen" + } + } + } + }, "Initialize Repository" : { "localizations" : { "da" : { @@ -4044,6 +8161,210 @@ } } }, + "Input Text" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inputtekst" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eingabetext" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Texte de saisie" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inndatatekst" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inmatningstext" + } + } + } + }, + "Instruct Type" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Instruktionstype" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anweisungstyp" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Type d'instruction" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Instruksjonstype" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Instruktionstyp" + } + } + } + }, + "Intel Mac Support Ending" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Intel Mac-support afsluttes" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Intel-Mac-Unterstützung endet" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fin du support Intel Mac" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Intel Mac-støtte avsluttes" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Intel Mac-support upphör" + } + } + } + }, + "Jarvis" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jarvis" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jarvis" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jarvis" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jarvis" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jarvis" + } + } + } + }, + "Keep Both" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Behold begge" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Beide behalten" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Garder les deux" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Behold begge" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Behåll båda" + } + } + } + }, + "Keyboard Shortcuts" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tastaturgenveje" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tastenkombinationen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Raccourcis clavier" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tastatursnarveier" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tangentbordsgenvägar" + } + } + } + }, "Large files inflate the system prompt and may hit token limits." : { "comment" : "A warning displayed when a user adds a large file to a skill.", "isCommentAutoGenerated" : true, @@ -4080,6 +8401,40 @@ } } }, + "Last Backup" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Seneste sikkerhedskopi" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Letzte Sicherung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dernière sauvegarde" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Siste sikkerhetskopi" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Senaste säkerhetskopia" + } + } + } + }, "Last sync: %@" : { "localizations" : { "da" : { @@ -4114,6 +8469,74 @@ } } }, + "Later" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Senere" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Später" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Plus tard" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Senere" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Senare" + } + } + } + }, + "Leave blank for default" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lad stå tomt for standard" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Leer lassen für Standard" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Laisser vide pour la valeur par défaut" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "La stå tomt for standard" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lämna tomt för standard" + } + } + } + }, "Leave empty to use the default email handler system prompt." : { "localizations" : { "da" : { @@ -4148,6 +8571,247 @@ } } }, + "Let the AI access your Calendar, Reminders, and Location & Maps to answer questions about your schedule and surroundings. Each service is opt-in and uses standard macOS permission prompts. This functionality is in beta and may change." : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lad AI'en få adgang til din kalender, dine påmindelser og placering/kort for at besvare spørgsmål om din tidsplan og dine omgivelser. Hver tjeneste er valgfri og bruger macOS' standardtilladelsesanmodninger. Denne funktionalitet er i beta og kan ændre sig." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erlaube der KI den Zugriff auf deinen Kalender, deine Erinnerungen und Standort/Karten, um Fragen zu deinem Terminplan und deiner Umgebung zu beantworten. Jeder Dienst ist optional und nutzt die Standard-Berechtigungsabfragen von macOS. Diese Funktion befindet sich in der Beta-Phase und kann sich ändern." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Autorise l'IA à accéder à ton calendrier, tes rappels et ta position/cartes pour répondre à des questions sur ton emploi du temps et ton environnement. Chaque service est facultatif et utilise les demandes d'autorisation standard de macOS. Cette fonctionnalité est en bêta et peut évoluer." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "La KI-en få tilgang til kalenderen, påminnelsene og posisjon/kart for å svare på spørsmål om timeplanen og omgivelsene dine. Hver tjeneste er valgfri og bruker standard tillatelsesforespørsler fra macOS. Denne funksjonaliteten er i beta og kan endre seg." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Låt AI:n få åtkomst till din kalender, dina påminnelser och plats/kartor för att svara på frågor om ditt schema och din omgivning. Varje tjänst är valfri och använder standardbehörighetsförfrågningar från macOS. Den här funktionen är i beta och kan komma att ändras." + } + } + } + }, + "Let the AI spawn read-only research sub-agents to investigate multiple things in parallel (read files, list/search directories, search the web — no writing, no bash). Intended for genuinely independent research tasks, not everyday questions." : { + + }, + "Loading usage…" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Indlæser forbrug…" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nutzung wird geladen…" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Chargement de l'utilisation…" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Laster forbruk…" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Laddar användning…" + } + } + } + }, + "Loading..." : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Indlæser..." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wird geladen..." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Chargement..." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Laster..." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Laddar..." + } + } + } + }, + "Local Path" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lokal sti" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lokaler Pfad" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Chemin local" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lokal bane" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lokal sökväg" + } + } + } + }, + "Location & Maps" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Placering og kort" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standort & Karten" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Position et cartes" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Posisjon og kart" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Plats och kartor" + } + } + } + }, + "Log Level" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Logniveau" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Protokollstufe" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Niveau de journalisation" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Loggnivå" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Loggnivå" + } + } + } + }, + "Logging" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Logning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Protokollierung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Journalisation" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Logging" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Loggning" + } + } + } + }, "Low (~20%)" : { "localizations" : { "da" : { @@ -4218,6 +8882,40 @@ } } }, + "Manual Sync" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Manuel synkronisering" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Manuelle Synchronisierung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Synchronisation manuelle" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Manuell synkronisering" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Manuell synkronisering" + } + } + } + }, "Markdown instruction files injected into the system prompt. Compatible with SKILL.md format." : { "comment" : "A description of the format of agent skills.", "isCommentAutoGenerated" : true, @@ -4254,6 +8952,142 @@ } } }, + "Max Context Tokens" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maks konteksttokens" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maximale Kontext-Tokens" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokens de contexte max" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maks kontekst-tokens" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Max kontext-tokens" + } + } + } + }, + "Max Emails Per Hour" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maks e-mails pr. time" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Max. E-Mails pro Stunde" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "E-mails max par heure" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maks e-poster per time" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Max e-post per timme" + } + } + } + }, + "Max Response Tokens" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maks svartokens" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maximale Antwort-Tokens" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokens de réponse max" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maks svar-tokens" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Max svars-tokens" + } + } + } + }, + "Max Tokens" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maks tokens" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maximale Tokens" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokens max" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maks tokens" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Max tokens" + } + } + } + }, "Max Tokens: set to 0 to use model default. Higher values allow longer responses." : { "localizations" : { "da" : { @@ -4288,6 +9122,40 @@ } } }, + "Max Tool Calls" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maks værktøjskald" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Max. Tool-Aufrufe" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Appels d'outils max" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maks verktøykall" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Max verktygsanrop" + } + } + } + }, "MCP gives the AI controlled access to read and optionally write files on your computer. The AI can search, read, and analyze files in allowed folders to help with coding, analysis, and other tasks." : { "localizations" : { "da" : { @@ -4356,6 +9224,40 @@ } } }, + "Memory & Context" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hukommelse og kontekst" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Speicher und Kontext" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mémoire et contexte" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Minne og kontekst" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Minne och kontext" + } + } + } + }, "Merge method" : { "localizations" : { "da" : { @@ -4390,6 +9292,40 @@ } } }, + "Message Threshold" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Beskedtærskel" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nachrichtenschwelle" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Seuil de messages" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Meldingsterskel" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Meddelandetröskel" + } + } + } + }, "messages" : { "localizations" : { "da" : { @@ -4458,6 +9394,74 @@ } } }, + "Method" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Metode" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Methode" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Méthode" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Metode" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Metod" + } + } + } + }, + "Min Messages" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Min. beskeder" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Min. Nachrichten" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Messages min." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Min. meldinger" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Min. meddelanden" + } + } + } + }, "Minimal (~10%)" : { "localizations" : { "da" : { @@ -4492,6 +9496,74 @@ } } }, + "Modality" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modalitet" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modalität" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modalité" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modalitet" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modalitet" + } + } + } + }, + "Model" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Model" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modell" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modèle" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modell" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modell" + } + } + } + }, "Model Context Protocol" : { "localizations" : { "da" : { @@ -4526,6 +9598,40 @@ } } }, + "Model Details" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modeldetaljer" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modelldetails" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Détails du modèle" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modelldetaljer" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modelldetaljer" + } + } + } + }, "Model Info" : { "comment" : "A title for a view that displays information about a model.", "isCommentAutoGenerated" : true, @@ -4562,6 +9668,74 @@ } } }, + "Model Parameters" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modelparametre" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modellparameter" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Paramètres du modèle" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modellparametere" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modellparametrar" + } + } + } + }, + "Model Settings" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modelindstillinger" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modelleinstellungen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Réglages du modèle" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modellinnstillinger" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modellinställningar" + } + } + } + }, "Model thinks internally but reasoning is not shown in chat" : { "localizations" : { "da" : { @@ -4596,6 +9770,40 @@ } } }, + "Move & Copy Files" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Flyt og kopiér filer" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dateien verschieben und kopieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Déplacer et copier des fichiers" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Flytt og kopier filer" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Flytta och kopiera filer" + } + } + } + }, "Multi-provider AI chat client" : { "comment" : "A description of oAI.", "isCommentAutoGenerated" : true, @@ -4668,6 +9876,74 @@ } } }, + "needs input" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "kræver input" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "benötigt Eingabe" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "nécessite une saisie" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "krever input" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "kräver indata" + } + } + } + }, + "Needs input — user types after the command" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kræver input — brugeren skriver efter kommandoen" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Benötigt Eingabe — Benutzer tippt nach dem Befehl" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nécessite une saisie — l'utilisateur tape après la commande" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Krever input — brukeren skriver etter kommandoen" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kräver indata — användaren skriver efter kommandot" + } + } + } + }, "Never" : { "comment" : "A label displayed in the settings view that indicates when the last backup was taken.", "isCommentAutoGenerated" : true, @@ -4704,6 +9980,40 @@ } } }, + "New Agent" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ny agent" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Neuer Agent" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nouvel agent" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ny agent" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ny agent" + } + } + } + }, "New Chat" : { "localizations" : { "da" : { @@ -4772,6 +10082,74 @@ } } }, + "New Shortcut" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ny genvej" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Neue Verknüpfung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nouveau raccourci" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ny snarvei" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ny genväg" + } + } + } + }, + "New Skill" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ny færdighed" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Neuer Skill" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nouveau skill" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ny ferdighet" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ny färdighet" + } + } + } + }, "No credit data available" : { "comment" : "A message displayed when there is no credit data available.", "isCommentAutoGenerated" : true, @@ -4808,6 +10186,40 @@ } } }, + "No default model configured — set one in Settings → General." : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ingen standardmodel konfigureret — angiv en i Indstillinger → Generelt." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kein Standardmodell konfiguriert — lege eines in Einstellungen → Allgemein fest." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aucun modèle par défaut configuré — définis-en un dans Réglages → Général." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ingen standardmodell konfigurert — sett en i Innstillinger → Generelt." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ingen standardmodell konfigurerad — ställ in en i Inställningar → Allmänt." + } + } + } + }, "No email activity yet" : { "comment" : "A message displayed when the user has not yet received any email activity.", "isCommentAutoGenerated" : true, @@ -5200,6 +10612,40 @@ } } }, + "oAI Help" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "oAI-hjælp" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "oAI-Hilfe" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aide oAI" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "oAI-hjelp" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "oAI-hjälp" + } + } + } + }, "oAI v2.4 is the last version to support Intel Macs and Rosetta. Starting with macOS 28, oAI will require Apple Silicon. Consider upgrading your Mac to continue receiving updates." : { "comment" : "A warning that Intel Macs are no longer supported.", "isCommentAutoGenerated" : true, @@ -5236,6 +10682,40 @@ } } }, + "OK" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "OK" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "OK" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "OK" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "OK" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "OK" + } + } + } + }, "Ollama (Local)" : { "comment" : "A label displayed above the credits information for the local Ollie.", "isCommentAutoGenerated" : true, @@ -5272,6 +10752,244 @@ } } }, + "Ollama URL" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ollama-URL" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ollama-URL" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL Ollama" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ollama-URL" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ollama-URL" + } + } + } + }, + "On app quit" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ved app-afslutning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Beim Beenden der App" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "À la fermeture de l'app" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ved avslutning av app" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vid app-avslut" + } + } + } + }, + "On model switch" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ved modelskift" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Beim Modellwechsel" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Au changement de modèle" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ved modellbytte" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vid modellbyte" + } + } + } + }, + "Online" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Online" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Online" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "En ligne" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Online" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Online" + } + } + } + }, + "Online Mode (Web Search)" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onlinetilstand (websøgning)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Online-Modus (Websuche)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mode en ligne (recherche web)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nettmodus (websøk)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onlineläge (webbsökning)" + } + } + } + }, + "Online Mode: Off" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onlinetilstand: Fra" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Online-Modus: Aus" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mode en ligne : désactivé" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nettmodus: Av" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onlineläge: Av" + } + } + } + }, + "Online Mode: On" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onlinetilstand: Til" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Online-Modus: An" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mode en ligne : activé" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nettmodus: På" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onlineläge: På" + } + } + } + }, "Only emails with this text in the subject line will be processed. Example: \"[OAIBOT] What's the weather?\"" : { "localizations" : { "da" : { @@ -5306,6 +11024,74 @@ } } }, + "Open Chat…" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Åbn chat…" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Chat öffnen…" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ouvrir une discussion…" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Åpne chat…" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Öppna chatt…" + } + } + } + }, + "Open System Settings" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Åbn Systemindstillinger" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Systemeinstellungen öffnen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ouvrir Réglages Système" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Åpne Systeminnstillinger" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Öppna Systeminställningar" + } + } + } + }, "OpenAI (text-embedding-3-large)" : { "localizations" : { "da" : { @@ -5582,6 +11368,40 @@ } } }, + "Optional description" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Valgfri beskrivelse" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Optionale Beschreibung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Description facultative" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Valgfri beskrivelse" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Valfri beskrivning" + } + } + } + }, "Output" : { "localizations" : { "da" : { @@ -5616,6 +11436,244 @@ } } }, + "Overview" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Overblik" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Übersicht" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aperçu" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Oversikt" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Översikt" + } + } + } + }, + "Password" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Adgangskode" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Passwort" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mot de passe" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Passord" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lösenord" + } + } + } + }, + "Paused" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pauset" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pausiert" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "En pause" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pauset" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pausad" + } + } + } + }, + "Permissions" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tilladelser" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Berechtigungen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Autorisations" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tillatelser" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Behörigheter" + } + } + } + }, + "Personal Data" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Personlige data" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Persönliche Daten" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Données personnelles" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Personlige data" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Personliga data" + } + } + } + }, + "Pricing" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Priser" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Preise" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tarification" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Priser" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Priser" + } + } + } + }, + "Progressive Summarization" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Progressiv opsummering" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Progressive Zusammenfassung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Résumé progressif" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Progressiv sammendrag" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Progressiv sammanfattning" + } + } + } + }, "Prompt" : { "localizations" : { "da" : { @@ -5650,6 +11708,74 @@ } } }, + "Provider" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Udbyder" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anbieter" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fournisseur" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tilbyder" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Leverantör" + } + } + } + }, + "Rate Limiting" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hastighedsbegrænsning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ratenbegrenzung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Limitation de débit" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Frekvensbegrensning" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hastighetsbegränsning" + } + } + } + }, "Read access (always enabled)" : { "localizations" : { "da" : { @@ -5718,6 +11844,210 @@ } } }, + "Reasoning (Thinking)" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ræsonnement (tænkning)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reasoning (Denkprozess)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Raisonnement (réflexion)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Resonnering (tenking)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Resonemang (tänkande)" + } + } + } + }, + "Reasoning Effort" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ræsonnementniveau" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reasoning-Aufwand" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Effort de raisonnement" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Resonneringsnivå" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Resonemangsnivå" + } + } + } + }, + "Refresh" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Opdater" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aktualisieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Actualiser" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Oppdater" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Uppdatera" + } + } + } + }, + "Refresh agents" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Opdater agenter" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agenten aktualisieren" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Actualiser les agents" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Oppdater agenter" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Uppdatera agenter" + } + } + } + }, + "Release Page" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Udgivelsesside" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Release-Seite" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Page de version" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Utgivelsesside" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Utgivningssida" + } + } + } + }, + "Reminders" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Påmindelser" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erinnerungen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rappels" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Påminnelser" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Påminnelser" + } + } + } + }, "Remote: %@" : { "localizations" : { "da" : { @@ -5752,6 +12082,349 @@ } } }, + "Remove file" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fjern fil" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Datei entfernen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Supprimer le fichier" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fjern fil" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ta bort fil" + } + } + } + }, + "Rename" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Omdøb" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Umbenennen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Renommer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gi nytt navn" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Byt namn" + } + } + } + }, + "Rename conversation" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Omdøb samtale" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gespräch umbenennen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Renommer la conversation" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gi samtalen nytt navn" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Byt namn på konversation" + } + } + } + }, + "Replace" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erstat" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ersetzen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Remplacer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erstatt" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ersätt" + } + } + } + }, + "Request Access" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anmod om adgang" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zugriff anfordern" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Demander l'accès" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Be om tilgang" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Begär åtkomst" + } + } + } + }, + "Require Approval" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kræver godkendelse" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Genehmigung erforderlich" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Approbation requise" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Krever godkjenning" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kräver godkännande" + } + } + } + }, + "Require Approval for Changes" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kræver godkendelse for ændringer" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Genehmigung für Änderungen erforderlich" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Approbation requise pour les modifications" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Krever godkjenning for endringer" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kräver godkännande för ändringar" + } + } + } + }, + "Research Agents" : { + + }, + "Respect .gitignore" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Respekter .gitignore" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : ".gitignore beachten" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Respecter .gitignore" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Respekter .gitignore" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Respektera .gitignore" + } + } + } + }, + "Response Generation" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Svargenerering" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Antwortgenerierung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Génération de réponses" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Svargenerering" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Svarsgenerering" + } + } + } + }, + "Response Settings" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Svarindstillinger" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Antworteinstellungen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Réglages de réponse" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Svarinnstillinger" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Svarsinställningar" + } + } + } + }, "Restore from File…" : { "comment" : "A button that allows the user to restore their data from a file.", "isCommentAutoGenerated" : true, @@ -5788,6 +12461,74 @@ } } }, + "Retry" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prøv igen" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erneut versuchen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Réessayer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prøv igjen" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Försök igen" + } + } + } + }, + "Run agent now" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kør agent nu" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agent jetzt ausführen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exécuter l'agent maintenant" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kjør agent nå" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kör agent nu" + } + } + } + }, "Run History" : { "localizations" : { "da" : { @@ -5928,6 +12669,482 @@ } } }, + "Save" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gem" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Speichern" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Enregistrer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lagre" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Spara" + } + } + } + }, + "Save Chat" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gem chat" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Chat speichern" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Enregistrer la discussion" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lagre chat" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Spara chatt" + } + } + } + }, + "Save Chat As…" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gem chat som…" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Chat speichern als…" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Enregistrer la discussion sous…" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lagre chat som…" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Spara chatt som…" + } + } + } + }, + "Save to Downloads" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gem til Downloads" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "In Downloads speichern" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Enregistrer dans Téléchargements" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lagre til Nedlastinger" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Spara till Nedladdningar" + } + } + } + }, + "Schedule" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tidsplan" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zeitplan" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Planification" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tidsplan" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Schema" + } + } + } + }, + "Search by sender, subject, or content..." : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søg efter afsender, emne eller indhold..." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nach Absender, Betreff oder Inhalt suchen..." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rechercher par expéditeur, objet ou contenu..." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søk etter avsender, emne eller innhold..." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sök efter avsändare, ämne eller innehåll..." + } + } + } + }, + "Search by text or date (dd.mm.yyyy)..." : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søg efter tekst eller dato (dd.mm.åååå)..." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nach Text oder Datum suchen (TT.MM.JJJJ)..." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rechercher par texte ou date (jj.mm.aaaa)..." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søk etter tekst eller dato (dd.mm.åååå)..." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sök efter text eller datum (dd.mm.åååå)..." + } + } + } + }, + "Search commands, shortcuts, features..." : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søg i kommandoer, genveje, funktioner..." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Befehle, Verknüpfungen, Funktionen durchsuchen..." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rechercher des commandes, raccourcis, fonctionnalités..." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søk i kommandoer, snarveier, funksjoner..." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sök i kommandon, genvägar, funktioner..." + } + } + } + }, + "Search Conversations" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søg i samtaler" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gespräche durchsuchen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rechercher dans les conversations" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søk i samtaler" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sök i konversationer" + } + } + } + }, + "Search conversations..." : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søg i samtaler..." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gespräche durchsuchen..." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rechercher dans les conversations..." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søk i samtaler..." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sök i konversationer..." + } + } + } + }, + "Search conversations…" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søg i samtaler…" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gespräche durchsuchen…" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rechercher dans les conversations…" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søk i samtaler…" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sök i konversationer…" + } + } + } + }, + "Search Engine ID" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søgemaskine-ID" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Suchmaschinen-ID" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "ID du moteur de recherche" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søkemotor-ID" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sökmotor-ID" + } + } + } + }, + "Search models..." : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søg modeller..." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modelle durchsuchen..." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rechercher des modèles..." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søk modeller..." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sök modeller..." + } + } + } + }, + "Search Provider" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søgeudbyder" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Suchanbieter" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fournisseur de recherche" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Søketilbyder" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sökleverantör" + } + } + } + }, "Security Recommendation" : { "localizations" : { "da" : { @@ -5962,6 +13179,414 @@ } } }, + "Select" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vælg" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auswählen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sélectionner" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Velg" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Välj" + } + } + } + }, + "Select model" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vælg model" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modell auswählen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sélectionner le modèle" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Velg modell" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Välj modell" + } + } + } + }, + "Select Model" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vælg model" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modell auswählen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sélectionner le modèle" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Velg modell" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Välj modell" + } + } + } + }, + "Select model..." : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vælg model..." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modell auswählen..." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sélectionner le modèle..." + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Velg modell..." + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Välj modell..." + } + } + } + }, + "Semantic" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Semantisk" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Semantisch" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sémantique" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Semantisk" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Semantisk" + } + } + } + }, + "Semantic Search" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Semantisk søgning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Semantische Suche" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Recherche sémantique" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Semantisk søk" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Semantisk sökning" + } + } + } + }, + "Send message" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Send besked" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nachricht senden" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Envoyer le message" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Send melding" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skicka meddelande" + } + } + } + }, + "Server URL" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Server-URL" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Server-URL" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL du serveur" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Server-URL" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Server-URL" + } + } + } + }, + "Services" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tjenester" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dienste" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Services" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tjenester" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tjänster" + } + } + } + }, + "Session Info" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sessionsinfo" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sitzungsinfo" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Infos de session" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sesjonsinfo" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sessionsinfo" + } + } + } + }, + "Settings" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Indstillinger" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Einstellungen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Réglages" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Innstillinger" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inställningar" + } + } + } + }, + "Settings…" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Indstillinger…" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Einstellungen…" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Réglages…" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Innstillinger…" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inställningar…" + } + } + } + }, "Shell commands have full access to your system. Only approve commands you understand and trust." : { "comment" : "A warning banner displayed in the Bash Approval Sheet.", "isCommentAutoGenerated" : true, @@ -5998,6 +13623,142 @@ } } }, + "Show" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vis" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anzeigen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Afficher" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vis" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Visa" + } + } + } + }, + "Show favorites only" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vis kun favoritter" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nur Favoriten anzeigen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Afficher seulement les favoris" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vis bare favoritter" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Visa endast favoriter" + } + } + } + }, + "Show Icon Labels" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vis ikonetiketter" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Symbolbeschriftungen anzeigen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Afficher les libellés des icônes" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vis ikonetiketter" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Visa ikonetiketter" + } + } + } + }, + "Show model info" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vis modelinfo" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modellinfo anzeigen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Afficher les infos du modèle" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vis modellinfo" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Visa modellinfo" + } + } + } + }, "Show text labels below toolbar icons (helpful for new users)" : { "comment" : "A description of the feature that shows text labels below toolbar icons.", "isCommentAutoGenerated" : true, @@ -6138,6 +13899,176 @@ } } }, + "Skip" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Spring over" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Überspringen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ignorer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hopp over" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hoppa över" + } + } + } + }, + "Smart Context Selection" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Smart kontekstvalg" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Intelligente Kontextauswahl" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sélection intelligente du contexte" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Smart kontekstvalg" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Smart kontextval" + } + } + } + }, + "SMTP Host" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "SMTP-vært" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "SMTP-Host" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hôte SMTP" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "SMTP-vert" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "SMTP-värd" + } + } + } + }, + "SMTP Port" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "SMTP-port" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "SMTP-Port" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Port SMTP" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "SMTP-port" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "SMTP-port" + } + } + } + }, + "Software Update" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Softwareopdatering" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Software-Update" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mise à jour logicielle" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Programvareoppdatering" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Programvaruuppdatering" + } + } + } + }, "Sort" : { "localizations" : { "da" : { @@ -6206,6 +14137,210 @@ } } }, + "Star this message to always include it in context" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stjernemarkér denne besked for altid at inkludere den i konteksten" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Markiere diese Nachricht mit einem Stern, um sie immer in den Kontext einzubeziehen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Marque ce message d'une étoile pour toujours l'inclure dans le contexte" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stjernemerk denne meldingen for alltid å inkludere den i konteksten" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stjärnmärk detta meddelande för att alltid inkludera det i kontexten" + } + } + } + }, + "Statistics" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistik" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistiken" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistiques" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistikk" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistik" + } + } + } + }, + "Stats" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistik" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistik" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistiques" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistikk" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistik" + } + } + } + }, + "Status" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Status" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Status" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statut" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Status" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Status" + } + } + } + }, + "Stop agent" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stop agent" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agent stoppen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Arrêter l'agent" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stopp agent" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stoppa agent" + } + } + } + }, + "Stop generation" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stop generering" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Generierung stoppen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Arrêter la génération" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stopp generering" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stoppa generering" + } + } + } + }, "Stream responses as they're generated. Disable for single, complete responses." : { "localizations" : { "da" : { @@ -6240,6 +14375,74 @@ } } }, + "Subject Identifier" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Emneidentifikator" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Betreff-Kennung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Identifiant d'objet" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Emneidentifikator" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ämnesidentifierare" + } + } + } + }, + "Switch provider" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skift udbyder" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anbieter wechseln" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Changer de fournisseur" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bytt tilbyder" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Byt leverantör" + } + } + } + }, "Sync conversations and settings across multiple machines using Git." : { "localizations" : { "da" : { @@ -6308,6 +14511,142 @@ } } }, + "Sync Options" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Synkroniseringsindstillinger" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Synchronisierungsoptionen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Options de synchronisation" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Synkroniseringsalternativer" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Synkroniseringsalternativ" + } + } + } + }, + "System Prompt (Optional)" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Systemprompt (valgfri)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "System-Prompt (optional)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prompt système (facultatif)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Systemprompt (valgfri)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Systemprompt (valfri)" + } + } + } + }, + "System Prompts" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Systemprompter" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "System-Prompts" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prompts système" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Systemprompter" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Systemprompter" + } + } + } + }, + "Temperature" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Temperatur" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Temperatur" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Température" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Temperatur" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Temperatur" + } + } + } + }, "Temperature: 0 = model default · 0.0–0.7 = focused · 0.8–2.0 = creative" : { "localizations" : { "da" : { @@ -6448,6 +14787,40 @@ } } }, + "Text Sizes" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tekststørrelser" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Textgrößen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tailles de texte" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tekststørrelser" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Textstorlekar" + } + } + } + }, "The AI can read and search files in allowed folders" : { "localizations" : { "da" : { @@ -6516,6 +14889,40 @@ } } }, + "The AI wants to make a change to your calendar or reminders" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "AI'en vil foretage en ændring i din kalender eller dine påmindelser" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Die KI möchte eine Änderung an deinem Kalender oder deinen Erinnerungen vornehmen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "L'IA souhaite apporter une modification à ton calendrier ou tes rappels" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "KI-en vil gjøre en endring i kalenderen eller påminnelsene dine" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "AI:n vill göra en ändring i din kalender eller dina påminnelser" + } + } + } + }, "The AI wants to run the following command" : { "comment" : "A description of the command that the AI wants to run.", "isCommentAutoGenerated" : true, @@ -6552,6 +14959,40 @@ } } }, + "Thinking" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tænkning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Denken" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Réflexion" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tenking" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tänkande" + } + } + } + }, "Thinking…" : { "localizations" : { "da" : { @@ -6656,6 +15097,74 @@ } } }, + "Timeout (seconds)" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Timeout (sekunder)" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Timeout (Sekunden)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Délai (secondes)" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tidsavbrudd (sekunder)" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tidsgräns (sekunder)" + } + } + } + }, + "Token" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Token" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Token" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Token" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Token" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Token" + } + } + } + }, "Token Distribution" : { "comment" : "A label displayed under the token distribution bar.", "isCommentAutoGenerated" : true, @@ -6692,6 +15201,74 @@ } } }, + "Token Usage" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokenforbrug" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Token-Nutzung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Utilisation des tokens" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokenbruk" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokenanvändning" + } + } + } + }, + "Tokenizer" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokenizer" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokenizer" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokenizer" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokenizer" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tokenizer" + } + } + } + }, "tokens" : { "localizations" : { "da" : { @@ -6726,6 +15303,74 @@ } } }, + "Toolbar" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Værktøjslinje" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Symbolleiste" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Barre d'outils" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verktøylinje" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verktygsfält" + } + } + } + }, + "Tools" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Værktøjer" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Werkzeuge" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Outils" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verktøy" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verktyg" + } + } + } + }, "Total" : { "localizations" : { "da" : { @@ -7006,6 +15651,40 @@ } } }, + "URL" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL" + } + } + } + }, "Usage" : { "localizations" : { "da" : { @@ -7148,6 +15827,142 @@ } } }, + "Use AI-powered semantic search instead of keyword matching" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Brug AI-drevet semantisk søgning i stedet for nøgleordssøgning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "KI-gestützte semantische Suche statt Schlüsselwortabgleich verwenden" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Utiliser la recherche sémantique par IA au lieu de la correspondance par mots-clés" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bruk KI-drevet semantisk søk i stedet for nøkkelordsøk" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Använd AI-driven semantisk sökning istället för nyckelordsmatchning" + } + } + } + }, + "Use Only Your Prompt" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Brug kun din prompt" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nur deinen Prompt verwenden" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Utiliser uniquement ton prompt" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bruk bare din prompt" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Använd endast din prompt" + } + } + } + }, + "username" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "brugernavn" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Benutzername" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "nom d'utilisateur" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "brukernavn" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "användarnamn" + } + } + } + }, + "Username" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Brugernavn" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Benutzername" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nom d'utilisateur" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Brukernavn" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Användarnamn" + } + } + } + }, "Username + Password" : { "localizations" : { "da" : { @@ -7261,6 +16076,40 @@ } } }, + "View" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Visning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ansicht" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Affichage" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Visning" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Visning" + } + } + } + }, "View Email Log" : { "localizations" : { "da" : { @@ -7295,6 +16144,74 @@ } } }, + "Vision" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vision" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vision" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vision" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vision" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vision" + } + } + } + }, + "Web Search" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Websøgning" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Websuche" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Recherche web" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Websøk" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Webbsökning" + } + } + } + }, "When enabled, listing and searching skip gitignored files. Write operations always ignore .gitignore." : { "localizations" : { "da" : { @@ -7329,6 +16246,40 @@ } } }, + "Working Directory" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Arbejdsmappe" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Arbeitsverzeichnis" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Répertoire de travail" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Arbeidsmappe" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Arbetskatalog" + } + } + } + }, "Working directory:" : { "comment" : "A label displayed under the working directory of a pending shell command.", "isCommentAutoGenerated" : true, @@ -7365,6 +16316,74 @@ } } }, + "Write & Edit Files" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skriv og rediger filer" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dateien schreiben und bearbeiten" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Écrire et modifier des fichiers" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skriv og rediger filer" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skriv och redigera filer" + } + } + } + }, + "Write Actions" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skrivehandlinger" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Schreibaktionen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Actions d'écriture" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skrivehandlinger" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Skrivåtgärder" + } + } + } + }, "You can import any SKILL.md file from skill0.io or write your own." : { "comment" : "A description of how to use skills.", "isCommentAutoGenerated" : true, @@ -7401,6 +16420,40 @@ } } }, + "Your Shortcuts" : { + "localizations" : { + "da" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dine genveje" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Deine Verknüpfungen" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tes raccourcis" + } + }, + "nb" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dine snarveier" + } + }, + "sv" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dina genvägar" + } + } + } + }, "β" : { "comment" : "A beta badge.", "isCommentAutoGenerated" : true, @@ -7436,8438 +16489,6 @@ } } } - }, - "Cancel" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Annuller" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Abbrechen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Annuler" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Avbryt" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Avbryt" - } - } - } - }, - "Save" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Gem" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Speichern" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Enregistrer" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Lagre" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Spara" - } - } - } - }, - "Done" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Færdig" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Fertig" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Terminé" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ferdig" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Klar" - } - } - } - }, - "Delete" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Slet" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Löschen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Supprimer" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Slett" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ta bort" - } - } - } - }, - "Rename" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Omdøb" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Umbenennen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Renommer" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Gi nytt navn" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Byt namn" - } - } - } - }, - "Export" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Eksporter" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Exportieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Exporter" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Eksporter" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Exportera" - } - } - } - }, - "Import" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Importer" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Importieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Importer" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Importer" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Importera" - } - } - } - }, - "Retry" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Prøv igen" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Erneut versuchen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Réessayer" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Prøv igjen" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Försök igen" - } - } - } - }, - "Refresh" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Opdater" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktualisieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Actualiser" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Oppdater" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Uppdatera" - } - } - } - }, - "Dismiss" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Luk" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Schließen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Fermer" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Lukk" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Stäng" - } - } - } - }, - "Select" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vælg" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Auswählen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sélectionner" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Velg" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Välj" - } - } - } - }, - "Clear" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ryd" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Leeren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Effacer" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tøm" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Rensa" - } - } - } - }, - "Skip" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Spring over" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Überspringen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ignorer" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Hopp over" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Hoppa över" - } - } - } - }, - "Replace" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Erstat" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ersetzen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Remplacer" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Erstatt" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ersätt" - } - } - } - }, - "Keep Both" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Behold begge" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Beide behalten" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Garder les deux" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Behold begge" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Behåll båda" - } - } - } - }, - "Got It" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Forstået" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Verstanden" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Compris" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Skjønner" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Förstått" - } - } - } - }, - "Later" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Senere" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Später" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Plus tard" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Senere" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Senare" - } - } - } - }, - "OK" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "OK" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "OK" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "OK" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "OK" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "OK" - } - } - } - }, - "Release Page" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Udgivelsesside" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Release-Seite" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Page de version" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Utgivelsesside" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Utgivningssida" - } - } - } - }, - "Download v%@" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Hent v%@" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "v%@ herunterladen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Télécharger v%@" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Last ned v%@" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ladda ner v%@" - } - } - } - }, - "Allow Once" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tillad denne gang" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Einmal erlauben" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Autoriser une fois" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tillat denne gangen" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tillåt denna gång" - } - } - } - }, - "Allow for Session" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tillad for sessionen" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Für Sitzung erlauben" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Autoriser pour la session" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tillat for sesjonen" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tillåt för sessionen" - } - } - } - }, - "Deny" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Afvis" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Verweigern" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Refuser" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Avslå" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Neka" - } - } - } - }, - "Choose…" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vælg…" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Auswählen…" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Choisir…" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Velg…" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Välj…" - } - } - } - }, - "Save to Downloads" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Gem til Downloads" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "In Downloads speichern" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Enregistrer dans Téléchargements" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Lagre til Nedlastinger" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Spara till Nedladdningar" - } - } - } - }, - "Copy Image" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kopiér billede" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bild kopieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Copier l'image" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kopier bilde" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kopiera bild" - } - } - } - }, - "Add File" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tilføj fil" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Datei hinzufügen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ajouter un fichier" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Legg til fil" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Lägg till fil" - } - } - } - }, - "New Skill" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ny færdighed" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Neuer Skill" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nouveau skill" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ny ferdighet" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ny färdighet" - } - } - } - }, - "Export All" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Eksporter alle" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Alle exportieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tout exporter" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Eksporter alle" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Exportera alla" - } - } - } - }, - "Your Shortcuts" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dine genveje" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Deine Verknüpfungen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tes raccourcis" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dine snarveier" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dina genvägar" - } - } - } - }, - "New Shortcut" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ny genvej" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Neue Verknüpfung" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nouveau raccourci" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ny snarvei" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ny genväg" - } - } - } - }, - "needs input" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "kræver input" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "benötigt Eingabe" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "nécessite une saisie" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "krever input" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "kräver indata" - } - } - } - }, - "immediate" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "umiddelbar" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "sofort" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "immédiat" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "umiddelbar" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "omedelbar" - } - } - } - }, - "No default model configured — set one in Settings → General." : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ingen standardmodel konfigureret — angiv en i Indstillinger → Generelt." - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kein Standardmodell konfiguriert — lege eines in Einstellungen → Allgemein fest." - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aucun modèle par défaut configuré — définis-en un dans Réglages → Général." - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ingen standardmodell konfigurert — sett en i Innstillinger → Generelt." - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ingen standardmodell konfigurerad — ställ in en i Inställningar → Allmänt." - } - } - } - }, - "Delete original conversations after combining" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Slet de oprindelige samtaler efter sammenlægning" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ursprüngliche Gespräche nach dem Zusammenführen löschen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Supprimer les conversations d'origine après la fusion" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Slett originalsamtalene etter sammenslåing" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ta bort originalkonversationerna efter sammanslagning" - } - } - } - }, - "Combine" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sammenlæg" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Zusammenführen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Fusionner" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Slå sammen" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Slå samman" - } - } - } - }, - "Semantic" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Semantisk" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Semantisch" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sémantique" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Semantisk" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Semantisk" - } - } - } - }, - "Keyboard Shortcuts" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tastaturgenveje" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tastenkombinationen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Raccourcis clavier" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tastatursnarveier" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tangentbordsgenvägar" - } - } - } - }, - "Jarvis" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Jarvis" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Jarvis" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Jarvis" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Jarvis" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Jarvis" - } - } - } - }, - "New Agent" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ny agent" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Neuer Agent" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nouvel agent" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ny agent" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ny agent" - } - } - } - }, - "Paused" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Pauset" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Pausiert" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "En pause" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Pauset" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Pausad" - } - } - } - }, - "Idle" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Inaktiv" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Inaktiv" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Inactif" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Inaktiv" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Inaktiv" - } - } - } - }, - "Add Folder…" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tilføj mappe…" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ordner hinzufügen…" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ajouter un dossier…" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Legg til mappe…" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Lägg till mapp…" - } - } - } - }, - "Embed All Conversations" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Indlejr alle samtaler" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Alle Gespräche einbetten" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Intégrer toutes les conversations" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bygg inn alle samtaler" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bädda in alla konversationer" - } - } - } - }, - "Needs input — user types after the command" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kræver input — brugeren skriver efter kommandoen" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Benötigt Eingabe — Benutzer tippt nach dem Befehl" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nécessite une saisie — l'utilisateur tape après la commande" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Krever input — brukeren skriver etter kommandoen" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kräver indata — användaren skriver efter kommandot" - } - } - } - }, - "Executes immediately — no extra input needed" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Udføres umiddelbart — ingen ekstra input nødvendig" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Wird sofort ausgeführt — keine zusätzliche Eingabe nötig" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "S'exécute immédiatement — aucune saisie supplémentaire nécessaire" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Utføres umiddelbart — ingen ekstra input nødvendig" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Körs omedelbart — ingen extra indata behövs" - } - } - } - }, - "About oAI" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Om oAI" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Über oAI" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "À propos d'oAI" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Om oAI" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Om oAI" - } - } - } - }, - "Settings…" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Indstillinger…" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Einstellungen…" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Réglages…" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Innstillinger…" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Inställningar…" - } - } - } - }, - "Clear Chat" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ryd chat" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Chat leeren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Effacer la discussion" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tøm chat" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Rensa chatt" - } - } - } - }, - "Open Chat…" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Åbn chat…" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Chat öffnen…" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ouvrir une discussion…" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Åpne chat…" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Öppna chatt…" - } - } - } - }, - "Search Conversations" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Søg i samtaler" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Gespräche durchsuchen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Rechercher dans les conversations" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Søk i samtaler" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sök i konversationer" - } - } - } - }, - "Save Chat" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Gem chat" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Chat speichern" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Enregistrer la discussion" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Lagre chat" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Spara chatt" - } - } - } - }, - "Save Chat As…" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Gem chat som…" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Chat speichern als…" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Enregistrer la discussion sous…" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Lagre chat som…" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Spara chatt som…" - } - } - } - }, - "Stats" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Statistik" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Statistik" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Statistiques" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Statistikk" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Statistik" - } - } - } - }, - "Export as Markdown…" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Eksporter som Markdown…" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Als Markdown exportieren…" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Exporter en Markdown…" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Eksporter som Markdown…" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Exportera som Markdown…" - } - } - } - }, - "View" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Visning" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ansicht" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Affichage" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Visning" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Visning" - } - } - } - }, - "Select Model" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vælg model" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modell auswählen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sélectionner le modèle" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Velg modell" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Välj modell" - } - } - } - }, - "In-App Help" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Hjælp i appen" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Hilfe in der App" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aide dans l'app" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Hjelp i appen" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Hjälp i appen" - } - } - } - }, - "Credits" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kreditter" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Guthaben" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Crédits" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kreditter" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Krediter" - } - } - } - }, - "oAI Help" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "oAI-hjælp" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "oAI-Hilfe" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aide oAI" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "oAI-hjelp" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "oAI-hjälp" - } - } - } - }, - "%@ tokens" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ tokens" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ tokens" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ tokens" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ tokens" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ tokens" - } - } - } - }, - "^[%@ skill](inflect: true) imported" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ færdighed](inflect: true) importeret" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ Skill](inflect: true) importiert" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ skill](inflect: true) importé" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ ferdighet](inflect: true) importert" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ färdighet](inflect: true) importerad" - } - } - } - }, - "^[%@ skill](inflect: true) exported to Downloads" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ færdighed](inflect: true) eksporteret til Downloads" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ Skill](inflect: true) nach Downloads exportiert" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ skill](inflect: true) exporté vers Téléchargements" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ ferdighet](inflect: true) eksportert til Nedlastinger" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ färdighet](inflect: true) exporterad till Nedladdningar" - } - } - } - }, - "^[%@ file](inflect: true)" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ fil](inflect: true)" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ Datei](inflect: true)" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ fichier](inflect: true)" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ fil](inflect: true)" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ fil](inflect: true)" - } - } - } - }, - "^[%@ skill](inflect: true) active — appended to every system prompt" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ færdighed](inflect: true) aktiv — tilføjet til hver systemprompt" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ Skill](inflect: true) aktiv — an jeden System-Prompt angehängt" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ skill](inflect: true) actif — ajouté à chaque prompt système" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ ferdighet](inflect: true) aktiv — lagt til i hver systemprompt" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ färdighet](inflect: true) aktiv — lagd till i varje systemprompt" - } - } - } - }, - "^[%@ running](inflect: true)" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ kørende](inflect: true)" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ laufend](inflect: true)" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ en cours](inflect: true)" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ kjørende](inflect: true)" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "^[%@ igång](inflect: true)" - } - } - } - }, - "Search conversations…" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Søg i samtaler…" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Gespräche durchsuchen…" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Rechercher dans les conversations…" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Søk i samtaler…" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sök i konversationer…" - } - } - } - }, - "e.g. Code Review, Test Writer, Security Auditor" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "f.eks. Kodegennemgang, Testskribent, Sikkerhedsrevisor" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "z. B. Code-Review, Test-Autor, Sicherheitsprüfer" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "ex. Revue de code, Rédacteur de tests, Auditeur sécurité" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "f.eks. Kodegjennomgang, Testskriving, Sikkerhetsrevisor" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "t.ex. Kodgranskning, Testskrivare, Säkerhetsgranskare" - } - } - } - }, - "Brief summary (optional — auto-extracted from content if left blank)" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kort resumé (valgfrit — udtrækkes automatisk fra indholdet, hvis det er tomt)" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kurze Zusammenfassung (optional — wird automatisch aus dem Inhalt extrahiert, wenn leer)" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Résumé bref (facultatif — extrait automatiquement du contenu si laissé vide)" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kort sammendrag (valgfritt — hentes automatisk fra innholdet hvis tomt)" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kort sammanfattning (valfritt — extraheras automatiskt från innehållet om tomt)" - } - } - } - }, - "Search conversations..." : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Søg i samtaler..." - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Gespräche durchsuchen..." - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Rechercher dans les conversations..." - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Søk i samtaler..." - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sök i konversationer..." - } - } - } - }, - "Loading..." : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Indlæser..." - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Wird geladen..." - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Chargement..." - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Laster..." - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Laddar..." - } - } - } - }, - "Search by sender, subject, or content..." : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Søg efter afsender, emne eller indhold..." - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nach Absender, Betreff oder Inhalt suchen..." - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Rechercher par expéditeur, objet ou contenu..." - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Søk etter avsender, emne eller innhold..." - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sök efter avsändare, ämne eller innehåll..." - } - } - } - }, - "Search commands, shortcuts, features..." : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Søg i kommandoer, genveje, funktioner..." - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Befehle, Verknüpfungen, Funktionen durchsuchen..." - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Rechercher des commandes, raccourcis, fonctionnalités..." - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Søk i kommandoer, snarveier, funksjoner..." - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sök i kommandon, genvägar, funktioner..." - } - } - } - }, - "Search by text or date (dd.mm.yyyy)..." : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Søg efter tekst eller dato (dd.mm.åååå)..." - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nach Text oder Datum suchen (TT.MM.JJJJ)..." - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Rechercher par texte ou date (jj.mm.aaaa)..." - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Søk etter tekst eller dato (dd.mm.åååå)..." - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sök efter text eller datum (dd.mm.åååå)..." - } - } - } - }, - "Loading usage…" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Indlæser forbrug…" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nutzung wird geladen…" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Chargement de l'utilisation…" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Laster forbruk…" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Laddar användning…" - } - } - } - }, - "Agent name" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Agentnavn" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Agentenname" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nom de l'agent" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Agentnavn" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Agentnamn" - } - } - } - }, - "Optional description" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Valgfri beskrivelse" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Optionale Beschreibung" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Description facultative" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Valgfri beskrivelse" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Valfri beskrivning" - } - } - } - }, - "Cron expression (e.g. 0 * * * *)" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Cron-udtryk (f.eks. 0 * * * *)" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Cron-Ausdruck (z. B. 0 * * * *)" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Expression cron (ex. 0 * * * *)" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Cron-uttrykk (f.eks. 0 * * * *)" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Cron-uttryck (t.ex. 0 * * * *)" - } - } - } - }, - "Leave blank for default" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Lad stå tomt for standard" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Leer lassen für Standard" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Laisser vide pour la valeur par défaut" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "La stå tomt for standard" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Lämna tomt för standard" - } - } - } - }, - "Search models..." : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Søg modeller..." - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modelle durchsuchen..." - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Rechercher des modèles..." - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Søk modeller..." - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sök modeller..." - } - } - } - }, - "username" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "brugernavn" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Benutzername" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "nom d'utilisateur" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "brukernavn" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "användarnamn" - } - } - } - }, - "Brief description shown in the command dropdown" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kort beskrivelse vist i kommando-rullemenuen" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kurze Beschreibung im Befehlsmenü" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Brève description affichée dans le menu de commandes" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kort beskrivelse vist i kommando-rullegardinmenyen" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kort beskrivning som visas i kommandomenyn" - } - } - } - }, - "Session Info" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sessionsinfo" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sitzungsinfo" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Infos de session" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sesjonsinfo" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sessionsinfo" - } - } - } - }, - "Token Usage" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tokenforbrug" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Token-Nutzung" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Utilisation des tokens" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tokenbruk" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tokenanvändning" - } - } - } - }, - "Costs" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Omkostninger" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kosten" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Coûts" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kostnader" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kostnader" - } - } - } - }, - "Model Details" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modeldetaljer" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modelldetails" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Détails du modèle" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modelldetaljer" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modelldetaljer" - } - } - } - }, - "Intel Mac Support Ending" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Intel Mac-support afsluttes" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Intel-Mac-Unterstützung endet" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Fin du support Intel Mac" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Intel Mac-støtte avsluttes" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Intel Mac-support upphör" - } - } - } - }, - "Software Update" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Softwareopdatering" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Software-Update" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Mise à jour logicielle" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Programvareoppdatering" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Programvaruuppdatering" - } - } - } - }, - "A new version is available — click to open the releases page" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "En ny version er tilgængelig — klik for at åbne udgivelsessiden" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Eine neue Version ist verfügbar — klicke, um die Release-Seite zu öffnen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Une nouvelle version est disponible — clique pour ouvrir la page des versions" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "En ny versjon er tilgjengelig — klikk for å åpne utgivelsessiden" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "En ny version är tillgänglig — klicka för att öppna utgivningssidan" - } - } - } - }, - "Switch provider" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Skift udbyder" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Anbieter wechseln" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Changer de fournisseur" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bytt tilbyder" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Byt leverantör" - } - } - } - }, - "Select model" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vælg model" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modell auswählen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sélectionner le modèle" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Velg modell" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Välj modell" - } - } - } - }, - "Attach file" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vedhæft fil" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Datei anhängen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Joindre un fichier" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Legg til fil" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bifoga fil" - } - } - } - }, - "Stop generation" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Stop generering" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Generierung stoppen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Arrêter la génération" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Stopp generering" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Stoppa generering" - } - } - } - }, - "Send message" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Send besked" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nachricht senden" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Envoyer le message" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Send melding" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Skicka meddelande" - } - } - } - }, - "Star this message to always include it in context" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Stjernemarkér denne besked for altid at inkludere den i konteksten" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Markiere diese Nachricht mit einem Stern, um sie immer in den Kontext einzubeziehen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Marque ce message d'une étoile pour toujours l'inclure dans le contexte" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Stjernemerk denne meldingen for alltid å inkludere den i konteksten" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Stjärnmärk detta meddelande för att alltid inkludera det i kontexten" - } - } - } - }, - "Advanced search — semantic search, bulk delete, export" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Avanceret søgning — semantisk søgning, massesletning, eksport" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Erweiterte Suche — semantische Suche, Massenlöschung, Export" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Recherche avancée — recherche sémantique, suppression groupée, export" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Avansert søk — semantisk søk, massesletting, eksport" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Avancerad sökning — semantisk sökning, massradering, export" - } - } - } - }, - "Remove file" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Fjern fil" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Datei entfernen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Supprimer le fichier" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Fjern fil" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ta bort fil" - } - } - } - }, - "Delete skill" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Slet færdighed" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Skill löschen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Supprimer le skill" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Slett ferdighet" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ta bort färdighet" - } - } - } - }, - "Use AI-powered semantic search instead of keyword matching" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Brug AI-drevet semantisk søgning i stedet for nøgleordssøgning" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "KI-gestützte semantische Suche statt Schlüsselwortabgleich verwenden" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Utiliser la recherche sémantique par IA au lieu de la correspondance par mots-clés" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bruk KI-drevet semantisk søk i stedet for nøkkelordsøk" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Använd AI-driven semantisk sökning istället för nyckelordsmatchning" - } - } - } - }, - "Rename conversation" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Omdøb samtale" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Gespräch umbenennen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Renommer la conversation" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Gi samtalen nytt navn" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Byt namn på konversation" - } - } - } - }, - "Delete conversation" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Slet samtale" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Gespräch löschen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Supprimer la conversation" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Slett samtale" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ta bort konversation" - } - } - } - }, - "Clear Email Log?" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ryd e-maillog?" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "E-Mail-Protokoll löschen?" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Effacer le journal e-mail ?" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tøm e-postlogg?" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Rensa e-postlogg?" - } - } - } - }, - "Refresh agents" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Opdater agenter" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Agenten aktualisieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Actualiser les agents" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Oppdater agenter" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Uppdatera agenter" - } - } - } - }, - "Stop agent" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Stop agent" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Agent stoppen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Arrêter l'agent" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Stopp agent" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Stoppa agent" - } - } - } - }, - "Run agent now" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kør agent nu" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Agent jetzt ausführen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Exécuter l'agent maintenant" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kjør agent nå" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kör agent nu" - } - } - } - }, - "Filter by category" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Filtrer efter kategori" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nach Kategorie filtern" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Filtrer par catégorie" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Filtrer etter kategori" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Filtrera efter kategori" - } - } - } - }, - "Show favorites only" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vis kun favoritter" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nur Favoriten anzeigen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Afficher seulement les favoris" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vis bare favoritter" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Visa endast favoriter" - } - } - } - }, - "Show model info" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vis modelinfo" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modellinfo anzeigen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Afficher les infos du modèle" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vis modellinfo" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Visa modellinfo" - } - } - } - }, - "Enter your Ollama server URL to enable the Ollama provider" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Indtast din Ollama-server-URL for at aktivere Ollama-udbyderen" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Gib die URL deines Ollama-Servers ein, um den Ollama-Anbieter zu aktivieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Saisis l'URL de ton serveur Ollama pour activer le fournisseur Ollama" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Skriv inn Ollama-serverens URL for å aktivere Ollama-tilbyderen" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ange din Ollama-servers URL för att aktivera Ollama-leverantören" - } - } - } - }, - "Generate embeddings for all existing messages (one-time operation)" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Generer indlejringer for alle eksisterende beskeder (enkeltstående handling)" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Embeddings für alle vorhandenen Nachrichten generieren (einmaliger Vorgang)" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Générer des embeddings pour tous les messages existants (opération unique)" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Generer innbygginger for alle eksisterende meldinger (engangsoperasjon)" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Generera embeddings för alla befintliga meddelanden (engångsoperation)" - } - } - } - }, - "Duplicate Shortcut" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dupliker genvej" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Verknüpfung duplizieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dupliquer le raccourci" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dupliser snarvei" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Duplicera genväg" - } - } - } - }, - "Export shortcut" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Eksporter genvej" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Verknüpfung exportieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Exporter le raccourci" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Eksporter snarvei" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Exportera genväg" - } - } - } - }, - "Delete shortcut" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Slet genvej" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Verknüpfung löschen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Supprimer le raccourci" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Slett snarvei" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ta bort genväg" - } - } - } - }, - "Statistics" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Statistik" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Statistiken" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Statistiques" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Statistikk" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Statistik" - } - } - } - }, - "Select model..." : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vælg model..." - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modell auswählen..." - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sélectionner le modèle..." - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Velg modell..." - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Välj modell..." - } - } - } - }, - "Hide" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Skjul" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Verbergen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Masquer" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Skjul" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dölj" - } - } - } - }, - "Show" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vis" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Anzeigen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Afficher" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vis" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Visa" - } - } - } - }, - "Provider" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Udbyder" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Anbieter" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Fournisseur" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tilbyder" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Leverantör" - } - } - } - }, - "Default Provider" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Standardudbyder" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Standardanbieter" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Fournisseur par défaut" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Standardtilbyder" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Standardleverantör" - } - } - } - }, - "API Keys" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "API-nøgler" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "API-Schlüssel" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Clés API" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "API-nøkler" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "API-nycklar" - } - } - } - }, - "Ollama URL" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ollama-URL" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ollama-URL" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "URL Ollama" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ollama-URL" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ollama-URL" - } - } - } - }, - "Features" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Funktioner" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Funktionen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Fonctionnalités" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Funksjoner" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Funktioner" - } - } - } - }, - "Online Mode (Web Search)" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Onlinetilstand (websøgning)" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Online-Modus (Websuche)" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Mode en ligne (recherche web)" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nettmodus (websøk)" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Onlineläge (webbsökning)" - } - } - } - }, - "Conversation Memory" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Samtalehukommelse" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Gesprächsspeicher" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Mémoire de conversation" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Samtaleminne" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Konversationsminne" - } - } - } - }, - "Reasoning (Thinking)" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ræsonnement (tænkning)" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Reasoning (Denkprozess)" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Raisonnement (réflexion)" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Resonnering (tenking)" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Resonemang (tänkande)" - } - } - } - }, - "Reasoning Effort" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ræsonnementniveau" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Reasoning-Aufwand" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Effort de raisonnement" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Resonneringsnivå" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Resonemangsnivå" - } - } - } - }, - "Hide Reasoning in Response" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Skjul ræsonnement i svar" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Reasoning in Antwort verbergen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Masquer le raisonnement dans la réponse" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Skjul resonnering i svar" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dölj resonemang i svar" - } - } - } - }, - "Web Search" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Websøgning" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Websuche" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Recherche web" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Websøk" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Webbsökning" - } - } - } - }, - "Search Provider" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Søgeudbyder" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Suchanbieter" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Fournisseur de recherche" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Søketilbyder" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sökleverantör" - } - } - } - }, - "Google API Key" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Google API-nøgle" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Google-API-Schlüssel" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Clé API Google" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Google API-nøkkel" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Google API-nyckel" - } - } - } - }, - "Search Engine ID" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Søgemaskine-ID" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Suchmaschinen-ID" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "ID du moteur de recherche" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Søkemotor-ID" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sökmotor-ID" - } - } - } - }, - "Model Settings" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modelindstillinger" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modelleinstellungen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Réglages du modèle" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modellinnstillinger" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modellinställningar" - } - } - } - }, - "Default Model" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Standardmodel" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Standardmodell" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modèle par défaut" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Standardmodell" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Standardmodell" - } - } - } - }, - "Logging" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Logning" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Protokollierung" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Journalisation" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Logging" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Loggning" - } - } - } - }, - "Log Level" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Logniveau" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Protokollstufe" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Niveau de journalisation" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Loggnivå" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Loggnivå" - } - } - } - }, - "Status" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Status" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Status" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Statut" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Status" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Status" - } - } - } - }, - "Enable MCP" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver MCP" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "MCP aktivieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activer MCP" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver MCP" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktivera MCP" - } - } - } - }, - "Allowed Folders" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tilladte mapper" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Erlaubte Ordner" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dossiers autorisés" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tillatte mapper" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tillåtna mappar" - } - } - } - }, - "Permissions" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tilladelser" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Berechtigungen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Autorisations" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tillatelser" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Behörigheter" - } - } - } - }, - "Write & Edit Files" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Skriv og rediger filer" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dateien schreiben und bearbeiten" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Écrire et modifier des fichiers" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Skriv og rediger filer" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Skriv och redigera filer" - } - } - } - }, - "Delete Files" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Slet filer" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dateien löschen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Supprimer des fichiers" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Slett filer" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ta bort filer" - } - } - } - }, - "Create Directories" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Opret mapper" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Verzeichnisse erstellen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Créer des dossiers" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Opprett mapper" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Skapa mappar" - } - } - } - }, - "Move & Copy Files" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Flyt og kopiér filer" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dateien verschieben und kopieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Déplacer et copier des fichiers" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Flytt og kopier filer" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Flytta och kopiera filer" - } - } - } - }, - "Filtering" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Filtrering" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Filterung" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Filtrage" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Filtrering" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Filtrering" - } - } - } - }, - "Respect .gitignore" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Respekter .gitignore" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : ".gitignore beachten" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Respecter .gitignore" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Respekter .gitignore" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Respektera .gitignore" - } - } - } - }, - "Enable Bash Execution" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver Bash-udførelse" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bash-Ausführung aktivieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activer l'exécution Bash" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver Bash-kjøring" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktivera Bash-körning" - } - } - } - }, - "Settings" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Indstillinger" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Einstellungen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Réglages" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Innstillinger" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Inställningar" - } - } - } - }, - "Require Approval" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kræver godkendelse" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Genehmigung erforderlich" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Approbation requise" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Krever godkjenning" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kräver godkännande" - } - } - } - }, - "Working Directory" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Arbejdsmappe" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Arbeitsverzeichnis" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Répertoire de travail" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Arbeidsmappe" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Arbetskatalog" - } - } - } - }, - "Timeout (seconds)" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Timeout (sekunder)" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Timeout (Sekunden)" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Délai (secondes)" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tidsavbrudd (sekunder)" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tidsgräns (sekunder)" - } - } - } - }, - "Text Sizes" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tekststørrelser" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Textgrößen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tailles de texte" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tekststørrelser" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Textstorlekar" - } - } - } - }, - "GUI Text" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "GUI-tekst" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "GUI-Text" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Texte de l'interface" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "GUI-tekst" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "GUI-text" - } - } - } - }, - "Dialog Text" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dialogtekst" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dialogtext" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Texte des boîtes de dialogue" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dialogtekst" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dialogtext" - } - } - } - }, - "Input Text" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Inputtekst" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Eingabetext" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Texte de saisie" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Inndatatekst" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Inmatningstext" - } - } - } - }, - "Toolbar" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Værktøjslinje" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Symbolleiste" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Barre d'outils" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Verktøylinje" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Verktygsfält" - } - } - } - }, - "Icon Size" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ikonstørrelse" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Symbolgröße" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Taille des icônes" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ikonstørrelse" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ikonstorlek" - } - } - } - }, - "Show Icon Labels" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vis ikonetiketter" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Symbolbeschriftungen anzeigen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Afficher les libellés des icônes" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vis ikonetiketter" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Visa ikonetiketter" - } - } - } - }, - "Response Generation" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Svargenerering" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Antwortgenerierung" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Génération de réponses" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Svargenerering" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Svarsgenerering" - } - } - } - }, - "Enable Streaming" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver streaming" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Streaming aktivieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activer le streaming" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver strømming" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktivera streaming" - } - } - } - }, - "Model Parameters" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modelparametre" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modellparameter" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Paramètres du modèle" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modellparametere" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modellparametrar" - } - } - } - }, - "Max Tokens" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Maks tokens" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Maximale Tokens" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tokens max" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Maks tokens" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Max tokens" - } - } - } - }, - "Temperature" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Temperatur" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Temperatur" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Température" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Temperatur" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Temperatur" - } - } - } - }, - "System Prompts" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Systemprompter" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "System-Prompts" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Prompts système" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Systemprompter" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Systemprompter" - } - } - } - }, - "Use Only Your Prompt" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Brug kun din prompt" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nur deinen Prompt verwenden" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Utiliser uniquement ton prompt" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bruk bare din prompt" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Använd endast din prompt" - } - } - } - }, - "Memory & Context" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Hukommelse og kontekst" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Speicher und Kontext" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Mémoire et contexte" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Minne og kontekst" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Minne och kontext" - } - } - } - }, - "Smart Context Selection" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Smart kontekstvalg" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Intelligente Kontextauswahl" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sélection intelligente du contexte" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Smart kontekstvalg" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Smart kontextval" - } - } - } - }, - "Max Context Tokens" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Maks konteksttokens" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Maximale Kontext-Tokens" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tokens de contexte max" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Maks kontekst-tokens" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Max kontext-tokens" - } - } - } - }, - "Semantic Search" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Semantisk søgning" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Semantische Suche" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Recherche sémantique" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Semantisk søk" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Semantisk sökning" - } - } - } - }, - "Enable Embeddings" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver indlejringer" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Embeddings aktivieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activer les embeddings" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver innbygginger" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktivera embeddings" - } - } - } - }, - "Model" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Model" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modell" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modèle" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modell" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modell" - } - } - } - }, - "Progressive Summarization" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Progressiv opsummering" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Progressive Zusammenfassung" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Résumé progressif" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Progressiv sammendrag" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Progressiv sammanfattning" - } - } - } - }, - "Enable Summarization" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver opsummering" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Zusammenfassung aktivieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activer le résumé" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver sammendrag" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktivera sammanfattning" - } - } - } - }, - "Message Threshold" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Beskedtærskel" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nachrichtenschwelle" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Seuil de messages" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Meldingsterskel" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Meddelandetröskel" - } - } - } - }, - "Git Sync" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Git-synkronisering" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Git-Synchronisierung" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Synchronisation Git" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Git-synkronisering" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Git-synkronisering" - } - } - } - }, - "Enable Git Sync" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver Git-synkronisering" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Git-Synchronisierung aktivieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activer la synchronisation Git" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver Git-synkronisering" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktivera Git-synkronisering" - } - } - } - }, - "Connection" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Forbindelse" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Verbindung" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Connexion" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tilkobling" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Anslutning" - } - } - } - }, - "URL" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "URL" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "URL" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "URL" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "URL" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "URL" - } - } - } - }, - "Local Path" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Lokal sti" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Lokaler Pfad" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Chemin local" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Lokal bane" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Lokal sökväg" - } - } - } - }, - "Authentication" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Godkendelse" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Authentifizierung" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Authentification" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Autentisering" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Autentisering" - } - } - } - }, - "Method" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Metode" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Methode" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Méthode" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Metode" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Metod" - } - } - } - }, - "Username" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Brugernavn" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Benutzername" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nom d'utilisateur" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Brukernavn" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Användarnamn" - } - } - } - }, - "Password" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Adgangskode" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Passwort" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Mot de passe" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Passord" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Lösenord" - } - } - } - }, - "Token" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Token" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Token" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Token" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Token" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Token" - } - } - } - }, - "Sync Options" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Synkroniseringsindstillinger" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Synchronisierungsoptionen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Options de synchronisation" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Synkroniseringsalternativer" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Synkroniseringsalternativ" - } - } - } - }, - "Auto-export on save" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Auto-eksporter ved gem" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Automatisch exportieren beim Speichern" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Exporter automatiquement à l'enregistrement" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Auto-eksporter ved lagring" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Auto-exportera vid sparande" - } - } - } - }, - "Auto-pull on launch" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Auto-hent ved start" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Automatisch abrufen beim Start" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Récupérer automatiquement au démarrage" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Auto-hent ved oppstart" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Auto-hämta vid start" - } - } - } - }, - "Auto-Save" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Auto-gem" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Automatisches Speichern" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Enregistrement automatique" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Auto-lagring" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Auto-spara" - } - } - } - }, - "Enable Auto-Save" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver auto-gem" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Automatisches Speichern aktivieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activer l'enregistrement automatique" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver auto-lagring" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktivera auto-spara" - } - } - } - }, - "Min Messages" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Min. beskeder" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Min. Nachrichten" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Messages min." - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Min. meldinger" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Min. meddelanden" - } - } - } - }, - "On model switch" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ved modelskift" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Beim Modellwechsel" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Au changement de modèle" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ved modellbytte" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vid modellbyte" - } - } - } - }, - "On app quit" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ved app-afslutning" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Beim Beenden der App" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "À la fermeture de l'app" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ved avslutning av app" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vid app-avslut" - } - } - } - }, - "After idle timeout" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Efter inaktivitetstid" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nach Inaktivitäts-Timeout" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Après délai d'inactivité" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Etter inaktivitetstid" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Efter inaktivitetstid" - } - } - } - }, - "Idle Timeout" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Inaktivitetstid" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Inaktivitäts-Timeout" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Délai d'inactivité" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Inaktivitetstid" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Inaktivitetstid" - } - } - } - }, - "Manual Sync" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Manuel synkronisering" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Manuelle Synchronisierung" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Synchronisation manuelle" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Manuell synkronisering" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Manuell synkronisering" - } - } - } - }, - "AI Email Handler" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "AI-e-mailbehandler" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "KI-E-Mail-Handler" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Gestionnaire d'e-mails IA" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "KI-e-postbehandler" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "AI-e-posthanterare" - } - } - } - }, - "Enable Email Handler" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver e-mailbehandler" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "E-Mail-Handler aktivieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activer le gestionnaire d'e-mails" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver e-postbehandler" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktivera e-posthanterare" - } - } - } - }, - "AI Configuration" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "AI-konfiguration" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "KI-Konfiguration" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Configuration de l'IA" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "KI-konfigurasjon" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "AI-konfiguration" - } - } - } - }, - "AI Provider" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "AI-udbyder" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "KI-Anbieter" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Fournisseur IA" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "KI-tilbyder" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "AI-leverantör" - } - } - } - }, - "AI Model" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "AI-model" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "KI-Modell" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modèle IA" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "KI-modell" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "AI-modell" - } - } - } - }, - "Email Server" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "E-mailserver" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "E-Mail-Server" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Serveur e-mail" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "E-postserver" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "E-postserver" - } - } - } - }, - "IMAP Host" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "IMAP-vært" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "IMAP-Host" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Hôte IMAP" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "IMAP-vert" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "IMAP-värd" - } - } - } - }, - "SMTP Host" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "SMTP-vært" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "SMTP-Host" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Hôte SMTP" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "SMTP-vert" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "SMTP-värd" - } - } - } - }, - "IMAP Port" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "IMAP-port" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "IMAP-Port" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Port IMAP" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "IMAP-port" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "IMAP-port" - } - } - } - }, - "SMTP Port" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "SMTP-port" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "SMTP-Port" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Port SMTP" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "SMTP-port" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "SMTP-port" - } - } - } - }, - "Email Trigger" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "E-mailudløser" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "E-Mail-Trigger" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Déclencheur e-mail" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "E-postutløser" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "E-postutlösare" - } - } - } - }, - "Subject Identifier" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Emneidentifikator" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Betreff-Kennung" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Identifiant d'objet" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Emneidentifikator" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ämnesidentifierare" - } - } - } - }, - "Rate Limiting" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Hastighedsbegrænsning" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ratenbegrenzung" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Limitation de débit" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Frekvensbegrensning" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Hastighetsbegränsning" - } - } - } - }, - "Enable Rate Limit" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver hastighedsbegrænsning" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ratenbegrenzung aktivieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activer la limitation de débit" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver frekvensbegrensning" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktivera hastighetsbegränsning" - } - } - } - }, - "Max Emails Per Hour" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Maks e-mails pr. time" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Max. E-Mails pro Stunde" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "E-mails max par heure" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Maks e-poster per time" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Max e-post per timme" - } - } - } - }, - "Response Settings" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Svarindstillinger" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Antworteinstellungen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Réglages de réponse" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Svarinnstillinger" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Svarsinställningar" - } - } - } - }, - "Max Response Tokens" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Maks svartokens" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Maximale Antwort-Tokens" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tokens de réponse max" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Maks svar-tokens" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Max svars-tokens" - } - } - } - }, - "Enable Online Mode" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver onlinetilstand" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Online-Modus aktivieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activer le mode en ligne" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver nettmodus" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktivera onlineläge" - } - } - } - }, - "System Prompt (Optional)" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Systemprompt (valgfri)" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "System-Prompt (optional)" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Prompt système (facultatif)" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Systemprompt (valgfri)" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Systemprompt (valfri)" - } - } - } - }, - "Activity" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktivitet" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktivität" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activité" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktivitet" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktivitet" - } - } - } - }, - "Email Log" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "E-maillog" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "E-Mail-Protokoll" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Journal e-mail" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "E-postlogg" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "E-postlogg" - } - } - } - }, - "Enable Paperless" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver Paperless" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Paperless aktivieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activer Paperless" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver Paperless" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktivera Paperless" - } - } - } - }, - "Base URL" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Base-URL" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Basis-URL" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "URL de base" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Base-URL" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bas-URL" - } - } - } - }, - "API Token" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "API-token" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "API-Token" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Token API" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "API-token" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "API-token" - } - } - } - }, - "Enable Anytype" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver Anytype" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Anytype aktivieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activer Anytype" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver Anytype" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktivera Anytype" - } - } - } - }, - "API URL" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "API-URL" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "API-URL" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "URL API" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "API-URL" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "API-URL" - } - } - } - }, - "API Key" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "API-nøgle" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "API-Schlüssel" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Clé API" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "API-nøkkel" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "API-nyckel" - } - } - } - }, - "Enable Jarvis" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver Jarvis" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Jarvis aktivieren" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activer Jarvis" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiver Jarvis" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktivera Jarvis" - } - } - } - }, - "Server URL" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Server-URL" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Server-URL" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "URL du serveur" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Server-URL" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Server-URL" - } - } - } - }, - "iCloud Drive Backup" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "iCloud Drive-sikkerhedskopi" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "iCloud-Drive-Sicherung" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sauvegarde iCloud Drive" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "iCloud Drive-sikkerhetskopi" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "iCloud Drive-säkerhetskopia" - } - } - } - }, - "Last Backup" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Seneste sikkerhedskopi" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Letzte Sicherung" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dernière sauvegarde" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Siste sikkerhetskopi" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Senaste säkerhetskopia" - } - } - } - }, - "Actions" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Handlinger" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktionen" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Actions" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Handlinger" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Åtgärder" - } - } - } - }, - "Overview" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Overblik" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Übersicht" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aperçu" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Oversikt" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Översikt" - } - } - } - }, - "ID" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "ID" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "ID" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "ID" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "ID" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "ID" - } - } - } - }, - "Pricing" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Priser" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Preise" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tarification" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Priser" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Priser" - } - } - } - }, - "1K tokens" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "1K tokens" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "1K Tokens" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "1K tokens" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "1K tokens" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "1K tokens" - } - } - } - }, - "10K tokens" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "10K tokens" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "10K Tokens" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "10K tokens" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "10K tokens" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "10K tokens" - } - } - } - }, - "100K tokens" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "100K tokens" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "100K Tokens" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "100K tokens" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "100K tokens" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "100K tokens" - } - } - } - }, - "Context Window" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kontekstvindue" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kontextfenster" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Fenêtre de contexte" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kontekstvindu" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kontextfönster" - } - } - } - }, - "Categories" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kategorier" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kategorien" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Catégories" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kategorier" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kategorier" - } - } - } - }, - "Architecture" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Arkitektur" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Architektur" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Architecture" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Arkitektur" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Arkitektur" - } - } - } - }, - "Modality" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modalitet" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modalität" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modalité" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modalitet" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modalitet" - } - } - } - }, - "Tokenizer" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tokenizer" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tokenizer" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tokenizer" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tokenizer" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tokenizer" - } - } - } - }, - "Instruct Type" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Instruktionstype" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Anweisungstyp" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Type d'instruction" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Instruksjonstype" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Instruktionstyp" - } - } - } - }, - "Vision" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vision" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vision" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vision" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vision" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vision" - } - } - } - }, - "Tools" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Værktøjer" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Werkzeuge" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Outils" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Verktøy" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Verktyg" - } - } - } - }, - "Online" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Online" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Online" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "En ligne" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Online" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Online" - } - } - } - }, - "Image Gen" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Billedgenerering" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bildgenerierung" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Génération d'images" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bildegenerering" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bildgenerering" - } - } - } - }, - "Thinking" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tænkning" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Denken" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Réflexion" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tenking" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tänkande" - } - } - } - }, - "Schedule" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tidsplan" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Zeitplan" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Planification" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tidsplan" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Schema" - } - } - } - }, - "Max Tool Calls" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Maks værktøjskald" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Max. Tool-Aufrufe" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Appels d'outils max" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Maks verktøykall" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Max verktygsanrop" - } - } - } - }, - "Enabled" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiveret" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiviert" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activé" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktivert" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktiverad" - } - } - } - }, - "Online Mode: On" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Onlinetilstand: Til" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Online-Modus: An" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Mode en ligne : activé" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nettmodus: På" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Onlineläge: På" - } - } - } - }, - "Online Mode: Off" : { - "localizations" : { - "da" : { - "stringUnit" : { - "state" : "translated", - "value" : "Onlinetilstand: Fra" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Online-Modus: Aus" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Mode en ligne : désactivé" - } - }, - "nb" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nettmodus: Av" - } - }, - "sv" : { - "stringUnit" : { - "state" : "translated", - "value" : "Onlineläge: Av" - } - } - } } }, "version" : "1.1" diff --git a/oAI/Models/AgentSkill.swift b/oAI/Models/AgentSkill.swift index c771ae6..0f3d2e4 100644 --- a/oAI/Models/AgentSkill.swift +++ b/oAI/Models/AgentSkill.swift @@ -57,4 +57,10 @@ struct AgentSkill: Codable, Identifiable { } return name } + + /// Matches the user's "2nd Brain" skill by name — there's no canonical skill ID, + /// so this is the only way to recognize it (used to gate the "always trust" bash setting). + var isSecondBrainSkill: Bool { + name.trimmingCharacters(in: .whitespacesAndNewlines).caseInsensitiveCompare("2nd Brain") == .orderedSame + } } diff --git a/oAI/Providers/AIProvider.swift b/oAI/Providers/AIProvider.swift index 10f2d00..42f52ea 100644 --- a/oAI/Providers/AIProvider.swift +++ b/oAI/Providers/AIProvider.swift @@ -229,6 +229,19 @@ struct Tool: Codable { let type: String let description: String let `enum`: [String]? + let items: Items? + + /// Item schema for `type: "array"` properties (e.g. an array of strings). + struct Items: Codable { + let type: String + } + + init(type: String, description: String, enum: [String]? = nil, items: Items? = nil) { + self.type = type + self.description = description + self.enum = `enum` + self.items = items + } } } } diff --git a/oAI/Providers/AnthropicProvider.swift b/oAI/Providers/AnthropicProvider.swift index d801467..bb5bdbe 100644 --- a/oAI/Providers/AnthropicProvider.swift +++ b/oAI/Providers/AnthropicProvider.swift @@ -753,6 +753,9 @@ class AnthropicProvider: AIProvider { if let enumVals = prop.enum { propDict["enum"] = enumVals } + if let items = prop.items { + propDict["items"] = ["type": items.type] + } props[key] = propDict } var dict: [String: Any] = [ diff --git a/oAI/Services/ContactsService.swift b/oAI/Services/ContactsService.swift new file mode 100644 index 0000000..c6f4920 --- /dev/null +++ b/oAI/Services/ContactsService.swift @@ -0,0 +1,250 @@ +// +// ContactsService.swift +// oAI +// +// Read-only Contacts integration: search and "my card" lookup +// +// SPDX-License-Identifier: AGPL-3.0-or-later +// Copyright (C) 2026 Rune Olsen +// +// This file is part of oAI. +// +// oAI is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// oAI is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General +// Public License for more details. +// +// You should have received a copy of the GNU Affero General Public +// License along with oAI. If not, see . + + +import Contacts +import Foundation +import os + +@Observable +class ContactsService { + static let shared = ContactsService() + + private let store = CNContactStore() + private let maxResults = 20 + private let maxScan = 5000 + + private init() {} + + // MARK: - Authorization + + var authStatus: CNAuthorizationStatus { + CNContactStore.authorizationStatus(for: .contacts) + } + + var authorized: Bool { + authStatus == .authorized + } + + var accessState: PersonalDataAccessState { + let status = authStatus + Log.mcp.debug("ContactsService.accessState -> status=\(Self.describe(status)) (raw=\(status.rawValue))") + switch status { + case .authorized: return .granted + case .notDetermined: return .notDetermined + default: return .denied + } + } + + @discardableResult + func requestAccess() async -> Bool { + let before = CNContactStore.authorizationStatus(for: .contacts) + Log.mcp.info("ContactsService.requestAccess: status before request = \(Self.describe(before)) (raw=\(before.rawValue))") + return await withCheckedContinuation { continuation in + store.requestAccess(for: .contacts) { granted, error in + let after = CNContactStore.authorizationStatus(for: .contacts) + if let error { + Log.mcp.error("ContactsService.requestAccess: error=\(error.localizedDescription); granted=\(granted); status after = \(Self.describe(after)) (raw=\(after.rawValue))") + } else { + Log.mcp.info("ContactsService.requestAccess: granted=\(granted); status after = \(Self.describe(after)) (raw=\(after.rawValue))") + } + continuation.resume(returning: granted) + } + } + } + + nonisolated static func describe(_ status: CNAuthorizationStatus) -> String { + switch status { + case .notDetermined: return "notDetermined" + case .restricted: return "restricted" + case .denied: return "denied" + case .authorized: return "authorized" + case .limited: return "limited" + @unknown default: return "unknown" + } + } + + // MARK: - Tool Schemas + + func getToolSchemas() -> [Tool] { + [ + makeTool( + name: "contacts_search", + description: "Search Contacts by name, phone number, or email address. Returns matching contacts with their phone numbers and emails. This does NOT match relationship labels like 'mother' or 'spouse' — for those, call contacts_get_me first to find the related person's name, then search for that name.", + properties: [ + "query": prop("string", "Name, phone number, or email fragment to search for") + ], + required: ["query"] + ), + makeTool( + name: "contacts_get_me", + description: "Get the user's own contact card (\"My Card\" in Contacts.app), if configured. Includes any defined relationships (e.g. mother, spouse, child) with the related person's name — use contacts_search with that name to find their phone/email.", + properties: [:], + required: [] + ) + ] + } + + // MARK: - Tool Execution + + func executeTool(name: String, arguments: String) async -> [String: Any] { + Log.mcp.info("Executing Contacts tool: \(name)") + guard authorized else { + return ["error": "Contacts permission not granted. Grant access in Settings > MCP."] + } + + switch name { + case "contacts_search": + guard let data = arguments.data(using: .utf8), + let args = try? JSONSerialization.jsonObject(with: data) as? [String: Any], + let query = args["query"] as? String, !query.isEmpty else { + return ["error": "Missing required parameter: query"] + } + return search(query: query) + + case "contacts_get_me": + return getMe() + + default: + return ["error": "Unknown Contacts tool: \(name)"] + } + } + + // MARK: - Implementation + + private let keysToFetch: [CNKeyDescriptor] = [ + CNContactGivenNameKey as CNKeyDescriptor, + CNContactFamilyNameKey as CNKeyDescriptor, + CNContactOrganizationNameKey as CNKeyDescriptor, + CNContactPhoneNumbersKey as CNKeyDescriptor, + CNContactEmailAddressesKey as CNKeyDescriptor, + CNContactRelationsKey as CNKeyDescriptor + ] + + private func search(query: String) -> [String: Any] { + var matches: [CNContact] = [] + + // Fast path: name predicate + let namePredicate = CNContact.predicateForContacts(matchingName: query) + if let nameMatches = try? store.unifiedContacts(matching: namePredicate, keysToFetch: keysToFetch) { + matches.append(contentsOf: nameMatches) + } + + // Fallback: scan for phone/email substring matches + if matches.isEmpty { + let lowerQuery = query.lowercased() + let digitsQuery = query.filter(\.isNumber) + let request = CNContactFetchRequest(keysToFetch: keysToFetch) + var scanned = 0 + try? store.enumerateContacts(with: request) { contact, stop in + scanned += 1 + if scanned > self.maxScan || matches.count >= self.maxResults { + stop.pointee = true + return + } + let emailMatch = contact.emailAddresses.contains { + ($0.value as String).lowercased().contains(lowerQuery) + } + let phoneMatch = !digitsQuery.isEmpty && contact.phoneNumbers.contains { + $0.value.stringValue.filter(\.isNumber).contains(digitsQuery) + } + if emailMatch || phoneMatch { + matches.append(contact) + } + } + } + + let deduped = dedupContacts(matches) + let formatted = deduped.prefix(maxResults).map(formatContact) + return ["count": formatted.count, "contacts": Array(formatted)] + } + + /// Collapses contacts that share a phone number or email — Contacts.app's "linked contacts" + /// merge doesn't catch every real-world duplicate card, so do a best-effort merge here too. + private func dedupContacts(_ contacts: [CNContact]) -> [CNContact] { + var result: [CNContact] = [] + outer: for contact in contacts { + let phones = Set(contact.phoneNumbers.map { $0.value.stringValue.filter(\.isNumber) }) + let emails = Set(contact.emailAddresses.map { ($0.value as String).lowercased() }) + for existing in result { + let existingPhones = Set(existing.phoneNumbers.map { $0.value.stringValue.filter(\.isNumber) }) + let existingEmails = Set(existing.emailAddresses.map { ($0.value as String).lowercased() }) + if !phones.isDisjoint(with: existingPhones) || !emails.isDisjoint(with: existingEmails) { + continue outer + } + } + result.append(contact) + } + return result + } + + private func getMe() -> [String: Any] { + guard let me = try? store.unifiedMeContactWithKeys(toFetch: keysToFetch) else { + return ["error": "No 'My Card' is configured in Contacts.app"] + } + return formatContact(me) + } + + private func formatContact(_ contact: CNContact) -> [String: Any] { + var item: [String: Any] = [ + "given_name": contact.givenName, + "family_name": contact.familyName + ] + if !contact.organizationName.isEmpty { + item["organization"] = contact.organizationName + } + if !contact.phoneNumbers.isEmpty { + item["phones"] = contact.phoneNumbers.map { $0.value.stringValue } + } + if !contact.emailAddresses.isEmpty { + item["emails"] = contact.emailAddresses.map { $0.value as String } + } + if !contact.contactRelations.isEmpty { + item["relations"] = contact.contactRelations.map { labeled -> [String: String] in + let label = labeled.label.map { CNLabeledValue.localizedString(forLabel: $0) } ?? "relation" + return ["label": label, "name": labeled.value.name] + } + } + return item + } + + private func makeTool(name: String, description: String, properties: [String: Tool.Function.Parameters.Property], required: [String]) -> Tool { + Tool( + type: "function", + function: Tool.Function( + name: name, + description: description, + parameters: Tool.Function.Parameters( + type: "object", + properties: properties, + required: required + ) + ) + ) + } + + private func prop(_ type: String, _ description: String) -> Tool.Function.Parameters.Property { + Tool.Function.Parameters.Property(type: type, description: description, enum: nil) + } +} diff --git a/oAI/Services/EventKitService.swift b/oAI/Services/EventKitService.swift new file mode 100644 index 0000000..7a4bb62 --- /dev/null +++ b/oAI/Services/EventKitService.swift @@ -0,0 +1,593 @@ +// +// EventKitService.swift +// oAI +// +// Calendar and Reminders integration via EventKit +// +// SPDX-License-Identifier: AGPL-3.0-or-later +// Copyright (C) 2026 Rune Olsen +// +// This file is part of oAI. +// +// oAI is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// oAI is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General +// Public License for more details. +// +// You should have received a copy of the GNU Affero General Public +// License along with oAI. If not, see . + + +import EventKit +import Foundation +import os + +/// Shared tri-state authorization status for the Settings UI across all Personal Data services. +/// `.denied` also covers `.restricted` and (for Calendar) `.writeOnly` — states where the OS +/// will not show a request dialog again; the user must go to System Settings manually. +enum PersonalDataAccessState { + case notDetermined + case denied + case granted +} + +@Observable +class EventKitService { + static let shared = EventKitService() + + private let store = EKEventStore() + + private init() {} + + // MARK: - Authorization + + var calendarAuthStatus: EKAuthorizationStatus { + let status = EKEventStore.authorizationStatus(for: .event) + Log.mcp.debug("EventKitService.calendarAuthStatus -> \(Self.describe(status)) (raw=\(status.rawValue))") + return status + } + + var reminderAuthStatus: EKAuthorizationStatus { + let status = EKEventStore.authorizationStatus(for: .reminder) + Log.mcp.debug("EventKitService.reminderAuthStatus -> \(Self.describe(status)) (raw=\(status.rawValue))") + return status + } + + var calendarAuthorized: Bool { + calendarAuthStatus == .fullAccess + } + + var reminderAuthorized: Bool { + reminderAuthStatus == .fullAccess + } + + var calendarAccessState: PersonalDataAccessState { + switch calendarAuthStatus { + case .fullAccess: return .granted + case .notDetermined: return .notDetermined + default: return .denied // .denied, .restricted, .writeOnly (no read access for our tools) + } + } + + var reminderAccessState: PersonalDataAccessState { + switch reminderAuthStatus { + case .fullAccess: return .granted + case .notDetermined: return .notDetermined + default: return .denied + } + } + + @discardableResult + func requestCalendarAccess() async -> Bool { + let before = EKEventStore.authorizationStatus(for: .event) + Log.mcp.info("requestCalendarAccess: status before request = \(Self.describe(before)) (raw=\(before.rawValue))") + do { + let granted = try await store.requestFullAccessToEvents() + let after = EKEventStore.authorizationStatus(for: .event) + Log.mcp.info("requestCalendarAccess: API returned granted=\(granted); status after request = \(Self.describe(after)) (raw=\(after.rawValue))") + return granted + } catch { + let after = EKEventStore.authorizationStatus(for: .event) + Log.mcp.error("requestCalendarAccess: threw error: \(error.localizedDescription); status after = \(Self.describe(after)) (raw=\(after.rawValue))") + return false + } + } + + @discardableResult + func requestReminderAccess() async -> Bool { + let before = EKEventStore.authorizationStatus(for: .reminder) + Log.mcp.info("requestReminderAccess: status before request = \(Self.describe(before)) (raw=\(before.rawValue))") + do { + let granted = try await store.requestFullAccessToReminders() + let after = EKEventStore.authorizationStatus(for: .reminder) + Log.mcp.info("requestReminderAccess: API returned granted=\(granted); status after request = \(Self.describe(after)) (raw=\(after.rawValue))") + return granted + } catch { + let after = EKEventStore.authorizationStatus(for: .reminder) + Log.mcp.error("requestReminderAccess: threw error: \(error.localizedDescription); status after = \(Self.describe(after)) (raw=\(after.rawValue))") + return false + } + } + + nonisolated static func describe(_ status: EKAuthorizationStatus) -> String { + switch status { + case .notDetermined: return "notDetermined" + case .restricted: return "restricted" + case .denied: return "denied" + case .fullAccess: return "fullAccess" + case .writeOnly: return "writeOnly" + @unknown default: return "unknown" + } + } + + // MARK: - Tool Schemas + + func getToolSchemas(calendarEnabled: Bool, remindersEnabled: Bool) -> [Tool] { + var tools: [Tool] = [] + + if calendarEnabled { + tools.append(makeTool( + name: "calendar_list_calendars", + description: "List all calendars available on this Mac (e.g. iCloud, Work, Home).", + properties: [:], + required: [] + )) + tools.append(makeTool( + name: "calendar_list_events", + description: "List calendar events within a date range. Dates are ISO8601 (e.g. '2026-06-20T00:00:00' or '2026-06-20'). Range is limited to 1 year. For open-ended queries like 'next appointment' or 'upcoming events', do NOT limit the range to just today — use a generous forward-looking window (e.g. today through +90 days) so you don't miss events further out.", + properties: [ + "start_date": prop("string", "Start of the date range (ISO8601)"), + "end_date": prop("string", "End of the date range (ISO8601)"), + "calendar_name": prop("string", "Optional: only list events from this calendar") + ], + required: ["start_date", "end_date"] + )) + tools.append(makeTool( + name: "calendar_create_event", + description: "Create a new calendar event. Requires user approval before it is actually created.", + properties: [ + "title": prop("string", "Event title"), + "start_date": prop("string", "Start date/time (ISO8601, e.g. '2026-06-20T14:00:00')"), + "end_date": prop("string", "End date/time (ISO8601)"), + "calendar_name": prop("string", "Optional: calendar to add the event to (defaults to the system default calendar)"), + "location": prop("string", "Optional: event location text"), + "notes": prop("string", "Optional: event notes"), + "all_day": prop("boolean", "Optional: whether this is an all-day event (default: false)"), + "alarm_minutes_before": prop("number", "Optional: minutes before the start time to show an alert") + ], + required: ["title", "start_date", "end_date"] + )) + } + + if remindersEnabled { + tools.append(makeTool( + name: "reminders_list_lists", + description: "List all reminder lists available on this Mac.", + properties: [:], + required: [] + )) + tools.append(makeTool( + name: "reminders_list", + description: "List reminders. Omit list_name to search across ALL reminder lists in a single call — prefer this over calling once per list. Incomplete reminders only unless include_completed is true.", + properties: [ + "list_name": prop("string", "Optional: only list reminders from this one list (omit to search all lists at once)"), + "include_completed": prop("boolean", "Optional: include completed reminders (default: false)") + ], + required: [] + )) + tools.append(makeTool( + name: "reminders_create", + description: "Create a new reminder. Requires user approval before it is actually created.", + properties: [ + "title": prop("string", "Reminder title"), + "list_name": prop("string", "Optional: reminder list to add to (defaults to the system default list)"), + "due_date": prop("string", "Optional: due date/time (ISO8601)"), + "priority": prop("string", "Optional: priority level", enumValues: ["none", "low", "medium", "high"]), + "notes": prop("string", "Optional: reminder notes") + ], + required: ["title"] + )) + tools.append(makeTool( + name: "reminders_complete", + description: "Mark a reminder as completed. Requires user approval. Use reminders_list to find the reminder_id first.", + properties: [ + "reminder_id": prop("string", "The reminder's identifier, from reminders_list") + ], + required: ["reminder_id"] + )) + } + + return tools + } + + // MARK: - Read Tool Execution + + func executeTool(name: String, arguments: String) async -> [String: Any] { + Log.mcp.info("Executing EventKit tool: \(name)") + let args = Self.parseArgs(arguments) + + switch name { + case "calendar_list_calendars": + guard calendarAuthorized else { return Self.permissionError(domain: "Calendar") } + return listCalendars() + + case "calendar_list_events": + guard calendarAuthorized else { return Self.permissionError(domain: "Calendar") } + guard let startStr = args["start_date"] as? String, let start = Self.parseDate(startStr) else { + return ["error": "Missing or invalid parameter: start_date"] + } + guard let endStr = args["end_date"] as? String, let end = Self.parseDate(endStr) else { + return ["error": "Missing or invalid parameter: end_date"] + } + let calendarName = args["calendar_name"] as? String + return listEvents(start: start, end: end, calendarName: calendarName) + + case "reminders_list_lists": + guard reminderAuthorized else { return Self.permissionError(domain: "Reminders") } + return listReminderLists() + + case "reminders_list": + guard reminderAuthorized else { return Self.permissionError(domain: "Reminders") } + let listName = args["list_name"] as? String + let includeCompleted = args["include_completed"] as? Bool ?? false + return await listReminders(listName: listName, includeCompleted: includeCompleted) + + default: + return ["error": "Unknown EventKit tool: \(name)"] + } + } + + // MARK: - Write Tool Execution (called only after approval) + + func executeWriteTool(name: String, arguments: String) async -> [String: Any] { + Log.mcp.info("Executing EventKit write tool: \(name)") + let args = Self.parseArgs(arguments) + + switch name { + case "calendar_create_event": + guard calendarAuthorized else { return Self.permissionError(domain: "Calendar") } + return createEvent(args: args) + + case "reminders_create": + guard reminderAuthorized else { return Self.permissionError(domain: "Reminders") } + return createReminder(args: args) + + case "reminders_complete": + guard reminderAuthorized else { return Self.permissionError(domain: "Reminders") } + guard let reminderId = args["reminder_id"] as? String else { + return ["error": "Missing required parameter: reminder_id"] + } + return completeReminder(reminderId: reminderId) + + default: + return ["error": "Unknown EventKit write tool: \(name)"] + } + } + + // MARK: - Approval Summary + + /// Human-readable description shown in the approval sheet before a write tool runs. + func approvalSummary(forTool name: String, arguments: String) -> String { + let args = Self.parseArgs(arguments) + switch name { + case "calendar_create_event": + let title = args["title"] as? String ?? "Untitled event" + let start = (args["start_date"] as? String).flatMap(Self.parseDate) ?? Date() + let end = (args["end_date"] as? String).flatMap(Self.parseDate) ?? start + return "Create calendar event \"\(title)\" from \(Self.displayFormatter.string(from: start)) to \(Self.displayFormatter.string(from: end))" + case "reminders_create": + let title = args["title"] as? String ?? "Untitled reminder" + if let dueStr = args["due_date"] as? String, let due = Self.parseDate(dueStr) { + return "Create reminder \"\(title)\" due \(Self.displayFormatter.string(from: due))" + } + return "Create reminder \"\(title)\"" + case "reminders_complete": + return "Mark reminder as completed" + default: + return "Perform action: \(name)" + } + } + + // MARK: - Calendar Read Implementations + + private func listCalendars() -> [String: Any] { + let calendars = store.calendars(for: .event).map { cal -> [String: Any] in + [ + "name": cal.title, + "type": calendarTypeDescription(cal), + "allows_modifications": cal.allowsContentModifications + ] + } + return ["calendars": calendars] + } + + private func listEvents(start: Date, end: Date, calendarName: String?) -> [String: Any] { + guard end > start else { return ["error": "end_date must be after start_date"] } + guard end.timeIntervalSince(start) <= 366 * 24 * 60 * 60 else { + return ["error": "Date range too large — limit to 1 year or less"] + } + + var calendars = store.calendars(for: .event) + if let calendarName { + calendars = calendars.filter { $0.title.caseInsensitiveCompare(calendarName) == .orderedSame } + if calendars.isEmpty { + return ["error": "No calendar found named '\(calendarName)'"] + } + } + + let predicate = store.predicateForEvents(withStart: start, end: end, calendars: calendars) + let events = store.events(matching: predicate) + .sorted { $0.startDate < $1.startDate } + .prefix(200) + .map { event -> [String: Any] in + var item: [String: Any] = [ + "id": event.eventIdentifier ?? "", + "title": event.title ?? "Untitled", + "start": Self.isoFormatter.string(from: event.startDate), + "end": Self.isoFormatter.string(from: event.endDate), + "all_day": event.isAllDay, + "calendar": event.calendar?.title ?? "" + ] + if let location = event.location, !location.isEmpty { + item["location"] = location + } + if let notes = event.notes, !notes.isEmpty { + item["notes"] = String(notes.prefix(500)) + } + return item + } + + return ["count": events.count, "events": Array(events)] + } + + private func createEvent(args: [String: Any]) -> [String: Any] { + guard let title = args["title"] as? String, !title.isEmpty else { + return ["error": "Missing required parameter: title"] + } + guard let startStr = args["start_date"] as? String, let start = Self.parseDate(startStr) else { + return ["error": "Missing or invalid parameter: start_date"] + } + guard let endStr = args["end_date"] as? String, let end = Self.parseDate(endStr) else { + return ["error": "Missing or invalid parameter: end_date"] + } + guard end >= start else { + return ["error": "end_date must not be before start_date"] + } + + let event = EKEvent(eventStore: store) + event.title = title + event.startDate = start + event.endDate = end + event.isAllDay = args["all_day"] as? Bool ?? false + + if let calendarName = args["calendar_name"] as? String, + let calendar = store.calendars(for: .event).first(where: { $0.title.caseInsensitiveCompare(calendarName) == .orderedSame }) { + event.calendar = calendar + } else if let defaultCalendar = store.defaultCalendarForNewEvents { + event.calendar = defaultCalendar + } else { + guard let fallback = store.calendars(for: .event).first(where: { $0.allowsContentModifications }) else { + return ["error": "No writable calendar available"] + } + event.calendar = fallback + } + + if let location = args["location"] as? String { event.location = location } + if let notes = args["notes"] as? String { event.notes = notes } + if let minutesBefore = (args["alarm_minutes_before"] as? Double) ?? (args["alarm_minutes_before"] as? Int).map(Double.init) { + event.addAlarm(EKAlarm(relativeOffset: -(minutesBefore * 60))) + } + + do { + try store.save(event, span: .thisEvent, commit: true) + return ["success": true, "event_id": event.eventIdentifier ?? "", "calendar": event.calendar?.title ?? ""] + } catch { + Log.mcp.error("calendar_create_event failed: \(error.localizedDescription)") + return ["error": "Failed to create event: \(error.localizedDescription)"] + } + } + + // MARK: - Reminders Read Implementations + + private func listReminderLists() -> [String: Any] { + let lists = store.calendars(for: .reminder).map { cal -> [String: Any] in + ["name": cal.title, "allows_modifications": cal.allowsContentModifications] + } + return ["lists": lists] + } + + private func listReminders(listName: String?, includeCompleted: Bool) async -> [String: Any] { + var lists = store.calendars(for: .reminder) + if let listName { + lists = lists.filter { $0.title.caseInsensitiveCompare(listName) == .orderedSame } + if lists.isEmpty { + return ["error": "No reminder list found named '\(listName)'"] + } + } + + let predicate = store.predicateForReminders(in: lists) + let reminders: [EKReminder] = await withCheckedContinuation { continuation in + store.fetchReminders(matching: predicate) { results in + continuation.resume(returning: results ?? []) + } + } + + let filtered = reminders + .filter { includeCompleted || !$0.isCompleted } + .sorted { lhs, rhs in + let l = lhs.dueDateComponents?.date ?? .distantFuture + let r = rhs.dueDateComponents?.date ?? .distantFuture + return l < r + } + .prefix(200) + .map { reminder -> [String: Any] in + var item: [String: Any] = [ + "id": reminder.calendarItemIdentifier, + "title": reminder.title ?? "Untitled", + "completed": reminder.isCompleted, + "list": reminder.calendar?.title ?? "" + ] + if let due = reminder.dueDateComponents?.date { + item["due"] = Self.isoFormatter.string(from: due) + } + if reminder.priority > 0 { + item["priority"] = priorityDescription(reminder.priority) + } + if let notes = reminder.notes, !notes.isEmpty { + item["notes"] = String(notes.prefix(500)) + } + return item + } + + return ["count": filtered.count, "reminders": Array(filtered)] + } + + private func createReminder(args: [String: Any]) -> [String: Any] { + guard let title = args["title"] as? String, !title.isEmpty else { + return ["error": "Missing required parameter: title"] + } + + let reminder = EKReminder(eventStore: store) + reminder.title = title + + if let listName = args["list_name"] as? String, + let list = store.calendars(for: .reminder).first(where: { $0.title.caseInsensitiveCompare(listName) == .orderedSame }) { + reminder.calendar = list + } else if let defaultList = store.defaultCalendarForNewReminders() { + reminder.calendar = defaultList + } else { + guard let fallback = store.calendars(for: .reminder).first(where: { $0.allowsContentModifications }) else { + return ["error": "No writable reminder list available"] + } + reminder.calendar = fallback + } + + if let dueStr = args["due_date"] as? String, let due = Self.parseDate(dueStr) { + reminder.dueDateComponents = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute, .second], from: due) + } + if let notes = args["notes"] as? String { reminder.notes = notes } + if let priority = args["priority"] as? String { reminder.priority = priorityValue(priority) } + + do { + try store.save(reminder, commit: true) + return ["success": true, "reminder_id": reminder.calendarItemIdentifier, "list": reminder.calendar?.title ?? ""] + } catch { + Log.mcp.error("reminders_create failed: \(error.localizedDescription)") + return ["error": "Failed to create reminder: \(error.localizedDescription)"] + } + } + + private func completeReminder(reminderId: String) -> [String: Any] { + guard let item = store.calendarItem(withIdentifier: reminderId) as? EKReminder else { + return ["error": "No reminder found with id '\(reminderId)'"] + } + item.isCompleted = true + item.completionDate = Date() + + do { + try store.save(item, commit: true) + return ["success": true, "reminder_id": reminderId, "title": item.title ?? ""] + } catch { + Log.mcp.error("reminders_complete failed: \(error.localizedDescription)") + return ["error": "Failed to complete reminder: \(error.localizedDescription)"] + } + } + + // MARK: - Helpers + + private func calendarTypeDescription(_ cal: EKCalendar) -> String { + switch cal.type { + case .local: return "local" + case .calDAV: return "caldav" + case .exchange: return "exchange" + case .subscription: return "subscription" + case .birthday: return "birthday" + @unknown default: return "unknown" + } + } + + private func priorityDescription(_ value: Int) -> String { + switch value { + case 1...4: return "high" + case 5: return "medium" + case 6...9: return "low" + default: return "none" + } + } + + private func priorityValue(_ description: String) -> Int { + switch description.lowercased() { + case "high": return 1 + case "medium": return 5 + case "low": return 9 + default: return 0 + } + } + + private func makeTool(name: String, description: String, properties: [String: Tool.Function.Parameters.Property], required: [String]) -> Tool { + Tool( + type: "function", + function: Tool.Function( + name: name, + description: description, + parameters: Tool.Function.Parameters( + type: "object", + properties: properties, + required: required + ) + ) + ) + } + + private func prop(_ type: String, _ description: String, enumValues: [String]? = nil) -> Tool.Function.Parameters.Property { + Tool.Function.Parameters.Property(type: type, description: description, enum: enumValues) + } + + nonisolated static func parseArgs(_ arguments: String) -> [String: Any] { + guard let data = arguments.data(using: .utf8), + let dict = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { + return [:] + } + return dict + } + + nonisolated static func permissionError(domain: String) -> [String: Any] { + ["error": "\(domain) permission not granted. Grant access in Settings > MCP."] + } + + nonisolated(unsafe) static let isoFormatter: ISO8601DateFormatter = { + let f = ISO8601DateFormatter() + f.formatOptions = [.withInternetDateTime] + return f + }() + + nonisolated static let displayFormatter: DateFormatter = { + let f = DateFormatter() + f.dateStyle = .medium + f.timeStyle = .short + return f + }() + + nonisolated static func parseDate(_ string: String) -> Date? { + if let date = isoFormatter.date(from: string) { return date } + + let isoNoTimezone = ISO8601DateFormatter() + isoNoTimezone.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + if let date = isoNoTimezone.date(from: string) { return date } + + let localDateTime = DateFormatter() + localDateTime.dateFormat = "yyyy-MM-dd'T'HH:mm:ss" + if let date = localDateTime.date(from: string) { return date } + + let dateOnly = DateFormatter() + dateOnly.dateFormat = "yyyy-MM-dd" + if let date = dateOnly.date(from: string) { return date } + + return nil + } +} diff --git a/oAI/Services/LocationMapsService.swift b/oAI/Services/LocationMapsService.swift new file mode 100644 index 0000000..7bab13b --- /dev/null +++ b/oAI/Services/LocationMapsService.swift @@ -0,0 +1,343 @@ +// +// LocationMapsService.swift +// oAI +// +// Read-only Location and Maps integration via CoreLocation and MapKit +// +// SPDX-License-Identifier: AGPL-3.0-or-later +// Copyright (C) 2026 Rune Olsen +// +// This file is part of oAI. +// +// oAI is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// oAI is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General +// Public License for more details. +// +// You should have received a copy of the GNU Affero General Public +// License along with oAI. If not, see . + + +import CoreLocation +import Foundation +import MapKit +import os + +@Observable +class LocationMapsService: NSObject, CLLocationManagerDelegate { + static let shared = LocationMapsService() + + private let locationManager = CLLocationManager() + + private var authContinuation: CheckedContinuation? + private var locationContinuation: CheckedContinuation? + + private override init() { + super.init() + locationManager.delegate = self + } + + // MARK: - Authorization + + var authStatus: CLAuthorizationStatus { + locationManager.authorizationStatus + } + + var authorized: Bool { + authStatus == .authorizedAlways || authStatus == .authorized + } + + var accessState: PersonalDataAccessState { + let status = authStatus + Log.mcp.debug("LocationMapsService.accessState -> status=\(Self.describe(status)) (raw=\(status.rawValue))") + switch status { + case .authorizedAlways, .authorized: return .granted + case .notDetermined: return .notDetermined + default: return .denied + } + } + + @discardableResult + func requestAccess() async -> Bool { + let before = locationManager.authorizationStatus + Log.mcp.info("LocationMapsService.requestAccess: status before = \(Self.describe(before)) (raw=\(before.rawValue))") + if before != .notDetermined { + Log.mcp.info("LocationMapsService.requestAccess: skipping OS prompt (not notDetermined)") + return authorized + } + return await withCheckedContinuation { continuation in + self.authContinuation = continuation + locationManager.requestWhenInUseAuthorization() + } + } + + func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { + let status = manager.authorizationStatus + Log.mcp.info("LocationMapsService: authorization changed -> \(Self.describe(status)) (raw=\(status.rawValue))") + authContinuation?.resume(returning: authorized) + authContinuation = nil + } + + nonisolated static func describe(_ status: CLAuthorizationStatus) -> String { + switch status { + case .notDetermined: return "notDetermined" + case .restricted: return "restricted" + case .denied: return "denied" + case .authorizedAlways: return "authorizedAlways" + case .authorized: return "authorized" + @unknown default: return "unknown" + } + } + + func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { + locationContinuation?.resume(returning: locations.last) + locationContinuation = nil + } + + func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { + Log.mcp.error("Location request failed: \(error.localizedDescription)") + locationContinuation?.resume(returning: nil) + locationContinuation = nil + } + + private func currentLocation() async -> CLLocation? { + await withCheckedContinuation { continuation in + self.locationContinuation = continuation + locationManager.requestLocation() + } + } + + // MARK: - Tool Schemas + + func getToolSchemas() -> [Tool] { + [ + makeTool( + name: "location_get_current", + description: "Get the device's current location, including a human-readable address.", + properties: [:], + required: [] + ), + makeTool( + name: "maps_search_places", + description: "Search for places (businesses, landmarks, addresses) by name or category.", + properties: [ + "query": prop("string", "What to search for, e.g. 'coffee shops' or 'Eiffel Tower'"), + "near": prop("string", "Optional: an address or 'latitude,longitude' to search near") + ], + required: ["query"] + ), + makeTool( + name: "maps_geocode", + description: "Convert an address into geographic coordinates and a formatted address.", + properties: [ + "address": prop("string", "The address to geocode") + ], + required: ["address"] + ), + makeTool( + name: "maps_get_directions", + description: "Get distance and estimated travel time between two locations.", + properties: [ + "origin": prop("string", "Starting address or 'latitude,longitude'"), + "destination": prop("string", "Destination address or 'latitude,longitude'"), + "transport_type": prop("string", "Mode of transport", enumValues: ["driving", "walking", "transit"]) + ], + required: ["origin", "destination"] + ) + ] + } + + // MARK: - Tool Execution + + func executeTool(name: String, arguments: String) async -> [String: Any] { + Log.mcp.info("Executing LocationMaps tool: \(name)") + let args = parseArgs(arguments) + + switch name { + case "location_get_current": + guard authorized else { return ["error": "Location permission not granted. Grant access in Settings > MCP."] } + return await getCurrentLocation() + + case "maps_search_places": + guard let query = args["query"] as? String, !query.isEmpty else { + return ["error": "Missing required parameter: query"] + } + let near = args["near"] as? String + return await searchPlaces(query: query, near: near) + + case "maps_geocode": + guard let address = args["address"] as? String, !address.isEmpty else { + return ["error": "Missing required parameter: address"] + } + return await geocode(address: address) + + case "maps_get_directions": + guard let origin = args["origin"] as? String, let destination = args["destination"] as? String else { + return ["error": "Missing required parameter: origin and/or destination"] + } + let transportType = args["transport_type"] as? String ?? "driving" + return await getDirections(origin: origin, destination: destination, transportType: transportType) + + default: + return ["error": "Unknown LocationMaps tool: \(name)"] + } + } + + // MARK: - Implementations + + private func getCurrentLocation() async -> [String: Any] { + guard let location = await currentLocation() else { + return ["error": "Could not determine current location"] + } + var result: [String: Any] = [ + "latitude": location.coordinate.latitude, + "longitude": location.coordinate.longitude + ] + if let mapItem = await reverseGeocode(location), let address = addressString(for: mapItem) { + result["address"] = address + } + return result + } + + private func searchPlaces(query: String, near: String?) async -> [String: Any] { + let request = MKLocalSearch.Request() + request.naturalLanguageQuery = query + if let near, let coordinate = await coordinate(for: near) { + request.region = MKCoordinateRegion(center: coordinate, latitudinalMeters: 20_000, longitudinalMeters: 20_000) + } + + do { + let response = try await MKLocalSearch(request: request).start() + let places = response.mapItems.prefix(15).map { item -> [String: Any] in + var place: [String: Any] = ["name": item.name ?? "Unknown"] + place["latitude"] = item.location.coordinate.latitude + place["longitude"] = item.location.coordinate.longitude + if let address = addressString(for: item) { + place["address"] = address + } + if let phone = item.phoneNumber { place["phone"] = phone } + return place + } + return ["count": places.count, "places": Array(places)] + } catch { + return ["error": "Search failed: \(error.localizedDescription)"] + } + } + + private func geocode(address: String) async -> [String: Any] { + guard let request = MKGeocodingRequest(addressString: address) else { + return ["error": "Invalid address: \(address)"] + } + do { + guard let mapItem = try await request.mapItems.first else { + return ["error": "No results found for address: \(address)"] + } + var result: [String: Any] = [ + "latitude": mapItem.location.coordinate.latitude, + "longitude": mapItem.location.coordinate.longitude + ] + if let formatted = addressString(for: mapItem) { + result["formatted_address"] = formatted + } + return result + } catch { + return ["error": "Geocoding failed: \(error.localizedDescription)"] + } + } + + private func getDirections(origin: String, destination: String, transportType: String) async -> [String: Any] { + guard let originCoordinate = await coordinate(for: origin) else { + return ["error": "Could not resolve origin: \(origin)"] + } + guard let destinationCoordinate = await coordinate(for: destination) else { + return ["error": "Could not resolve destination: \(destination)"] + } + + let request = MKDirections.Request() + request.source = MKMapItem(location: CLLocation(latitude: originCoordinate.latitude, longitude: originCoordinate.longitude), address: nil) + request.destination = MKMapItem(location: CLLocation(latitude: destinationCoordinate.latitude, longitude: destinationCoordinate.longitude), address: nil) + switch transportType { + case "walking": request.transportType = .walking + case "transit": request.transportType = .transit + default: request.transportType = .automobile + } + + do { + let response = try await MKDirections(request: request).calculate() + guard let route = response.routes.first else { + return ["error": "No route found"] + } + let distanceFormatter = MKDistanceFormatter() + let durationFormatter = DateComponentsFormatter() + durationFormatter.allowedUnits = [.hour, .minute] + durationFormatter.unitsStyle = .short + + return [ + "distance_meters": route.distance, + "distance_text": distanceFormatter.string(fromDistance: route.distance), + "duration_seconds": route.expectedTravelTime, + "duration_text": durationFormatter.string(from: route.expectedTravelTime) ?? "", + "transport_type": transportType + ] + } catch { + return ["error": "Directions failed: \(error.localizedDescription)"] + } + } + + // MARK: - Helpers + + private func coordinate(for text: String) async -> CLLocationCoordinate2D? { + let parts = text.split(separator: ",").map { $0.trimmingCharacters(in: .whitespaces) } + if parts.count == 2, let lat = Double(parts[0]), let lon = Double(parts[1]) { + return CLLocationCoordinate2D(latitude: lat, longitude: lon) + } + guard let request = MKGeocodingRequest(addressString: text) else { return nil } + if let mapItems = try? await request.mapItems, let mapItem = mapItems.first { + return mapItem.location.coordinate + } + return nil + } + + private func reverseGeocode(_ location: CLLocation) async -> MKMapItem? { + guard let request = MKReverseGeocodingRequest(location: location) else { return nil } + let mapItems = try? await request.mapItems + return mapItems?.first + } + + private func addressString(for mapItem: MKMapItem) -> String? { + mapItem.address?.fullAddress + ?? mapItem.addressRepresentations?.fullAddress(includingRegion: true, singleLine: true) + } + + private func parseArgs(_ arguments: String) -> [String: Any] { + guard let data = arguments.data(using: .utf8), + let dict = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { + return [:] + } + return dict + } + + private func makeTool(name: String, description: String, properties: [String: Tool.Function.Parameters.Property], required: [String]) -> Tool { + Tool( + type: "function", + function: Tool.Function( + name: name, + description: description, + parameters: Tool.Function.Parameters( + type: "object", + properties: properties, + required: required + ) + ) + ) + } + + private func prop(_ type: String, _ description: String, enumValues: [String]? = nil) -> Tool.Function.Parameters.Property { + Tool.Function.Parameters.Property(type: type, description: description, enum: enumValues) + } +} diff --git a/oAI/Services/MCPService.swift b/oAI/Services/MCPService.swift index 0e9c9ee..ef8b964 100644 --- a/oAI/Services/MCPService.swift +++ b/oAI/Services/MCPService.swift @@ -111,6 +111,9 @@ class MCPService { private let anytypeService = AnytypeMCPService.shared private let paperlessService = PaperlessService.shared + private let eventKitService = EventKitService.shared + private let contactsService = ContactsService.shared + private let locationMapsService = LocationMapsService.shared // MARK: - Bash Approval State @@ -124,6 +127,19 @@ class MCPService { private var pendingBashContinuation: CheckedContinuation<[String: Any], Never>? = nil private(set) var bashSessionApproved: Bool = false + // MARK: - Personal Data (Calendar/Reminders) Approval State + + struct PendingPersonalDataAction: Identifiable { + let id = UUID() + let toolName: String + let argumentsJSON: String + let summary: String + } + + private(set) var pendingPersonalDataAction: PendingPersonalDataAction? = nil + private var pendingPersonalDataContinuation: CheckedContinuation<[String: Any], Never>? = nil + private(set) var personalDataSessionApproved: Bool = false + // MARK: - Tool Schema Generation func getToolSchemas(onlineMode: Bool = false) -> [Tool] { @@ -232,6 +248,24 @@ class MCPService { tools.append(contentsOf: paperlessService.getToolSchemas()) } + // Add Calendar/Reminders tools if enabled + if settings.calendarEnabled || settings.remindersEnabled { + tools.append(contentsOf: eventKitService.getToolSchemas( + calendarEnabled: settings.calendarEnabled, + remindersEnabled: settings.remindersEnabled + )) + } + + // Add Contacts tools if enabled + if settings.contactsEnabled { + tools.append(contentsOf: contactsService.getToolSchemas()) + } + + // Add Location/Maps tools if enabled + if settings.locationMapsEnabled { + tools.append(contentsOf: locationMapsService.getToolSchemas()) + } + // Add bash_execute tool when bash is enabled if settings.bashEnabled { let workDir = settings.bashWorkingDirectory @@ -260,6 +294,22 @@ class MCPService { )) } + // Add spawn_research_agents when Research Agents are enabled + if settings.agentsEnabled { + tools.append(makeTool( + name: "spawn_research_agents", + description: "Spawn multiple READ-ONLY research sub-agents that investigate independent questions IN PARALLEL. Each sub-agent gets its own read_file/list_directory/search_files/web_search loop — no write, no bash, no nesting (sub-agents cannot call this tool). ONLY use this when you have 2 or more genuinely independent research questions that benefit from running at the same time (e.g. comparing several unrelated files, topics, or sources). Do NOT use this for a single lookup, a sequential task, or anything answerable with one direct tool call — call read_file/search_files/web_search yourself instead. Each sub-agent is its own full chain of model calls and meaningfully increases cost and latency; using this for trivial tasks is wasteful. Prefer the smallest number of tasks that actually need to run in parallel.", + properties: [ + "tasks": Tool.Function.Parameters.Property( + type: "array", + description: "List of independent, self-contained research questions — one per sub-agent. Keep this list as short as the task genuinely requires.", + items: .init(type: "string") + ) + ], + required: ["tasks"] + )) + } + return tools } @@ -284,7 +334,10 @@ class MCPService { // MARK: - Tool Execution - func executeTool(name: String, arguments: String) async -> [String: Any] { + /// `agentProvider`/`agentModelId` are only needed for `spawn_research_agents`, which drives + /// its own model calls — every other tool ignores them. Passed in by the caller's active + /// chat session rather than stored on MCPService, since this service has no provider state. + func executeTool(name: String, arguments: String, agentProvider: AIProvider? = nil, agentModelId: String? = nil) async -> [String: Any] { Log.mcp.info("Executing tool: \(name)") guard let argData = arguments.data(using: .utf8), let args = try? JSONSerialization.jsonObject(with: argData) as? [String: Any] else { @@ -399,6 +452,25 @@ class MCPService { let mapped = results.map { ["title": $0.title, "url": $0.url, "snippet": $0.snippet] } return ["results": mapped] + case "spawn_research_agents": + guard settings.agentsEnabled else { + return ["error": "Research agents are disabled. Enable 'Research Agents' in Settings > MCP."] + } + guard let agentProvider, let agentModelId else { + return ["error": "Internal error: missing model context for spawn_research_agents"] + } + guard let tasks = args["tasks"] as? [String], !tasks.isEmpty else { + return ["error": "Missing required parameter: tasks (non-empty array of strings)"] + } + return await runResearchAgents(tasks: tasks, provider: agentProvider, modelId: agentModelId) + + case "calendar_create_event", "reminders_create", "reminders_complete": + guard settings.calendarEnabled || settings.remindersEnabled else { + return ["error": "Calendar/Reminders access is disabled. Enable it in Settings > MCP."] + } + let summary = eventKitService.approvalSummary(forTool: name, arguments: arguments) + return await executePersonalDataAction(toolName: name, argumentsJSON: arguments, summary: summary) + default: // Route anytype_* tools to AnytypeMCPService if name.hasPrefix("anytype_") { @@ -408,6 +480,18 @@ class MCPService { if name.hasPrefix("paperless_") { return await paperlessService.executeTool(name: name, arguments: arguments) } + // Route calendar_*/reminders_* read tools to EventKitService + if name.hasPrefix("calendar_") || name.hasPrefix("reminders_") { + return await eventKitService.executeTool(name: name, arguments: arguments) + } + // Route contacts_* tools to ContactsService + if name.hasPrefix("contacts_") { + return await contactsService.executeTool(name: name, arguments: arguments) + } + // Route location_*/maps_* tools to LocationMapsService + if name.hasPrefix("location_") || name.hasPrefix("maps_") { + return await locationMapsService.executeTool(name: name, arguments: arguments) + } return ["error": "Unknown tool: \(name)"] } } @@ -754,6 +838,11 @@ class MCPService { if bashSessionApproved { return await runBashCommand(command, workingDirectory: workingDirectory) } + // 2nd Brain calls its helper script via bash_execute — let the user mark that + // specific traffic as always-trusted instead of approving it every time. + if isTrustedSecondBrainCommand(command) { + return await runBashCommand(command, workingDirectory: workingDirectory) + } return await withCheckedContinuation { continuation in DispatchQueue.main.async { self.pendingBashCommand = PendingBashCommand(command: command, workingDirectory: workingDirectory) @@ -786,6 +875,190 @@ class MCPService { bashSessionApproved = false } + private func isTrustedSecondBrainCommand(_ command: String) -> Bool { + guard settings.trustSecondBrainSkill, command.contains(".brain_helper.py") else { return false } + return settings.agentSkills.contains { $0.isActive && $0.isSecondBrainSkill } + } + + // MARK: - Research Agents (read-only, parallel) + + /// Runs `tasks.count` sub-agents (capped) with bounded concurrency, each in its own + /// read-only tool loop, and returns their findings concatenated for the orchestrator. + private func runResearchAgents(tasks: [String], provider: AIProvider, modelId: String) async -> [String: Any] { + let maxConcurrent = max(1, min(5, settings.maxConcurrentAgents)) + // Hard cap on total sub-agents regardless of concurrency setting, so a model + // requesting an unreasonably long task list can't run away with cost. + let cappedTasks = Array(tasks.prefix(8)) + + var results: [(Int, String)] = [] + await withTaskGroup(of: (Int, String).self) { group in + var nextIndex = 0 + func launchNext() { + guard nextIndex < cappedTasks.count else { return } + let idx = nextIndex + let task = cappedTasks[idx] + nextIndex += 1 + group.addTask { + let answer = await self.runSingleResearchAgent(task: task, provider: provider, modelId: modelId) + return (idx, answer) + } + } + for _ in 0.. cappedTasks.count { + response["note"] = "Only the first \(cappedTasks.count) of \(tasks.count) requested tasks were run (per-call cap)." + } + return response + } + + /// A single sub-agent's self-contained tool loop. Read-only tools only; cannot write, + /// run bash, or spawn further sub-agents (spawn_research_agents is not in its tool list). + private func runSingleResearchAgent(task: String, provider: AIProvider, modelId: String) async -> String { + let readOnlyTools: [Tool] = [ + makeTool( + name: "read_file", + description: "Read the contents of a file. Maximum file size is 10MB.", + properties: ["file_path": prop("string", "The absolute path to the file to read")], + required: ["file_path"] + ), + makeTool( + name: "list_directory", + description: "List the contents of a directory. Skips hidden/build directories like .git, node_modules, etc.", + properties: [ + "dir_path": prop("string", "The absolute path to the directory to list"), + "recursive": prop("boolean", "Whether to list recursively (default: false)") + ], + required: ["dir_path"] + ), + makeTool( + name: "search_files", + description: "Search for files by name pattern or content.", + properties: [ + "pattern": prop("string", "Glob pattern to match filenames (e.g. '*.py', 'README*')"), + "search_path": prop("string", "Directory to search in (defaults to first allowed folder)"), + "content_search": prop("string", "Optional text to search for inside files") + ], + required: ["pattern"] + ), + makeTool( + name: "web_search", + description: "Search the web for current information using DuckDuckGo.", + properties: ["query": prop("string", "The search query to look up")], + required: ["query"] + ) + ] + let allowedNames = Set(readOnlyTools.map { $0.function.name }) + + var apiMessages: [[String: Any]] = [ + ["role": "system", "content": "You are a read-only research sub-agent. Investigate the assigned task using the available tools and report concise findings as plain text. You cannot write, delete, or execute anything, and cannot spawn further sub-agents. Once you have enough information, respond with your final answer and stop calling tools."], + ["role": "user", "content": task] + ] + + let maxIterations = 6 + for iteration in 0.. String { + guard let data = try? JSONSerialization.data(withJSONObject: result), + let str = String(data: data, encoding: .utf8) else { + return "{\"error\": \"Failed to serialize result\"}" + } + guard str.utf8.count > maxBytes, let truncated = String(str.utf8.prefix(maxBytes)) else { + return str + } + return truncated + "\n... (result truncated)" + } + + // MARK: - Personal Data (Calendar/Reminders) Approval + + private func executePersonalDataAction(toolName: String, argumentsJSON: String, summary: String) async -> [String: Any] { + guard settings.personalDataRequireApproval, !personalDataSessionApproved else { + return await eventKitService.executeWriteTool(name: toolName, arguments: argumentsJSON) + } + return await withCheckedContinuation { continuation in + DispatchQueue.main.async { + self.pendingPersonalDataAction = PendingPersonalDataAction(toolName: toolName, argumentsJSON: argumentsJSON, summary: summary) + self.pendingPersonalDataContinuation = continuation + } + } + } + + func approvePendingPersonalDataAction(forSession: Bool = false) { + guard let pending = pendingPersonalDataAction, let cont = pendingPersonalDataContinuation else { return } + pendingPersonalDataAction = nil + pendingPersonalDataContinuation = nil + if forSession { + personalDataSessionApproved = true + } + Task.detached(priority: .userInitiated) { + let result = await self.eventKitService.executeWriteTool(name: pending.toolName, arguments: pending.argumentsJSON) + cont.resume(returning: result) + } + } + + func denyPendingPersonalDataAction() { + guard pendingPersonalDataAction != nil else { return } + pendingPersonalDataAction = nil + pendingPersonalDataContinuation?.resume(returning: ["error": "User denied this action"]) + pendingPersonalDataContinuation = nil + } + + func resetPersonalDataSessionApproval() { + personalDataSessionApproved = false + } + private func runBashCommand(_ command: String, workingDirectory: String) async -> [String: Any] { let timeoutSeconds = settings.bashTimeout let workDir = ((workingDirectory as NSString).expandingTildeInPath as NSString).standardizingPath diff --git a/oAI/Services/SettingsService.swift b/oAI/Services/SettingsService.swift index 5191f70..c8f923e 100644 --- a/oAI/Services/SettingsService.swift +++ b/oAI/Services/SettingsService.swift @@ -27,6 +27,18 @@ import Foundation import os import Security +/// Kill switch for the Personal Data tools (Calendar/Reminders/Contacts/Location & Maps). +/// Flip `isHiddenPendingAppleFix` back to `false` once Apple fixes the macOS 27 beta TCC bug +/// (filed with Apple). Each flag hides the relevant UI and forces the `*Enabled` getter to +/// return `false` regardless of the persisted DB value — no code deleted, just inert. +enum PersonalDataTools { + /// Hides the entire Personal Data section. Flip to `false` once all four services work. + static let isHiddenPendingAppleFix = false + /// Hides only the Contacts row. Contacts TCC still broken under hardened runtime on + /// macOS 27 beta 2 while Calendar/Reminders/Location are fixed. Flip to `false` once fixed. + static let isContactsHiddenPendingAppleFix = true +} + @Observable class SettingsService { static let shared = SettingsService() @@ -577,6 +589,37 @@ class SettingsService { } } + // MARK: - Research Agents Settings + + /// When true, the AI can call `spawn_research_agents` to run multiple read-only + /// sub-agents in parallel. Each sub-agent is its own full chain of model calls, so + /// this can noticeably increase cost — opt-in, off by default. + var agentsEnabled: Bool { + get { cache["agentsEnabled"] == "true" } + set { + cache["agentsEnabled"] = String(newValue) + DatabaseService.shared.setSetting(key: "agentsEnabled", value: String(newValue)) + } + } + + var maxConcurrentAgents: Int { + get { cache["maxConcurrentAgents"].flatMap(Int.init) ?? 3 } + set { + cache["maxConcurrentAgents"] = String(newValue) + DatabaseService.shared.setSetting(key: "maxConcurrentAgents", value: String(newValue)) + } + } + + /// When true (and an active "2nd Brain" Agent Skill is installed), bash commands that + /// invoke the 2nd Brain helper script skip the approval dialog entirely. + var trustSecondBrainSkill: Bool { + get { cache["trustSecondBrainSkill"] == "true" } + set { + cache["trustSecondBrainSkill"] = String(newValue) + DatabaseService.shared.setSetting(key: "trustSecondBrainSkill", value: String(newValue)) + } + } + var bashWorkingDirectory: String { get { cache["bashWorkingDirectory"] ?? "~" } set { @@ -593,6 +636,48 @@ class SettingsService { } } + // MARK: - Personal Data Settings (Calendar/Reminders/Contacts/Location/Maps) + + var calendarEnabled: Bool { + get { !PersonalDataTools.isHiddenPendingAppleFix && cache["calendarEnabled"] == "true" } + set { + cache["calendarEnabled"] = String(newValue) + DatabaseService.shared.setSetting(key: "calendarEnabled", value: String(newValue)) + } + } + + var remindersEnabled: Bool { + get { !PersonalDataTools.isHiddenPendingAppleFix && cache["remindersEnabled"] == "true" } + set { + cache["remindersEnabled"] = String(newValue) + DatabaseService.shared.setSetting(key: "remindersEnabled", value: String(newValue)) + } + } + + var contactsEnabled: Bool { + get { !PersonalDataTools.isHiddenPendingAppleFix && !PersonalDataTools.isContactsHiddenPendingAppleFix && cache["contactsEnabled"] == "true" } + set { + cache["contactsEnabled"] = String(newValue) + DatabaseService.shared.setSetting(key: "contactsEnabled", value: String(newValue)) + } + } + + var locationMapsEnabled: Bool { + get { !PersonalDataTools.isHiddenPendingAppleFix && cache["locationMapsEnabled"] == "true" } + set { + cache["locationMapsEnabled"] = String(newValue) + DatabaseService.shared.setSetting(key: "locationMapsEnabled", value: String(newValue)) + } + } + + var personalDataRequireApproval: Bool { + get { cache["personalDataRequireApproval"].map { $0 == "true" } ?? true } + set { + cache["personalDataRequireApproval"] = String(newValue) + DatabaseService.shared.setSetting(key: "personalDataRequireApproval", value: String(newValue)) + } + } + // MARK: - Paperless-NGX Settings var paperlessEnabled: Bool { diff --git a/oAI/ViewModels/ChatViewModel.swift b/oAI/ViewModels/ChatViewModel.swift index e217b0b..44f852d 100644 --- a/oAI/ViewModels/ChatViewModel.swift +++ b/oAI/ViewModels/ChatViewModel.swift @@ -799,8 +799,10 @@ Don't narrate future actions ("Let me...") - just use the tools. let mcpActive = mcpEnabled || settings.mcpEnabled let anytypeActive = settings.anytypeMcpEnabled && settings.anytypeMcpConfigured let bashActive = settings.bashEnabled + let personalDataActive = settings.calendarEnabled || settings.remindersEnabled || settings.contactsEnabled || settings.locationMapsEnabled + let researchAgentsActive = settings.agentsEnabled let modelSupportTools = selectedModel?.capabilities.tools ?? false - if modelSupportTools && (anytypeActive || bashActive || (mcpActive && !mcp.allowedFolders.isEmpty)) { + if modelSupportTools && (anytypeActive || bashActive || personalDataActive || researchAgentsActive || (mcpActive && !mcp.allowedFolders.isEmpty)) { generateAIResponseWithTools(provider: provider, modelId: modelId) return } @@ -1354,6 +1356,7 @@ Don't narrate future actions ("Let me...") - just use the tools. var didContinueAfterImages = false // Only inject temp-file continuation once var totalUsage: ChatResponse.Usage? var hitIterationLimit = false // Track if we exited due to hitting the limit + var finishedWithEmptyContent = false // Model stopped calling tools but said nothing for iteration in 0.. Void let onExport: () -> Void let onDelete: () -> Void + var isTrusted: Bool = false + var onToggleTrust: (() -> Void)? = nil private var fileCount: Int { AgentSkillFilesService.shared.listFiles(for: skill.id).count @@ -378,6 +382,14 @@ private struct AgentSkillRow: View { Spacer() + // 2nd Brain: let the user mark bash calls to its helper script as always-trusted, + // skipping the bash approval dialog. Only shown for this specific skill while active. + if skill.isActive, skill.isSecondBrainSkill, let onToggleTrust { + Toggle("Trust", isOn: Binding(get: { isTrusted }, set: { _ in onToggleTrust() })) + .toggleStyle(.switch).controlSize(.small) + .help("When on, bash commands that call the 2nd Brain helper script run without asking for approval each time.") + } + // File count badge if fileCount > 0 { Label("^[\(fileCount) file](inflect: true)", systemImage: "doc") @@ -479,7 +491,9 @@ struct AgentSkillsTabContent: View { onToggle: { settings.toggleAgentSkill(id: skill.id) }, onEdit: { editContext = SkillEditContext(skill: skill) }, onExport: { exportOne(skill) }, - onDelete: { settings.deleteAgentSkill(id: skill.id) } + onDelete: { settings.deleteAgentSkill(id: skill.id) }, + isTrusted: settings.trustSecondBrainSkill, + onToggleTrust: { settings.trustSecondBrainSkill.toggle() } ) if idx < settings.agentSkills.count - 1 { Divider() } } diff --git a/oAI/Views/Screens/PersonalDataApprovalSheet.swift b/oAI/Views/Screens/PersonalDataApprovalSheet.swift new file mode 100644 index 0000000..7533dff --- /dev/null +++ b/oAI/Views/Screens/PersonalDataApprovalSheet.swift @@ -0,0 +1,97 @@ +// +// PersonalDataApprovalSheet.swift +// oAI +// +// Approval UI for AI-requested Calendar/Reminders write actions +// +// SPDX-License-Identifier: AGPL-3.0-or-later +// Copyright (C) 2026 Rune Olsen +// +// This file is part of oAI. +// +// oAI is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// oAI is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General +// Public License for more details. +// +// You should have received a copy of the GNU Affero General Public +// License along with oAI. If not, see . + + +import SwiftUI + +struct PersonalDataApprovalSheet: View { + let pending: MCPService.PendingPersonalDataAction + let onApprove: (_ forSession: Bool) -> Void + let onDeny: () -> Void + + var body: some View { + VStack(alignment: .leading, spacing: 20) { + // Header + HStack(spacing: 12) { + Image(systemName: "calendar.badge.exclamationmark") + .font(.title2) + .foregroundStyle(.orange) + VStack(alignment: .leading, spacing: 2) { + Text("Allow This Action?") + .font(.system(size: 17, weight: .semibold)) + Text("The AI wants to make a change to your calendar or reminders") + .font(.system(size: 13)) + .foregroundStyle(.secondary) + } + Spacer() + } + + // Action description + VStack(alignment: .leading, spacing: 6) { + Text("ACTION") + .font(.system(size: 11, weight: .medium)) + .foregroundStyle(.secondary) + Text(pending.summary) + .font(.system(size: 13)) + .foregroundStyle(.primary) + .frame(maxWidth: .infinity, alignment: .leading) + .textSelection(.enabled) + .padding(12) + .background(Color.secondary.opacity(0.08)) + .clipShape(RoundedRectangle(cornerRadius: 8)) + .overlay( + RoundedRectangle(cornerRadius: 8) + .stroke(Color.secondary.opacity(0.2), lineWidth: 1) + ) + } + + // Buttons + HStack(spacing: 8) { + Button("Deny") { + onDeny() + } + .buttonStyle(.bordered) + .tint(.red) + .keyboardShortcut(.escape, modifiers: []) + + Spacer() + + Button("Allow Once") { + onApprove(false) + } + .buttonStyle(.bordered) + .tint(.orange) + + Button("Allow for Session") { + onApprove(true) + } + .buttonStyle(.borderedProminent) + .tint(.orange) + .keyboardShortcut(.return, modifiers: []) + } + } + .padding(24) + .frame(width: 480) + } +} diff --git a/oAI/Views/Screens/SettingsView.swift b/oAI/Views/Screens/SettingsView.swift index aed4728..13eabae 100644 --- a/oAI/Views/Screens/SettingsView.swift +++ b/oAI/Views/Screens/SettingsView.swift @@ -75,6 +75,12 @@ struct SettingsView: View { // Default model picker state @State private var showDefaultModelPicker = false + // Personal Data state (Calendar/Reminders/Contacts/Location/Maps) + @State private var calendarAccessState = EventKitService.shared.calendarAccessState + @State private var remindersAccessState = EventKitService.shared.reminderAccessState + @State private var contactsAccessState = ContactsService.shared.accessState + @State private var locationAccessState = LocationMapsService.shared.accessState + // Paperless-NGX state @State private var paperlessURL = "" @State private var paperlessToken = "" @@ -752,6 +758,163 @@ It's better to admit "I need more information" or "I cannot do that" than to fak .padding(.horizontal, 4) } } + + // MARK: Research Agents + Divider() + + VStack(alignment: .leading, spacing: 8) { + HStack(spacing: 8) { + Image(systemName: "person.3.fill") + .font(.title2) + .foregroundStyle(.indigo) + Text("Research Agents") + .font(.system(size: 18, weight: .semibold)) + } + Text("Let the AI spawn read-only research sub-agents to investigate multiple things in parallel (read files, list/search directories, search the web — no writing, no bash). Intended for genuinely independent research tasks, not everyday questions.") + .font(.system(size: 14)) + .foregroundStyle(.secondary) + .fixedSize(horizontal: false, vertical: true) + } + .padding(.bottom, 4) + + VStack(alignment: .leading, spacing: 6) { + sectionHeader("Status") + formSection { + row("Enable Research Agents") { + Toggle("", isOn: $settingsService.agentsEnabled) + .toggleStyle(.switch) + } + } + } + + HStack(alignment: .top, spacing: 6) { + Image(systemName: "exclamationmark.triangle.fill") + .font(.system(size: 12)) + .foregroundStyle(.orange) + .padding(.top, 1) + Text("Cost warning: each sub-agent runs its own full chain of model calls. A single request that spawns several agents can cost several times a normal reply. The AI is instructed to only use this for genuinely parallel research, but model behavior can vary — leave this off unless you want that tradeoff.") + .font(.system(size: 13)) + .foregroundStyle(.secondary) + .fixedSize(horizontal: false, vertical: true) + } + .padding(.horizontal, 4) + + if settingsService.agentsEnabled { + VStack(alignment: .leading, spacing: 6) { + sectionHeader("Settings") + formSection { + row("Max Concurrent Agents") { + HStack(spacing: 8) { + Stepper("", value: $settingsService.maxConcurrentAgents, in: 1...5) + .labelsHidden() + Text("\(settingsService.maxConcurrentAgents)") + .font(.system(size: 13)) + .foregroundStyle(.secondary) + .frame(width: 24, alignment: .trailing) + } + } + } + } + } + + // MARK: Personal Data + // isHiddenPendingAppleFix hides the entire section (macOS 27 beta TCC bug). + // isContactsHiddenPendingAppleFix hides just the Contacts row (still broken in beta 2 + // under hardened runtime while Calendar/Reminders/Location are fixed). Flip each flag + // to false once Apple ships a fix. + if !PersonalDataTools.isHiddenPendingAppleFix { + Divider() + + VStack(alignment: .leading, spacing: 8) { + HStack(spacing: 8) { + Image(systemName: "person.crop.circle.badge.checkmark") + .font(.title2) + .foregroundStyle(.teal) + Text("Personal Data") + .font(.system(size: 18, weight: .semibold)) + if PersonalDataTools.isContactsHiddenPendingAppleFix { + Text("β") + .font(.system(size: 11, weight: .bold)) + .foregroundStyle(.orange) + .padding(.horizontal, 5) + .padding(.vertical, 2) + .background(Color.orange.opacity(0.15)) + .clipShape(RoundedRectangle(cornerRadius: 4)) + .help("Beta Feature. May change.") + } + } + Text("Let the AI access your Calendar, Reminders, and Location & Maps to answer questions about your schedule and surroundings. Each service is opt-in and uses standard macOS permission prompts. This functionality is in beta and may change.") + .font(.system(size: 14)) + .foregroundStyle(.secondary) + .fixedSize(horizontal: false, vertical: true) + } + .padding(.bottom, 4) + .onAppear { + // Permission status can change outside the app (System Settings, or a prior + // request elsewhere) — re-read it fresh every time this tab appears rather than + // trusting the one-time @State initializer. + calendarAccessState = EventKitService.shared.calendarAccessState + remindersAccessState = EventKitService.shared.reminderAccessState + contactsAccessState = ContactsService.shared.accessState + locationAccessState = LocationMapsService.shared.accessState + } + + VStack(alignment: .leading, spacing: 6) { + sectionHeader("Services") + formSection { + personalDataRow( + title: "Calendar", + isEnabled: $settingsService.calendarEnabled, + state: calendarAccessState, + systemSettingsAnchor: "Privacy_Calendars", + requestAccess: { calendarAccessState = await EventKitService.shared.requestCalendarAccess() ? .granted : EventKitService.shared.calendarAccessState } + ) + rowDivider() + personalDataRow( + title: "Reminders", + isEnabled: $settingsService.remindersEnabled, + state: remindersAccessState, + systemSettingsAnchor: "Privacy_Reminders", + requestAccess: { remindersAccessState = await EventKitService.shared.requestReminderAccess() ? .granted : EventKitService.shared.reminderAccessState } + ) + rowDivider() + if !PersonalDataTools.isContactsHiddenPendingAppleFix { + personalDataRow( + title: "Contacts", + isEnabled: $settingsService.contactsEnabled, + state: contactsAccessState, + systemSettingsAnchor: "Privacy_Contacts", + requestAccess: { contactsAccessState = await ContactsService.shared.requestAccess() ? .granted : ContactsService.shared.accessState } + ) + rowDivider() + } + personalDataRow( + title: "Location & Maps", + isEnabled: $settingsService.locationMapsEnabled, + state: locationAccessState, + systemSettingsAnchor: "Privacy_LocationServices", + requestAccess: { locationAccessState = await LocationMapsService.shared.requestAccess() ? .granted : LocationMapsService.shared.accessState } + ) + } + } + + if settingsService.calendarEnabled || settingsService.remindersEnabled { + VStack(alignment: .leading, spacing: 6) { + sectionHeader("Write Actions") + formSection { + row("Require Approval for Changes") { + Toggle("", isOn: $settingsService.personalDataRequireApproval) + .toggleStyle(.switch) + } + } + } + Text("Creating calendar events or reminders, and completing reminders, will ask for your approval first.") + .font(.system(size: 13)) + .foregroundStyle(.secondary) + .fixedSize(horizontal: false, vertical: true) + .padding(.horizontal, 4) + } + } } // MARK: - Appearance Tab @@ -2446,6 +2609,57 @@ It's better to admit "I need more information" or "I cannot do that" than to fak Divider().padding(.leading, 16) } + @ViewBuilder + private func personalDataRow(title: LocalizedStringKey, isEnabled: Binding, state: PersonalDataAccessState, systemSettingsAnchor: String, requestAccess: @escaping () async -> Void) -> some View { + VStack(alignment: .leading, spacing: 6) { + HStack(alignment: .center, spacing: 12) { + Text(title).font(.system(size: 14)) + Spacer() + Toggle("", isOn: isEnabled) + .toggleStyle(.switch) + } + if isEnabled.wrappedValue { + HStack(spacing: 6) { + Image(systemName: state == .granted ? "checkmark.circle.fill" : (state == .denied ? "exclamationmark.circle.fill" : "circle")) + .foregroundStyle(state == .granted ? .green : (state == .denied ? .orange : .secondary)) + .font(.system(size: 12)) + Text(statusText(for: state)) + .font(.system(size: 12)) + .foregroundStyle(.secondary) + Spacer() + if state == .notDetermined { + Button("Request Access") { + Task { await requestAccess() } + } + .buttonStyle(.bordered) + .controlSize(.small) + } else if state == .denied { + Button("Open System Settings") { + openPrivacySettings(anchor: systemSettingsAnchor) + } + .buttonStyle(.bordered) + .controlSize(.small) + } + } + } + } + .padding(.horizontal, 16) + .padding(.vertical, 10) + } + + private func statusText(for state: PersonalDataAccessState) -> LocalizedStringKey { + switch state { + case .granted: return "Access granted" + case .denied: return "Access denied — enable in System Settings" + case .notDetermined: return "Access not granted" + } + } + + private func openPrivacySettings(anchor: String) { + guard let url = URL(string: "x-apple.systempreferences:com.apple.preference.security?\(anchor)") else { return } + NSWorkspace.shared.open(url) + } + private func abbreviatePath(_ path: String) -> String { let home = NSHomeDirectory() if path.hasPrefix(home) { diff --git a/oAI/oAI-InfoPlist.xcstrings b/oAI/oAI-InfoPlist.xcstrings index 62030c1..fb5f7cd 100644 --- a/oAI/oAI-InfoPlist.xcstrings +++ b/oAI/oAI-InfoPlist.xcstrings @@ -36,6 +36,54 @@ } } } + }, + "NSCalendarsFullAccessUsageDescription" : { + "comment" : "Privacy - Calendars Full Access Usage Description", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "oAI can read and create calendar events when you ask it to, if you enable Calendar access in Settings." + } + } + } + }, + "NSContactsUsageDescription" : { + "comment" : "Privacy - Contacts Usage Description", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "oAI can search your contacts when you ask it to, if you enable Contacts access in Settings." + } + } + } + }, + "NSLocationWhenInUseUsageDescription" : { + "comment" : "Privacy - Location When In Use Usage Description", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "oAI can use your current location to answer questions, if you enable Location & Maps access in Settings." + } + } + } + }, + "NSRemindersFullAccessUsageDescription" : { + "comment" : "Privacy - Reminders Full Access Usage Description", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "oAI can read and create reminders when you ask it to, if you enable Reminders access in Settings." + } + } + } } }, "version" : "1.1" diff --git a/oAI/oAI.entitlements b/oAI/oAI.entitlements index 0953aeb..97a7c31 100644 --- a/oAI/oAI.entitlements +++ b/oAI/oAI.entitlements @@ -8,5 +8,13 @@ com.apple.security.network.server + com.apple.security.personal-information.calendars + + com.apple.security.personal-information.reminders + + com.apple.security.personal-information.contacts + + com.apple.security.personal-information.location + -- 2.52.0 From f2949cea3b5a44f833e9f2ba21b516bfe0715454 Mon Sep 17 00:00:00 2001 From: Rune Olsen Date: Mon, 29 Jun 2026 14:34:56 +0200 Subject: [PATCH 05/10] Add OpenRouter dedicated images API support Fetches /api/v1/images/models in parallel with /models and merges results into the model picker. Image-only models (e.g. Sourceful, Seedream, Flux via this endpoint) were previously invisible since they don't appear in the standard /models endpoint. Models from the images API get usesImagesAPI=true and route through a new generateImageAPIResponse() path in ChatViewModel that POSTs to /api/v1/images with {model, prompt} instead of the chat completions endpoint. The response's b64_json data is decoded and displayed via the existing GeneratedImagesView. Cost is taken directly from the usage.cost field in the images API response (USD per image) via a new rawCostUSD field on ChatResponse.Usage, bypassing the token-based calculateCost() path used for chat models. Co-Authored-By: Claude Sonnet 4.6 --- oAI/Models/ModelInfo.swift | 1 + oAI/Providers/AIProvider.swift | 16 ++- oAI/Providers/OpenRouterModels.swift | 61 ++++++++++++ oAI/Providers/OpenRouterProvider.swift | 132 ++++++++++++++++++++----- oAI/ViewModels/ChatViewModel.swift | 56 +++++++++++ 5 files changed, 243 insertions(+), 23 deletions(-) diff --git a/oAI/Models/ModelInfo.swift b/oAI/Models/ModelInfo.swift index e3387db..e46c2ad 100644 --- a/oAI/Models/ModelInfo.swift +++ b/oAI/Models/ModelInfo.swift @@ -47,6 +47,7 @@ struct ModelInfo: Identifiable, Codable, Hashable { let online: Bool // Web search var imageGeneration: Bool = false // Image output var thinking: Bool = false // Reasoning/thinking tokens + var usesImagesAPI: Bool = false // OpenRouter dedicated /images endpoint } struct Architecture: Codable, Hashable { diff --git a/oAI/Providers/AIProvider.swift b/oAI/Providers/AIProvider.swift index 42f52ea..1749370 100644 --- a/oAI/Providers/AIProvider.swift +++ b/oAI/Providers/AIProvider.swift @@ -132,15 +132,19 @@ struct ChatResponse: Codable { let totalTokens: Int let cacheCreationInputTokens: Int? let cacheReadInputTokens: Int? + /// Direct USD cost returned by the images API (bypasses token-based calculation). + let rawCostUSD: Double? - init(promptTokens: Int, completionTokens: Int, totalTokens: Int, cacheCreationInputTokens: Int? = nil, cacheReadInputTokens: Int? = nil) { + init(promptTokens: Int, completionTokens: Int, totalTokens: Int, cacheCreationInputTokens: Int? = nil, cacheReadInputTokens: Int? = nil, rawCostUSD: Double? = nil) { self.promptTokens = promptTokens self.completionTokens = completionTokens self.totalTokens = totalTokens self.cacheCreationInputTokens = cacheCreationInputTokens self.cacheReadInputTokens = cacheReadInputTokens + self.rawCostUSD = rawCostUSD } + // rawCostUSD is set programmatically, never decoded from API responses enum CodingKeys: String, CodingKey { case promptTokens = "prompt_tokens" case completionTokens = "completion_tokens" @@ -148,6 +152,16 @@ struct ChatResponse: Codable { case cacheCreationInputTokens = "cache_creation_input_tokens" case cacheReadInputTokens = "cache_read_input_tokens" } + + init(from decoder: Decoder) throws { + let c = try decoder.container(keyedBy: CodingKeys.self) + promptTokens = try c.decode(Int.self, forKey: .promptTokens) + completionTokens = try c.decode(Int.self, forKey: .completionTokens) + totalTokens = try c.decode(Int.self, forKey: .totalTokens) + cacheCreationInputTokens = try c.decodeIfPresent(Int.self, forKey: .cacheCreationInputTokens) + cacheReadInputTokens = try c.decodeIfPresent(Int.self, forKey: .cacheReadInputTokens) + rawCostUSD = nil + } } // Custom Codable since ToolCallInfo/generatedImages are not from API directly diff --git a/oAI/Providers/OpenRouterModels.swift b/oAI/Providers/OpenRouterModels.swift index 4fbb6b3..466ae5b 100644 --- a/oAI/Providers/OpenRouterModels.swift +++ b/oAI/Providers/OpenRouterModels.swift @@ -420,6 +420,67 @@ struct ToolResultMessage: Encodable { } } +// MARK: - Images API — Model Discovery + +struct OpenRouterImageModelsResponse: Codable { + let data: [ImageModelData] + + struct ImageModelData: Codable { + let id: String + let name: String + let description: String? + let architecture: Architecture? + let supportsStreaming: Bool? + + struct Architecture: Codable { + let inputModalities: [String]? + let outputModalities: [String]? + + enum CodingKeys: String, CodingKey { + case inputModalities = "input_modalities" + case outputModalities = "output_modalities" + } + } + + enum CodingKeys: String, CodingKey { + case id, name, description, architecture + case supportsStreaming = "supports_streaming" + } + } +} + +// MARK: - Images API — Generation Response + +struct OpenRouterImageGenerationResponse: Codable { + let created: Int? + let data: [ImageData] + let usage: Usage? + + struct ImageData: Codable { + let b64Json: String + let mediaType: String? + + enum CodingKeys: String, CodingKey { + case b64Json = "b64_json" + case mediaType = "media_type" + } + } + + struct Usage: Codable { + let promptTokens: Int + let completionTokens: Int + let totalTokens: Int + let cost: Double? + + enum CodingKeys: String, CodingKey { + case promptTokens = "prompt_tokens" + case completionTokens = "completion_tokens" + case totalTokens = "total_tokens" + case cost + } + } +} + // MARK: - Error Response struct OpenRouterErrorResponse: Codable { diff --git a/oAI/Providers/OpenRouterProvider.swift b/oAI/Providers/OpenRouterProvider.swift index bcc874a..55d86bc 100644 --- a/oAI/Providers/OpenRouterProvider.swift +++ b/oAI/Providers/OpenRouterProvider.swift @@ -53,30 +53,16 @@ class OpenRouterProvider: AIProvider { func listModels() async throws -> [ModelInfo] { Log.api.info("Fetching model list from OpenRouter") - let url = URL(string: "\(baseURL)/models")! - var request = URLRequest(url: url) - request.addValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization") - request.addValue("application/json", forHTTPHeaderField: "Content-Type") - let (data, response) = try await session.data(for: request) + // Fetch chat models and image models in parallel + async let chatData = fetchRaw(path: "/models") + async let imageData = fetchRaw(path: "/images/models") + let (chatRaw, imageRaw) = try await (chatData, imageData) - guard let httpResponse = response as? HTTPURLResponse else { - Log.api.error("OpenRouter models: invalid response (not HTTP)") - throw ProviderError.invalidResponse - } + let modelsResponse = try JSONDecoder().decode(OpenRouterModelsResponse.self, from: chatRaw) + Log.api.info("OpenRouter loaded \(modelsResponse.data.count) chat models") - guard httpResponse.statusCode == 200 else { - if let errorResponse = try? JSONDecoder().decode(OpenRouterErrorResponse.self, from: data) { - Log.api.error("OpenRouter models HTTP \(httpResponse.statusCode): \(errorResponse.error.message)") - throw ProviderError.unknown(errorResponse.error.message) - } - Log.api.error("OpenRouter models HTTP \(httpResponse.statusCode)") - throw ProviderError.unknown("HTTP \(httpResponse.statusCode)") - } - - let modelsResponse = try JSONDecoder().decode(OpenRouterModelsResponse.self, from: data) - Log.api.info("OpenRouter loaded \(modelsResponse.data.count) models") - return modelsResponse.data.map { modelData in + var models = modelsResponse.data.map { modelData in let promptPrice = Double(modelData.pricing.prompt) ?? 0.0 let completionPrice = Double(modelData.pricing.completion) ?? 0.0 @@ -129,8 +115,110 @@ class OpenRouterProvider: AIProvider { ) return info } + + // Merge dedicated image models (these don't appear in /models) + if let imageModelsResponse = try? JSONDecoder().decode(OpenRouterImageModelsResponse.self, from: imageRaw) { + Log.api.info("OpenRouter loaded \(imageModelsResponse.data.count) image models") + let existingIds = Set(models.map { $0.id }) + let imageModels = imageModelsResponse.data.compactMap { m -> ModelInfo? in + guard !existingIds.contains(m.id) else { return nil } + let acceptsImageInput = m.architecture?.inputModalities?.contains("image") ?? false + var info = ModelInfo( + id: m.id, + name: m.name, + description: m.description, + contextLength: 0, + pricing: ModelInfo.Pricing(prompt: 0, completion: 0), + capabilities: ModelInfo.ModelCapabilities( + vision: acceptsImageInput, + tools: false, + online: false, + imageGeneration: true, + thinking: false, + usesImagesAPI: true + ), + topProvider: m.id.components(separatedBy: "/").first + ) + info.categories = ModelCategory.infer(name: m.name, id: m.id, description: m.description) + return info + } + models.append(contentsOf: imageModels) + } + + return models } - + + private func fetchRaw(path: String) async throws -> Data { + let url = URL(string: "\(baseURL)\(path)")! + var request = URLRequest(url: url) + request.addValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization") + request.addValue("application/json", forHTTPHeaderField: "Content-Type") + let (data, response) = try await session.data(for: request) + guard let httpResponse = response as? HTTPURLResponse else { throw ProviderError.invalidResponse } + guard httpResponse.statusCode == 200 else { + if let err = try? JSONDecoder().decode(OpenRouterErrorResponse.self, from: data) { + throw ProviderError.unknown(err.error.message) + } + throw ProviderError.unknown("HTTP \(httpResponse.statusCode)") + } + return data + } + + // MARK: - Images API + + func generateImage(model: String, prompt: String) async throws -> ChatResponse { + Log.api.info("OpenRouter images API: model=\(model)") + let url = URL(string: "\(baseURL)/images")! + var urlRequest = URLRequest(url: url) + urlRequest.httpMethod = "POST" + urlRequest.addValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization") + urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type") + urlRequest.addValue("https://github.com/yourusername/oAI", forHTTPHeaderField: "HTTP-Referer") + urlRequest.addValue("oAI-Swift", forHTTPHeaderField: "X-Title") + urlRequest.httpBody = try JSONSerialization.data(withJSONObject: ["model": model, "prompt": prompt]) + + let (data, response) = try await session.data(for: urlRequest) + guard let httpResponse = response as? HTTPURLResponse else { throw ProviderError.invalidResponse } + + if httpResponse.statusCode != 200 { + if let err = try? JSONDecoder().decode(OpenRouterErrorResponse.self, from: data) { + Log.api.error("OpenRouter images HTTP \(httpResponse.statusCode): \(err.error.message)") + throw ProviderError.unknown(err.error.message) + } + Log.api.error("OpenRouter images HTTP \(httpResponse.statusCode)") + throw ProviderError.unknown("HTTP \(httpResponse.statusCode)") + } + + if let rawStr = String(data: data, encoding: .utf8) { + Log.api.debug("Images API raw response (first 200 chars): \(rawStr.prefix(200))") + } + + let imageResponse = try JSONDecoder().decode(OpenRouterImageGenerationResponse.self, from: data) + let images: [Data] = imageResponse.data.compactMap { item in + Data(base64Encoded: item.b64Json) + } + + let usage: ChatResponse.Usage? = imageResponse.usage.map { u in + ChatResponse.Usage( + promptTokens: u.promptTokens, + completionTokens: u.completionTokens, + totalTokens: u.totalTokens, + rawCostUSD: u.cost + ) + } + + return ChatResponse( + id: UUID().uuidString, + model: model, + content: "", + role: "assistant", + finishReason: "stop", + usage: usage, + created: Date(), + generatedImages: images.isEmpty ? nil : images + ) + } + func getModel(_ id: String) async throws -> ModelInfo? { let models = try await listModels() return models.first { $0.id == id } diff --git a/oAI/ViewModels/ChatViewModel.swift b/oAI/ViewModels/ChatViewModel.swift index 44f852d..78b716e 100644 --- a/oAI/ViewModels/ChatViewModel.swift +++ b/oAI/ViewModels/ChatViewModel.swift @@ -801,6 +801,13 @@ Don't narrate future actions ("Let me...") - just use the tools. let bashActive = settings.bashEnabled let personalDataActive = settings.calendarEnabled || settings.remindersEnabled || settings.contactsEnabled || settings.locationMapsEnabled let researchAgentsActive = settings.agentsEnabled + // Dedicated images API path (OpenRouter /images endpoint — separate from chat completions) + if selectedModel?.capabilities.usesImagesAPI == true, + let orProvider = provider as? OpenRouterProvider { + generateImageAPIResponse(orProvider: orProvider, modelId: modelId, prompt: prompt) + return + } + let modelSupportTools = selectedModel?.capabilities.tools ?? false if modelSupportTools && (anytypeActive || bashActive || personalDataActive || researchAgentsActive || (mcpActive && !mcp.allowedFolders.isEmpty)) { generateAIResponseWithTools(provider: provider, modelId: modelId) @@ -1263,6 +1270,55 @@ Don't narrate future actions ("Let me...") - just use the tools. // MARK: - AI Response with Tool Calls + // MARK: - Images API Generation + + private func generateImageAPIResponse(orProvider: OpenRouterProvider, modelId: String, prompt: String) { + isGenerating = true + streamingTask?.cancel() + streamingTask = Task { + let startTime = Date() + let assistantMessage = Message( + role: .assistant, + content: ThinkingVerbs.random(), + tokens: nil, + cost: nil, + timestamp: Date(), + attachments: nil, + modelId: modelId, + isStreaming: true + ) + let messageId = assistantMessage.id + messages.append(assistantMessage) + + do { + let response = try await orProvider.generateImage(model: modelId, prompt: prompt) + let responseTime = Date().timeIntervalSince(startTime) + + if let index = messages.firstIndex(where: { $0.id == messageId }) { + messages[index].content = response.content + messages[index].isStreaming = false + messages[index].generatedImages = response.generatedImages + messages[index].responseTime = responseTime + + if let usage = response.usage { + messages[index].tokens = usage.completionTokens + let cost = usage.rawCostUSD + messages[index].cost = cost + sessionStats.addMessage(inputTokens: usage.promptTokens, outputTokens: usage.completionTokens, cost: cost) + } + } + _ = detectGoodbyePhrase(in: "") + } catch { + if let index = messages.firstIndex(where: { $0.id == messageId }) { + messages[index].content = "❌ Image generation failed: \(error.localizedDescription)" + messages[index].isStreaming = false + } + Log.api.error("Images API error: \(error)") + } + isGenerating = false + } + } + private func generateAIResponseWithTools(provider: AIProvider, modelId: String) { let mcp = MCPService.shared Log.ui.info("generateAIResponseWithTools: model=\(modelId)") -- 2.52.0 From e6f965ff19a9d27b5689e813a19e6e6fe0c786fb Mon Sep 17 00:00:00 2001 From: Rune Olsen Date: Tue, 14 Jul 2026 08:01:00 +0200 Subject: [PATCH 06/10] Add external MCP server support (stdio JSON-RPC) Lets the AI connect to any external stdio MCP server (e.g. safaridriver --mcp) configured in Settings, with tools auto-discovered and prefixed by server slug. Includes crash detection with backoff restart (5s/15s/30s) and a Settings UI to add/enable/disable/remove servers. Fixes the temp-dir allowlist in MCPService.isPathAllowed to also match /tmp and /private/tmp (not just NSTemporaryDirectory(), which resolves to a different per-user Darwin temp dir) so the MCP file tools can actually read files external servers and image generation write there. Also switches the Add Server sheet's argument parsing to a quote-aware tokenizer so args containing spaces survive intact. Co-Authored-By: Claude Sonnet 5 --- oAI/Services/ExternalMCPClient.swift | 280 ++++++++++++++++++++++++++ oAI/Services/ExternalMCPManager.swift | 202 +++++++++++++++++++ oAI/Services/ExternalMCPModels.swift | 170 ++++++++++++++++ oAI/Services/MCPService.swift | 18 ++ oAI/Services/SettingsService.swift | 42 ++++ oAI/Utilities/Logging.swift | 1 + oAI/ViewModels/ChatViewModel.swift | 9 +- oAI/Views/Screens/SettingsView.swift | 212 +++++++++++++++++++ oAI/oAIApp.swift | 5 +- 9 files changed, 937 insertions(+), 2 deletions(-) create mode 100644 oAI/Services/ExternalMCPClient.swift create mode 100644 oAI/Services/ExternalMCPManager.swift create mode 100644 oAI/Services/ExternalMCPModels.swift diff --git a/oAI/Services/ExternalMCPClient.swift b/oAI/Services/ExternalMCPClient.swift new file mode 100644 index 0000000..41f7ea8 --- /dev/null +++ b/oAI/Services/ExternalMCPClient.swift @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later +// Copyright (C) 2026 Rune Olsen + +import Foundation + +// MARK: - ExternalMCPClient + +/// Manages one MCP stdio server process. All state is MainActor-isolated +/// (consistent with SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor project setting). +/// Background I/O runs in Task.detached; state mutations hop back to MainActor. +@MainActor +final class ExternalMCPClient { + let server: ExternalMCPServer + weak var stateDelegate: (any ExternalMCPStateDelegate)? + + private var process: Process? + private var stdinHandle: FileHandle? + private var readTask: Task? + private var stderrTask: Task? + + private var nextRequestId: Int = 1 + private var pendingCalls: [Int: CheckedContinuation] = [:] + private var lineBuffer = Data() + + private(set) var state: MCPClientState = .idle + private(set) var discoveredTools: [MCPToolDefinition] = [] + + init(server: ExternalMCPServer, stateDelegate: (any ExternalMCPStateDelegate)?) { + self.server = server + self.stateDelegate = stateDelegate + } + + // MARK: - Lifecycle + + func start() async throws { + guard state == .idle || state == .stopped || state == .crashed else { return } + state = .connecting + stateDelegate?.clientDidChangeState(id: server.id, state: .connecting) + + let proc = Process() + if server.command.hasPrefix("/") { + proc.executableURL = URL(fileURLWithPath: server.command) + proc.arguments = server.args + } else { + proc.executableURL = URL(fileURLWithPath: "/usr/bin/env") + proc.arguments = [server.command] + server.args + } + proc.environment = ProcessInfo.processInfo.environment + + let stdinPipe = Pipe() + let stdoutPipe = Pipe() + let stderrPipe = Pipe() + proc.standardInput = stdinPipe + proc.standardOutput = stdoutPipe + proc.standardError = stderrPipe + + proc.terminationHandler = { [weak self] _ in + Task { @MainActor [weak self] in self?.handleProcessTerminated() } + } + + do { + try proc.run() + } catch { + state = .error(error.localizedDescription) + stateDelegate?.clientDidChangeState(id: server.id, state: .error(error.localizedDescription)) + throw MCPClientError.processLaunchFailed(error.localizedDescription) + } + + process = proc + stdinHandle = stdinPipe.fileHandleForWriting + startReadLoop(pipe: stdoutPipe) + startStderrLoop(pipe: stderrPipe) + + do { + let _: MCPInitializeResult = try await timedRequest(seconds: 15, method: "initialize", params: [ + "protocolVersion": "2024-11-05", + "capabilities": [:] as [String: Any], + "clientInfo": ["name": "oAI", "version": "1.0"] as [String: Any] + ]) + try sendNotification(method: "notifications/initialized") + + let toolsResult: MCPToolsListResult = try await timedRequest(seconds: 15, method: "tools/list", params: nil) + discoveredTools = toolsResult.tools + } catch { + state = .error(error.localizedDescription) + stateDelegate?.clientDidChangeState(id: server.id, state: .error(error.localizedDescription)) + proc.terminate() + throw error + } + + state = .ready + stateDelegate?.clientDidBecomeReady(id: server.id, tools: discoveredTools, server: server) + } + + func stop() { + state = .stopped + readTask?.cancel() + stderrTask?.cancel() + process?.terminate() + process = nil + stdinHandle = nil + lineBuffer = Data() + for (_, cont) in pendingCalls { cont.resume(throwing: MCPClientError.notConnected) } + pendingCalls.removeAll() + } + + // MARK: - Tool Execution + + func callTool(originalName: String, argumentsJSON: String) async -> [String: Any] { + guard state == .ready else { + return ["error": "MCP server '\(server.name)' is not connected"] + } + guard let argData = argumentsJSON.data(using: .utf8), + let argsDict = try? JSONSerialization.jsonObject(with: argData) as? [String: Any] else { + return ["error": "Invalid arguments JSON for tool \(originalName)"] + } + do { + let result: MCPToolCallResult = try await timedRequest( + seconds: server.timeout, + method: "tools/call", + params: ["name": originalName, "arguments": argsDict] + ) + return convertMCPResult(result) + } catch MCPClientError.timeout { + return ["error": "MCP server '\(server.name)' timed out after \(Int(server.timeout))s"] + } catch { + return ["error": "MCP call '\(originalName)' failed: \(error.localizedDescription)"] + } + } + + // MARK: - I/O Loops (detached from MainActor) + + private func startReadLoop(pipe: Pipe) { + readTask = Task.detached { [weak self] in + let handle = pipe.fileHandleForReading + while true { + let data = handle.availableData + if data.isEmpty { break } + await self?.receiveData(data) + } + } + } + + private func startStderrLoop(pipe: Pipe) { + let name = server.name + stderrTask = Task.detached { + let handle = pipe.fileHandleForReading + var buf = Data() + while true { + let data = handle.availableData + if data.isEmpty { break } + buf.append(data) + while let idx = buf.firstIndex(of: UInt8(ascii: "\n")) { + let line = String(data: buf[buf.startIndex..(seconds: Double, method: String, params: [String: Any]?) async throws -> T { + let id = nextRequestId + nextRequestId += 1 + var message: [String: Any] = ["jsonrpc": "2.0", "method": method, "id": id] + if let params { message["params"] = params } + try writeJSON(message) + + // Schedule timeout: cancels the specific pending call by ID + let timeoutId = id + Task { [weak self, timeoutId] in + try? await Task.sleep(nanoseconds: UInt64(seconds * 1_000_000_000)) + self?.cancelPendingCall(id: timeoutId, with: MCPClientError.timeout) + } + + // Await response data, then decode on MainActor + let resultData: Data = try await withCheckedThrowingContinuation { cont in + pendingCalls[id] = cont + } + return try JSONDecoder().decode(T.self, from: resultData) + } + + private func cancelPendingCall(id: Int, with error: Error) { + pendingCalls.removeValue(forKey: id)?.resume(throwing: error) + } + + private func sendNotification(method: String) throws { + try writeJSON(["jsonrpc": "2.0", "method": method]) + } + + private func writeJSON(_ message: [String: Any]) throws { + guard let handle = stdinHandle, process?.isRunning == true else { + throw MCPClientError.writeFailed + } + guard let data = try? JSONSerialization.data(withJSONObject: message), + let line = String(data: data, encoding: .utf8) else { + throw MCPClientError.writeFailed + } + do { + try handle.write(contentsOf: Data((line + "\n").utf8)) + } catch { + throw MCPClientError.writeFailed + } + } + + // MARK: - Process termination + + private func handleProcessTerminated() { + guard state != .stopped else { return } + state = .crashed + for (_, cont) in pendingCalls { cont.resume(throwing: MCPClientError.notConnected) } + pendingCalls.removeAll() + stateDelegate?.clientDidChangeState(id: server.id, state: .crashed) + } + + // MARK: - Result conversion + + private func convertMCPResult(_ result: MCPToolCallResult) -> [String: Any] { + let isError = result.isError ?? false + var parts: [String] = [] + for content in result.content { + switch content.type { + case "text": + if let text = content.text { parts.append(text) } + case "image": + if let base64 = content.data, let imageData = Data(base64Encoded: base64) { + parts.append("[Image saved to: \(writeTempImage(imageData, mimeType: content.mimeType))]") + } + case "resource": + if let text = content.text { parts.append(text) } + else if let uri = content.uri { parts.append("[Resource: \(uri)]") } + default: + if let text = content.text { parts.append(text) } + } + } + let combined = parts.joined(separator: "\n") + return isError ? ["error": combined.isEmpty ? "Tool returned an error" : combined] : ["output": combined] + } + + private func writeTempImage(_ data: Data, mimeType: String?) -> String { + let ext = mimeType?.contains("png") == true ? "png" : "jpg" + let path = "/tmp/oai_mcp_\(Int(Date().timeIntervalSince1970 * 1000)).\(ext)" + try? data.write(to: URL(fileURLWithPath: path)) + return path + } +} diff --git a/oAI/Services/ExternalMCPManager.swift b/oAI/Services/ExternalMCPManager.swift new file mode 100644 index 0000000..c4c6ea7 --- /dev/null +++ b/oAI/Services/ExternalMCPManager.swift @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later +// Copyright (C) 2026 Rune Olsen + +import Foundation + +// MARK: - ExternalMCPManager + +@Observable +@MainActor +final class ExternalMCPManager { + nonisolated static let shared = ExternalMCPManager() + + private(set) var clientStates: [UUID: MCPClientState] = [:] + private(set) var cachedToolSchemas: [Tool] = [] + + // Keep server config alongside client so we can access slug without await + private var clients: [UUID: ExternalMCPClient] = [:] + private var serverConfigs: [UUID: ExternalMCPServer] = [:] + private var restartTasks: [UUID: Task] = [:] + private var restartAttempts: [UUID: Int] = [:] + + private nonisolated init() {} + + // MARK: - Lifecycle + + func startAll() { + for server in SettingsService.shared.externalMCPServers where server.isEnabled { + startClient(for: server) + } + } + + func stopAll() { + for client in clients.values { client.stop() } + clients.removeAll() + serverConfigs.removeAll() + clientStates.removeAll() + cachedToolSchemas.removeAll() + for task in restartTasks.values { task.cancel() } + restartTasks.removeAll() + restartAttempts.removeAll() + } + + func reconfigure(servers: [ExternalMCPServer]) { + let activeIds = Set(servers.filter { $0.isEnabled }.map { $0.id }) + for id in clients.keys where !activeIds.contains(id) { + clients[id]?.stop() + clients.removeValue(forKey: id) + serverConfigs.removeValue(forKey: id) + clientStates.removeValue(forKey: id) + restartTasks[id]?.cancel() + restartTasks.removeValue(forKey: id) + restartAttempts.removeValue(forKey: id) + removeCachedSchemas(for: id) + } + for server in servers where server.isEnabled && clients[server.id] == nil { + startClient(for: server) + } + } + + private func startClient(for server: ExternalMCPServer) { + // Stop any existing client for this ID before creating a new one + clients[server.id]?.stop() + let client = ExternalMCPClient(server: server, stateDelegate: self) + clients[server.id] = client + serverConfigs[server.id] = server + clientStates[server.id] = .connecting + Task { + do { + try await client.start() + } catch MCPClientError.processLaunchFailed(let msg) { + // Process never started — termination handler won't fire, so manually trigger crashed + Log.extMcp.error("Failed to launch '\(server.name)': \(msg)") + clientDidChangeState(id: server.id, state: .crashed) + } catch { + // Handshake/other failure — proc.terminate() was called in start(), termination + // handler will fire and set .crashed, which drives the restart from one place only. + Log.extMcp.warning("'\(server.name)' start failed: \(error.localizedDescription)") + } + } + } + + private func scheduleRestart(for server: ExternalMCPServer, attempt: Int) { + let delays: [Double] = [5, 15, 30] + let delay = delays[min(attempt - 1, delays.count - 1)] + Log.extMcp.warning("MCP server '\(server.name)' crashed — restarting in \(Int(delay))s (attempt \(attempt)/3)") + + restartTasks[server.id]?.cancel() + let id = server.id + restartTasks[id] = Task { [weak self, id] in + try? await Task.sleep(nanoseconds: UInt64(delay * 1_000_000_000)) + guard !Task.isCancelled, let self, + self.clients[id] != nil, + SettingsService.shared.externalMCPServers.contains(where: { $0.id == id && $0.isEnabled }) + else { return } + // startClient is the single place that creates and launches clients. + // It handles processLaunchFailed by calling clientDidChangeState(.crashed), + // and all other failures let the termination handler drive the .crashed callback. + self.startClient(for: server) + } + } + + // MARK: - Tool Schema Integration (synchronous) + + func getToolSchemas() -> [Tool] { cachedToolSchemas } + + func isExternalTool(_ name: String) -> Bool { + cachedToolSchemas.contains { $0.function.name == name } + } + + // MARK: - Tool Execution + + func executeTool(name: String, argumentsJSON: String) async -> [String: Any] { + for (id, client) in clients { + guard clientStates[id] == .ready, + let server = serverConfigs[id] else { continue } + let prefix = "\(server.slug)_" + if name.hasPrefix(prefix) { + let originalName = String(name.dropFirst(prefix.count)) + return await client.callTool(originalName: originalName, argumentsJSON: argumentsJSON) + } + } + return ["error": "No external MCP server found for tool: \(name)"] + } + + // MARK: - Schema Cache + + private func rebuildCache(for server: ExternalMCPServer, tools: [MCPToolDefinition]) { + removeCachedSchemas(for: server.id, slug: server.slug) + let prefixed = tools.compactMap { convertToolDefinition($0, server: server) } + cachedToolSchemas.append(contentsOf: prefixed) + Log.extMcp.info("[\(server.name)] cached \(prefixed.count) tools: \(prefixed.map { $0.function.name }.joined(separator: ", "))") + } + + private func removeCachedSchemas(for id: UUID) { + guard let server = serverConfigs[id] else { return } + removeCachedSchemas(for: id, slug: server.slug) + } + + private func removeCachedSchemas(for id: UUID, slug: String) { + cachedToolSchemas.removeAll { $0.function.name.hasPrefix("\(slug)_") } + } + + private func convertToolDefinition(_ def: MCPToolDefinition, server: ExternalMCPServer) -> Tool? { + Tool( + type: "function", + function: Tool.Function( + name: "\(server.slug)_\(def.name)", + description: "[\(server.name)] \(def.description ?? "")", + parameters: convertInputSchema(def.inputSchema) + ) + ) + } + + private func convertInputSchema(_ schema: MCPInputSchema) -> Tool.Function.Parameters { + var properties: [String: Tool.Function.Parameters.Property] = [:] + for (key, prop) in schema.properties ?? [:] { + let normalized: String + switch prop.type ?? "string" { + case "integer": normalized = "number" + case "string", "number", "boolean", "array", "object": normalized = prop.type! + default: normalized = "string" + } + var items: Tool.Function.Parameters.Property.Items? = nil + if normalized == "array", let t = prop.items?.type { items = .init(type: t) } + properties[key] = Tool.Function.Parameters.Property( + type: normalized, + description: prop.description ?? "", + enum: prop.enum, + items: items + ) + } + return Tool.Function.Parameters(type: "object", properties: properties, required: schema.required) + } +} + +// MARK: - ExternalMCPStateDelegate + +extension ExternalMCPManager: ExternalMCPStateDelegate { + func clientDidBecomeReady(id: UUID, tools: [MCPToolDefinition], server: ExternalMCPServer) { + clientStates[id] = .ready + restartAttempts.removeValue(forKey: id) + rebuildCache(for: server, tools: tools) + } + + func clientDidChangeState(id: UUID, state: MCPClientState) { + clientStates[id] = state + if case .crashed = state, + let server = serverConfigs[id], + SettingsService.shared.externalMCPServers.contains(where: { $0.id == id && $0.isEnabled }) { + removeCachedSchemas(for: id, slug: server.slug) + let attempt = (restartAttempts[id] ?? 0) + 1 + guard attempt <= 3 else { + Log.extMcp.error("MCP server '\(server.name)' gave up after 3 restart attempts") + clientStates[id] = .error("Maximum restart attempts reached") + restartAttempts.removeValue(forKey: id) + return + } + restartAttempts[id] = attempt + scheduleRestart(for: server, attempt: attempt) + } + } +} diff --git a/oAI/Services/ExternalMCPModels.swift b/oAI/Services/ExternalMCPModels.swift new file mode 100644 index 0000000..a209371 --- /dev/null +++ b/oAI/Services/ExternalMCPModels.swift @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later +// Copyright (C) 2026 Rune Olsen + +import Foundation + +// MARK: - Server Configuration + +struct ExternalMCPServer: Codable, Identifiable, Sendable { + var id: UUID + var name: String + var command: String + var args: [String] + var isEnabled: Bool + var timeout: TimeInterval + var createdAt: Date + + init(id: UUID = UUID(), name: String, command: String, args: [String] = [], + isEnabled: Bool = true, timeout: TimeInterval = 30, createdAt: Date = Date()) { + self.id = id + self.name = name + self.command = command + self.args = args + self.isEnabled = isEnabled + self.timeout = timeout + self.createdAt = createdAt + } + + var slug: String { Self.makeSlug(from: name) } + + static func makeSlug(from name: String) -> String { + let s = name + .lowercased() + .components(separatedBy: CharacterSet.alphanumerics.inverted) + .filter { !$0.isEmpty } + .joined(separator: "_") + return s.isEmpty ? "ext" : s + } + + /// Splits a raw arguments string into tokens, respecting single/double-quoted + /// segments so arguments containing spaces (e.g. `--root "/Users/x/My Documents"`) + /// survive intact instead of being split on every space. + static func parseArguments(_ input: String) -> [String] { + var args: [String] = [] + var current = "" + var inSingleQuotes = false + var inDoubleQuotes = false + + for char in input { + if char == "'" && !inDoubleQuotes { + inSingleQuotes.toggle() + } else if char == "\"" && !inSingleQuotes { + inDoubleQuotes.toggle() + } else if char.isWhitespace && !inSingleQuotes && !inDoubleQuotes { + if !current.isEmpty { + args.append(current) + current = "" + } + } else { + current.append(char) + } + } + if !current.isEmpty { args.append(current) } + return args + } + + static let reservedSlugs: Set = [ + "anytype", "paperless", "calendar", "reminders", + "contacts", "location", "maps", "bash", "web", "read", "write", + "list", "search", "edit", "delete", "create", "move", "copy", "spawn" + ] + + var isSlugReserved: Bool { Self.reservedSlugs.contains(slug) } +} + +// MARK: - Client State + +enum MCPClientState: Equatable { + case idle + case connecting + case ready + case error(String) + case crashed + case stopped +} + +// MARK: - State Delegate (all callbacks on MainActor) + +@MainActor +protocol ExternalMCPStateDelegate: AnyObject { + func clientDidBecomeReady(id: UUID, tools: [MCPToolDefinition], server: ExternalMCPServer) + func clientDidChangeState(id: UUID, state: MCPClientState) +} + +// MARK: - Client Errors + +enum MCPClientError: LocalizedError { + case notConnected + case invalidResponse(String) + case timeout + case processLaunchFailed(String) + case handshakeFailed(String) + case writeFailed + + var errorDescription: String? { + switch self { + case .notConnected: return "MCP server is not connected" + case .invalidResponse(let s): return "Invalid MCP response: \(s)" + case .timeout: return "MCP request timed out" + case .processLaunchFailed(let s): return "Failed to launch MCP server: \(s)" + case .handshakeFailed(let s): return "MCP handshake failed: \(s)" + case .writeFailed: return "Failed to write to MCP server stdin" + } + } +} + +// MARK: - MCP Protocol Types + +struct MCPInitializeResult: Decodable { + let protocolVersion: String + let capabilities: MCPCapabilities + let serverInfo: MCPServerInfo? +} + +struct MCPCapabilities: Decodable { + let tools: MCPToolsCapability? + struct MCPToolsCapability: Decodable { let listChanged: Bool? } +} + +struct MCPServerInfo: Decodable { + let name: String + let version: String? +} + +struct MCPToolsListResult: Decodable { + let tools: [MCPToolDefinition] + let nextCursor: String? +} + +struct MCPToolDefinition: Decodable { + let name: String + let description: String? + let inputSchema: MCPInputSchema +} + +struct MCPInputSchema: Decodable { + let type: String + let properties: [String: MCPPropertySchema]? + let required: [String]? +} + +struct MCPPropertySchema: Decodable { + let type: String? + let description: String? + let `enum`: [String]? + let items: MCPItemsSchema? + struct MCPItemsSchema: Decodable { let type: String? } +} + +struct MCPToolCallResult: Decodable { + let content: [MCPContent] + let isError: Bool? +} + +struct MCPContent: Decodable { + let type: String + let text: String? + let data: String? + let mimeType: String? + let uri: String? +} diff --git a/oAI/Services/MCPService.swift b/oAI/Services/MCPService.swift index ef8b964..837767d 100644 --- a/oAI/Services/MCPService.swift +++ b/oAI/Services/MCPService.swift @@ -98,6 +98,17 @@ class MCPService { func isPathAllowed(_ path: String) -> Bool { let resolved = ((path as NSString).expandingTildeInPath as NSString).standardizingPath + // Always allow the system temp directory — external MCP servers and tools write + // intermediate data there (e.g. Safari MCP page-content files, generated images). + // Check both NSTemporaryDirectory() (per-user Darwin temp dir) and /tmp (what this + // codebase's own temp files actually use, e.g. ChatViewModel's /tmp/oai_generated_* + // and ExternalMCPClient's /tmp/oai_mcp_* — they resolve to different directories. + let tmpCandidates = [ + (NSTemporaryDirectory() as NSString).standardizingPath, + "/tmp", + "/private/tmp" + ] + if tmpCandidates.contains(where: { resolved.hasPrefix($0) }) { return true } return allowedFolders.contains { resolved.hasPrefix($0) } } @@ -310,6 +321,9 @@ class MCPService { )) } + // Add tools from external MCP servers (stdio JSON-RPC protocol) + tools.append(contentsOf: ExternalMCPManager.shared.getToolSchemas()) + return tools } @@ -472,6 +486,10 @@ class MCPService { return await executePersonalDataAction(toolName: name, argumentsJSON: arguments, summary: summary) default: + // Route to external MCP servers (stdio JSON-RPC) + if ExternalMCPManager.shared.isExternalTool(name) { + return await ExternalMCPManager.shared.executeTool(name: name, argumentsJSON: arguments) + } // Route anytype_* tools to AnytypeMCPService if name.hasPrefix("anytype_") { return await anytypeService.executeTool(name: name, arguments: arguments) diff --git a/oAI/Services/SettingsService.swift b/oAI/Services/SettingsService.swift index c8f923e..8729792 100644 --- a/oAI/Services/SettingsService.swift +++ b/oAI/Services/SettingsService.swift @@ -461,6 +461,48 @@ class SettingsService { } } + // MARK: - External MCP Servers + + var externalMCPServers: [ExternalMCPServer] { + get { + guard let json = cache["externalMCPServers"], + let data = json.data(using: .utf8) else { return [] } + let decoder = JSONDecoder() + decoder.dateDecodingStrategy = .iso8601 + return (try? decoder.decode([ExternalMCPServer].self, from: data)) ?? [] + } + set { + let encoder = JSONEncoder() + encoder.dateEncodingStrategy = .iso8601 + if let data = try? encoder.encode(newValue), + let json = String(data: data, encoding: .utf8) { + cache["externalMCPServers"] = json + DatabaseService.shared.setSetting(key: "externalMCPServers", value: json) + } + Task { @MainActor in ExternalMCPManager.shared.reconfigure(servers: newValue) } + } + } + + func addExternalMCPServer(_ server: ExternalMCPServer) { + externalMCPServers = externalMCPServers + [server] + } + + func updateExternalMCPServer(_ server: ExternalMCPServer) { + externalMCPServers = externalMCPServers.map { $0.id == server.id ? server : $0 } + } + + func deleteExternalMCPServer(id: UUID) { + externalMCPServers = externalMCPServers.filter { $0.id != id } + } + + func toggleExternalMCPServer(id: UUID) { + externalMCPServers = externalMCPServers.map { s in + s.id == id ? ExternalMCPServer(id: s.id, name: s.name, command: s.command, + args: s.args, isEnabled: !s.isEnabled, + timeout: s.timeout, createdAt: s.createdAt) : s + } + } + // MARK: - Favorite Models var favoriteModelIds: Set { diff --git a/oAI/Utilities/Logging.swift b/oAI/Utilities/Logging.swift index 93dac72..87d7994 100644 --- a/oAI/Utilities/Logging.swift +++ b/oAI/Utilities/Logging.swift @@ -153,4 +153,5 @@ enum Log { nonisolated static let search = AppLogger(subsystem: subsystem, category: "search") nonisolated static let ui = AppLogger(subsystem: subsystem, category: "ui") nonisolated static let general = AppLogger(subsystem: subsystem, category: "general") + nonisolated static let extMcp = AppLogger(subsystem: subsystem, category: "ext-mcp") } diff --git a/oAI/ViewModels/ChatViewModel.swift b/oAI/ViewModels/ChatViewModel.swift index 78b716e..1ec6937 100644 --- a/oAI/ViewModels/ChatViewModel.swift +++ b/oAI/ViewModels/ChatViewModel.swift @@ -801,6 +801,7 @@ Don't narrate future actions ("Let me...") - just use the tools. let bashActive = settings.bashEnabled let personalDataActive = settings.calendarEnabled || settings.remindersEnabled || settings.contactsEnabled || settings.locationMapsEnabled let researchAgentsActive = settings.agentsEnabled + let externalMCPActive = !settings.externalMCPServers.filter { $0.isEnabled }.isEmpty // Dedicated images API path (OpenRouter /images endpoint — separate from chat completions) if selectedModel?.capabilities.usesImagesAPI == true, let orProvider = provider as? OpenRouterProvider { @@ -809,7 +810,7 @@ Don't narrate future actions ("Let me...") - just use the tools. } let modelSupportTools = selectedModel?.capabilities.tools ?? false - if modelSupportTools && (anytypeActive || bashActive || personalDataActive || researchAgentsActive || (mcpActive && !mcp.allowedFolders.isEmpty)) { + if modelSupportTools && (anytypeActive || bashActive || personalDataActive || researchAgentsActive || externalMCPActive || (mcpActive && !mcp.allowedFolders.isEmpty)) { generateAIResponseWithTools(provider: provider, modelId: modelId) return } @@ -1360,6 +1361,12 @@ Don't narrate future actions ("Let me...") - just use the tools. systemParts.append("You have access to the user's Anytype knowledge base through tool calls (anytype_* tools). You can search across all spaces, list spaces, get objects, and create or update notes, tasks, and pages. Use these tools proactively when the user asks about their notes, tasks, or knowledge base.") } + let activeExternalServers = settings.externalMCPServers.filter { $0.isEnabled } + if !activeExternalServers.isEmpty { + let names = activeExternalServers.map { $0.name }.joined(separator: ", ") + systemParts.append("You have access to external tools from MCP servers: \(names). Their tools are prefixed with the server slug (e.g. safari_navigate_to_url). Use them proactively when the user's request relates to what those servers provide.") + } + var systemContent = systemParts.joined(separator: "\n\n") // Append the complete system prompt (default + custom) diff --git a/oAI/Views/Screens/SettingsView.swift b/oAI/Views/Screens/SettingsView.swift index 13eabae..98540d5 100644 --- a/oAI/Views/Screens/SettingsView.swift +++ b/oAI/Views/Screens/SettingsView.swift @@ -75,6 +75,14 @@ struct SettingsView: View { // Default model picker state @State private var showDefaultModelPicker = false + // External MCP Servers state + @State private var showAddExternalMCPServer = false + @State private var newMCPServerName = "" + @State private var newMCPServerCommand = "" + @State private var newMCPServerArgs = "" + @State private var newMCPServerTimeout: Double = 30 + private var externalMCPManager = ExternalMCPManager.shared + // Personal Data state (Calendar/Reminders/Contacts/Location/Maps) @State private var calendarAccessState = EventKitService.shared.calendarAccessState @State private var remindersAccessState = EventKitService.shared.reminderAccessState @@ -817,6 +825,10 @@ It's better to admit "I need more information" or "I cannot do that" than to fak } } + // MARK: External MCP Servers + Divider() + externalMCPSection + // MARK: Personal Data // isHiddenPendingAppleFix hides the entire section (macOS 27 beta TCC bug). // isContactsHiddenPendingAppleFix hides just the Contacts row (still broken in beta 2 @@ -917,6 +929,206 @@ It's better to admit "I need more information" or "I cannot do that" than to fak } } + // MARK: - External MCP Servers Section + + @ViewBuilder + private var externalMCPSection: some View { + VStack(alignment: .leading, spacing: 8) { + HStack(spacing: 8) { + Image(systemName: "server.rack") + .font(.title2) + .foregroundStyle(.purple) + Text("External MCP Servers") + .font(.system(size: 18, weight: .semibold)) + } + Text("Connect any stdio MCP server (e.g. safaridriver --mcp) to give the AI access to its tools. Tool names are prefixed with the server slug.") + .font(.system(size: 14)) + .foregroundStyle(.secondary) + .fixedSize(horizontal: false, vertical: true) + } + .padding(.bottom, 4) + + VStack(alignment: .leading, spacing: 6) { + sectionHeader("Configured Servers") + formSection { + if settingsService.externalMCPServers.isEmpty { + VStack(spacing: 8) { + Image(systemName: "server.rack") + .font(.system(size: 32)) + .foregroundStyle(.tertiary) + Text("No external servers configured") + .font(.system(size: 14, weight: .medium)) + .foregroundStyle(.secondary) + Text("Add a server below, e.g.: safaridriver --mcp") + .font(.system(size: 12)) + .foregroundStyle(.tertiary) + } + .frame(maxWidth: .infinity) + .padding(.vertical, 20) + } else { + ForEach(settingsService.externalMCPServers) { server in + HStack(spacing: 10) { + Circle() + .fill(mcpStatusColor(externalMCPManager.clientStates[server.id])) + .frame(width: 8, height: 8) + VStack(alignment: .leading, spacing: 2) { + Text(server.name) + .font(.system(size: 14)) + Text(([server.command] + server.args).joined(separator: " ")) + .font(.system(size: 11, design: .monospaced)) + .foregroundStyle(.secondary) + .lineLimit(1) + } + Spacer() + Text(mcpStatusLabel(externalMCPManager.clientStates[server.id])) + .font(.system(size: 11)) + .foregroundStyle(.secondary) + Toggle("", isOn: Binding( + get: { server.isEnabled }, + set: { _ in settingsService.toggleExternalMCPServer(id: server.id) } + )) + .toggleStyle(.switch) + .labelsHidden() + Button { + settingsService.deleteExternalMCPServer(id: server.id) + } label: { + Image(systemName: "trash.fill") + .foregroundStyle(.red) + .font(.system(size: 13)) + } + .buttonStyle(.plain) + } + .padding(.horizontal, 16) + .padding(.vertical, 10) + if server.id != settingsService.externalMCPServers.last?.id { + rowDivider() + } + } + } + } + + Button { + newMCPServerName = "" + newMCPServerCommand = "" + newMCPServerArgs = "" + newMCPServerTimeout = 30 + showAddExternalMCPServer = true + } label: { + Label("Add Server…", systemImage: "plus") + .font(.system(size: 13, weight: .medium)) + .foregroundStyle(.white) + .padding(.horizontal, 14) + .padding(.vertical, 7) + .background(Color.purple) + .clipShape(RoundedRectangle(cornerRadius: 8)) + } + .buttonStyle(.plain) + } + .sheet(isPresented: $showAddExternalMCPServer) { + addExternalMCPServerSheet + } + } + + @ViewBuilder + private var addExternalMCPServerSheet: some View { + VStack(alignment: .leading, spacing: 20) { + Text("Add External MCP Server") + .font(.system(size: 16, weight: .semibold)) + .frame(maxWidth: .infinity, alignment: .center) + + formSection { + row("Name") { + TextField("Safari", text: $newMCPServerName) + .textFieldStyle(.roundedBorder) + .frame(width: 240) + } + rowDivider() + row("Command") { + TextField("safaridriver", text: $newMCPServerCommand) + .textFieldStyle(.roundedBorder) + .font(.system(size: 13, design: .monospaced)) + .frame(width: 240) + } + rowDivider() + row("Arguments") { + TextField("--mcp", text: $newMCPServerArgs) + .textFieldStyle(.roundedBorder) + .font(.system(size: 13, design: .monospaced)) + .frame(width: 240) + .help("Space-separated arguments") + } + rowDivider() + row("Timeout") { + HStack(spacing: 8) { + Stepper("", value: $newMCPServerTimeout, in: 5...120, step: 5) + .labelsHidden() + Text("\(Int(newMCPServerTimeout))s") + .font(.system(size: 13)) + .foregroundStyle(.secondary) + .frame(width: 32, alignment: .leading) + } + } + } + + if !newMCPServerName.isEmpty { + let slug = ExternalMCPServer.makeSlug(from: newMCPServerName) + HStack(spacing: 6) { + Text("Tool prefix:") + .font(.system(size: 12)) + .foregroundStyle(.secondary) + Text("\(slug)_") + .font(.system(size: 12, design: .monospaced)) + .foregroundStyle(.secondary) + } + if ExternalMCPServer.reservedSlugs.contains(slug) { + Text("'\(slug)' is a reserved prefix. Choose a different name.") + .font(.system(size: 12)) + .foregroundStyle(.red) + } + } + + HStack { + Button("Cancel") { showAddExternalMCPServer = false } + Spacer() + Button("Add") { + let args = ExternalMCPServer.parseArguments(newMCPServerArgs) + let server = ExternalMCPServer( + name: newMCPServerName, + command: newMCPServerCommand, + args: args, + timeout: newMCPServerTimeout + ) + settingsService.addExternalMCPServer(server) + showAddExternalMCPServer = false + } + .buttonStyle(.borderedProminent) + .disabled(newMCPServerName.isEmpty || newMCPServerCommand.isEmpty || + ExternalMCPServer.reservedSlugs.contains(ExternalMCPServer.makeSlug(from: newMCPServerName))) + } + } + .padding(24) + .frame(minWidth: 460, minHeight: 320) + } + + private func mcpStatusColor(_ state: MCPClientState?) -> Color { + switch state { + case .ready: return .green + case .connecting: return .orange + case .error, .crashed: return .red + default: return Color(nsColor: .tertiaryLabelColor) + } + } + + private func mcpStatusLabel(_ state: MCPClientState?) -> LocalizedStringKey { + switch state { + case .ready: return "Connected" + case .connecting: return "Connecting…" + case .error: return "Error" + case .crashed: return "Crashed" + default: return "Not started" + } + } + // MARK: - Appearance Tab @ViewBuilder diff --git a/oAI/oAIApp.swift b/oAI/oAIApp.swift index 2717fe3..0858f27 100644 --- a/oAI/oAIApp.swift +++ b/oAI/oAIApp.swift @@ -37,6 +37,9 @@ struct oAIApp: App { // Start email handler on app launch EmailHandlerService.shared.start() + // Start external MCP servers + Task { @MainActor in ExternalMCPManager.shared.startAll() } + // Sync Git changes on app launch (pull + import) Task { await GitSyncService.shared.syncOnStartup() @@ -56,7 +59,7 @@ struct oAIApp: App { } #if os(macOS) .onReceive(NotificationCenter.default.publisher(for: NSApplication.willTerminateNotification)) { _ in - // Trigger auto-save on app quit + Task { @MainActor in ExternalMCPManager.shared.stopAll() } Task { await chatViewModel.onAppWillTerminate() } -- 2.52.0 From 7119cd1d066ace66a96307ca626f4e04bf8c4641 Mon Sep 17 00:00:00 2001 From: Rune Olsen Date: Tue, 14 Jul 2026 08:05:07 +0200 Subject: [PATCH 07/10] Silence placeholder/continuing messages in the tool-call auto-retry path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tool loop's max-iterations and empty-response fallbacks were showing placeholder assistant bubbles ("[Tool loop reached maximum iterations]", "[No response from the model — retrying]") followed by a "↩ Continuing…" system message before silently re-running. None of that added anything for the user, so the auto-continue now happens without any visible message when there's no real content to show; genuine partial content is still displayed as before, and usage/cost tracking is unaffected. Co-Authored-By: Claude Sonnet 5 --- oAI/ViewModels/ChatViewModel.swift | 76 +++++++++++++++++------------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/oAI/ViewModels/ChatViewModel.swift b/oAI/ViewModels/ChatViewModel.swift index 1ec6937..02b09ea 100644 --- a/oAI/ViewModels/ChatViewModel.swift +++ b/oAI/ViewModels/ChatViewModel.swift @@ -360,7 +360,6 @@ Don't narrate future actions ("Let me...") - just use the tools. } func startAutoContinue() { - showSystemMessage("↩ Continuing…") silentContinuePrompt = "Please continue from where you left off." Task { @MainActor in generateAIResponse(to: "", attachments: nil) @@ -1475,9 +1474,8 @@ Don't narrate future actions ("Let me...") - just use the tools. if finalContent.isEmpty { // Some models (observed with Qwen via OpenRouter) stop calling tools // after a long tool-call chain but return no summarizing text at all. - // Surface a placeholder and nudge a follow-up turn instead of a silent blank bubble. + // Silently nudge a follow-up turn instead of showing a placeholder bubble. finishedWithEmptyContent = true - finalContent = "[No response from the model — retrying]" } break } @@ -1566,9 +1564,7 @@ Don't narrate future actions ("Let me...") - just use the tools. // If this was the last iteration, note it if iteration == maxIterations - 1 { hitIterationLimit = true // We're exiting with pending tool calls - finalContent = response.content.isEmpty - ? "[Tool loop reached maximum iterations]" - : response.content + finalContent = response.content } } @@ -1577,41 +1573,57 @@ Don't narrate future actions ("Let me...") - just use the tools. wasCancelled = true } + // If we hit the iteration limit or the model returned no text at all, silently + // nudge a follow-up turn instead of showing a placeholder/blank bubble. + let willAutoContinue = (hitIterationLimit || finishedWithEmptyContent) && !wasCancelled + // Display the final response as an assistant message let responseTime = Date().timeIntervalSince(startTime) - let assistantMessage = Message( - role: .assistant, - content: finalContent, - tokens: totalUsage?.completionTokens, - cost: nil, - timestamp: Date(), - attachments: nil, - responseTime: responseTime, - wasInterrupted: wasCancelled, - modelId: modelId, - generatedImages: finalImages.isEmpty ? nil : finalImages - ) - messages.append(assistantMessage) - - // Calculate cost - if let usage = totalUsage, let model = selectedModel { - let hasPricing = model.pricing.prompt > 0 || model.pricing.completion > 0 - let cost: Double? = hasPricing ? calculateCost(usage: usage, pricing: model.pricing) : nil - if let index = messages.lastIndex(where: { $0.id == assistantMessage.id }) { - messages[index].cost = cost + if willAutoContinue && finalContent.isEmpty { + // Nothing worth showing yet — still record usage/cost for this turn. + if let usage = totalUsage, let model = selectedModel { + let hasPricing = model.pricing.prompt > 0 || model.pricing.completion > 0 + let cost: Double? = hasPricing ? calculateCost(usage: usage, pricing: model.pricing) : nil + sessionStats.addMessage( + inputTokens: usage.promptTokens, + outputTokens: usage.completionTokens, + cost: cost + ) } - sessionStats.addMessage( - inputTokens: usage.promptTokens, - outputTokens: usage.completionTokens, - cost: cost + } else { + let assistantMessage = Message( + role: .assistant, + content: finalContent, + tokens: totalUsage?.completionTokens, + cost: nil, + timestamp: Date(), + attachments: nil, + responseTime: responseTime, + wasInterrupted: wasCancelled, + modelId: modelId, + generatedImages: finalImages.isEmpty ? nil : finalImages ) + messages.append(assistantMessage) + + // Calculate cost + if let usage = totalUsage, let model = selectedModel { + let hasPricing = model.pricing.prompt > 0 || model.pricing.completion > 0 + let cost: Double? = hasPricing ? calculateCost(usage: usage, pricing: model.pricing) : nil + if let index = messages.lastIndex(where: { $0.id == assistantMessage.id }) { + messages[index].cost = cost + } + sessionStats.addMessage( + inputTokens: usage.promptTokens, + outputTokens: usage.completionTokens, + cost: cost + ) + } } isGenerating = false streamingTask = nil - // If we hit the iteration limit, or the model returned no text at all, nudge a follow-up turn - if (hitIterationLimit || finishedWithEmptyContent) && !wasCancelled { + if willAutoContinue { startAutoContinue() } -- 2.52.0 From bfcdd0164ca13e32b611c14cc3f17c10046396cb Mon Sep 17 00:00:00 2001 From: Rune Olsen Date: Tue, 14 Jul 2026 08:38:39 +0200 Subject: [PATCH 08/10] =?UTF-8?q?Fix=20assistant=20message=20text=20trunca?= =?UTF-8?q?ting=20with=20"=E2=80=A6"=20instead=20of=20wrapping?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two contributing layout issues in the chat message bubble: 1. MessageRow's content VStack (icon + text HStack) had no .frame(maxWidth: .infinity), so it sized to its content's ideal width instead of the space actually available. 2. swift-markdown-ui renders paragraphs with mixed inline styling (bold/italic runs next to plain text) as concatenated Text(+) segments, which on macOS report their ideal unwrapped single-line size for height purposes instead of wrapping — truncating with "…" regardless of window width. Plain single-style paragraphs (a single Text) weren't affected, which is why some lines wrapped fine and others didn't. Fixed by adding .frame(maxWidth: .infinity, alignment: .leading) to the MessageRow content stack, and .fixedSize(horizontal: false, vertical: true) to the markdown paragraph label so height is recomputed for the width actually given instead of the ideal width. Co-Authored-By: Claude Sonnet 5 --- oAI/Views/Main/MarkdownContentView.swift | 7 +++++++ oAI/Views/Main/MessageRow.swift | 1 + 2 files changed, 8 insertions(+) diff --git a/oAI/Views/Main/MarkdownContentView.swift b/oAI/Views/Main/MarkdownContentView.swift index 4772519..7c60873 100644 --- a/oAI/Views/Main/MarkdownContentView.swift +++ b/oAI/Views/Main/MarkdownContentView.swift @@ -61,8 +61,15 @@ struct MarkdownContentView: View { .markdownBlockStyle(\.paragraph) { configuration in configuration.label .markdownMargin(top: 0, bottom: 8) + // MarkdownUI builds mixed-style paragraphs (bold/italic runs alongside + // plain text) as concatenated Text(+) segments, which on macOS report + // their ideal (unwrapped, single-line) size instead of wrapping to the + // width actually available — truncating with "…" mid-word. Forcing the + // height to be recomputed for the given (flexible) width fixes it. + .fixedSize(horizontal: false, vertical: true) } .textSelection(.enabled) + .frame(maxWidth: .infinity, alignment: .leading) } // MARK: - Parsing diff --git a/oAI/Views/Main/MessageRow.swift b/oAI/Views/Main/MessageRow.swift index 16f554c..ee42c0c 100644 --- a/oAI/Views/Main/MessageRow.swift +++ b/oAI/Views/Main/MessageRow.swift @@ -185,6 +185,7 @@ struct MessageRow: View { .foregroundColor(.oaiSecondary) } } + .frame(maxWidth: .infinity, alignment: .leading) } .padding(16) .background(Color.messageBackground(for: message.role)) -- 2.52.0 From 8cba92d768b994647437cf31d4e2be86fc4ce1b5 Mon Sep 17 00:00:00 2001 From: Rune Olsen Date: Tue, 14 Jul 2026 10:33:50 +0200 Subject: [PATCH 09/10] Document External MCP Servers, Personal Data Tools, and Research Agents in Help Adds three new Help sections covering the 2.4.1 features: connecting external stdio MCP servers, Calendar/Reminders/Location access with its approval flow, and parallel read-only research sub-agents. Also notes French as a supported language and that OpenRouter's dedicated image models are merged into the model picker automatically. Cleans up a stray misplaced HTML comment above the Anytype section. Co-Authored-By: Claude Sonnet 5 --- .../Contents/Resources/en.lproj/index.html | 111 +++++++++++++++++- 1 file changed, 109 insertions(+), 2 deletions(-) diff --git a/oAI/Resources/oAI.help/Contents/Resources/en.lproj/index.html b/oAI/Resources/oAI.help/Contents/Resources/en.lproj/index.html index dfd00e2..9d32f91 100644 --- a/oAI/Resources/oAI.help/Contents/Resources/en.lproj/index.html +++ b/oAI/Resources/oAI.help/Contents/Resources/en.lproj/index.html @@ -36,6 +36,9 @@
  • Shortcuts (Prompt Templates)
  • Agent Skills (SKILL.md)
  • Anytype Integration
  • +
  • External MCP Servers
  • +
  • Personal Data Tools
  • +
  • Research Agents
  • Bash Execution
  • iCloud Backup
  • Reasoning / Thinking Tokens
  • @@ -49,7 +52,7 @@

    Getting Started

    -

    oAI is a powerful AI chat assistant that connects to multiple AI providers including OpenAI, Anthropic, OpenRouter, and local models via Ollama. The app is available in English, Norwegian Bokmål, Swedish, Danish, and German — it follows your macOS language preference automatically.

    +

    oAI is a powerful AI chat assistant that connects to multiple AI providers including OpenAI, Anthropic, OpenRouter, and local models via Ollama. The app is available in English, Norwegian Bokmål, Swedish, Danish, German, and French — it follows your macOS language preference automatically.

    Quick Start

    @@ -115,6 +118,10 @@
  • 🧠 Thinking — models that support reasoning / thinking tokens
  • +
    + Note: On OpenRouter, dedicated image-generation models (e.g. Sourceful, Seedream, Flux) are fetched from OpenRouter's separate images catalog and merged into the picker automatically — you don't need to configure anything extra to see them. +
    +

    Sorting

    Click the ↑↓ Sort button to sort the list by:

      @@ -1370,7 +1377,6 @@ Whenever the user asks you to translate something, translate it to Norwegian Bok
    -

    Anytype Integration

    @@ -1413,6 +1419,104 @@ Whenever the user asks you to translate something, translate it to Norwegian Bok
    + +
    +

    External MCP Servers

    +

    Connect any external MCP server that speaks the stdio JSON-RPC protocol (for example safaridriver --mcp) and give the AI access to its tools — no custom integration code needed.

    + +

    Adding a Server

    +
      +
    1. Press ⌘, to open Settings
    2. +
    3. Go to the MCP tab → External MCP Servers section
    4. +
    5. Click Add Server…
    6. +
    7. Enter a Name (used to prefix its tools, e.g. "Safari" → safari_navigate_to_url), the Command to launch it, and any Arguments
    8. +
    9. Click Add — the server starts automatically and its tools are discovered
    10. +
    + +
    + 💡 Tip: Arguments containing spaces can be quoted, e.g. --root "/Users/you/My Documents". +
    + +

    Server Status

    +

    Each configured server shows a status dot and label:

    +
      +
    • 🟢 Connected — running and its tools are available to the AI
    • +
    • 🟠 Connecting… — starting up or performing the initial handshake
    • +
    • 🔴 Error / Crashed — failed to start or exited unexpectedly
    • +
    • ⚪ Not started — disabled via the toggle
    • +
    +

    Toggle a server off/on or delete it entirely with the trash icon. Crashed servers automatically restart up to 3 times with increasing delay (5s, 15s, 30s) before giving up.

    + +
    + Note: Tool names from every external server are prefixed with that server's slug (derived from its Name) so they never collide with oAI's built-in tools or each other. +
    +
    + + +
    +

    Personal Data Tools Beta

    +

    Let the AI access your Calendar, Reminders, and Location & Maps to answer questions about your schedule and surroundings. Each service is opt-in and uses Apple's own frameworks (EventKit, CoreLocation, MapKit) with standard macOS permission prompts — nothing goes through a third-party service.

    + +

    Enabling a Service

    +
      +
    1. Press ⌘, to open Settings
    2. +
    3. Go to the MCP tab → Personal Data section
    4. +
    5. Toggle on the services you want: Calendar, Reminders, or Location & Maps
    6. +
    7. Click Request Access next to a service — macOS shows its standard permission prompt
    8. +
    + +

    What the AI Can Do

    +
      +
    • Calendar — list your calendars and upcoming events, create new events
    • +
    • Reminders — list reminder lists and items, create new reminders, mark reminders complete
    • +
    • Location & Maps — get your current location, search for places, geocode addresses, and get directions (all read-only)
    • +
    + +
    + ⚠️ Write actions require approval: Creating a calendar event or reminder, or completing a reminder, shows an approval sheet first with a plain-language summary of what will happen. Choose Deny, Allow Once, or Allow for Session. Toggle this requirement off in Settings → MCP → Personal Data → Require Approval for Changes. +
    + +
    + Note: Contacts support exists internally but is currently hidden while a macOS permission bug affecting hardened-runtime apps is worked out on Apple's side. +
    + +

    Example Prompts

    +
      +
    • "What's on my calendar tomorrow?"
    • +
    • "Remind me to call the dentist on Friday at 2pm"
    • +
    • "How far is the nearest coffee shop from here?"
    • +
    +
    + + +
    +

    Research Agents

    +

    For tasks that involve searching or reading many files, the AI can spawn several read-only research sub-agents that work in parallel instead of doing everything itself, one step at a time.

    + +
    + ⚠️ Cost warning: Each sub-agent runs its own full chain of model calls. A single request that spawns several agents can cost several times a normal reply. Leave this off unless you specifically want that tradeoff. +
    + +

    Enabling Research Agents

    +
      +
    1. Press ⌘, to open Settings
    2. +
    3. Go to the MCP tab → Research Agents section
    4. +
    5. Toggle Enable Research Agents on
    6. +
    7. Adjust Max Concurrent Agents (1–5, default 3) to control how many sub-agents can run at once
    8. +
    + +

    What Sub-Agents Can Do

    +

    Sub-agents are intentionally limited to read-only investigation — they cannot write files, run shell commands, or spawn further sub-agents:

    +
      +
    • Read file contents
    • +
    • List directory contents
    • +
    • Search for files
    • +
    • Search the web
    • +
    + +

    Intended for genuinely independent research tasks (e.g. "compare these five files" or "look into three unrelated topics"), not everyday questions — the AI is instructed to reserve this for cases that actually benefit from parallelism.

    +
    +

    Keyboard Shortcuts

    Work faster with these keyboard shortcuts.

    @@ -1490,6 +1594,9 @@ Whenever the user asks you to translate something, translate it to Norwegian Bok
  • Enable/disable write, delete, move, and bash execution permissions
  • Configure gitignore respect
  • Bash Execution — enable AI shell access, set working directory, timeout, and approval behaviour (see Bash Execution)
  • +
  • Research Agents — let the AI spawn parallel read-only research sub-agents (see Research Agents)
  • +
  • External MCP Servers — connect any stdio MCP server for additional tools (see External MCP Servers)
  • +
  • Personal Data — Calendar, Reminders, and Location & Maps access (see Personal Data Tools)
  • Sync Tab

    -- 2.52.0 From 0cefef16e4a7d43b5a2c34037996c1bb22305830 Mon Sep 17 00:00:00 2001 From: Rune Olsen Date: Tue, 14 Jul 2026 10:46:53 +0200 Subject: [PATCH 10/10] =?UTF-8?q?Change=20Command=20History=20shortcut=20f?= =?UTF-8?q?rom=20=E2=8C=98H=20to=20=E2=87=A7=E2=8C=98H?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ⌘H is reserved by macOS for "Hide Application" and pre-empts app-level menu bindings before they ever fire, so the Command History shortcut never actually worked. Moved to ⇧⌘H and updated all references (in-app help, macOS Help Book, README). Co-Authored-By: Claude Sonnet 5 --- README.md | 6 +++--- .../oAI.help/Contents/Resources/en.lproj/index.html | 2 +- oAI/Views/Screens/HelpView.swift | 2 +- oAI/oAIApp.swift | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e21cab8..31de591 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ A powerful native macOS AI chat application with support for multiple providers, - **Reasoning / Thinking Tokens** - Stream live reasoning from thinking-capable models (DeepSeek R1, Claude 3.7+, o1/o3, Qwen); configurable effort level (High/Medium/Low/Minimal); collapsible block auto-expands while thinking and collapses when the answer arrives - **Online Mode** - DuckDuckGo and Google web search integration - **Session Statistics** - Track token usage, costs, and response times -- **Command History** - Navigate previous commands with searchable modal (⌘H) +- **Command History** - Navigate previous commands with searchable modal (⇧⌘H) ### 🧠 Enhanced Memory & Context System - **Smart Context Selection** - Automatically select relevant messages to reduce token usage by 50-80% @@ -193,7 +193,7 @@ Add your API keys in Settings (⌘,) → General tab: - `/load` or `/list` - List and load saved conversations (⌘L) - `/delete ` - Delete a saved conversation - `/export [filename]` - Export conversation -- `/history` - Open command history modal (⌘H) +- `/history` - Open command history modal (⇧⌘H) ### Provider & Settings - `/provider [name]` - Switch or display current provider @@ -238,7 +238,7 @@ Can you review this code? @~/project/main.swift - `⌘,` - Open settings - `⌘N` - New conversation - `⌘L` - List saved conversations -- `⌘H` - Command history +- `⇧⌘H` - Command history - `Esc` - Cancel generation / Close dropdown - `↑/↓` - Navigate command dropdown (when typing `/`) - `Return` - Send message diff --git a/oAI/Resources/oAI.help/Contents/Resources/en.lproj/index.html b/oAI/Resources/oAI.help/Contents/Resources/en.lproj/index.html index 9d32f91..7592fe8 100644 --- a/oAI/Resources/oAI.help/Contents/Resources/en.lproj/index.html +++ b/oAI/Resources/oAI.help/Contents/Resources/en.lproj/index.html @@ -1535,7 +1535,7 @@ Whenever the user asks you to translate something, translate it to Norwegian Bok
    ⌘L
    Browse Conversations
    -
    ⌘H
    +
    ⇧⌘H
    Command History
    ⌘M
    diff --git a/oAI/Views/Screens/HelpView.swift b/oAI/Views/Screens/HelpView.swift index 634ec2f..3a0bf92 100644 --- a/oAI/Views/Screens/HelpView.swift +++ b/oAI/Views/Screens/HelpView.swift @@ -52,7 +52,7 @@ private let helpCategories: [CommandCategory] = [ brief: "View command history", detail: "Opens a searchable modal showing all your previous messages with timestamps in European format (dd.MM.yyyy HH:mm:ss). Search by text content or date to find specific messages. Click any entry to reuse it.", examples: ["/history"], - shortcut: "⌘H" + shortcut: "⇧⌘H" ), CommandDetail( command: "/clear", diff --git a/oAI/oAIApp.swift b/oAI/oAIApp.swift index 0858f27..5cb44da 100644 --- a/oAI/oAIApp.swift +++ b/oAI/oAIApp.swift @@ -132,7 +132,7 @@ struct oAIApp: App { Divider() Button("Command History") { chatViewModel.showHistory = true } - .keyboardShortcut("h", modifiers: .command) + .keyboardShortcut("h", modifiers: [.command, .shift]) Button("In-App Help") { chatViewModel.showHelp = true } .keyboardShortcut("/", modifiers: .command) -- 2.52.0