From afa136245bc21d34c7f0f78316462556f2f262b3 Mon Sep 17 00:00:00 2001 From: Ivan Mercedes Date: Tue, 7 Jul 2026 14:25:19 -0400 Subject: [PATCH] feat(i18n): translate dashboard overview components - Added `Dashboard` namespace to English dictionary. - Translated metric cards, quick actions, and activity feed. - Localized charts (conversations, pipeline donut, response time) and empty states. --- messages/en.json | 65 +++++++++++++++++++ src/app/(dashboard)/dashboard/page.tsx | 33 ++++++---- src/components/dashboard/activity-feed.tsx | 28 ++++---- .../dashboard/conversations-chart.tsx | 27 ++++---- src/components/dashboard/empty-state.tsx | 9 ++- src/components/dashboard/pipeline-donut.tsx | 18 +++-- src/components/dashboard/quick-actions.tsx | 16 +++-- .../dashboard/response-time-chart.tsx | 18 ++--- 8 files changed, 155 insertions(+), 59 deletions(-) diff --git a/messages/en.json b/messages/en.json index b45f3f3..939d20a 100644 --- a/messages/en.json +++ b/messages/en.json @@ -59,5 +59,70 @@ }, "ModeToggle": { "switchMode": "Switch to {mode} mode" + }, + "Dashboard": { + "page": { + "title": "Dashboard", + "description": "Live analytics across conversations, contacts, deals, broadcasts, and automations.", + "activeConversations": "Active Conversations", + "newContactsToday": "New Contacts Today", + "openDealsValue": "Open Deals Value", + "messagesSentToday": "Messages Sent Today", + "newTodayVsYesterday": "new today vs yesterday", + "vsYesterday": "vs yesterday", + "openDeals": "{count} open {count, plural, =1 {deal} other {deals}}", + "noChange": "No change {suffix}" + }, + "quickActions": { + "newContact": "New Contact", + "newDeal": "New Deal", + "newBroadcast": "New Broadcast", + "newAutomation": "New Automation" + }, + "activityFeed": { + "title": "Recent Activity", + "viewAll": "View all →", + "noActivity": "No activity yet", + "noActivityHint": "Activity from messages, deals, broadcasts, and automations will appear here.", + "showingOf": "Showing {visible} of {totalLoaded}{plus}", + "show": "Show", + "timeS": "{sec}s ago", + "timeM": "{min}m ago", + "timeH": "{hr}h ago", + "timeD": "{day}d ago" + }, + "conversationsChart": { + "title": "Conversations Over Time", + "description": "Daily message volume by direction", + "days": "{count} days", + "noActivity": "No message activity in this range", + "noActivityHint": "Send or receive messages to start populating this chart.", + "incoming": "Incoming", + "outgoing": "Outgoing", + "tooltipIncoming": "{count} incoming", + "tooltipOutgoing": "{count} outgoing", + "ariaLabel": "Conversations per day" + }, + "pipelineDonut": { + "title": "Pipeline Value", + "description": "Open deals by stage", + "noOpenDeals": "No open deals yet", + "noOpenDealsHint": "Create deals in Pipelines to see stage breakdowns here.", + "dealCount": "{count} {count, plural, =1 {deal} other {deals}}", + "total": "Total", + "ariaLabel": "Pipeline value by stage" + }, + "responseTimeChart": { + "title": "Average First Response Time", + "description": "Minutes to reply to a customer's first unreplied message, by weekday", + "target": "target {minutes}m", + "thisWeek": "This week:", + "lastWeek": "Last week:", + "noReplies": "No replies recorded yet", + "noRepliesHint": "This chart fills in as you reply to customer messages." + }, + "emptyState": { + "title": "Not enough data yet" + } } } diff --git a/src/app/(dashboard)/dashboard/page.tsx b/src/app/(dashboard)/dashboard/page.tsx index fd2227e..5b8caa4 100644 --- a/src/app/(dashboard)/dashboard/page.tsx +++ b/src/app/(dashboard)/dashboard/page.tsx @@ -34,9 +34,12 @@ import { PipelineDonut } from '@/components/dashboard/pipeline-donut' import { ResponseTimeChart } from '@/components/dashboard/response-time-chart' import { ActivityFeed } from '@/components/dashboard/activity-feed' +import { useTranslations } from 'next-intl' + type RangeDays = 7 | 30 | 90 export default function DashboardPage() { + const t = useTranslations('Dashboard.page') const { defaultCurrency } = useAuth() const [metrics, setMetrics] = useState(null) const [metricsLoading, setMetricsLoading] = useState(true) @@ -122,9 +125,9 @@ export default function DashboardPage() {
{/* Header */}
-

Dashboard

+

{t('title')}

- Live analytics across conversations, contacts, deals, broadcasts, and automations. + {t('description')}

@@ -135,16 +138,20 @@ export default function DashboardPage() { ) : ( <> @@ -218,8 +227,8 @@ export default function DashboardPage() { // ------------------------------------------------------------ -function deltaLabel(delta: number, suffix: string): string { - if (delta === 0) return `No change ${suffix}` +function deltaLabel(delta: number, suffix: string, noChangeLabel: string): string { + if (delta === 0) return noChangeLabel const sign = delta > 0 ? '+' : '' return `${sign}${delta.toLocaleString()} ${suffix}` } diff --git a/src/components/dashboard/activity-feed.tsx b/src/components/dashboard/activity-feed.tsx index 346a485..a5b39e7 100644 --- a/src/components/dashboard/activity-feed.tsx +++ b/src/components/dashboard/activity-feed.tsx @@ -38,7 +38,10 @@ const KIND_THEME: Record = { automation: { icon: Zap, badge: 'bg-rose-500/10 text-rose-400' }, } +import { useTranslations } from 'next-intl' + export function ActivityFeed({ items, loading }: ActivityFeedProps) { + const t = useTranslations('Dashboard.activityFeed') // Start at 5 — a quick scan of the most recent events without // dominating vertical real estate. User expands explicitly via the // footer control when they want deeper history. @@ -56,12 +59,12 @@ export function ActivityFeed({ items, loading }: ActivityFeedProps) { return (
-

Recent Activity

+

{t('title')}

- View all → + {t('viewAll')}
@@ -75,8 +78,8 @@ export function ActivityFeed({ items, loading }: ActivityFeedProps) {
) : ( @@ -103,7 +106,7 @@ export function ActivityFeed({ items, loading }: ActivityFeedProps) { {it.text} - {relativeTime(it.at)} + {relativeTime(it.at, t)}
) @@ -122,11 +125,10 @@ export function ActivityFeed({ items, loading }: ActivityFeedProps) {