From 30eb7ef72da6a9aed4261fad4c2d8a149b0b96a4 Mon Sep 17 00:00:00 2001 From: Till JS Date: Sun, 26 Apr 2026 21:27:24 +0200 Subject: [PATCH] =?UTF-8?q?feat(settings):=20full=20i18n=20coverage=20?= =?UTF-8?q?=E2=80=94=20DE/EN/ES/FR/IT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Settings page on the workbench was 100% hardcoded German across 14 files / ~5200 LOC. Added a `settings` namespace (~280 keys × 5 locales) and wired every component through `$_()`. - New apps/mana/apps/web/src/lib/i18n/locales/settings/{de,en,es,fr,it}.json - searchIndex.ts now exports `getCategories(t)` + `searchSettings(t, q)`; hash-anchor lookup goes through the locale-free `findCategoryByAnchor` - VaultSection (recovery-code wizard, ZK opt-in, key rotate) + AiSettings (4 tier cards), MyDataSection (DSGVO retention/danger-zone), SyncSection, PrivacySection translated end-to-end - Locale-aware Date/Number formatting (toLocaleString uses get(locale)) in SyncSection + MyDataSection - validate:i18n-parity: 38 namespaces × 5 locales — 3323 keys aligned - svelte-check: 7639 files, 0 errors Co-Authored-By: Claude Opus 4.7 (1M context) --- .../lib/components/settings/AiSettings.svelte | 121 +++-- .../settings/ByokKeysManager.svelte | 71 ++- .../settings/SettingsSidebar.svelte | 25 +- .../lib/components/settings/searchIndex.ts | 269 ++++-------- .../settings/sections/AiSection.svelte | 5 +- .../settings/sections/GeneralSection.svelte | 53 +-- .../settings/sections/MyDataSection.svelte | 166 ++++--- .../settings/sections/PrivacySection.svelte | 47 +- .../settings/sections/SecuritySection.svelte | 5 +- .../settings/sections/SyncSection.svelte | 111 +++-- .../sections/TagPresetsSection.svelte | 47 +- .../settings/sections/VaultSection.svelte | 187 ++++---- .../web/src/lib/i18n/locales/settings/de.json | 411 +++++++++++++++++ .../web/src/lib/i18n/locales/settings/en.json | 405 +++++++++++++++++ .../web/src/lib/i18n/locales/settings/es.json | 414 ++++++++++++++++++ .../web/src/lib/i18n/locales/settings/fr.json | 414 ++++++++++++++++++ .../web/src/lib/i18n/locales/settings/it.json | 408 +++++++++++++++++ .../src/lib/modules/settings/ListView.svelte | 6 +- 18 files changed, 2614 insertions(+), 551 deletions(-) create mode 100644 apps/mana/apps/web/src/lib/i18n/locales/settings/de.json create mode 100644 apps/mana/apps/web/src/lib/i18n/locales/settings/en.json create mode 100644 apps/mana/apps/web/src/lib/i18n/locales/settings/es.json create mode 100644 apps/mana/apps/web/src/lib/i18n/locales/settings/fr.json create mode 100644 apps/mana/apps/web/src/lib/i18n/locales/settings/it.json diff --git a/apps/mana/apps/web/src/lib/components/settings/AiSettings.svelte b/apps/mana/apps/web/src/lib/components/settings/AiSettings.svelte index 232e81c72..91c5c4647 100644 --- a/apps/mana/apps/web/src/lib/components/settings/AiSettings.svelte +++ b/apps/mana/apps/web/src/lib/components/settings/AiSettings.svelte @@ -7,6 +7,7 @@ * means for privacy + speed + cost. The cloud tier is gated behind * an additional consent step the first time it's enabled. */ + import { _ } from 'svelte-i18n'; import { llmSettingsState, updateLlmSettings, tierLabel, type LlmTier } from '@mana/shared-llm'; import { isLocalLlmSupported, @@ -62,53 +63,53 @@ warning?: string; }; - const tierCards: TierCard[] = [ + const tierCards = $derived([ { tier: 'browser', icon: Cpu, - title: 'Auf deinem Gerät', - subtitle: 'Gemma 4 E2B (Google) im Browser', + title: $_('settings.ai.tier_browser_title'), + subtitle: $_('settings.ai.tier_browser_subtitle'), bullets: [ - '100% lokal — Daten verlassen dein Gerät nicht', - '~500 MB einmaliger Download', - 'Braucht WebGPU + 2 GB freien GPU-Speicher', + $_('settings.ai.tier_browser_bullet_1'), + $_('settings.ai.tier_browser_bullet_2'), + $_('settings.ai.tier_browser_bullet_3'), ], }, { tier: 'mana-server', icon: HardDrive, - title: 'Mana-Server', - subtitle: 'Selbst-gehostet auf unserem Mac Mini', + title: $_('settings.ai.tier_mana_server_title'), + subtitle: $_('settings.ai.tier_mana_server_subtitle'), bullets: [ - 'Schneller und stärker als Browser-LLM', - 'Daten laufen verschlüsselt zu unserem Server', - 'Keine Inhalte werden gespeichert', + $_('settings.ai.tier_mana_server_bullet_1'), + $_('settings.ai.tier_mana_server_bullet_2'), + $_('settings.ai.tier_mana_server_bullet_3'), ], }, { tier: 'byok', icon: Key, - title: 'Eigener API-Key', - subtitle: 'OpenAI, Anthropic, Google Gemini oder Mistral', + title: $_('settings.ai.tier_byok_title'), + subtitle: $_('settings.ai.tier_byok_subtitle'), bullets: [ - 'Direkt aus dem Browser — keine Mana-Server-Zwischenstation', - 'Du zahlst beim Provider, wir sehen nichts davon', - 'Schlüssel werden verschlüsselt in deinem Vault gespeichert', + $_('settings.ai.tier_byok_bullet_1'), + $_('settings.ai.tier_byok_bullet_2'), + $_('settings.ai.tier_byok_bullet_3'), ], }, { tier: 'cloud', icon: Cloud, - title: 'Google Gemini', - subtitle: 'Cloud-API über unseren Server-Proxy', + title: $_('settings.ai.tier_cloud_title'), + subtitle: $_('settings.ai.tier_cloud_subtitle'), bullets: [ - 'Stärkste Qualität für komplexe Aufgaben', - 'Schnellste Antworten', - 'Daten werden von Google verarbeitet', + $_('settings.ai.tier_cloud_bullet_1'), + $_('settings.ai.tier_cloud_bullet_2'), + $_('settings.ai.tier_cloud_bullet_3'), ], - warning: 'Nur empfehlenswert für nicht-sensitive Inhalte', + warning: $_('settings.ai.tier_cloud_warning'), }, - ]; + ]); function isEnabled(tier: LlmTier): boolean { return settings.allowedTiers.includes(tier); @@ -125,15 +126,11 @@
- Lokal (ohne KI) - immer aktiv + {$_('settings.ai.tier_local_title')} + {$_('settings.ai.tier_local_badge')}
-

Basis-Funktionen ohne jede KI

-

- Mana funktioniert auch ganz ohne KI: Datum-Erkennung, Suche und einfache Klassifikation - laufen über klassische Algorithmen. Manche Funktionen sind dann begrenzt, dafür ist alles - 100% offline und kostet nichts. -

+

{$_('settings.ai.tier_local_subtitle')}

+

{$_('settings.ai.tier_local_description')}

@@ -157,7 +154,7 @@
{card.title} {#if enabled} - aktiv + {$_('settings.ai.badge_active')} {/if}

{card.subtitle}

@@ -176,12 +173,15 @@ {#if card.tier === 'browser' && enabled && webgpuSupported}
{#if browserCacheReady} - ✓ Modell geladen + {$_('settings.ai.tier_browser_loaded')} {:else if localLlmStatus.current.state === 'downloading'} - Lade {defaultModelInfo.displayName} ({( - localLlmStatus.current.progress * 100 - ).toFixed(0)}%)… + {$_('settings.ai.tier_browser_loading', { + values: { + name: defaultModelInfo.displayName, + percent: (localLlmStatus.current.progress * 100).toFixed(0), + }, + })} {:else} @@ -195,8 +195,10 @@ class="action-btn" > {loadingBrowser - ? 'Lade…' - : `Modell laden (~${defaultModelInfo.downloadSizeMb} MB)`} + ? $_('settings.ai.tier_browser_load_btn_loading') + : $_('settings.ai.tier_browser_load_btn', { + values: { size: defaultModelInfo.downloadSizeMb }, + })} {/if}
@@ -204,8 +206,7 @@ {#if card.tier === 'browser' && tierBlocked}

- WebGPU nicht verfügbar in deinem Browser. Funktioniert in Chrome/Edge 113+ oder Safari - 18+. + {$_('settings.ai.tier_browser_blocked')}

{/if} @@ -227,11 +228,8 @@ onkeydown={(e) => e.stopPropagation()} role="presentation" > - - + + {/if} @@ -253,7 +251,7 @@ onkeydown={(e) => e.stopPropagation()} role="presentation" > - ✓ Cloud-Zustimmung erteilt + {$_('settings.ai.tier_cloud_consent_ok')} {/if} @@ -274,12 +272,14 @@
- Aktuelle Reihenfolge: + {$_('settings.ai.summary_label')} {#if settings.allowedTiers.length === 0} - Nur lokal (ohne KI) — die meisten KI-Funktionen sind begrenzt. + {$_('settings.ai.summary_local_only')} {:else} - {settings.allowedTiers.map((t) => tierLabel(t)).join(' → ')} → Lokal (Fallback) + {settings.allowedTiers.map((t) => tierLabel(t)).join(' → ')} → {$_( + 'settings.ai.summary_chain_local_fallback' + )} {/if}
@@ -288,18 +288,15 @@
-

Bei Fehler auf „Lokal" zurückfallen

-

- Wenn die gewählte KI-Schicht eine Anfrage nicht beantworten kann, versucht Mana es mit der - lokalen Variante (sofern verfügbar). Aus: zeigt stattdessen einen Fehler an. -

+

{$_('settings.ai.fallback_title')}

+

{$_('settings.ai.fallback_description')}

@@ -307,19 +304,15 @@
-

Quelle bei jedem KI-Resultat anzeigen

-

- Zeigt unter jeder KI-generierten Antwort eine kleine Markierung wie „Auf deinem Gerät" - oder „via Google Gemini" — damit du immer siehst, wo deine Daten gerade verarbeitet - wurden. -

+

{$_('settings.ai.show_source_title')}

+

{$_('settings.ai.show_source_description')}

diff --git a/apps/mana/apps/web/src/lib/components/settings/ByokKeysManager.svelte b/apps/mana/apps/web/src/lib/components/settings/ByokKeysManager.svelte index 0ab2d7856..ac324afc2 100644 --- a/apps/mana/apps/web/src/lib/components/settings/ByokKeysManager.svelte +++ b/apps/mana/apps/web/src/lib/components/settings/ByokKeysManager.svelte @@ -3,6 +3,7 @@ --> -