Skip to content

Commit 2f1fb09

Browse files
fix(notifications): user notifications page rendered raw i18n keys + wrong type field (#308)
Found while QA-testing the community & notifications area (#291). The student/shared notifications page (`/dashboard/notifications`) was fully broken visually: 1. The entire `dashboard.student.notifications` i18n namespace was missing from en.json and es.json. Every label rendered as its raw key path — "dashboard.student.notifications.title", "dashboard.student.notifications.tabs.all", ".empty.none", etc. Added the complete namespace in both locales (title, description, tabs, empty, actions, toasts, priority, types). 2. `NotificationsClient` read `notification.notification.type`, but the joined `notifications` row exposes `notification_type` (there is no `type` column). The type badge therefore resolved to `undefined` and showed a raw `types.undefined` key. Switched to `notification_type` and guarded the lookup with `t.has()` so an unmapped type falls back to the raw value instead of leaking the key path. Verified end-to-end as Alice Student (4 certificate notifications): - en + es chrome fully translated (title/description/tabs/empty) - priority badge → "High"/"Alta", type badge → "Certificate"/"Certificado" - "Mark all as read" flips Unread 4→0 / Read 0→4 with the localized toast - admin (no notifications) shows the proper empty state Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 862d2ec commit 2f1fb09

4 files changed

Lines changed: 95 additions & 3 deletions

File tree

components/notifications-client.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ type UserNotification = {
3333
id: number
3434
title: string
3535
content: string
36-
type: string
36+
notification_type: string
3737
priority: string
3838
}
3939
}
@@ -207,8 +207,10 @@ export function NotificationsClient({ notifications: initialNotifications }: Not
207207
>
208208
{t(`priority.${notification.notification.priority}`) || notification.notification.priority}
209209
</Badge>
210-
<Badge variant="outline" className={`text-xs ${getTypeColor(notification.notification.type)}`}>
211-
{t(`types.${notification.notification.type}`) || notification.notification.type}
210+
<Badge variant="outline" className={`text-xs ${getTypeColor(notification.notification.notification_type)}`}>
211+
{t.has(`types.${notification.notification.notification_type}`)
212+
? t(`types.${notification.notification.notification_type}`)
213+
: notification.notification.notification_type}
212214
</Badge>
213215
<span className="text-xs text-muted-foreground">
214216
{formatDistanceToNow(new Date(notification.created_at), {
3.18 MB
Loading

messages/en.json

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,51 @@
154154
},
155155
"dashboard": {
156156
"student": {
157+
"notifications": {
158+
"title": "Notifications",
159+
"description": "Stay up to date with activity across your school.",
160+
"tabs": {
161+
"all": "All",
162+
"unread": "Unread",
163+
"read": "Read"
164+
},
165+
"empty": {
166+
"title": "No notifications",
167+
"none": "You don't have any notifications yet.",
168+
"caughtUp": "You're all caught up!"
169+
},
170+
"actions": {
171+
"markAllAsRead": "Mark all as read"
172+
},
173+
"toasts": {
174+
"markAsReadSuccess": "Notification marked as read",
175+
"markAsReadError": "Couldn't mark notification as read",
176+
"markAllAsReadSuccess": "All notifications marked as read",
177+
"markAllAsReadError": "Couldn't mark all as read",
178+
"dismissSuccess": "Notification dismissed",
179+
"dismissError": "Couldn't dismiss notification",
180+
"error": "Something went wrong"
181+
},
182+
"priority": {
183+
"low": "Low",
184+
"normal": "Normal",
185+
"high": "High",
186+
"urgent": "Urgent"
187+
},
188+
"types": {
189+
"info": "Info",
190+
"success": "Success",
191+
"warning": "Warning",
192+
"error": "Error",
193+
"alert": "Alert",
194+
"certificate_issued": "Certificate",
195+
"comment": "Comment",
196+
"comment_reply": "Reply",
197+
"exam_review": "Exam review",
198+
"order_renewal": "Order renewal",
199+
"subscription_renewal": "Subscription renewal"
200+
}
201+
},
157202
"title": "My Learning",
158203
"welcome": "Welcome back! Continue where you left off.",
159204
"enrolledCourses": "Enrolled Courses",

messages/es.json

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,51 @@
154154
},
155155
"dashboard": {
156156
"student": {
157+
"notifications": {
158+
"title": "Notificaciones",
159+
"description": "Mantente al día con la actividad de tu escuela.",
160+
"tabs": {
161+
"all": "Todas",
162+
"unread": "No leídas",
163+
"read": "Leídas"
164+
},
165+
"empty": {
166+
"title": "Sin notificaciones",
167+
"none": "Aún no tienes notificaciones.",
168+
"caughtUp": "¡Estás al día!"
169+
},
170+
"actions": {
171+
"markAllAsRead": "Marcar todas como leídas"
172+
},
173+
"toasts": {
174+
"markAsReadSuccess": "Notificación marcada como leída",
175+
"markAsReadError": "No se pudo marcar como leída",
176+
"markAllAsReadSuccess": "Todas las notificaciones marcadas como leídas",
177+
"markAllAsReadError": "No se pudieron marcar todas como leídas",
178+
"dismissSuccess": "Notificación descartada",
179+
"dismissError": "No se pudo descartar la notificación",
180+
"error": "Algo salió mal"
181+
},
182+
"priority": {
183+
"low": "Baja",
184+
"normal": "Normal",
185+
"high": "Alta",
186+
"urgent": "Urgente"
187+
},
188+
"types": {
189+
"info": "Información",
190+
"success": "Éxito",
191+
"warning": "Advertencia",
192+
"error": "Error",
193+
"alert": "Alerta",
194+
"certificate_issued": "Certificado",
195+
"comment": "Comentario",
196+
"comment_reply": "Respuesta",
197+
"exam_review": "Revisión de examen",
198+
"order_renewal": "Renovación de pedido",
199+
"subscription_renewal": "Renovación de suscripción"
200+
}
201+
},
157202
"title": "Mi Aprendizaje",
158203
"welcome": "¡Bienvenido de nuevo! Continúa donde lo dejaste.",
159204
"enrolledCourses": "Cursos Inscritos",

0 commit comments

Comments
 (0)