feat(i18n): replace 126 hardcoded German strings with $_() calls (Phase 4)

Systematically replace hardcoded UI strings across 48 files with svelte-i18n
$_('common.*') calls. Added 14 new common translation keys (saving, close,
create, creating, edit, add, search, settings, upload, uploading,
error_saving, error_loading, error_deleting, click_to_close) in all 5 languages.

Covers: profile modals, onboarding, workbench, calendar, cards, contacts,
context, credits, gifts, inventar, memoro, moodlit, mukke, nutriphi, photos,
picture, planta, questions, settings, skilltree, storage, subscription,
times, todo, uload — all common button/action/error strings now i18n-ready.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-04-02 18:09:10 +02:00
parent 2e44a717d3
commit 033d070362
48 changed files with 209 additions and 82 deletions

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { authStore } from '$lib/stores/auth.svelte';
import { profileService } from '$lib/api/profile';
import { Camera, Check } from '@manacore/shared-icons';
@ -70,7 +71,7 @@
// Refresh auth store
// The profile update should update the user in authStore
} catch (e) {
error = e instanceof Error ? e.message : 'Fehler beim Speichern';
error = e instanceof Error ? e.message : $_('common.error_saving');
} finally {
saving = false;
}

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { profileService } from '$lib/api/profile';
import { Warning, XCircle } from '@manacore/shared-icons';
@ -141,7 +142,7 @@
onclick={onClose}
class="flex-1 px-4 py-2 border rounded-lg hover:bg-muted transition-colors"
>
Abbrechen
{$_('common.cancel')}
</button>
<button
onclick={handleContinue}
@ -198,7 +199,7 @@
disabled={deleting}
class="flex-1 px-4 py-2 border rounded-lg hover:bg-muted transition-colors disabled:opacity-50"
>
Zurück
{$_('common.back')}
</button>
<button
onclick={handleDelete}

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { profileService, type UserProfile } from '$lib/api/profile';
import { PencilSimple } from '@manacore/shared-icons';
@ -119,7 +120,7 @@
onSuccess(updatedUser);
onClose();
} catch (e) {
error = e instanceof Error ? e.message : 'Fehler beim Speichern';
error = e instanceof Error ? e.message : $_('common.error_saving');
} finally {
saving = false;
uploadingAvatar = false;
@ -271,7 +272,7 @@
disabled={saving || uploadingAvatar}
class="flex-1 px-4 py-2 border rounded-lg hover:bg-muted transition-colors disabled:opacity-50"
>
Abbrechen
{$_('common.cancel')}
</button>
<button
type="submit"
@ -294,9 +295,9 @@
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
<span>{uploadingAvatar ? 'Hochladen...' : 'Speichern...'}</span>
<span>{uploadingAvatar ? $_('common.uploading') : $_('common.saving')}</span>
{:else}
Speichern
{$_('common.save')}
{/if}
</button>
</div>

View file

@ -3,6 +3,7 @@
Lazy-loads the app's AppView component and renders it inside the page shell.
-->
<script lang="ts">
import { _ } from 'svelte-i18n';
import {
X,
Minus,
@ -117,7 +118,7 @@
{#if maximized}<CornersIn size={14} />{:else}<CornersOut size={14} />{/if}
</button>
{/if}
<button class="header-btn" onclick={onClose} title="Schließen">
<button class="header-btn" onclick={onClose} title={$_('common.close')}>
<X size={14} />
</button>
</div>

View file

@ -2,6 +2,7 @@
AppPagePicker — Shows available apps to add as pages to the workbench.
-->
<script lang="ts">
import { _ } from 'svelte-i18n';
import { X } from '@manacore/shared-icons';
import { APP_REGISTRY } from './app-registry';
@ -19,7 +20,7 @@
<div class="app-picker">
<div class="picker-header">
<h3 class="picker-title">App hinzufügen</h3>
<button class="close-btn" onclick={onClose} title="Schließen"><X size={16} /></button>
<button class="close-btn" onclick={onClose} title={$_('common.close')}><X size={16} /></button>
</div>
<div class="picker-list">
{#each availableApps as app, i (app.id)}

View file

@ -1,7 +1,21 @@
{
"save": "Speichern",
"saving": "Speichern...",
"cancel": "Abbrechen",
"delete": "Löschen",
"back": "Zurück",
"loading": "Lädt..."
"loading": "Lädt...",
"close": "Schließen",
"create": "Erstellen",
"creating": "Erstelle...",
"edit": "Bearbeiten",
"add": "Hinzufügen",
"search": "Suchen...",
"settings": "Einstellungen",
"upload": "Hochladen",
"uploading": "Hochladen...",
"error_saving": "Fehler beim Speichern",
"error_loading": "Fehler beim Laden",
"error_deleting": "Fehler beim Löschen",
"click_to_close": "Klicken zum Schließen"
}

View file

@ -1,7 +1,21 @@
{
"save": "Save",
"saving": "Saving...",
"cancel": "Cancel",
"delete": "Delete",
"back": "Back",
"loading": "Loading..."
"loading": "Loading...",
"close": "Close",
"create": "Create",
"creating": "Creating...",
"edit": "Edit",
"add": "Add",
"search": "Search...",
"settings": "Settings",
"upload": "Upload",
"uploading": "Uploading...",
"error_saving": "Error saving",
"error_loading": "Error loading",
"error_deleting": "Error deleting",
"click_to_close": "Click to close"
}

View file

@ -1,7 +1,21 @@
{
"save": "Guardar",
"saving": "Guardando...",
"cancel": "Cancelar",
"delete": "Eliminar",
"back": "Atrás",
"loading": "Cargando..."
"loading": "Cargando...",
"close": "Cerrar",
"create": "Crear",
"creating": "Creando...",
"edit": "Editar",
"add": "Añadir",
"search": "Buscar...",
"settings": "Ajustes",
"upload": "Subir",
"uploading": "Subiendo...",
"error_saving": "Error al guardar",
"error_loading": "Error al cargar",
"error_deleting": "Error al eliminar",
"click_to_close": "Clic para cerrar"
}

View file

@ -1,7 +1,21 @@
{
"save": "Enregistrer",
"saving": "Enregistrement...",
"cancel": "Annuler",
"delete": "Supprimer",
"back": "Retour",
"loading": "Chargement..."
"loading": "Chargement...",
"close": "Fermer",
"create": "Créer",
"creating": "Création...",
"edit": "Modifier",
"add": "Ajouter",
"search": "Rechercher...",
"settings": "Paramètres",
"upload": "Télécharger",
"uploading": "Téléchargement...",
"error_saving": "Erreur lors de l'enregistrement",
"error_loading": "Erreur lors du chargement",
"error_deleting": "Erreur lors de la suppression",
"click_to_close": "Cliquer pour fermer"
}

View file

@ -1,7 +1,21 @@
{
"save": "Salva",
"saving": "Salvataggio...",
"cancel": "Annulla",
"delete": "Elimina",
"back": "Indietro",
"loading": "Caricamento..."
"loading": "Caricamento...",
"close": "Chiudi",
"create": "Crea",
"creating": "Creazione...",
"edit": "Modifica",
"add": "Aggiungi",
"search": "Cerca...",
"settings": "Impostazioni",
"upload": "Carica",
"uploading": "Caricamento...",
"error_saving": "Errore durante il salvataggio",
"error_loading": "Errore durante il caricamento",
"error_deleting": "Errore durante l'eliminazione",
"click_to_close": "Clicca per chiudere"
}

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { getContext } from 'svelte';
import { eventsStore } from '../stores/events.svelte';
import { getCalendarById, getCalendarColor } from '../queries';
@ -173,18 +174,22 @@
<button class="btn btn-ghost" onclick={copyToClipboard} title="Kopieren">
{#if copied}<Check size={16} />{:else}<Copy size={16} />{/if}
</button>
<button class="btn btn-ghost" onclick={() => (isEditing = true)} title="Bearbeiten">
<button
class="btn btn-ghost"
onclick={() => (isEditing = true)}
title={$_('common.edit')}
>
<PencilSimple size={16} />
</button>
<button
class="btn btn-ghost text-destructive"
onclick={handleDeleteClick}
title="Löschen"
title={$_('common.delete')}
>
<Trash size={16} />
</button>
{/if}
<button class="btn btn-ghost btn-close" onclick={onClose} aria-label="Schließen">
<button class="btn btn-ghost btn-close" onclick={onClose} aria-label={$_('common.close')}>
<X size={20} />
</button>
</div>
@ -290,7 +295,7 @@
Alle Termine der Serie
</button>
<button class="btn btn-ghost" onclick={() => (showDeleteOptions = false)}>
Abbrechen
{$_('common.cancel')}
</button>
</div>
</div>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { getContext } from 'svelte';
import { getDefaultCalendar } from '../queries';
import type { Calendar, CalendarEvent } from '../types';
@ -214,9 +215,11 @@
</div>
<div class="form-actions">
<button type="button" class="btn btn-secondary" onclick={onCancel}> Abbrechen </button>
<button type="button" class="btn btn-secondary" onclick={onCancel}>
{$_('common.cancel')}
</button>
<button type="submit" class="btn btn-primary" disabled={submitting || !title.trim()}>
{mode === 'create' ? 'Erstellen' : 'Speichern'}
{mode === 'create' ? $_('common.create') : $_('common.save')}
</button>
</div>
</form>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { getContext, onMount, tick } from 'svelte';
import { getDefaultCalendar, getCalendarColor } from '../queries';
import type { Calendar } from '../types';
@ -139,7 +140,7 @@
<!-- Header -->
<div class="popover-header">
<span class="header-title">Neuer Termin</span>
<button type="button" class="close-btn" onclick={onClose} aria-label="Schließen">
<button type="button" class="close-btn" onclick={onClose} aria-label={$_('common.close')}>
<X size={16} />
</button>
</div>
@ -238,14 +239,14 @@
<!-- Actions -->
<div class="popover-actions">
<button type="button" onclick={onClose} class="cancel-btn">Abbrechen</button>
<button type="button" onclick={onClose} class="cancel-btn">{$_('common.cancel')}</button>
<button
type="submit"
disabled={!title.trim()}
class="save-btn"
style="background-color: {calendarColor};"
>
Speichern
{$_('common.save')}
</button>
</div>
</form>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { deckStore } from '../stores/decks.svelte';
import { TagField, ColorPicker, COLORS_12, DEFAULT_COLOR } from '@manacore/shared-ui';
import { useAllTags } from '@manacore/shared-stores';
@ -135,14 +136,14 @@
class="rounded-lg px-4 py-2 text-sm text-muted-foreground hover:text-foreground"
onclick={handleClose}
>
Abbrechen
{$_('common.cancel')}
</button>
<button
type="submit"
class="rounded-lg bg-primary px-4 py-2 text-sm text-white disabled:opacity-50"
disabled={submitting || !title.trim()}
>
{submitting ? 'Erstelle...' : 'Deck erstellen'}
{submitting ? $_('common.creating') : 'Deck erstellen'}
</button>
</div>
</form>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { X } from '@manacore/shared-icons';
interface Props {
@ -85,14 +86,14 @@
onclick={onClose}
disabled={loading}
>
Abbrechen
{$_('common.cancel')}
</button>
<button
type="submit"
class="rounded-lg bg-primary px-4 py-2 text-sm font-medium text-white hover:bg-primary/90 disabled:opacity-50"
disabled={!name.trim() || loading}
>
{loading ? 'Erstelle...' : 'Erstellen'}
{loading ? $_('common.creating') : $_('common.create')}
</button>
</div>
</form>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import type { Skill, SkillBranch } from '../types';
import { BRANCH_INFO } from '../types';
import { X } from '@manacore/shared-icons';
@ -111,14 +112,14 @@
onclick={onClose}
class="flex-1 rounded-lg border border-gray-600 bg-transparent px-4 py-2 font-medium text-gray-300 transition-colors hover:bg-gray-700"
>
Abbrechen
{$_('common.cancel')}
</button>
<button
type="submit"
disabled={!name.trim() || saving}
class="flex-1 rounded-lg bg-emerald-600 px-4 py-2 font-medium text-white transition-colors hover:bg-emerald-500 disabled:cursor-not-allowed disabled:opacity-50"
>
{saving ? 'Speichern...' : 'Erstellen'}
{saving ? $_('common.saving') : $_('common.create')}
</button>
</div>
</form>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import type { Skill } from '../types';
import { LEVEL_NAMES } from '../types';
import { X, Lightning, Clock, Star } from '@manacore/shared-icons';
@ -156,14 +157,14 @@
onclick={onClose}
class="flex-1 rounded-lg border border-gray-600 bg-transparent px-4 py-2 font-medium text-gray-300 transition-colors hover:bg-gray-700"
>
Abbrechen
{$_('common.cancel')}
</button>
<button
type="submit"
disabled={xp <= 0 || saving}
class="flex-1 rounded-lg bg-emerald-600 px-4 py-2 font-medium text-white transition-colors hover:bg-emerald-500 disabled:cursor-not-allowed disabled:opacity-50"
>
{saving ? 'Speichern...' : 'XP vergeben'}
{saving ? $_('common.saving') : 'XP vergeben'}
</button>
</div>
</form>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import type { Skill, SkillBranch } from '../types';
import { BRANCH_INFO } from '../types';
import { X, Trash } from '@manacore/shared-icons';
@ -82,13 +83,13 @@
onclick={() => (showDeleteConfirm = false)}
class="flex-1 rounded-lg border border-gray-600 bg-transparent px-4 py-2 font-medium text-gray-300 transition-colors hover:bg-gray-700"
>
Abbrechen
{$_('common.cancel')}
</button>
<button
onclick={confirmDelete}
class="flex-1 rounded-lg bg-red-600 px-4 py-2 font-medium text-white transition-colors hover:bg-red-500"
>
Löschen
{$_('common.delete')}
</button>
</div>
</div>
@ -167,7 +168,7 @@
type="button"
onclick={() => (showDeleteConfirm = true)}
class="rounded-lg bg-red-600/20 p-2 text-red-400 transition-colors hover:bg-red-600/30"
title="Löschen"
title={$_('common.delete')}
>
<Trash class="h-5 w-5" />
</button>
@ -176,14 +177,14 @@
onclick={onClose}
class="flex-1 rounded-lg border border-gray-600 bg-transparent px-4 py-2 font-medium text-gray-300 transition-colors hover:bg-gray-700"
>
Abbrechen
{$_('common.cancel')}
</button>
<button
type="submit"
disabled={!name.trim() || saving}
class="flex-1 rounded-lg bg-emerald-600 px-4 py-2 font-medium text-white transition-colors hover:bg-emerald-500 disabled:cursor-not-allowed disabled:opacity-50"
>
{saving ? 'Speichern...' : 'Speichern'}
{saving ? $_('common.saving') : $_('common.save')}
</button>
</div>
</form>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import type { Skill } from '../types';
import { BRANCH_INFO, LEVEL_NAMES, xpProgress, xpForNextLevel } from '../types';
import { Plus, Trash, PencilSimple, Star } from '@manacore/shared-icons';
@ -100,14 +101,14 @@
<button
onclick={onEdit}
class="rounded-lg bg-gray-600/20 p-2 text-gray-400 opacity-0 transition-all hover:bg-gray-600/30 hover:text-white group-hover:opacity-100"
title="Bearbeiten"
title={$_('common.edit')}
>
<PencilSimple class="h-4 w-4" />
</button>
<button
onclick={onDelete}
class="rounded-lg bg-red-600/20 p-2 text-red-400 opacity-0 transition-all hover:bg-red-600/30 group-hover:opacity-100"
title="Löschen"
title={$_('common.delete')}
>
<Trash class="h-4 w-4" />
</button>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import {
Circle,
CheckCircle,
@ -80,7 +81,7 @@
<div class="page-picker">
<div class="picker-header">
<h3 class="picker-title">Neue Seite</h3>
<button class="close-btn" onclick={onClose} title="Schließen"><X size={16} /></button>
<button class="close-btn" onclick={onClose} title={$_('common.close')}><X size={16} /></button>
</div>
<div class="picker-list">
{#each availableOptions as option, i (option.id)}

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { getContext } from 'svelte';
import { calendarsStore } from '$lib/modules/calendar/stores/calendars.svelte';
import type { Calendar } from '$lib/modules/calendar/types';
@ -173,7 +174,7 @@
<button
onclick={() => handleDelete(cal.id)}
class="rounded-lg p-1.5 text-muted-foreground hover:text-red-600 transition-colors"
title="Löschen"
title={$_('common.delete')}
>
<Trash size={16} />
</button>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { page } from '$app/stores';
import { goto } from '$app/navigation';
import { getContext } from 'svelte';
@ -216,14 +217,14 @@
<button
onclick={startEditing}
class="rounded-lg p-2 text-muted-foreground hover:bg-muted hover:text-foreground transition-colors"
title="Bearbeiten"
title={$_('common.edit')}
>
<PencilSimple size={18} />
</button>
<button
onclick={handleDelete}
class="rounded-lg p-2 text-muted-foreground hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-950/20 transition-colors"
title="Löschen"
title={$_('common.delete')}
>
<Trash size={18} />
</button>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { getContext } from 'svelte';
import { goto } from '$app/navigation';
import { deckStore } from '$lib/modules/cards/stores/decks.svelte';
@ -39,7 +40,7 @@
<!-- Error State -->
{#if deckStore.error}
<div class="rounded-lg bg-destructive/10 p-4 text-destructive">
<p class="font-medium">Fehler beim Laden</p>
<p class="font-medium">{$_('common.error_loading')}</p>
<p class="mt-1 text-sm">{deckStore.error}</p>
</div>
{:else if (allDecks?.value ?? []).length === 0}

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { goto } from '$app/navigation';
import { getContext } from 'svelte';
import { templatesStore } from '$lib/modules/chat/stores/templates.svelte';
@ -301,7 +302,7 @@
disabled={!formName.trim() || !formSystemPrompt.trim()}
class="rounded-lg bg-[hsl(var(--primary))] px-4 py-2 text-sm font-medium text-[hsl(var(--primary-foreground))] hover:opacity-90 disabled:opacity-50"
>
{editingId ? 'Speichern' : 'Erstellen'}
{editingId ? $_('common.save') : $_('common.create')}
</button>
</div>
</form>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { page } from '$app/stores';
import { goto } from '$app/navigation';
import { getContext } from 'svelte';
@ -189,7 +190,7 @@
<button
onclick={() => startEdit()}
class="rounded-lg p-2 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
title="Bearbeiten"
title={$_('common.edit')}
>
<PencilSimple size={18} />
</button>
@ -432,13 +433,13 @@
type="button"
onclick={cancelEdit}
class="rounded-lg border border-border px-4 py-2 text-sm font-medium text-foreground hover:bg-muted"
>Abbrechen</button
>{$_('common.cancel')}</button
>
<button
type="button"
onclick={saveEdit}
class="rounded-lg bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90"
>Speichern</button
>{$_('common.save')}</button
>
</div>
</div>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { page } from '$app/stores';
import { goto } from '$app/navigation';
import { Plus, ArrowLeft, PencilSimple, Check, X, MagnifyingGlass } from '@manacore/shared-icons';
@ -157,7 +158,7 @@
<button
class="rounded-lg p-2 opacity-60 transition-colors hover:bg-gray-100 hover:opacity-100 dark:hover:bg-gray-700"
onclick={startEdit}
title="Bearbeiten"
title={$_('common.edit')}
>
<PencilSimple size={18} />
</button>
@ -189,7 +190,7 @@
<input
type="text"
bind:value={searchQuery}
placeholder="Suchen..."
placeholder={$_('common.search')}
class="w-48 rounded-lg border border-gray-300 bg-white py-1.5 pl-8 pr-3 text-sm focus:border-indigo-500 focus:outline-none dark:border-gray-600 dark:bg-gray-700"
/>
</div>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { onMount } from 'svelte';
import { page } from '$app/stores';
import { Card, PageHeader } from '@manacore/shared-ui';
@ -139,7 +140,7 @@
transactions = transactionsData;
packages = packagesData.filter((p) => p.active).sort((a, b) => a.sortOrder - b.sortOrder);
} catch (e) {
error = e instanceof Error ? e.message : 'Fehler beim Laden der Daten';
error = e instanceof Error ? e.message : $_('common.error_loading');
console.error('Failed to load credits data:', e);
} finally {
loading = false;

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { onMount } from 'svelte';
import { page } from '$app/stores';
import { Card, PageHeader } from '@manacore/shared-ui';
@ -60,7 +61,7 @@
createdGifts = created;
balance = balanceData;
} catch (e) {
error = e instanceof Error ? e.message : 'Fehler beim Laden der Daten';
error = e instanceof Error ? e.message : $_('common.error_loading');
console.error('Failed to load gifts data:', e);
} finally {
loading = false;

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { Plus, PencilSimple, X, ArrowsOut } from '@manacore/shared-icons';
import AppPage from '$lib/components/workbench/AppPage.svelte';
import AppPagePicker from '$lib/components/workbench/AppPagePicker.svelte';
@ -286,7 +287,11 @@
>
<ArrowsOut size={12} />
</button>
<button class="tab-close" onclick={() => handleRemoveApp(app.appId)} title="Schließen">
<button
class="tab-close"
onclick={() => handleRemoveApp(app.appId)}
title={$_('common.close')}
>
<X size={12} />
</button>
</div>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { Plus } from '@manacore/shared-icons';
import { getContext } from 'svelte';
import { categoriesStore } from '$lib/modules/inventar/stores/categories.svelte';
@ -100,11 +101,12 @@
onclick={save}
disabled={!name.trim()}
class="rounded-lg bg-[hsl(var(--primary))] px-4 text-sm text-[hsl(var(--primary-foreground))] disabled:opacity-50"
>Speichern</button
>{$_('common.save')}</button
>
<button
onclick={() => (showForm = false)}
class="rounded-lg border border-[hsl(var(--border))] px-3 text-sm">Abbrechen</button
class="rounded-lg border border-[hsl(var(--border))] px-3 text-sm"
>{$_('common.cancel')}</button
>
</div>
</div>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { page } from '$app/stores';
import { goto } from '$app/navigation';
import { CaretLeft } from '@manacore/shared-icons';
@ -133,18 +134,18 @@
<button
onclick={() => (editing = false)}
class="rounded-lg border border-[hsl(var(--border))] px-3 py-1.5 text-sm"
>Abbrechen</button
>{$_('common.cancel')}</button
>
<button
onclick={saveEdit}
class="rounded-lg bg-[hsl(var(--primary))] px-4 py-1.5 text-sm font-medium text-[hsl(var(--primary-foreground))]"
>Speichern</button
>{$_('common.save')}</button
>
{:else}
<button
onclick={startEditing}
class="rounded-lg border border-[hsl(var(--border))] px-3 py-1.5 text-sm text-[hsl(var(--foreground))]"
>Bearbeiten</button
>{$_('common.edit')}</button
>
<button
onclick={deleteItem}

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { getContext } from 'svelte';
import { tagMutations } from '$lib/modules/memoro/stores/tags.svelte';
import type { Tag } from '@manacore/shared-tags';
@ -201,7 +202,7 @@
disabled={!formName.trim()}
class="rounded-lg bg-[hsl(var(--primary))] px-4 py-2 text-sm font-medium text-[hsl(var(--primary-foreground))] hover:opacity-90 disabled:opacity-50"
>
{editingId ? 'Speichern' : 'Erstellen'}
{editingId ? $_('common.save') : $_('common.create')}
</button>
</div>
</form>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { useLiveQuery } from '@manacore/local-store/svelte';
import { moodTable } from '$lib/modules/moodlit/collections';
import { moodsStore } from '$lib/modules/moodlit/stores/moods.svelte';
@ -129,7 +130,7 @@
onclick={createMood}
disabled={!newName}
class="mt-4 rounded-lg bg-purple-600 px-6 py-2 font-medium text-white hover:bg-purple-700 disabled:opacity-50"
>Erstellen</button
>{$_('common.create')}</button
>
</div>
{/if}

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { useLiveQuery } from '@manacore/local-store/svelte';
import { db } from '$lib/data/database';
import { sequencesStore } from '$lib/modules/moodlit/stores/sequences.svelte';
@ -83,7 +84,7 @@
onclick={createSequence}
disabled={!newName}
class="rounded-lg bg-purple-600 px-4 py-2 text-sm font-medium text-white disabled:opacity-50"
>Erstellen</button
>{$_('common.create')}</button
>
</div>
</div>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { getContext } from 'svelte';
import { playlistsStore } from '$lib/modules/mukke/stores/playlists.svelte';
import type { Playlist } from '$lib/modules/mukke/types';
@ -168,7 +169,7 @@
disabled={!newName.trim() || isCreating}
class="rounded-lg bg-[hsl(var(--primary))] px-4 py-2 text-sm font-medium text-[hsl(var(--primary-foreground))] hover:opacity-90 disabled:opacity-50"
>
{isCreating ? 'Erstellen...' : 'Erstellen'}
{isCreating ? $_('common.creating') : $_('common.create')}
</button>
</div>
</form>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { getContext } from 'svelte';
import { projectsStore } from '$lib/modules/mukke/stores/projects.svelte';
import type { Project } from '$lib/modules/mukke/types';
@ -168,7 +169,7 @@
disabled={!newTitle.trim() || isCreating}
class="rounded-lg bg-[hsl(var(--primary))] px-4 py-2 text-sm font-medium text-[hsl(var(--primary-foreground))] hover:opacity-90 disabled:opacity-50"
>
{isCreating ? 'Erstellen...' : 'Erstellen'}
{isCreating ? $_('common.creating') : $_('common.create')}
</button>
</div>
</form>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { goto } from '$app/navigation';
import { db } from '$lib/data/database';
import { useAllFavorites } from '$lib/modules/nutriphi/queries';
@ -261,7 +262,7 @@
disabled={saving || !description.trim()}
class="flex-1 rounded-lg bg-[hsl(var(--primary))] px-4 py-3 text-sm font-medium text-[hsl(var(--primary-foreground))] hover:opacity-90 disabled:opacity-50"
>
{saving ? 'Speichert...' : 'Speichern'}
{saving ? $_('common.saving') : $_('common.save')}
</button>
</div>
</div>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { goto } from '$app/navigation';
import { getContext } from 'svelte';
import { boardsStore } from '$lib/modules/picture/stores/boards.svelte';
@ -204,7 +205,7 @@
disabled={!boardName.trim() || isCreating}
class="flex-1 rounded-lg bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors disabled:opacity-50"
>
{isCreating ? 'Erstelle...' : 'Erstellen'}
{isCreating ? $_('common.creating') : $_('common.create')}
</button>
</div>
</form>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { page } from '$app/stores';
import { goto } from '$app/navigation';
import { getContext } from 'svelte';
@ -74,14 +75,14 @@
<button
onclick={startEditing}
class="rounded-lg p-1.5 text-muted-foreground hover:bg-muted hover:text-foreground transition-colors"
title="Bearbeiten"
title={$_('common.edit')}
>
<PencilSimple size={18} />
</button>
<button
onclick={handleDelete}
class="rounded-lg p-1.5 text-muted-foreground hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-950/20 transition-colors"
title="Löschen"
title={$_('common.delete')}
>
<Trash size={18} />
</button>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { page } from '$app/stores';
import { db } from '$lib/data/database';
import {
@ -249,7 +250,7 @@
<button
onclick={startEditing}
class="rounded-lg border border-[hsl(var(--border))] p-2 text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))]"
title="Bearbeiten"
title={$_('common.edit')}
>
<PencilSimple class="h-4 w-4" />
</button>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { db } from '$lib/data/database';
import {
useAllCollections,
@ -175,7 +176,7 @@
<button
onclick={() => openEditModal(collection)}
class="rounded-lg p-2 text-[hsl(var(--muted-foreground))] hover:bg-[hsl(var(--muted))] hover:text-[hsl(var(--foreground))]"
title="Bearbeiten"
title={$_('common.edit')}
>
<PencilSimple class="h-4 w-4" />
</button>
@ -275,14 +276,14 @@
onclick={closeModal}
class="rounded-lg border border-[hsl(var(--border))] px-4 py-2 text-sm text-[hsl(var(--foreground))] hover:bg-[hsl(var(--muted))]"
>
Abbrechen
{$_('common.cancel')}
</button>
<button
onclick={handleSave}
disabled={!formName.trim()}
class="rounded-lg bg-[hsl(var(--primary))] px-4 py-2 text-sm font-medium text-[hsl(var(--primary-foreground))] hover:opacity-90 disabled:opacity-50"
>
{editingCollection ? 'Speichern' : 'Erstellen'}
{editingCollection ? $_('common.save') : $_('common.create')}
</button>
</div>
</div>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { goto } from '$app/navigation';
import { db } from '$lib/data/database';
import { useAllCollections } from '$lib/modules/questions/queries';
@ -247,7 +248,7 @@
disabled={loading || !title.trim()}
class="flex-1 rounded-lg bg-[hsl(var(--primary))] px-4 py-3 text-sm font-medium text-[hsl(var(--primary-foreground))] hover:opacity-90 disabled:opacity-50"
>
{loading ? 'Erstelle...' : 'Frage stellen'}
{loading ? $_('common.creating') : 'Frage stellen'}
</button>
</div>
</form>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { onMount } from 'svelte';
import { Button, Input, Card, PageHeader, GlobalSettingsSection } from '@manacore/shared-ui';
import {
@ -85,7 +86,7 @@
profileSuccess = true;
ManaCoreEvents.profileUpdated();
} catch (e) {
profileError = e instanceof Error ? e.message : 'Fehler beim Speichern';
profileError = e instanceof Error ? e.message : $_('common.error_saving');
} finally {
savingProfile = false;
}
@ -94,7 +95,7 @@
<div>
<PageHeader
title="Einstellungen"
title={$_('common.settings')}
description="Verwalte deine Kontoeinstellungen und Präferenzen"
size="lg"
/>
@ -164,7 +165,7 @@
</div>
<Button onclick={handleUpdateProfile} loading={savingProfile} class="w-full sm:w-auto">
{savingProfile ? 'Speichern...' : 'Änderungen speichern'}
{savingProfile ? $_('common.saving') : 'Änderungen speichern'}
</Button>
</div>
</div>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { onMount } from 'svelte';
import { page } from '$app/stores';
import { Card, PageHeader } from '@manacore/shared-ui';
@ -60,7 +61,7 @@
currentSubscription = subscriptionData;
invoices = invoicesData;
} catch (e) {
error = e instanceof Error ? e.message : 'Fehler beim Laden der Daten';
error = e instanceof Error ? e.message : $_('common.error_loading');
console.error('Failed to load subscription data:', e);
} finally {
loading = false;

View file

@ -117,7 +117,7 @@
toast.success('Wecker aktualisiert');
closeEditModal();
} else {
toast.error(result.error || 'Fehler beim Speichern');
toast.error(result.error || $_('common.error_saving'));
}
}
@ -126,7 +126,7 @@
if (result.success) {
toast.success('Wecker gelöscht');
} else {
toast.error(result.error || 'Fehler beim Löschen');
toast.error(result.error || $_('common.error_deleting'));
}
}

View file

@ -317,7 +317,7 @@
</div>
<div class="todo-header-actions">
<SyncIndicator />
<a href="/todo/settings" class="settings-btn" title="Einstellungen">
<a href="/todo/settings" class="settings-btn" title={$_('common.settings')}>
<Gear size={16} />
</a>
</div>
@ -437,7 +437,11 @@
>
<ArrowsOut size={12} />
</button>
<button class="tab-close" onclick={() => handleRemovePage(page.id)} title="Schließen">
<button
class="tab-close"
onclick={() => handleRemovePage(page.id)}
title={$_('common.close')}
>
<X size={12} />
</button>
</div>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import {
useAllLinks,
useAllTags,
@ -562,7 +563,7 @@
<button
onclick={() => openEdit(link)}
class="rounded-lg p-2 opacity-0 transition-all hover:bg-gray-100 group-hover:opacity-100 dark:hover:bg-gray-700"
title="Bearbeiten"
title={$_('common.edit')}
>
<PencilSimple size={16} />
</button>

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { uloadTagTable, useAllTags, useAllLinkTags, slugify } from '$lib/modules/uload';
import type { LocalTag } from '$lib/modules/uload';
import { toast } from 'svelte-sonner';
@ -122,12 +123,13 @@
<input type="color" bind:value={editingTag.color} class="h-8 w-12 rounded" />
<button
onclick={updateTag}
class="rounded bg-indigo-600 px-3 py-1 text-sm text-white">Speichern</button
class="rounded bg-indigo-600 px-3 py-1 text-sm text-white"
>{$_('common.save')}</button
>
<button
onclick={() => (editingTag = null)}
class="rounded border border-white/10 px-3 py-1 text-sm text-white/60"
>Abbrechen</button
>{$_('common.cancel')}</button
>
</div>
</div>