Remove next-intl localization infrastructure
Strips out the i18n layer (next-intl, message files, language switcher, provider) to reduce complexity. Nav components now use plain English strings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,6 @@ import Link from 'next/link'
|
||||
import type { Route } from 'next'
|
||||
import { usePathname } from 'next/navigation'
|
||||
import { signOut } from 'next-auth/react'
|
||||
import { useTranslations } from 'next-intl'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
@@ -42,7 +41,6 @@ import { EditionSelector } from '@/components/shared/edition-selector'
|
||||
import { useEdition } from '@/contexts/edition-context'
|
||||
import { UserAvatar } from '@/components/shared/user-avatar'
|
||||
import { NotificationBell } from '@/components/shared/notification-bell'
|
||||
import { LanguageSwitcher } from '@/components/shared/language-switcher'
|
||||
import { useSession } from 'next-auth/react'
|
||||
import { trpc } from '@/lib/trpc/client'
|
||||
|
||||
@@ -147,7 +145,6 @@ const roleLabels: Record<string, string> = {
|
||||
|
||||
export function AdminSidebar({ user }: AdminSidebarProps) {
|
||||
const pathname = usePathname()
|
||||
const tAuth = useTranslations('auth')
|
||||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false)
|
||||
const { status: sessionStatus } = useSession()
|
||||
const isAuthenticated = sessionStatus === 'authenticated'
|
||||
@@ -173,7 +170,6 @@ export function AdminSidebar({ user }: AdminSidebarProps) {
|
||||
<div className="fixed top-0 left-0 right-0 z-40 flex h-16 items-center justify-between border-b bg-card px-4 lg:hidden">
|
||||
<Logo showText textSuffix="Admin" />
|
||||
<div className="flex items-center gap-2">
|
||||
<LanguageSwitcher />
|
||||
<NotificationBell />
|
||||
<Button
|
||||
variant="ghost"
|
||||
@@ -209,7 +205,6 @@ export function AdminSidebar({ user }: AdminSidebarProps) {
|
||||
<div className="flex h-16 items-center justify-between border-b px-6">
|
||||
<Logo showText textSuffix="Admin" />
|
||||
<div className="hidden lg:flex items-center gap-1">
|
||||
<LanguageSwitcher />
|
||||
<NotificationBell />
|
||||
</div>
|
||||
</div>
|
||||
@@ -349,7 +344,7 @@ export function AdminSidebar({ user }: AdminSidebarProps) {
|
||||
className="flex cursor-pointer items-center gap-2.5 rounded-md px-2 py-2 text-destructive focus:bg-destructive/10 focus:text-destructive"
|
||||
>
|
||||
<LogOut className="h-4 w-4" />
|
||||
<span>{tAuth('signOut')}</span>
|
||||
<span>Sign Out</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
@@ -2,32 +2,30 @@
|
||||
|
||||
import { Home, Users, FileText, MessageSquare } from 'lucide-react'
|
||||
import { RoleNav, type NavItem, type RoleNavUser } from '@/components/layouts/role-nav'
|
||||
import { useTranslations } from 'next-intl'
|
||||
|
||||
interface ApplicantNavProps {
|
||||
user: RoleNavUser
|
||||
}
|
||||
|
||||
export function ApplicantNav({ user }: ApplicantNavProps) {
|
||||
const t = useTranslations('nav')
|
||||
const navigation: NavItem[] = [
|
||||
{
|
||||
name: t('dashboard'),
|
||||
name: 'Dashboard',
|
||||
href: '/applicant',
|
||||
icon: Home,
|
||||
},
|
||||
{
|
||||
name: t('team'),
|
||||
name: 'Team',
|
||||
href: '/applicant/team',
|
||||
icon: Users,
|
||||
},
|
||||
{
|
||||
name: t('documents'),
|
||||
name: 'Documents',
|
||||
href: '/applicant/documents',
|
||||
icon: FileText,
|
||||
},
|
||||
{
|
||||
name: t('mentoring'),
|
||||
name: 'Mentoring',
|
||||
href: '/applicant/mentor',
|
||||
icon: MessageSquare,
|
||||
},
|
||||
|
||||
@@ -4,7 +4,6 @@ import { BookOpen, ClipboardList, GitCompare, Home, Trophy } from 'lucide-react'
|
||||
import { RoleNav, type NavItem, type RoleNavUser } from '@/components/layouts/role-nav'
|
||||
import { trpc } from '@/lib/trpc/client'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { useTranslations } from 'next-intl'
|
||||
|
||||
interface JuryNavProps {
|
||||
user: RoleNavUser
|
||||
@@ -43,30 +42,29 @@ function RemainingBadge() {
|
||||
}
|
||||
|
||||
export function JuryNav({ user }: JuryNavProps) {
|
||||
const t = useTranslations('nav')
|
||||
const navigation: NavItem[] = [
|
||||
{
|
||||
name: t('dashboard'),
|
||||
name: 'Dashboard',
|
||||
href: '/jury',
|
||||
icon: Home,
|
||||
},
|
||||
{
|
||||
name: t('assignments'),
|
||||
name: 'Assignments',
|
||||
href: '/jury/assignments',
|
||||
icon: ClipboardList,
|
||||
},
|
||||
{
|
||||
name: t('awards'),
|
||||
name: 'Awards',
|
||||
href: '/jury/awards',
|
||||
icon: Trophy,
|
||||
},
|
||||
{
|
||||
name: t('compare'),
|
||||
name: 'Compare',
|
||||
href: '/jury/compare',
|
||||
icon: GitCompare,
|
||||
},
|
||||
{
|
||||
name: t('learningHub'),
|
||||
name: 'Learning Hub',
|
||||
href: '/jury/learning',
|
||||
icon: BookOpen,
|
||||
},
|
||||
|
||||
@@ -2,27 +2,25 @@
|
||||
|
||||
import { BookOpen, Home, Users } from 'lucide-react'
|
||||
import { RoleNav, type NavItem, type RoleNavUser } from '@/components/layouts/role-nav'
|
||||
import { useTranslations } from 'next-intl'
|
||||
|
||||
interface MentorNavProps {
|
||||
user: RoleNavUser
|
||||
}
|
||||
|
||||
export function MentorNav({ user }: MentorNavProps) {
|
||||
const t = useTranslations('nav')
|
||||
const navigation: NavItem[] = [
|
||||
{
|
||||
name: t('dashboard'),
|
||||
name: 'Dashboard',
|
||||
href: '/mentor',
|
||||
icon: Home,
|
||||
},
|
||||
{
|
||||
name: t('myProjects'),
|
||||
name: 'My Projects',
|
||||
href: '/mentor/projects',
|
||||
icon: Users,
|
||||
},
|
||||
{
|
||||
name: t('learningHub'),
|
||||
name: 'Learning Hub',
|
||||
href: '/mentor/resources',
|
||||
icon: BookOpen,
|
||||
},
|
||||
|
||||
@@ -2,22 +2,20 @@
|
||||
|
||||
import { BarChart3, Home } from 'lucide-react'
|
||||
import { RoleNav, type NavItem, type RoleNavUser } from '@/components/layouts/role-nav'
|
||||
import { useTranslations } from 'next-intl'
|
||||
|
||||
interface ObserverNavProps {
|
||||
user: RoleNavUser
|
||||
}
|
||||
|
||||
export function ObserverNav({ user }: ObserverNavProps) {
|
||||
const t = useTranslations('nav')
|
||||
const navigation: NavItem[] = [
|
||||
{
|
||||
name: t('dashboard'),
|
||||
name: 'Dashboard',
|
||||
href: '/observer',
|
||||
icon: Home,
|
||||
},
|
||||
{
|
||||
name: t('reports'),
|
||||
name: 'Reports',
|
||||
href: '/observer/reports',
|
||||
icon: BarChart3,
|
||||
},
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useState, useEffect } from 'react'
|
||||
import Link from 'next/link'
|
||||
import { usePathname } from 'next/navigation'
|
||||
import { signOut, useSession } from 'next-auth/react'
|
||||
import { useTranslations } from 'next-intl'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { UserAvatar } from '@/components/shared/user-avatar'
|
||||
@@ -22,7 +21,6 @@ import { LogOut, Menu, Moon, Settings, Sun, User, X } from 'lucide-react'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { Logo } from '@/components/shared/logo'
|
||||
import { NotificationBell } from '@/components/shared/notification-bell'
|
||||
import { LanguageSwitcher } from '@/components/shared/language-switcher'
|
||||
|
||||
export type NavItem = {
|
||||
name: string
|
||||
@@ -51,8 +49,6 @@ function isNavItemActive(pathname: string, href: string, basePath: string): bool
|
||||
|
||||
export function RoleNav({ navigation, roleName, user, basePath, statusBadge }: RoleNavProps) {
|
||||
const pathname = usePathname()
|
||||
const tCommon = useTranslations('common')
|
||||
const tAuth = useTranslations('auth')
|
||||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false)
|
||||
const { status: sessionStatus } = useSession()
|
||||
const isAuthenticated = sessionStatus === 'authenticated'
|
||||
@@ -111,7 +107,6 @@ export function RoleNav({ navigation, roleName, user, basePath, statusBadge }: R
|
||||
)}
|
||||
</Button>
|
||||
)}
|
||||
<LanguageSwitcher />
|
||||
<NotificationBell />
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
@@ -135,7 +130,7 @@ export function RoleNav({ navigation, roleName, user, basePath, statusBadge }: R
|
||||
<DropdownMenuItem asChild>
|
||||
<Link href={"/settings/profile" as Route} className="flex cursor-pointer items-center">
|
||||
<Settings className="mr-2 h-4 w-4" />
|
||||
{tCommon('settings')}
|
||||
Settings
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
@@ -144,7 +139,7 @@ export function RoleNav({ navigation, roleName, user, basePath, statusBadge }: R
|
||||
className="text-destructive focus:text-destructive"
|
||||
>
|
||||
<LogOut className="mr-2 h-4 w-4" />
|
||||
{tAuth('signOut')}
|
||||
Sign Out
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
@@ -196,7 +191,7 @@ export function RoleNav({ navigation, roleName, user, basePath, statusBadge }: R
|
||||
onClick={() => signOut({ callbackUrl: '/login' })}
|
||||
>
|
||||
<LogOut className="mr-2 h-4 w-4" />
|
||||
{tAuth('signOut')}
|
||||
Sign Out
|
||||
</Button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import { useTransition } from 'react'
|
||||
import { useLocale } from 'next-intl'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu'
|
||||
import { Globe, Check } from 'lucide-react'
|
||||
|
||||
const LANGUAGES = [
|
||||
{ code: 'en', label: 'English', flag: 'EN' },
|
||||
{ code: 'fr', label: 'Fran\u00e7ais', flag: 'FR' },
|
||||
] as const
|
||||
|
||||
type LanguageCode = (typeof LANGUAGES)[number]['code']
|
||||
|
||||
export function LanguageSwitcher() {
|
||||
const locale = useLocale() as LanguageCode
|
||||
const router = useRouter()
|
||||
const [isPending, startTransition] = useTransition()
|
||||
|
||||
const currentLang = LANGUAGES.find((l) => l.code === locale) ?? LANGUAGES[0]
|
||||
|
||||
const switchLanguage = (code: LanguageCode) => {
|
||||
// Set cookie with 1 year expiry
|
||||
document.cookie = `locale=${code};path=/;max-age=${365 * 24 * 60 * 60};samesite=lax`
|
||||
// Refresh to re-run server components with new locale
|
||||
startTransition(() => {
|
||||
router.refresh()
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size="sm" className="gap-2" disabled={isPending}>
|
||||
<Globe className="h-4 w-4" />
|
||||
<span className="font-medium">{currentLang.flag}</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
{LANGUAGES.map((lang) => (
|
||||
<DropdownMenuItem
|
||||
key={lang.code}
|
||||
onClick={() => switchLanguage(lang.code)}
|
||||
className="gap-2"
|
||||
>
|
||||
<span className="font-medium w-6">{lang.flag}</span>
|
||||
<span>{lang.label}</span>
|
||||
{locale === lang.code && <Check className="ml-auto h-4 w-4" />}
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user