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
@@ -124,6 +124,46 @@ const ru: Record<keyof typeof en, string> = {
"game.view.report": "отчёт хода",
"game.view.battle": "журнал боёв",
"game.view.mail": "дипломатическая почта",
"game.view.mail.badge": "{count}",
"game.events.mail_new.message": "новое письмо от {from}",
"game.events.mail_new.action": "открыть",
"game.mail.loading": "загрузка почты…",
"game.mail.load_failed": "не удалось загрузить почту",
"game.mail.empty": "дипломатических сообщений пока нет",
"game.mail.back": "назад",
"game.mail.compose_action": "написать",
"game.mail.select_thread": "выбери ветку слева",
"game.mail.broadcast.title": "твоя рассылка",
"game.mail.admin.title": "административное уведомление",
"game.mail.system.generic.title": "системное сообщение",
"game.mail.system.game_paused.title": "игра поставлена на паузу",
"game.mail.system.game_cancelled.title": "игра отменена",
"game.mail.system.membership_removed.title": "членство удалено",
"game.mail.system.membership_blocked.title": "членство заблокировано",
"game.mail.subject_placeholder": "тема (необязательно)",
"game.mail.body_placeholder": "твоё сообщение…",
"game.mail.recipient_label": "раса",
"game.mail.recipient_required": "выбери расу-получателя",
"game.mail.body_required": "тело сообщения не может быть пустым",
"game.mail.body_too_long": "длина тела превышает лимит {limit} байт",
"game.mail.subject_too_long": "длина темы превышает лимит {limit} байт",
"game.mail.compose.send": "отправить",
"game.mail.compose.cancel": "отмена",
"game.mail.compose.target_personal": "личное",
"game.mail.compose.target_broadcast": "рассылка",
"game.mail.compose.target_admin": "админ.",
"game.mail.compose.recipients_active": "активным членам",
"game.mail.compose.recipients_active_and_removed": "активным + удалённым",
"game.mail.compose.recipients_all_members": "всем членам",
"game.mail.compose.target_label": "тип",
"game.mail.compose.recipients_label": "адресаты",
"game.mail.compose.send_failed": "отправка не удалась",
"game.mail.show_original": "показать оригинал",
"game.mail.show_translation": "показать перевод",
"game.mail.translation_unavailable": "перевод недоступен",
"game.mail.reply_label": "ответить",
"game.mail.delete_action": "удалить",
"game.mail.outgoing_label": "ты",
"game.view.designer.ship_class": "конструктор класса кораблей",
"game.view.designer.science": "редактор наук",
"game.sidebar.tab.calculator": "калькулятор",