diff --git a/entrypoints/popup/index.html b/entrypoints/popup/index.html
index 4e95b5c..f608ab6 100644
--- a/entrypoints/popup/index.html
+++ b/entrypoints/popup/index.html
@@ -50,6 +50,7 @@
Settings
+
diff --git a/entrypoints/sidebar/index.html b/entrypoints/sidebar/index.html
index 15dd10d..cfab411 100644
--- a/entrypoints/sidebar/index.html
+++ b/entrypoints/sidebar/index.html
@@ -51,6 +51,7 @@
Settings
+
diff --git a/public/_locales/de/messages.json b/public/_locales/de/messages.json
new file mode 100644
index 0000000..a6b0e54
--- /dev/null
+++ b/public/_locales/de/messages.json
@@ -0,0 +1,748 @@
+{
+ "extensionName": {
+ "message": "Auto Tab Groups",
+ "description": "The name of the extension as it appears in the browser store and toolbar."
+ },
+ "extensionDescription": {
+ "message": "Gruppiert Tabs automatisch nach Domains.",
+ "description": "Short description shown in the extensions list."
+ },
+
+ "popupTitle": {
+ "message": "Auto Tab Groups",
+ "description": "Heading shown at the top of the popup/sidebar."
+ },
+ "popupGroupTabs": {
+ "message": "Tabs gruppieren",
+ "description": "Button that groups all open tabs immediately."
+ },
+ "popupUngroupAll": {
+ "message": "Alle Gruppen auflösen",
+ "description": "Button that removes every tab group."
+ },
+ "popupGenerateNewColors": {
+ "message": "Neue Farbe erzeugen",
+ "description": "Button that randomizes the colors of all groups."
+ },
+ "popupGenerateNewColorsTitle": {
+ "message": "Zufällige Gruppenfarbe. Farben werden automatisch für jede Domain/Regel gesichert und wieder hergestellt.",
+ "description": "Tooltip for the Generate New Colors button."
+ },
+ "popupCollapseAll": {
+ "message": "Alle zusammenklappen",
+ "description": "Button that collapses every group."
+ },
+ "popupExpandAll": {
+ "message": "Alle aufklappen",
+ "description": "Button that expands every group."
+ },
+
+ "settingsHeading": {
+ "message": "Einstellungen",
+ "description": "Heading for the main settings section."
+ },
+ "settingLanguage": {
+ "message": "Sprache",
+ "description": "Label for the UI language picker."
+ },
+ "settingLanguageAuto": {
+ "message": "Auto (Browser standard)",
+ "description": "Picker option that defers to the browser's UI language."
+ },
+ "settingAutoGroupMode": {
+ "message": "Autogruppierungsmodus",
+ "description": "Label for the toggle that enables automatic grouping."
+ },
+ "settingGroupBy": {
+ "message": "Gruppierung nach",
+ "description": "Label for the group-by mode selector."
+ },
+ "settingGroupByRulesOnly": {
+ "message": "Nur Regeln",
+ "description": "Option that groups only by custom rules."
+ },
+ "settingGroupByRulesAndDomain": {
+ "message": "Regeln & Domains",
+ "description": "Option that groups by rules plus base domain (popup)."
+ },
+ "settingGroupByRulesAndSubdomain": {
+ "message": "Regeln & Sub-domains",
+ "description": "Option that groups by rules plus subdomain (popup)."
+ },
+ "settingGroupByDomain": {
+ "message": "Domain",
+ "description": "Option that groups by base domain (sidebar)."
+ },
+ "settingGroupBySubdomain": {
+ "message": "Sub-domain",
+ "description": "Option that groups by subdomain (sidebar)."
+ },
+ "settingGroupNewEmptyTabs": {
+ "message": "Neuen leeren Tab in \"System\" einordnen",
+ "description": "Label for the toggle that groups blank/new tabs under a System group."
+ },
+ "settingMinimumTabsForGroup": {
+ "message": "Minimale Anzahl an Tabs für Erzeugung einer Gruppe",
+ "description": "Label for the numeric input that sets the minimum tab count required to create a group."
+ },
+ "settingAutoCollapseInactive": {
+ "message": "Autom. Zusammenklappen inaktiver Gruppen",
+ "description": "Label for the toggle that auto-collapses groups the user isn't looking at."
+ },
+ "settingCollapseDelay": {
+ "message": "Verzögerung des Zusammenklappens",
+ "description": "Label for the numeric input that sets the auto-collapse delay."
+ },
+ "settingCollapseDelayHelp": {
+ "message": "0 = sofort, oder eine Verzögerungszeit setzen (100-5000ms)",
+ "description": "Help text under the collapse-delay input."
+ },
+ "settingOpenNewTabsNextToCurrent": {
+ "message": "Neuen Tab neben aktuellen Tab öffnen",
+ "description": "Label for the toggle that opens new tabs adjacent to the active tab."
+ },
+ "settingPinnedTabsNote": {
+ "message": "Angepinnte Tabs nie gruppieren",
+ "description": "Informational note about pinned tabs."
+ },
+
+ "sortingSectionTitle": {
+ "message": "Sortierung",
+ "description": "Title for the collapsible sorting section."
+ },
+ "settingSortGroupsAlphabetically": {
+ "message": "Gruppen alphabetisch sortieren",
+ "description": "Toggle that keeps tab groups sorted alphabetically."
+ },
+ "settingSortDirection": {
+ "message": "Sortierreihenfolge",
+ "description": "Label for the sort direction toggle (A-Z vs Z-A)."
+ },
+ "settingSortDirectionAsc": {
+ "message": "A - Z",
+ "description": "Ascending alphabetical sort direction option."
+ },
+ "settingSortDirectionDesc": {
+ "message": "Z - A",
+ "description": "Descending alphabetical sort direction option."
+ },
+ "settingNumberGroups": {
+ "message": "Gruppennummerierung (1. AI, 2. Docs...)",
+ "description": "Toggle that prefixes group titles with their sort index."
+ },
+ "settingNumberGroupsHelp": {
+ "message": "Positionsnummer für schnellen Zugriff zum Titel hizufügen",
+ "description": "Help text describing the Number Groups toggle."
+ },
+
+ "aiSectionTitle": {
+ "message": "KI Funktionen",
+ "description": "Title for the AI features section."
+ },
+ "aiExperimentalBadge": {
+ "message": "Experimentell",
+ "description": "Badge shown next to the AI Features title."
+ },
+ "aiHelpTooltip": {
+ "message": "KI generierte Vorschläge für Tabgruppierung. Diese Funktion ist experimentell. Alle Prozesse laufen lokal in Browser - Keine Datenübermittlung an externe Server",
+ "description": "Tooltip explaining the AI Features."
+ },
+ "aiBadgeOn": {
+ "message": "An",
+ "description": "Status badge shown when AI is enabled."
+ },
+ "aiBadgeOff": {
+ "message": "Aus",
+ "description": "Status badge shown when AI is disabled."
+ },
+ "aiEnable": {
+ "message": "KI einschalten",
+ "description": "Toggle that enables or disables AI features."
+ },
+ "aiModelLabel": {
+ "message": "Modell",
+ "description": "Label for the AI model selector."
+ },
+ "aiStatusLabel": {
+ "message": "Status:",
+ "description": "Label for the AI model status."
+ },
+ "aiStatusIdle": {
+ "message": "Leerlauf",
+ "description": "AI model status: idle."
+ },
+ "aiStatusReady": {
+ "message": "Fertig",
+ "description": "AI model status: ready."
+ },
+ "aiStatusLoading": {
+ "message": "Lade $progress$%",
+ "description": "AI model status while loading, with a progress percentage.",
+ "placeholders": {
+ "progress": { "content": "$1", "example": "42" }
+ }
+ },
+ "aiStatusError": {
+ "message": "Fehler",
+ "description": "AI model status: error."
+ },
+ "aiLoadModel": {
+ "message": "Lade Modell",
+ "description": "Button that starts loading the AI model."
+ },
+ "aiUnloadModel": {
+ "message": "Lösche Modell",
+ "description": "Button that unloads the AI model."
+ },
+ "aiLoadingButton": {
+ "message": "Lade...",
+ "description": "Label shown on the load button while loading."
+ },
+ "aiRetryLoad": {
+ "message": "Neu laden",
+ "description": "Button shown after an AI model load error."
+ },
+ "aiWebGpuUnavailable": {
+ "message": "WebGPU kann nicht angesprochen werden. KI Funktionen benötigen einen Browser mit WebGPU Unterstützung.",
+ "description": "Warning shown when WebGPU is not supported."
+ },
+ "aiDownloadNote": {
+ "message": "Modelle laufen lokal im Browser. Zuvor muß das Modell heruntergeladen werden (~250MB-900MB).",
+ "description": "Help text beneath the load model button."
+ },
+ "aiSuggestGroups": {
+ "message": "Vorgeschlagene Gruppe",
+ "description": "Button that asks the AI to suggest tab groups."
+ },
+ "aiAnalyzing": {
+ "message": "Analysiere den Tab...",
+ "description": "Status text while the AI analyzes open tabs."
+ },
+ "aiNoSuggestions": {
+ "message": "Kein Vorschlag gefunden",
+ "description": "Status text shown when the AI returns zero suggestions."
+ },
+ "aiFailedToGetSuggestions": {
+ "message": "Vorschlagsermittlung fehlgeschlagen",
+ "description": "Error shown when AI suggestion fails."
+ },
+ "aiDismiss": {
+ "message": "Ablehnen",
+ "description": "Button that dismisses AI suggestions."
+ },
+ "aiApply": {
+ "message": "Akzeptieren",
+ "description": "Button that applies an AI suggestion."
+ },
+ "aiApplying": {
+ "message": "Anwenden...",
+ "description": "Button label while applying a suggestion."
+ },
+ "aiApplied": {
+ "message": "Angewendet!",
+ "description": "Button label after applying a suggestion."
+ },
+ "aiFailed": {
+ "message": "Fehlgeschlagen",
+ "description": "Button label after a suggestion fails."
+ },
+ "aiCreateRule": {
+ "message": "Regel erzeugen",
+ "description": "Button that creates a rule from a suggestion."
+ },
+ "aiTabsCount": {
+ "message": "$count$ tab$plural$",
+ "description": "Tab count label for a suggestion.",
+ "placeholders": {
+ "count": { "content": "$1" },
+ "plural": { "content": "$2" }
+ }
+ },
+ "aiAppliedWithStale": {
+ "message": "Angewendet ($count$ tab$plural$ geschlossen)",
+ "description": "Shown when a suggestion is applied but some tabs were closed.",
+ "placeholders": {
+ "count": { "content": "$1" },
+ "plural": { "content": "$2" }
+ }
+ },
+ "aiFirefoxNotice": {
+ "message": "KI Funktionalität ist zur Zeit nur auf Chrome verfügbar. Firefox Unterstützung kommt später.",
+ "description": "Notice shown to Firefox users."
+ },
+
+ "rulesSectionTitle": {
+ "message": "Angepasste Regeln",
+ "description": "Title for the custom rules section."
+ },
+ "rulesAddNewRule": {
+ "message": "Neue Regel hinzufügen",
+ "description": "Button that opens the new rule dialog."
+ },
+ "rulesExport": {
+ "message": "Export",
+ "description": "Button that exports rules to JSON."
+ },
+ "rulesImport": {
+ "message": "Import",
+ "description": "Button that imports rules from JSON."
+ },
+ "rulesExportTitle": {
+ "message": "Exportieren aller Regeln in eine JSON Datei",
+ "description": "Tooltip on the Export button."
+ },
+ "rulesImportTitle": {
+ "message": "Importiere Regel aus einer JSON Datei",
+ "description": "Tooltip on the Import button."
+ },
+ "rulesExportImportHelp": {
+ "message": "Exportiere/importiere Regeln als JSON Datei für Backup oder Verteilung",
+ "description": "Help text under the export/import buttons."
+ },
+ "rulesEmptyState": {
+ "message": "Keine angepassten Regeln vorhanden. Erzeuge deine erste Regel für die Tapgruppierung nach deinen Wünschen!",
+ "description": "Shown when there are no custom rules."
+ },
+ "rulesEdit": {
+ "message": "Editieren",
+ "description": "Edit button on a rule row."
+ },
+ "rulesDelete": {
+ "message": "Löschen",
+ "description": "Delete button on a rule row."
+ },
+ "rulesEditTitle": {
+ "message": "Editiere Regel",
+ "description": "Tooltip for the edit button."
+ },
+ "rulesDeleteTitle": {
+ "message": "Lösche Regel",
+ "description": "Tooltip for the delete button."
+ },
+ "rulesAddTabTitle": {
+ "message": "Tab zu existierender Regel hinzufügen",
+ "description": "Tooltip for the + button that adds the current tab to a rule."
+ },
+ "rulesDeleteConfirm": {
+ "message": "Wollen sie die Regel \"$name$\" wirklich löschen?",
+ "description": "Confirmation prompt before deleting a rule.",
+ "placeholders": {
+ "name": { "content": "$1" }
+ }
+ },
+ "rulesFailedToLoad": {
+ "message": "Laden der angepassten Regeln fehlgeschlagen!",
+ "description": "Error when loading rules fails."
+ },
+ "rulesFailedToDelete": {
+ "message": "Löschen der Regel fehlgeschlagen!",
+ "description": "Error when deleting a rule fails."
+ },
+ "rulesExportSuccess": {
+ "message": "Regel erfolgreich exportiert!",
+ "description": "Confirmation after exporting rules."
+ },
+ "rulesFailedToExport": {
+ "message": "Export der Regeln fehlgeschlagen!",
+ "description": "Error when export fails."
+ },
+ "rulesImportSuccess": {
+ "message": "Regel erfolgreich importiert!",
+ "description": "Confirmation after importing rules."
+ },
+ "rulesImportSummary": {
+ "message": "Import erfolgreich!\nImportiert: $imported$ Regel(n)\nÜbersprungen: $skipped$ Regel(n)",
+ "description": "Summary shown after rules are imported.",
+ "placeholders": {
+ "imported": { "content": "$1" },
+ "skipped": { "content": "$2" }
+ }
+ },
+ "rulesFailedToImport": {
+ "message": "Import der Regeln fehlgeschlagen!",
+ "description": "Error when import fails."
+ },
+ "rulesImportReplacePrompt": {
+ "message": "Wollen sie alle Regeln ersetzen?\n\nKlick OK um alle Regeln durch die importierten zu ERSETZEN\nKlick Abbrechen um die importierten Regeln HINZUZUFÜGEN",
+ "description": "Prompt that asks whether to merge or replace on import."
+ },
+ "rulesNoExport": {
+ "message": "Keine Regeln zum exportieren",
+ "description": "Tooltip shown on a disabled export button when there are no rules."
+ },
+ "rulesNoDomains": {
+ "message": "Keine Domains",
+ "description": "Shown when a rule has no configured domains."
+ },
+ "rulesDomainsSeparator": {
+ "message": " und $count$ weitere",
+ "description": "Appended to truncated domain lists.",
+ "placeholders": {
+ "count": { "content": "$1" }
+ }
+ },
+ "rulesAddTabNoTab": {
+ "message": "Kein aktiver Tab gefunden",
+ "description": "Tooltip shown on the add-tab button when no active tab is available."
+ },
+ "rulesAddTabCantExtract": {
+ "message": "Kann die Domain von diesem Tab nicht ermitteln",
+ "description": "Tooltip when the current tab's URL has no domain."
+ },
+ "rulesAddTabAlreadyExists": {
+ "message": "Domain ist bereits in dieser Regel",
+ "description": "Tooltip when the tab's domain is already part of the rule."
+ },
+ "rulesAddTabAdded": {
+ "message": "Hinzugefügt!",
+ "description": "Tooltip shown briefly after adding a tab to a rule."
+ },
+ "rulesAddTabFailed": {
+ "message": "Hinzufügen der Domain fehlgeschlagen",
+ "description": "Tooltip when adding a domain fails."
+ },
+
+ "blacklistSectionTitle": {
+ "message": "Sperrliste",
+ "description": "Title for the blacklist section."
+ },
+ "blacklistAddButton": {
+ "message": "Zur Sperrliste hinzufügen",
+ "description": "Button to add a domain to the blacklist."
+ },
+ "blacklistHelp": {
+ "message": "Gesperrte Domains werden niemals gruppiert",
+ "description": "Help text under the blacklist section."
+ },
+ "blacklistEmpty": {
+ "message": "Keine gesperrten Domains vorhanden.",
+ "description": "Shown when the blacklist is empty."
+ },
+ "blacklistEditTitle": {
+ "message": "Sperrliste bearbeiten",
+ "description": "Tooltip for the blacklist edit button."
+ },
+ "blacklistDeleteTitle": {
+ "message": "Sperrliste leeren",
+ "description": "Tooltip for the blacklist delete button."
+ },
+
+ "advancedSectionTitle": {
+ "message": "Erweiterte Einstellungen",
+ "description": "Title for the advanced settings section."
+ },
+ "advancedHideContextMenu": {
+ "message": "Rechts-Klick Kontextmenu deaktivieren",
+ "description": "Toggle that hides the extension's context menu items."
+ },
+ "advancedHideContextMenuHelp": {
+ "message": "Wenn aktiviert, werden keine Auto Tab Group Einträge zum Kontext Menu hinzugefügt.",
+ "description": "Help text for the hide context menu toggle."
+ },
+
+ "footerMadeBy": {
+ "message": "Erstellt von",
+ "description": "Prefix for the author attribution in the footer."
+ },
+ "footerFor": {
+ "message": "für",
+ "description": "Connector text: 'Made by X, for Chrome'."
+ },
+ "footerBrowserChrome": {
+ "message": "Chrome",
+ "description": "Name of the Chrome browser in the footer."
+ },
+ "footerBrowserFirefox": {
+ "message": "Firefox",
+ "description": "Name of the Firefox browser in the footer."
+ },
+ "footerFeedback": {
+ "message": "Rückmeldung & Anregungen & Support",
+ "description": "Text of the feedback link."
+ },
+ "footerVersion": {
+ "message": "Version:",
+ "description": "Prefix before the version number."
+ },
+
+ "contextMenuCreateRuleFromGroup": {
+ "message": "Erzeuge Regel von Gruppe",
+ "description": "Right-click menu: create a custom rule from the clicked tab's group."
+ },
+ "contextMenuAddTabToExistingRule": {
+ "message": "Tab zu existierender Regel hinzufügen",
+ "description": "Right-click menu: submenu to add the current tab's domain to an existing rule."
+ },
+ "contextMenuAddToBlacklist": {
+ "message": "Zur Sperrliste hinzufügen",
+ "description": "Right-click menu: add the current tab's domain to the blacklist."
+ },
+ "contextMenuNoRulesYet": {
+ "message": "Keine Regeln vorhanden",
+ "description": "Disabled placeholder shown when the Add Tab submenu has no rules."
+ },
+
+ "ruleModalCreateTitle": {
+ "message": "Angepasste Regel erzeugen",
+ "description": "Title shown when creating a new rule."
+ },
+ "ruleModalEditTitle": {
+ "message": "Angepasste Regel bearbeiten",
+ "description": "Title shown when editing an existing rule."
+ },
+ "ruleModalNameLabel": {
+ "message": "Regelname",
+ "description": "Label for the rule name input."
+ },
+ "ruleModalNamePlaceholder": {
+ "message": "z.b., Arbeitsapps",
+ "description": "Placeholder for the rule name input."
+ },
+ "ruleModalNameHelp": {
+ "message": "Unterstützt alle Sprachen wie z.b. Chinesisch, Japanisch, Koreanisch und Emojis",
+ "description": "Help text under the rule name input."
+ },
+ "ruleModalAiAssistLabel": {
+ "message": "KI Assistent",
+ "description": "Label for the AI assist section."
+ },
+ "ruleModalAiAssistPlaceholder": {
+ "message": "Beschreibe deine Regel, z.b., 'Group all Google services' or 'Group AWS console tabs'",
+ "description": "Placeholder for the AI assist input."
+ },
+ "ruleModalAiGenerate": {
+ "message": "Erzeugen",
+ "description": "Button that asks the AI to generate a rule."
+ },
+ "ruleModalAiAssistHelp": {
+ "message": "Beschreibe, was du willst und die KI wird Namen, Domains und Farbe vorschlagen",
+ "description": "Help text under the AI assist input."
+ },
+ "ruleModalPatternModeLabel": {
+ "message": "Muster Modus",
+ "description": "Label for the pattern mode toggle."
+ },
+ "ruleModalPatternModeSimple": {
+ "message": "Einfach (Domains)",
+ "description": "Simple pattern mode: matches whole domains."
+ },
+ "ruleModalPatternModeExplicit": {
+ "message": "Speziell (komplette URLs)",
+ "description": "Explicit pattern mode: matches full URLs."
+ },
+ "ruleModalSimpleModeHint": {
+ "message": "Gruppiere alle Seiten mit dieser Domain",
+ "description": "Hint shown in simple pattern mode."
+ },
+ "ruleModalExplicitModeHint": {
+ "message": "Gruppiere nur Seiten, die auf das URL Muster passen",
+ "description": "Hint shown in explicit pattern mode."
+ },
+ "ruleModalPatternsLabel": {
+ "message": "URL Muster (eine pro Zeile)",
+ "description": "Label for the patterns textarea."
+ },
+ "ruleModalPatternsHelp": {
+ "message": "Akzeptiert: Domains, wildcards (*.example.com), Pfade (example.com/api/*), IP Adressen",
+ "description": "Help text for the patterns textarea."
+ },
+ "ruleModalColorLabel": {
+ "message": "Gruppenfarbe",
+ "description": "Label for the color picker."
+ },
+ "ruleModalColorBlue": { "message": "Blau", "description": "Color option: blue." },
+ "ruleModalColorRed": { "message": "Rot", "description": "Color option: red." },
+ "ruleModalColorYellow": { "message": "Gelb", "description": "Color option: yellow." },
+ "ruleModalColorGreen": { "message": "Grün", "description": "Color option: green." },
+ "ruleModalColorPink": { "message": "Rosa", "description": "Color option: pink." },
+ "ruleModalColorPurple": { "message": "Violett", "description": "Color option: purple." },
+ "ruleModalColorCyan": { "message": "Türkis", "description": "Color option: cyan." },
+ "ruleModalColorOrange": { "message": "Orange", "description": "Color option: orange." },
+ "ruleModalColorGrey": { "message": "Grau", "description": "Color option: grey." },
+ "ruleModalEnabledLabel": {
+ "message": "Aktiv",
+ "description": "Checkbox: whether the rule is enabled."
+ },
+ "ruleModalSave": {
+ "message": "Speichere Regel",
+ "description": "Submit button for the rule form."
+ },
+ "ruleModalUpdate": {
+ "message": "Aktualisiere Regel",
+ "description": "Submit button when editing an existing rule."
+ },
+ "ruleModalCancel": {
+ "message": "Abbrechen",
+ "description": "Cancel button for the rule form."
+ },
+ "ruleModalConflictTitle": {
+ "message": "Musterkonflikt erkannt",
+ "description": "Heading of the conflict warning box."
+ },
+ "ruleModalConflictSubtitle": {
+ "message": "Diese Muster kollidiert mit existierenden Regeln. Tabs, die zu mehreren Regeln passen, werden nur einer Gruppe zugeordnet.",
+ "description": "Subtitle of the conflict warning."
+ },
+ "ruleModalAiSuggestions": {
+ "message": "KI Vorschlag",
+ "description": "Heading for the AI-generated resolution suggestions."
+ },
+ "ruleModalSaveAnyway": {
+ "message": "Trotzdem Speichern",
+ "description": "Button that saves the rule despite conflicts."
+ },
+ "ruleModalGoBack": {
+ "message": "Zurück",
+ "description": "Button that returns to editing after a conflict warning."
+ },
+ "ruleModalChecking": {
+ "message": "Prüfen...",
+ "description": "Label shown on the save button while checking for conflicts."
+ },
+ "ruleModalGenerating": {
+ "message": "Erzeugen...",
+ "description": "Label shown on the AI generate button while generating a rule."
+ },
+ "ruleModalAiThinking": {
+ "message": "KI denkt nach...",
+ "description": "Status text while the AI generates a rule."
+ },
+ "ruleModalAiNeedsModel": {
+ "message": "Wähle ein KI Modell von dem KI Eigenschaftspopup für den KI Assistent",
+ "description": "Status shown when AI Assist is invoked but no model is loaded."
+ },
+ "ruleModalAiGenerated": {
+ "message": "Regel erzeugt! Überprüfe und bearbeite unten, dann Speichern.",
+ "description": "Status after the AI generates a rule."
+ },
+ "ruleModalAiGenerateError": {
+ "message": "Regelerzeugung gescheitert. Versuche deine Beschreibung zu optimieren.",
+ "description": "Error shown when AI rule generation fails."
+ },
+ "ruleModalAiEnterDescription": {
+ "message": "Bitte gebe eine Beschreibung ein",
+ "description": "Error shown when AI Assist is triggered with no description."
+ },
+ "ruleModalEnterPattern": {
+ "message": "Bitte gebe mindestens ein URL Muster an",
+ "description": "Alert shown when submitting with no patterns."
+ },
+ "ruleModalEnterName": {
+ "message": "Bitte gebe einen Name für die Regel ein",
+ "description": "Alert shown when submitting a rule with no name."
+ },
+ "ruleModalFailedToLoad": {
+ "message": "Laden der Regel zum Bearbeiten gescheitert",
+ "description": "Alert when the rule modal can't load the rule."
+ },
+ "ruleModalFailedToSave": {
+ "message": "Speichern der Regel zum Bearbeiten gescheitert",
+ "description": "Alert when saving a rule fails."
+ },
+
+ "importPageTitle": {
+ "message": "Importiere Regeln",
+ "description": "Title for the import rules page."
+ },
+ "importDropInstruction": {
+ "message": "Ziehe eine JSON Datei hierher",
+ "description": "Instruction shown in the import drop zone."
+ },
+ "importOr": {
+ "message": "oder",
+ "description": "Separator between drag-drop and button."
+ },
+ "importBrowseFiles": {
+ "message": "Suche Datei",
+ "description": "Button that opens the file picker."
+ },
+ "importPreviewHeading": {
+ "message": "Vorschau",
+ "description": "Heading above the import preview."
+ },
+ "importModeLabel": {
+ "message": "Import Modus",
+ "description": "Label above the import mode radio buttons."
+ },
+ "importMerge": {
+ "message": "Zusammenführen mit vorhandenen Regeln",
+ "description": "Radio option: merge on import."
+ },
+ "importReplace": {
+ "message": "Alle vorhandenen Regeln ersetzen",
+ "description": "Radio option: replace on import."
+ },
+ "importButton": {
+ "message": "Importiere Regeln",
+ "description": "Button that performs the import."
+ },
+ "importCancel": {
+ "message": "Abbrechen",
+ "description": "Cancel button on the import page."
+ },
+ "importStatValid": {
+ "message": "Gültige Regeln",
+ "description": "Label for the valid rule count in the import preview."
+ },
+ "importStatInvalid": {
+ "message": "Ungültig (wird ignoriert)",
+ "description": "Label for the invalid rule count in the import preview."
+ },
+ "importPatternsSuffix": {
+ "message": "$count$ Muster",
+ "description": "Label showing pattern count for an imported rule.",
+ "placeholders": {
+ "count": { "content": "$1" }
+ }
+ },
+ "importMoreRules": {
+ "message": "...und $count$ mehr Regeln",
+ "description": "Shown when more rules exist beyond the preview slice.",
+ "placeholders": {
+ "count": { "content": "$1" }
+ }
+ },
+ "importUnnamed": {
+ "message": "Unbekannt",
+ "description": "Placeholder name for rules with no name."
+ },
+ "importImporting": {
+ "message": "Importiere...",
+ "description": "Label on the import button while importing."
+ },
+ "importSuccess": {
+ "message": "Erfolgreich importierte $count$ Regeln",
+ "description": "Success message after import.",
+ "placeholders": {
+ "count": { "content": "$1" }
+ }
+ },
+ "importSuccessWithSkipped": {
+ "message": "Erfolgreich importierte $count$ Regeln ($skipped$ ignoriert)",
+ "description": "Success message when some rules are skipped.",
+ "placeholders": {
+ "count": { "content": "$1" },
+ "skipped": { "content": "$2" }
+ }
+ },
+ "importFailed": {
+ "message": "Import fehlgeschlagen",
+ "description": "Generic import failure message."
+ },
+ "importInvalidJson": {
+ "message": "Kein JSON",
+ "description": "Error when file is not valid JSON."
+ },
+ "importInvalidFormat": {
+ "message": "Ungültiges Dateiformat: Fehlende 'rules' Sektion",
+ "description": "Error when file has no 'rules' key."
+ },
+ "importNoRules": {
+ "message": "Keine Regel in der Datei gefunden",
+ "description": "Error when file has no rules."
+ },
+ "importSelectJson": {
+ "message": "Bitte eine JSON Datei auswählen",
+ "description": "Error when a non-JSON file is selected."
+ }
+}
diff --git a/types/storage.ts b/types/storage.ts
index 6748320..62afb4d 100644
--- a/types/storage.ts
+++ b/types/storage.ts
@@ -24,7 +24,7 @@ export type SortDirection = "asc" | "desc"
* User-selected UI locale. "auto" defers to the browser's UI locale.
* Widen this union when shipping additional locales.
*/
-export type UserLocale = "auto" | "en" | "he" | "ar" | "es" | "hi" | "ru" | "zh"
+export type UserLocale = "auto" | "en" | "he" | "ar" | "es" | "hi" | "ru" | "zh" | "de"
/**
* Mapping of group titles to their colors