added missing translations

This commit is contained in:
Codex Agent
2025-11-26 14:41:39 +01:00
parent ff168834b4
commit ecac9507a4
35 changed files with 2812 additions and 256 deletions

View File

@@ -34,7 +34,7 @@ interface TenantNotification {
export function NotificationCenter() {
const navigate = useNavigate();
const { t } = useTranslation('dashboard');
const { t } = useTranslation('management');
const [open, setOpen] = React.useState(false);
const [loading, setLoading] = React.useState(true);
const [notifications, setNotifications] = React.useState<TenantNotification[]>([]);
@@ -104,7 +104,7 @@ export function NotificationCenter() {
variant="ghost"
size="icon"
className="relative rounded-full border border-transparent text-slate-600 hover:text-rose-600 dark:text-slate-200"
aria-label={t('notifications.trigger', { defaultValue: 'Benachrichtigungen' })}
aria-label={t('notifications.trigger')}
>
<Bell className="h-5 w-5" />
{unreadCount > 0 ? (
@@ -116,9 +116,9 @@ export function NotificationCenter() {
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-80 space-y-1 p-0">
<DropdownMenuLabel className="flex items-center justify-between py-2">
<span>{t('notifications.title', { defaultValue: 'Notifications' })}</span>
<span>{t('notifications.title')}</span>
{!loading && unreadCount === 0 ? (
<Badge variant="outline">{t('notifications.empty', { defaultValue: 'Aktuell ruhig' })}</Badge>
<Badge variant="outline">{t('notifications.empty')}</Badge>
) : null}
</DropdownMenuLabel>
<DropdownMenuSeparator />
@@ -131,7 +131,7 @@ export function NotificationCenter() {
<div className="max-h-80 space-y-1 overflow-y-auto p-1">
{visibleNotifications.length === 0 ? (
<p className="px-3 py-4 text-sm text-slate-500">
{t('notifications.empty.message', { defaultValue: 'Alles erledigt wir melden uns bei Neuigkeiten.' })}
{t('notifications.empty.message')}
</p>
) : (
visibleNotifications.map((item) => (
@@ -163,7 +163,7 @@ export function NotificationCenter() {
className="h-7 rounded-full px-3 text-xs text-slate-500 hover:text-rose-600"
onClick={() => handleDismiss(item.id)}
>
{t('notifications.action.dismiss', { defaultValue: 'Ausblenden' })}
{t('notifications.action.dismiss')}
</Button>
</div>
</div>
@@ -183,7 +183,7 @@ export function NotificationCenter() {
}}
>
<Plus className="h-3.5 w-3.5" />
{t('notifications.action.refresh', { defaultValue: 'Neue Hinweise laden' })}
{t('notifications.action.refresh')}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
@@ -208,13 +208,11 @@ function buildNotifications({
if (events.length === 0) {
items.push({
id: 'no-events',
title: t('notifications.noEvents.title', { defaultValue: 'Legen wir los' }),
description: t('notifications.noEvents.description', {
defaultValue: 'Erstelle dein erstes Event, um Uploads, Aufgaben und Einladungen freizuschalten.',
}),
title: t('notifications.noEvents.title'),
description: t('notifications.noEvents.description'),
tone: 'warning',
action: {
label: t('notifications.noEvents.cta', { defaultValue: 'Event erstellen' }),
label: t('notifications.noEvents.cta'),
onSelect: () => navigate(ADMIN_EVENT_CREATE_PATH),
},
});
@@ -226,14 +224,12 @@ function buildNotifications({
if (event.status !== 'published') {
items.push({
id: `draft-${event.id}`,
title: t('notifications.draftEvent.title', { defaultValue: 'Event noch als Entwurf' }),
description: t('notifications.draftEvent.description', {
defaultValue: 'Veröffentliche das Event, um Einladungen und Galerie freizugeben.',
}),
title: t('notifications.draftEvent.title'),
description: t('notifications.draftEvent.description'),
tone: 'info',
action: event.slug
? {
label: t('notifications.draftEvent.cta', { defaultValue: 'Event öffnen' }),
label: t('notifications.draftEvent.cta'),
onSelect: () => navigate(ADMIN_EVENT_VIEW_PATH(event.slug!)),
}
: undefined,
@@ -244,37 +240,33 @@ function buildNotifications({
if (eventDate && eventDate > now) {
const days = Math.round((eventDate - now) / (1000 * 60 * 60 * 24));
if (days <= 7) {
items.push({
id: `upcoming-${event.id}`,
title: t('notifications.upcomingEvent.title', { defaultValue: 'Event startet bald' }),
description: t('notifications.upcomingEvent.description', {
defaultValue: days === 0
? 'Heute findet ein Event statt checke Uploads und Tasks.'
: `Noch ${days} Tage bereite Einladungen und Aufgaben vor.`,
}),
tone: 'info',
action: event.slug
? {
label: t('notifications.upcomingEvent.cta', { defaultValue: 'Zum Event' }),
onSelect: () => navigate(ADMIN_EVENT_VIEW_PATH(event.slug!)),
}
: undefined,
});
}
items.push({
id: `upcoming-${event.id}`,
title: t('notifications.upcomingEvent.title'),
description: days === 0
? t('notifications.upcomingEvent.description_today')
: t('notifications.upcomingEvent.description_days', { count: days }),
tone: 'info',
action: event.slug
? {
label: t('notifications.upcomingEvent.cta'),
onSelect: () => navigate(ADMIN_EVENT_VIEW_PATH(event.slug!)),
}
: undefined,
});
}
}
const pendingUploads = Number(event.pending_photo_count ?? 0);
if (pendingUploads > 0) {
items.push({
id: `pending-uploads-${event.id}`,
title: t('notifications.pendingUploads.title', { defaultValue: 'Uploads warten auf Freigabe' }),
description: t('notifications.pendingUploads.description', {
defaultValue: `${pendingUploads} neue Uploads benötigen Moderation.`,
}),
title: t('notifications.pendingUploads.title'),
description: t('notifications.pendingUploads.description', { count: pendingUploads }),
tone: 'warning',
action: event.slug
? {
label: t('notifications.pendingUploads.cta', { defaultValue: 'Uploads öffnen' }),
label: t('notifications.pendingUploads.cta'),
onSelect: () => navigate(`${ADMIN_EVENT_VIEW_PATH(event.slug!)}#photos`),
}
: undefined,
@@ -285,18 +277,16 @@ function buildNotifications({
if ((summary?.new_photos ?? 0) > 0) {
items.push({
id: 'summary-new-photos',
title: t('notifications.newPhotos.title', { defaultValue: 'Neue Fotos eingetroffen' }),
description: t('notifications.newPhotos.description', {
defaultValue: `${summary?.new_photos ?? 0} Uploads warten auf dich.`,
}),
title: t('notifications.newPhotos.title'),
description: t('notifications.newPhotos.description', { count: summary?.new_photos ?? 0 }),
tone: 'success',
action: primary?.slug
? {
label: t('notifications.newPhotos.cta', { defaultValue: 'Galerie öffnen' }),
label: t('notifications.newPhotos.cta'),
onSelect: () => navigate(ADMIN_EVENT_VIEW_PATH(primary.slug!)),
}
: {
label: t('notifications.newPhotos.ctaFallback', { defaultValue: 'Events ansehen' }),
label: t('notifications.newPhotos.ctaFallback'),
onSelect: () => navigate(ADMIN_EVENTS_PATH),
},
});