mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 20:01:09 +02:00
i18n(dreams): translate SymbolDetailView via $_() — header, merge dialog, sections, dream list
- Back button (← Symbole), Gespeichert hint, Zusammenführen…/Löschen actions
- Merge panel: label with {name} interpolation, "– Symbol wählen –" placeholder, OK/Abbrechen
- Empty: "Symbol nicht gefunden."
- Editable header: name placeholder, "Traum"/"Träume" via count_singular/plural
- Color picker: aria with {color} interpolation
- 4 section labels (Meine Bedeutung / Stimmungs-Verteilung / Häufig zusammen mit / Träume mit diesem Symbol) + meaning placeholder
- Mood label routed via $_('dreams.moods.' + mood) with valid-mood guard; "Unbekannt" fallback via symbol_detail.mood_unknown
- Co-occurring chip title with {name} interpolation
- Confirms: delete + merge with {name}/{source}/{target} interpolation
- Dream-ref title fallback via dreams.list_view.untitled
- MOOD_LABELS import dropped (constant kept in types.ts for non-Svelte callers)
Baselines: hardcoded 1074 → 1066 (8 cleared); missing-keys baseline +0 (dreams.moods.* dynamic key already baselined).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2491649767
commit
258edaa07d
3 changed files with 42 additions and 25 deletions
|
|
@ -12,7 +12,8 @@
|
||||||
useAllDreamSymbols,
|
useAllDreamSymbols,
|
||||||
} from '../queries';
|
} from '../queries';
|
||||||
import { dreamsStore } from '../stores/dreams.svelte';
|
import { dreamsStore } from '../stores/dreams.svelte';
|
||||||
import { MOOD_COLORS, MOOD_LABELS, type Dream, type DreamMood } from '../types';
|
import { MOOD_COLORS, type Dream, type DreamMood } from '../types';
|
||||||
|
import { _ } from 'svelte-i18n';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
symbolId,
|
symbolId,
|
||||||
|
|
@ -107,7 +108,7 @@
|
||||||
async function handleDelete() {
|
async function handleDelete() {
|
||||||
if (!symbol) return;
|
if (!symbol) return;
|
||||||
const ok = confirm(
|
const ok = confirm(
|
||||||
`Symbol "${symbol.name}" wirklich löschen? Es wird aus allen Träumen entfernt.`
|
$_('dreams.symbol_detail.confirm_delete', { values: { name: symbol.name } })
|
||||||
);
|
);
|
||||||
if (!ok) return;
|
if (!ok) return;
|
||||||
await dreamsStore.deleteSymbol(symbol.id);
|
await dreamsStore.deleteSymbol(symbol.id);
|
||||||
|
|
@ -119,7 +120,9 @@
|
||||||
const target = symbols.find((s) => s.id === mergeTargetId);
|
const target = symbols.find((s) => s.id === mergeTargetId);
|
||||||
if (!target) return;
|
if (!target) return;
|
||||||
const ok = confirm(
|
const ok = confirm(
|
||||||
`"${symbol.name}" in "${target.name}" zusammenführen? Alle Träume werden umgeschrieben.`
|
$_('dreams.symbol_detail.confirm_merge', {
|
||||||
|
values: { source: symbol.name, target: target.name },
|
||||||
|
})
|
||||||
);
|
);
|
||||||
if (!ok) return;
|
if (!ok) return;
|
||||||
await dreamsStore.mergeSymbols(symbol.id, mergeTargetId);
|
await dreamsStore.mergeSymbols(symbol.id, mergeTargetId);
|
||||||
|
|
@ -139,45 +142,54 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function moodLabel(mood: string): string {
|
function moodLabel(mood: string): string {
|
||||||
if (mood in MOOD_LABELS) return MOOD_LABELS[mood as DreamMood];
|
const valid: DreamMood[] = ['angenehm', 'neutral', 'unangenehm', 'albtraum'];
|
||||||
return 'Unbekannt';
|
if (valid.includes(mood as DreamMood)) return $_('dreams.moods.' + mood);
|
||||||
|
return $_('dreams.symbol_detail.mood_unknown');
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="detail-view">
|
<div class="detail-view">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<button class="back-btn" onclick={onBack}>← Symbole</button>
|
<button class="back-btn" onclick={onBack}>{$_('dreams.symbol_detail.back')}</button>
|
||||||
<div class="header-actions">
|
<div class="header-actions">
|
||||||
{#if savedHint}
|
{#if savedHint}
|
||||||
<span class="saved-hint">Gespeichert</span>
|
<span class="saved-hint">{$_('dreams.symbol_detail.saved')}</span>
|
||||||
{/if}
|
{/if}
|
||||||
{#if symbol && mergeCandidates.length > 0}
|
{#if symbol && mergeCandidates.length > 0}
|
||||||
<button class="meta-btn" onclick={() => (mergeOpen = !mergeOpen)}>Zusammenführen…</button>
|
<button class="meta-btn" onclick={() => (mergeOpen = !mergeOpen)}
|
||||||
|
>{$_('dreams.symbol_detail.action_merge')}</button
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
{#if symbol}
|
{#if symbol}
|
||||||
<button class="del-btn" onclick={handleDelete}>Löschen</button>
|
<button class="del-btn" onclick={handleDelete}
|
||||||
|
>{$_('dreams.symbol_detail.action_delete')}</button
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if mergeOpen && symbol}
|
{#if mergeOpen && symbol}
|
||||||
<div class="merge-panel">
|
<div class="merge-panel">
|
||||||
<span class="merge-label">"{symbol.name}" zusammenführen mit:</span>
|
<span class="merge-label"
|
||||||
|
>{$_('dreams.symbol_detail.merge_label', { values: { name: symbol.name } })}</span
|
||||||
|
>
|
||||||
<select class="merge-select" bind:value={mergeTargetId}>
|
<select class="merge-select" bind:value={mergeTargetId}>
|
||||||
<option value="">– Symbol wählen –</option>
|
<option value="">{$_('dreams.symbol_detail.merge_select_default')}</option>
|
||||||
{#each mergeCandidates as c}
|
{#each mergeCandidates as c}
|
||||||
<option value={c.id}>{c.name} ({c.count})</option>
|
<option value={c.id}>{c.name} ({c.count})</option>
|
||||||
{/each}
|
{/each}
|
||||||
</select>
|
</select>
|
||||||
<button class="merge-confirm" disabled={!mergeTargetId} onclick={handleMerge}>OK</button>
|
<button class="merge-confirm" disabled={!mergeTargetId} onclick={handleMerge}
|
||||||
|
>{$_('dreams.symbol_detail.merge_confirm')}</button
|
||||||
|
>
|
||||||
<button class="merge-cancel" onclick={() => ((mergeOpen = false), (mergeTargetId = ''))}
|
<button class="merge-cancel" onclick={() => ((mergeOpen = false), (mergeTargetId = ''))}
|
||||||
>Abbrechen</button
|
>{$_('dreams.symbol_detail.merge_cancel')}</button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if !symbol}
|
{#if !symbol}
|
||||||
<p class="empty">Symbol nicht gefunden.</p>
|
<p class="empty">{$_('dreams.symbol_detail.empty_not_found')}</p>
|
||||||
{:else}
|
{:else}
|
||||||
<!-- Editable header -->
|
<!-- Editable header -->
|
||||||
<div class="sym-header">
|
<div class="sym-header">
|
||||||
|
|
@ -185,10 +197,15 @@
|
||||||
class="name-input"
|
class="name-input"
|
||||||
type="text"
|
type="text"
|
||||||
bind:value={editName}
|
bind:value={editName}
|
||||||
placeholder="Symbolname"
|
placeholder={$_('dreams.symbol_detail.name_placeholder')}
|
||||||
style="color: {editColor}"
|
style="color: {editColor}"
|
||||||
/>
|
/>
|
||||||
<span class="count-badge">{symbol.count} {symbol.count === 1 ? 'Traum' : 'Träume'}</span>
|
<span class="count-badge"
|
||||||
|
>{symbol.count}
|
||||||
|
{symbol.count === 1
|
||||||
|
? $_('dreams.symbol_detail.count_singular')
|
||||||
|
: $_('dreams.symbol_detail.count_plural')}</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Color picker -->
|
<!-- Color picker -->
|
||||||
|
|
@ -199,18 +216,18 @@
|
||||||
class:active={editColor === color}
|
class:active={editColor === color}
|
||||||
style="background: {color}"
|
style="background: {color}"
|
||||||
onclick={() => (editColor = color)}
|
onclick={() => (editColor = color)}
|
||||||
aria-label={`Farbe ${color}`}
|
aria-label={$_('dreams.symbol_detail.color_aria', { values: { color } })}
|
||||||
></button>
|
></button>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Meaning -->
|
<!-- Meaning -->
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<span class="section-label">Meine Bedeutung</span>
|
<span class="section-label">{$_('dreams.symbol_detail.label_meaning')}</span>
|
||||||
<textarea
|
<textarea
|
||||||
class="meaning-input"
|
class="meaning-input"
|
||||||
bind:value={editMeaning}
|
bind:value={editMeaning}
|
||||||
placeholder="Was bedeutet dieses Symbol für dich? (optional)"
|
placeholder={$_('dreams.symbol_detail.meaning_placeholder')}
|
||||||
rows="3"
|
rows="3"
|
||||||
></textarea>
|
></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -218,7 +235,7 @@
|
||||||
<!-- Mood distribution -->
|
<!-- Mood distribution -->
|
||||||
{#if moodDist.length > 0}
|
{#if moodDist.length > 0}
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<span class="section-label">Stimmungs-Verteilung</span>
|
<span class="section-label">{$_('dreams.symbol_detail.label_mood_dist')}</span>
|
||||||
<div class="bars">
|
<div class="bars">
|
||||||
{#each moodDist as m}
|
{#each moodDist as m}
|
||||||
<div class="bar-row">
|
<div class="bar-row">
|
||||||
|
|
@ -239,13 +256,13 @@
|
||||||
<!-- Co-occurring -->
|
<!-- Co-occurring -->
|
||||||
{#if cooccurring.length > 0}
|
{#if cooccurring.length > 0}
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<span class="section-label">Häufig zusammen mit</span>
|
<span class="section-label">{$_('dreams.symbol_detail.label_cooccurring')}</span>
|
||||||
<div class="cooc-row">
|
<div class="cooc-row">
|
||||||
{#each cooccurring as c}
|
{#each cooccurring as c}
|
||||||
<button
|
<button
|
||||||
class="cooc-chip"
|
class="cooc-chip"
|
||||||
onclick={() => navigateToCooccurring(c.name)}
|
onclick={() => navigateToCooccurring(c.name)}
|
||||||
title={`Zu "${c.name}" wechseln`}
|
title={$_('dreams.symbol_detail.cooccurring_title', { values: { name: c.name } })}
|
||||||
>
|
>
|
||||||
{c.name} <span class="cooc-count">{c.count}</span>
|
{c.name} <span class="cooc-count">{c.count}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -257,7 +274,7 @@
|
||||||
<!-- Dream list -->
|
<!-- Dream list -->
|
||||||
{#if dreamsWithSymbol.length > 0}
|
{#if dreamsWithSymbol.length > 0}
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<span class="section-label">Träume mit diesem Symbol</span>
|
<span class="section-label">{$_('dreams.symbol_detail.label_dream_list')}</span>
|
||||||
<div class="dream-refs">
|
<div class="dream-refs">
|
||||||
{#each dreamsWithSymbol as d (d.id)}
|
{#each dreamsWithSymbol as d (d.id)}
|
||||||
<button class="dream-ref" onclick={() => onOpenDream?.(d)} disabled={!onOpenDream}>
|
<button class="dream-ref" onclick={() => onOpenDream?.(d)} disabled={!onOpenDream}>
|
||||||
|
|
@ -267,7 +284,7 @@
|
||||||
<span class="ref-dot empty"></span>
|
<span class="ref-dot empty"></span>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="ref-content">
|
<div class="ref-content">
|
||||||
<span class="ref-title">{d.title || 'Traum ohne Titel'}</span>
|
<span class="ref-title">{d.title || $_('dreams.list_view.untitled')}</span>
|
||||||
<span class="ref-date">{formatDreamDate(d.dreamDate)}</span>
|
<span class="ref-date">{formatDreamDate(d.dreamDate)}</span>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,6 @@
|
||||||
"apps/mana/apps/web/src/lib/modules/core/widgets/RecentContactsWidget.svelte": 2,
|
"apps/mana/apps/web/src/lib/modules/core/widgets/RecentContactsWidget.svelte": 2,
|
||||||
"apps/mana/apps/web/src/lib/modules/core/widgets/TasksTodayWidget.svelte": 1,
|
"apps/mana/apps/web/src/lib/modules/core/widgets/TasksTodayWidget.svelte": 1,
|
||||||
"apps/mana/apps/web/src/lib/modules/core/widgets/UpcomingEventsWidget.svelte": 1,
|
"apps/mana/apps/web/src/lib/modules/core/widgets/UpcomingEventsWidget.svelte": 1,
|
||||||
"apps/mana/apps/web/src/lib/modules/dreams/views/SymbolDetailView.svelte": 8,
|
|
||||||
"apps/mana/apps/web/src/lib/modules/drink/ListView.svelte": 5,
|
"apps/mana/apps/web/src/lib/modules/drink/ListView.svelte": 5,
|
||||||
"apps/mana/apps/web/src/lib/modules/finance/ListView.svelte": 6,
|
"apps/mana/apps/web/src/lib/modules/finance/ListView.svelte": 6,
|
||||||
"apps/mana/apps/web/src/lib/modules/goals/ListView.svelte": 1,
|
"apps/mana/apps/web/src/lib/modules/goals/ListView.svelte": 1,
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
"apps/mana/apps/web/src/lib/modules/broadcast/views/DetailView.svelte": 1,
|
"apps/mana/apps/web/src/lib/modules/broadcast/views/DetailView.svelte": 1,
|
||||||
"apps/mana/apps/web/src/lib/modules/credits/ListView.svelte": 1,
|
"apps/mana/apps/web/src/lib/modules/credits/ListView.svelte": 1,
|
||||||
"apps/mana/apps/web/src/lib/modules/dreams/ListView.svelte": 1,
|
"apps/mana/apps/web/src/lib/modules/dreams/ListView.svelte": 1,
|
||||||
|
"apps/mana/apps/web/src/lib/modules/dreams/views/SymbolDetailView.svelte": 1,
|
||||||
"apps/mana/apps/web/src/lib/modules/firsts/ListView.svelte": 2,
|
"apps/mana/apps/web/src/lib/modules/firsts/ListView.svelte": 2,
|
||||||
"apps/mana/apps/web/src/lib/modules/invoices/components/StatusBadge.svelte": 1,
|
"apps/mana/apps/web/src/lib/modules/invoices/components/StatusBadge.svelte": 1,
|
||||||
"apps/mana/apps/web/src/lib/modules/invoices/constants.ts": 1,
|
"apps/mana/apps/web/src/lib/modules/invoices/constants.ts": 1,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue