Commit graph

20 commits

Author SHA1 Message Date
Till JS
7dfa1c74be i18n(body+mood+questions): translate picker/quick-log/question-detail via $_()
- body/components/ExercisePicker: route remaining German strings
  (dialog/close/filter_all/create-form) through body.exercisePicker.*;
  drops { default: '...' } fallbacks now that all keys resolve
- mood/components/QuickLog: route through mood.quick_log.*
- questions/views/DetailView: route through questions.detail.*
  + dynamic questions.status.<id> / questions.priority.<id> /
  questions.detail.depth_<id>; drops local statusLabels/priorityLabels/
  depthLabels const blocks (re-uses existing status+priority keys
  extended with `normal`/`urgent`)

Baseline 851 → 833 (-18).
2026-04-27 19:13:18 +02:00
Till JS
a842537191 i18n(comic+quiz): translate picker/character-detail/play-view via $_()
- comic/components/CharacterPicker: route through comic.picker.* with
  HTML interpolation for the no-face/empty-garment alerts
- comic/views/DetailCharacterView: route through comic.character_detail.*
  + dynamic comic.styles.<id>; drops unused STYLE_LABELS import
- quiz/PlayView: route through quiz.play_view.* (back/empty/result/play
  all consolidated)

Baseline 869 → 851 (-18).
2026-04-27 18:47:37 +02:00
Till JS
7339fba3aa i18n(inventory+questions+invitations): translate 3 routes via $_()
- inventory/items/[id]/+page: route through inventory.detail.* +
  dynamic inventory.status.<id>; drops local statusLabels constant
  (re-uses existing inventory.status.* keys). Fixes pre-existing
  typos endgultig/loschen/Zuruck/hinzufugen via proper translations.
- questions/+page: route through questions.home.* + dynamic
  questions.home.depth_<id>; locale-aware date formatting via
  get(locale) instead of hardcoded de-DE; drops unused
  ResearchDepth import + depthLabels const.
- accept-invitation/+page: route through invitations.accept.*
  (new namespace); space-type label still uses SPACE_TYPE_LABELS
  from shared-branding (only de/en available — locale-prefix gate).

Baseline 920 → 899 (-21).
2026-04-27 18:29:17 +02:00
Till JS
63b9ff4684 i18n(comic+guides+cards): translate 3 detail/progress views via $_()
- comic/views/DetailView: route through comic.detail.* + dynamic
  comic.styles.<id>; drop unused STYLE_LABELS import
- guides/views/DetailView: route through guides.detail.* + dynamic
  guides.categories.<id> / guides.difficulties.<id>; drop unused
  DIFFICULTY_LABELS + Section type
- cards/progress/+page: route through cards.progress.* (also fixes
  pre-existing typos "Fallig"/"Ubersicht"/"Lernsitzungen" via
  proper translations across all 5 locales)

Baseline 961 → 940 (-21).
2026-04-27 18:17:08 +02:00
Till JS
092c45c835 i18n(places): translate views/DetailView via $_() — header, fields, sections, meta
- Shell labels (notFound + confirmDelete + Unbenannt fallback)
- Name input placeholder, map iframe title
- 5 row labels (Sichtbarkeit/Kategorie/Adresse/Koordinaten/Beschreibung) + Link share row
- Category options routed via $_('places.categories.' + v) — CATEGORIES constant inlined as PlaceCategory[] array
- Address + address-search placeholders, Lat/Lng coords placeholders, resolve title
- Tags / Letzte Besuche section labels
- 4 meta-row keys with {n}/{date} interpolation; toLocaleDateString switched to get(locale) ?? 'de'

Baselines: hardcoded 1033 → 1025 (8 cleared); missing-keys baseline +1 (places.categories.* dynamic key).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 15:02:54 +02:00
Till JS
66ab5f65f6 i18n(sleep): translate ListView via $_() — log CTA, last-night, week chart, stats, heatmap, hygiene
- Log CTA "Wie hast du geschlafen?" + "Jetzt loggen"
- Last-night card: "Letzte Nacht" label, "Bearbeiten" edit button, "{n}× aufgewacht" interpolation
- "Diese Woche" week section heading
- 5 stat labels (Ø Dauer (7T) / Ø Qualität / Schlafschuld / Konsistenz / Streak)
- Quality heatmap: section heading + cell title with {date}/{label} interpolation, label sourced via $_('sleep.qualities.' + n) (added qualities sub-namespace)
- Hygiene-correlation card: heading + with/without rows
- Action buttons: Schlaf loggen / Hygiene-Check
- QUALITY_LABELS import dropped (constant kept in types.ts for non-Svelte callers)

Baselines: hardcoded 1034 → 1033 (8 cleared from sleep + 7 added by parallel community-feature commits = net -1); missing-keys baseline +1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 14:58:45 +02:00
Till JS
258edaa07d 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>
2026-04-27 14:41:30 +02:00
Till JS
0ca93945de i18n(broadcast): translate ListView via $_() — header, stats, filters, list rows
- Page H1 (Broadcasts) + subtitle, settings + new-campaign actions
- 4 stats cards (Versendet {year}/Ø Öffnungsrate/Ø Klickrate/Entwürfe) with sublines
- Filter chips: "Alle" + status chips routed via $_('broadcast.statuses.' + status); STATUS_LABELS import dropped
- Search placeholder
- Empty states (no campaigns + no matches) + first-campaign action
- Row "{n} Empfänger" + open-rate tooltip + status pill

Baselines: hardcoded 1082 → 1074 (8 cleared); missing-keys baseline +0 (broadcast.statuses.* dynamic key already baselined from DetailView).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 14:34:32 +02:00
Till JS
391017bcfa i18n(ai-workbench): translate ListView via $_() — tabs, filters, audit table, timeline buckets
- Tabs (Timeline / Datenzugriff)
- Filter labels (Modul/Mission/Agent) with shared "alle" option
- Time-range buttons routed via dynamic key labelKey
- Audit: loading, error_prefix interpolation, empty paragraph, 4 column headers
- Timeline empty state
- Bucket revert button (title + Läuft… / Rückgängig label) + event-count tooltip + event-link "Zum Modul"
- Confirm + alert summary parts ({n} zurückgenommen / nicht unterstützt / fehlgeschlagen) + "Revert fehlgeschlagen — siehe Console." fallback
- Date/time formatters switched to get(locale) ?? 'de'

Baselines: hardcoded 1090 → 1082 (8 cleared); missing-keys baseline +1 (ai-workbench.list_view.range_* dynamic key).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 14:31:33 +02:00
Till JS
474f5aca8d i18n(broadcast): translate DetailView via $_() — header, actions, stats grid, polling, preview
- Status pill routed through $_('broadcast.statuses.' + status); STATUS_LABELS import dropped (constants kept for non-Svelte callers)
- Sent-at / scheduled-for date pills with locale-aware date formatter
- Action buttons (Duplizieren / Abbrechen / Zur Übersicht)
- 5 stats labels (sent/opened/clicked/bounced/unsubscribed) with interpolated sublines (von {n}, {n} Öffnungen, etc.)
- Polling hints (Live-Update… / Letzte Aktualisierung: {time}) + error fallback + inline error message
- "Wie die Kampagne aussah" preview heading
- "Geplante Kampagne abbrechen?" confirm

Baselines: hardcoded 1112 → 1103 (9 cleared); missing-keys baseline +1 (broadcast.statuses.* dynamic key).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 14:22:17 +02:00
Till JS
84bc904775 i18n(quiz): translate EditView via $_() — header, meta inputs, question list, new-question form
- Header: back-button aria + "Quiz" label, Spielen play button
- Empty: "Quiz nicht gefunden."
- Meta-section: Titel/Beschreibung/Kategorie/Tags placeholders, Sichtbarkeit row label, untitled fallback
- Question list: "Fragen ({n})" heading, empty state, type-pill, edit/delete title+aria, "Frage löschen?" confirm
- Question types routed through $_('quiz.question_types.' + q.type); QUESTION_TYPE_LABELS constant kept in types.ts for non-Svelte callers
- New-question section: edit/new heading, cancel button, type select (4 options), question/correct-answer/expected-input fields, options-label (multi/single variant), correct-toggle title+aria, "Antwort {n}" placeholder, remove aria, "Antwort hinzufügen", explanation field, save/add submit button
- truefalse default options ("Wahr"/"Falsch") now i18n'd

Baselines: hardcoded 1218 → 1205 (13 cleared); missing-keys baseline +1 (quiz.question_types.* dynamic key).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 12:42:11 +02:00
Till JS
779752e907 i18n(dreams): translate ListView via $_() — view tabs, insights, filters, editor, transcription badges
- View tabs (Träume/Symbole), insights ribbon, filter chips (Alle/Klarträume/Albträume/Wiederkehrend), search placeholder
- Inline editor: title placeholder, transcription status (transcribing/failed/done), content/symbols placeholders, sleep-row labels (Nacht/Ins Bett/Aufgewacht), sleep quality + star aria-label, Klartraum/Wiederkehrend toggles, Löschen/Fertig actions
- Dream-row: untitled fallback, transcribing/failed badge titles, STT-chip title
- FloatingInputBar placeholder + voice reason
- Mood labels routed through $_('dreams.moods.' + mood); MOOD_LABELS constant kept in types.ts for non-Svelte callers (SymbolDetailView)
- Context menu: edit/pin/unpin/delete via $_()

Baselines: hardcoded 1254 → 1242 (12 cleared); missing-keys baseline +1 (dreams.moods.* dynamic key).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 02:12:00 +02:00
Till JS
5c3c7ed3bc i18n(recipes): translate ListView via $_() — search, filters, ctx menu, detail panel, create form
- DIFFICULTY_LABELS map dropped from imports; routed through $_('recipes.difficulties.' + d) instead
- Context menu items, search placeholder, fav chip, add card, empty states, create-form labels all i18n'd
- Detail panel headings (Sichtbarkeit/Zutaten/Zubereitung) translated; servings suffix uses {n} interpolation
- Baselines ratcheted: hardcoded 1268 → 1254 (14 cleared); missing-keys baseline +1 (recipes.difficulties.* dynamic key, same pattern as firsts)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 02:08:40 +02:00
Till JS
fa5dbb2cfc i18n(firsts): wire ListView to namespace — 15 strings cleared
Patches tabs, quick-add, category filter, search, stats, dream/lived
edit forms, repeat picker, expectation-vs-reality labels, context menu,
all empty states, people-view "Alleine" fallback. CATEGORY_LABELS +
PRIORITY_LABELS routed through firsts.categories.* / firsts.priorities.*
keys; constants kept in milestones/categories.ts for non-Svelte
callers. Locale-aware Date via get(locale).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 01:59:09 +02:00
Till JS
36d832a3db i18n(library): wire DetailView to namespace — 16 strings cleared
Patches all action labels, kind/status/format pills (routed through
dynamic library.kinds.*, library.statuses.*, library.book_formats.*),
detail dt/dd pairs, restart label, times badge, review section.
constants.ts kept with literal {de,en} maps for non-Svelte callers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 01:39:25 +02:00
Till JS
4731bc80fd i18n(ai-missions): wire ListView to namespace — 22 strings cleared
Patches list/create/detail panes incl. PHASE_LABELS, describeCadence,
describeState, formatRelative, grant box, iteration phase block, error
details, feedback form. Locale JSONs landed in the previous commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 01:36:12 +02:00
Till JS
0a03e9e882 i18n(ai-agents): wire ListView to namespace — 23 strings cleared
Patches list/create/detail panes incl. POLICY_LABEL, TEMPLATES,
mission state labels, natural-language policy summary. Locale JSONs
landed in the previous commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 01:26:30 +02:00
Till JS
bcf150ea16 i18n(credits): wire ListView to namespace — 25 strings cleared
Patches all toast/error messages, balance labels, tabs, subscription
status/details, billing interval toggle, plan rows, invoices,
transaction table, package cards, costs filters/info-banner.
Locale-aware Date/number formatting via get(locale) ?? 'de'.
APP_LABELS + getCategoryLabel routed through namespace keys.
Locale JSONs landed in da330f0c7.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 01:20:34 +02:00
Till JS
5959f66387 i18n(wardrobe): translate all 5 locales — 36 strings
Adds wardrobe namespace (de/en/es/fr/it) covering ListView,
GridView, OutfitsView, DetailGarmentView, DetailOutfitView,
GarmentForm, OutfitComposer, GarmentTryOnButton, TryOnButton,
TryOnModelPicker, CategoryTabs, GarmentCard, OutfitCard, plus
the /wardrobe/compose route. Categories/occasions/seasons routed
through dynamic `wardrobe.categories.{key}` lookups so constants.ts
keeps the order-tuples without leaking DE labels into UI.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 00:12:18 +02:00
Till JS
fbbadc91f0 feat(calendar): M8.3 — calendar pilot for unlisted-share end-to-end
Wires Calendar through the M8.1+M8.2 backbone: flipping an event to
'unlisted' now publishes a server-side snapshot, the visible link in
the DetailView/EventDetailModal opens a real /share/[token] page, and
recipients can download an .ics file for their own calendar.

Changes:
- lib/data/unlisted/resolvers.ts (new):
    buildUnlistedBlob(collection, recordId) dispatcher.
    buildEventBlob: load LocalEvent + linked TimeBlock, decrypt
    client-side, return { title, location, startTime, endTime,
    isAllDay, timezone }. Description, reminders, tagIds, calendarId,
    color stay out of the blob — sensitive context the user didn't
    consent to share by flipping a single flag.
- modules/calendar/types: CalendarEvent gains `unlistedToken: string`
  (empty string when no active token). timeBlockToCalendarEvent
  forwards from LocalEvent. Draft-event scaffold initializes empty.
- modules/calendar/stores/events:
    setVisibility now coordinates with mana-api. Flip-to-unlisted:
      build blob -> publishUnlistedSnapshot -> store server-issued
      token in patch.unlistedToken -> commit local update. If the
      server call fails, no local change happens (no drift).
    Flip-from-unlisted: revoke server snapshot first, then clear
      local token + commit visibility change.
    deleteEvent: revoke active unlisted snapshot before tombstoning,
      so the share-link dies in lock-step with the local delete.
    updateEvent + updateSingleInstance fire-and-forget
      refreshUnlistedSnapshot(id) so the published blob tracks any
      whitelist-field edits. Failures log; the next successful
      refresh heals.
    New regenerateUnlistedToken(id): revoke + republish in one call,
      returns the fresh token. Powers the "Neu erzeugen" UI.
- routes/share/[token]/+layout.svelte: minimal anonymous chrome —
  no app nav, no auth, no Dexie. Light/dark via prefers-color-scheme.
  Footer carries "Geteilt via Mana" + signup CTA.
- routes/share/[token]/+page.server.ts: SSR loader. Fetches
  /api/v1/unlisted/public/:token, dispatches 404/410 cleanly,
  sets Cache-Control: private, max-age=60 + X-Robots-Tag: noindex.
- routes/share/[token]/+page.svelte: dispatcher; renders
  SharedEventView for collection='events', stub message otherwise.
- modules/calendar/SharedEventView.svelte: standalone public render —
  big date, location, "Zum eigenen Kalender hinzufügen" .ics link,
  optional expiry note. OG/Twitter meta tags for WhatsApp/Slack
  preview embedding. Uses $derived everywhere so prop updates
  propagate through reactive recompute.
- routes/share/[token]/ical/+server.ts: RFC 5545 builder. No npm
  library — small enough to inline. Escapes per spec, CRLF endings,
  DTSTART/DTEND swap between VALUE=DATE and UTC depending on isAllDay.
  Wrong-collection requests get 400.
- modules/calendar/views/DetailView (Workbench) + components/
  EventDetailModal (/calendar route): SharedLinkControls dropped in
  below the visibility row when event.visibility === 'unlisted'
  AND event.unlistedToken AND shareUrl computed. The URL is built
  client-side via buildShareUrl(window.location.origin, token) so it
  stays in sync with whichever host the editor is open on.

Verified:
- pnpm check (web): 7541 files, 0 errors, 0 warnings
- pnpm test calendar + website: 26/26
- typecheck of new resolver, store hooks, SSR loader, iCal builder

Manual test path:
1. Open /calendar event in Detail view, flip Sichtbarkeit -> "Per Link"
2. Server publishes snapshot, Dexie record gets the server token
3. SharedLinkControls appear with copy + regenerate + revoke buttons
4. Open the URL in incognito → SSR fetches snapshot, renders
   SharedEventView with date / location / .ics download
5. Edit the event title back in the main app → snapshot auto-refreshes
   (refreshUnlistedSnapshot fires after updateEvent succeeds)
6. Flip back to "Bereich" → snapshot revoked server-side; subsequent
   incognito reloads return 410 Gone

Next: M8.4 — same wiring for Library + Places. Uses the same
infra (resolvers dispatcher, share dispatcher) — just adds two new
buildXBlob functions, two SharedXView components, and the store
hooks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 11:40:53 +02:00