Commit graph

6 commits

Author SHA1 Message Date
Till JS
4e31c8d736 feat(calendar): full i18n coverage across 17 files — DE/EN/ES/FR/IT
Calendar already had a `calendar` namespace, but ~70 strings were
hardcoded across EventForm, EventDetailModal, CustomRecurrenceBuilder,
CalendarHeader (15 block-type filter chips), QuickEventPopover, AgendaView,
EventCard, SlotSuggestions, MiniCalendar, DateStrip, ListView,
SharedEventView, the inline DetailView, and 3 routes.

- Extended namespace with `event_form.*`, `event_card.*`, `event_modal.*`,
  `agenda.*`, `recurrence.*` (custom builder + preview format),
  `weekday_short.*` / `weekday_long.*`, `header.*` (15 block-type labels +
  4 ARIA), `date_strip.*`, `mini_cal.*`, `slots.*`, `quick_event.*`,
  `list_view.*`, `detail_route.*`, `detail_view.*`, `calendars_route.*`,
  `shared_view.*` — ~172 new keys × 5 locales = ~860 translations.
- Recurrence preview formatters in EventForm + EventDetailModal +
  CustomRecurrenceBuilder all rebuilt around `recurrence.every_n_unit` /
  `weekly_with_days` / weekday-short maps.
- Locale-aware Intl.DateTimeFormat in SharedEventView (was hardcoded
  'de-DE').
- Baseline ratchet: 1753 → 1687 (66 calendar strings cleared, 16 files
  fully clean).

- validate:i18n-parity: 40 namespaces × 5 locales — 3768 keys aligned
- svelte-check: 0 new errors from i18n changes (pre-existing drift
  in unrelated modules unchanged)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 22:17:34 +02:00
Till JS
679fb160c2 feat(invoices): full i18n coverage across 12 files — DE/EN/ES/FR/IT
Invoices module had 81 hardcoded German strings across ListView,
DetailView, InvoiceForm, SenderProfileForm, ClientPicker, LinesEditor,
SendModal, StatusBadge, the open-invoices widget, and 4 routes. New
`invoices` namespace (~215 keys × 5 locales = ~1075 translations) covers
list/detail/form/picker/sender-form/send-modal + Swiss + German VAT-rate
labels.

- constants.ts: STATUS_LABELS still kept as a literal map for non-Svelte
  callers (mail-template, PDF renderer); Svelte components now use
  `$_('invoices.status.<status>')`. VAT_RATES_CH/DE switched from
  literal `label` to `i18nKey`, resolved per-component via $_.
- Locale-aware Date.toLocaleString in DetailView meta + SenderProfileForm
  saved-at timestamp (was hardcoded 'de-DE'/default).
- Baseline ratchet: 1817 → 1753 (64 invoices strings + a handful of
  SettingsSidebar follow-ons cleared).

- validate:i18n-parity: 40 namespaces × 5 locales — 3596 keys aligned
- svelte-check: 7647 files, 0 errors

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 21:56:48 +02:00
Till JS
6c942e3ab2 feat(profile): translate ContextOverview into all 5 locales
ContextOverview ("Freundebuch" profile cards) was the single biggest
hardcoded-string hot-spot at 35 strings — every user sees this on their
profile. Extended `profile.context.*` namespace with section titles,
field labels (routine/social/leisure), placeholders, weekday short
names, and empty-state hints across DE/EN/ES/FR/IT.

Bonus: ratchet i18n-hardcoded baseline from 1879 → 1817 (settings
namespace + ContextOverview together cleared 62 violations).

- validate:i18n-parity: 39 namespaces × 5 locales — 3381 keys aligned
- svelte-check: 7647 files, 0 errors

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 21:37:57 +02:00
Till JS
bad935c258 feat(writing): print CSS + keyboard shortcuts
Two DetailView polish items.

Print / PDF (fixes M10's "Drucken / PDF" action):
- New <article class="print-target"> at the top of the route renders
  just the title + current version content. Hidden on screen, only
  visible under @media print so window.print() produces a clean
  manuscript instead of dumping the whole workbench chrome.
- :global(body > *) toggle suppresses the surrounding SvelteKit /
  workbench frame; the .shell + the per-card chrome are explicitly
  display:none in print. @page margin: 2cm gives a readable page
  with no further user setup.
- Body uses ui-serif so the printed prose looks like manuscript.

Keyboard shortcuts (DetailView document-level listener):
- ⌘G / Ctrl+G       → generate / re-generate (was: only the button)
- ⌘⇧S / Ctrl+Shift+S → save checkpoint
- ⌘Z / Ctrl+Z        → undo last refinement (only fires when refineUndo
                       is set; otherwise falls through to the textarea's
                       native undo as the user expects)

Buttons + the undo row carry the shortcut in their title attribute so
mouse-users discover them via tooltip.

i18n baseline +1 for DetailView (the new "(⌘Z)" tooltip suffix counts
as one additional German fragment per the validator's heuristic).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 12:10:32 +02:00
Till JS
26e25b7694 feat(writing): M5 expansion — kontext, goal, me-image references
Three more reference kinds the resolver previously stubbed out are now
fully wired through the briefing form into the LLM prompt.

- reference-resolver: three new resolveX functions.
  * Kontext is a singleton per space (the picker uses a sentinel
    targetId; the resolver ignores it and reads via scopedForModule
    + first non-deleted row). Decrypts content and trims to budget.
  * Goal reads from companionGoals (plaintext today) and surfaces
    title + description + status + current/target so the model can
    tie the draft into the user's actual progress.
  * MeImage reads from the space-scoped meImages table; encrypts
    label + tags. Hands the model a textual descriptor (kind / label /
    tags) since the binary blob can't help prose generation.

- ReferencePicker: three new kind-tabs (🗂 Kontext, 🎯 Ziel, 🖼 Bild).
  Kontext renders as a single-click "Kontext-Dokument verknüpfen" entry
  if the space has one (with /kontext deep-link otherwise). Goals
  active-first, then archived/done. Me-images render with thumbnail +
  label + tags. Live-resolved chips via labelFor() for all three.

- i18n baseline bumped by one for ReferencePicker (the new
  "Kontext-Dokument verknüpfen" string is intentional, in line with
  the rest of the picker's existing German labels).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 11:43:12 +02:00
Till JS
8b9fbd2e1c feat(scripts): validate:i18n-hardcoded — ratcheting baseline check
Stoppt das Wachsen des 1877-String-Backlogs hardgecodeter deutscher
User-facing Strings in .svelte Files. Per-file Count vs. committed
Baseline; Datei darf NIE über ihrer Baseline liegen, neue Files müssen
mit 0 Verstößen starten.

- Erkennt: placeholder/title/aria-label/label/alt mit Umlauten,
  Text-Content `>Großbuchstabe…<` (ohne Interpolation).
- Aktuelle Baseline: 1877 Verstöße in 428 Files; jeder Fix ratchet't
  den erlaubten Wert nach unten.
- Lokales Update nach gewolltem Wachstum: `pnpm run validate:i18n-hardcoded -- --update`.
- In validate:all + CI verdrahtet.
- Drift-Test bestätigt: ein zusätzlicher umlaut-Placeholder lässt die
  Datei "2 (was 1, +1)" failen.

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