Phase 28 (Steps 6+9): mail active view + i18n keys
Tests · UI / test (push) Has been cancelled
Tests · Integration / integration (pull_request) Successful in 1m36s
Tests · Go / test (pull_request) Successful in 3m19s
Tests · UI / test (pull_request) Waiting to run

Step 6 — mail active view + subcomponents.

- `lib/active-view/mail.svelte` replaces the Phase 10 stub with the
  list / detail layout: two-pane on desktop, one-pane stack on
  mobile (CSS media query, no separate route).
- `lib/active-view/mail/thread-list.svelte` renders per-race
  threads collapsed to their last message plus stand-alone
  system / admin / outgoing-broadcast items, with unread badges.
- `lib/active-view/mail/thread-pane.svelte` is the chat-style
  transcript for one race; bodies render through `textContent`,
  per-message Show original / translation toggles flip the
  rendering when a translated body is present, and a persistent
  reply box at the bottom calls `mailStore.composePersonal`.
- `lib/active-view/mail/system-item-pane.svelte` renders one
  stand-alone item read-only with the same translation toggle.
- `lib/active-view/mail/compose.svelte` is the compose dialog:
  recipient race picker fed from `report.races[]`, kind toggle
  (personal / broadcast / admin), admin sub-toggle for target
  user / all and recipient-scope picker. Server-side enforces
  paid-tier and owner gating; the UI surfaces 403 inline.
- `lib/active-view/mail/system-titles.ts` keeps the keyword →
  i18n-title mapping for lifecycle-hook system mail so both the
  list and the detail pane pick the same canonical title.

Step 9 — i18n strings (en + ru).

`game.mail.*`, `game.view.mail.badge`, `game.events.mail_new.*`,
`game.mail.system.*` keys added in lockstep across both locales
covering compose labels / validation copy / per-system titles /
translation toggle / reply / delete affordances.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ilia Denisov
2026-05-15 22:43:09 +02:00
parent fdd5fd193d
commit f7300f25a3
8 changed files with 1066 additions and 12 deletions
+40
View File
@@ -123,6 +123,46 @@ const en = {
"game.view.report": "turn report",
"game.view.battle": "battle log",
"game.view.mail": "diplomatic mail",
"game.view.mail.badge": "{count}",
"game.events.mail_new.message": "new mail from {from}",
"game.events.mail_new.action": "view",
"game.mail.loading": "loading mail…",
"game.mail.load_failed": "could not load mail",
"game.mail.empty": "no diplomatic messages yet",
"game.mail.back": "back",
"game.mail.compose_action": "compose",
"game.mail.select_thread": "pick a thread on the left to read it",
"game.mail.broadcast.title": "your broadcast",
"game.mail.admin.title": "admin notification",
"game.mail.system.generic.title": "system message",
"game.mail.system.game_paused.title": "game paused",
"game.mail.system.game_cancelled.title": "game cancelled",
"game.mail.system.membership_removed.title": "membership removed",
"game.mail.system.membership_blocked.title": "membership blocked",
"game.mail.subject_placeholder": "subject (optional)",
"game.mail.body_placeholder": "your message…",
"game.mail.recipient_label": "race",
"game.mail.recipient_required": "pick a recipient race",
"game.mail.body_required": "the message body cannot be empty",
"game.mail.body_too_long": "the body exceeds the {limit} byte limit",
"game.mail.subject_too_long": "the subject exceeds the {limit} byte limit",
"game.mail.compose.send": "send",
"game.mail.compose.cancel": "cancel",
"game.mail.compose.target_personal": "personal",
"game.mail.compose.target_broadcast": "broadcast",
"game.mail.compose.target_admin": "admin",
"game.mail.compose.recipients_active": "active members",
"game.mail.compose.recipients_active_and_removed": "active + removed",
"game.mail.compose.recipients_all_members": "all members",
"game.mail.compose.target_label": "kind",
"game.mail.compose.recipients_label": "audience",
"game.mail.compose.send_failed": "send failed",
"game.mail.show_original": "show original",
"game.mail.show_translation": "show translation",
"game.mail.translation_unavailable": "translation unavailable",
"game.mail.reply_label": "reply",
"game.mail.delete_action": "delete",
"game.mail.outgoing_label": "you",
"game.view.designer.ship_class": "ship-class designer",
"game.view.designer.science": "science designer",
"game.sidebar.tab.calculator": "calculator",