Phase 28 (Steps 6+9): mail active view + i18n keys
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:
@@ -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",
|
||||
|
||||
@@ -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": "калькулятор",
|
||||
|
||||
Reference in New Issue
Block a user