- Updated test components (`PasswordResetConfirmForm`, `PasswordChangeForm`) to use i18n keys directly, ensuring accurate validation messages. - Refined translations in `it.json` to standardize format and content. - Replaced text-based labels with localized strings in `PasswordResetRequestForm` and `RegisterForm`. - Introduced `generateLocalizedMetadata` utility and updated layout metadata generation for locale-aware SEO. - Enhanced e2e tests with locale-prefixed routes and updated assertions for consistency. - Added comprehensive i18n documentation (`I18N.md`) for usage, architecture, and testing.
60 lines
1.9 KiB
TypeScript
60 lines
1.9 KiB
TypeScript
/**
|
|
* 403 Forbidden Page
|
|
* Displayed when users try to access resources they don't have permission for
|
|
*/
|
|
|
|
import type { Metadata } from 'next';
|
|
import { Link } from '@/lib/i18n/routing';
|
|
import { ShieldAlert } from 'lucide-react';
|
|
import { Button } from '@/components/ui/button';
|
|
import { generatePageMetadata, type Locale } from '@/lib/i18n/metadata';
|
|
import { getTranslations } from 'next-intl/server';
|
|
|
|
export async function generateMetadata({
|
|
params,
|
|
}: {
|
|
params: Promise<{ locale: string }>;
|
|
}): Promise<Metadata> {
|
|
const { locale } = await params;
|
|
const t = await getTranslations({ locale, namespace: 'errors' });
|
|
|
|
return generatePageMetadata(
|
|
locale as Locale,
|
|
t('unauthorized'),
|
|
t('unauthorizedDescription'),
|
|
'/forbidden'
|
|
);
|
|
}
|
|
|
|
export default function ForbiddenPage() {
|
|
return (
|
|
<div className="container mx-auto px-6 py-16">
|
|
<div className="flex min-h-[60vh] flex-col items-center justify-center text-center">
|
|
<div className="mb-8 rounded-full bg-destructive/10 p-6">
|
|
<ShieldAlert className="h-16 w-16 text-destructive" aria-hidden="true" />
|
|
</div>
|
|
|
|
<h1 className="mb-4 text-4xl font-bold tracking-tight">403 - Access Forbidden</h1>
|
|
|
|
<p className="mb-2 text-lg text-muted-foreground max-w-md">
|
|
You don't have permission to access this resource.
|
|
</p>
|
|
|
|
<p className="mb-8 text-sm text-muted-foreground max-w-md">
|
|
This page requires administrator privileges. If you believe you should have access, please
|
|
contact your system administrator.
|
|
</p>
|
|
|
|
<div className="flex gap-4">
|
|
<Button asChild variant="default">
|
|
<Link href="/dashboard">Go to Dashboard</Link>
|
|
</Button>
|
|
<Button asChild variant="outline">
|
|
<Link href="/">Go to Home</Link>
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|