Skip to content

Commit 6e60ab2

Browse files
committed
feat: Implement dynamic language support in DashboardSidebar and LanguageSwitcher components
1 parent 4eeeaee commit 6e60ab2

3 files changed

Lines changed: 49 additions & 22 deletions

File tree

components/dashboard-sidebar.tsx

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,33 +27,37 @@ import { getCurrentUser, signOut } from "@/lib/auth"
2727
import { useEffect, useState } from "react"
2828
import type { User } from "@/lib/auth"
2929
import { NotificationsPanel } from "./notifications-panel"
30+
import { useLanguage } from "@/lib/i18n"
3031

31-
const navItems = [
32-
{ href: "/dashboard", label: "Dashboard", icon: LayoutDashboard },
33-
{ href: "/dashboard/projects", label: "Projects", icon: FolderKanban },
34-
{ href: "/dashboard/collaborators", label: "Collaborators", icon: Users },
35-
{ href: "/dashboard/chat", label: "Chat", icon: MessageCircle },
36-
{ href: "/dashboard/whiteboard", label: "Whiteboard", icon: Palette },
37-
{ href: "/dashboard/todo", label: "To Do", icon: CheckSquare },
38-
{ href: "/dashboard/meeting", label: "Meeting", icon: Calendar },
39-
{ href: "/dashboard/planning", label: "Planning", icon: ClipboardList },
40-
{ href: "/dashboard/diagrams", label: "Flow & Diagrams", icon: Workflow },
41-
{ href: "/dashboard/files", label: "Files", icon: FileText },
42-
{ href: "/dashboard/wiki", label: "Knowledge Base", icon: BookOpen },
43-
{ href: "/dashboard/community", label: "Community", icon: MessageSquare },
44-
{ href: "/dashboard/entertainment", label: "Entertainment", icon: Gamepad2 },
45-
{ href: "/dashboard/ai-tools", label: "AI Tools", icon: Sparkles },
46-
{ href: "/dashboard/support", label: "Live Support", icon: Headphones },
47-
{ href: "/dashboard/settings", label: "Settings", icon: Settings },
48-
]
32+
// navItems will be created inside the component so labels come from translations
4933

5034
export function DashboardSidebar() {
35+
const { t } = useLanguage()
5136
const pathname = usePathname()
5237
const router = useRouter()
5338
const [user, setUser] = useState<User | null>(null)
5439
const [isLoaded, setIsLoaded] = useState(false)
5540
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false)
5641

42+
const navItems = [
43+
{ href: "/dashboard", label: t.nav.dashboard || "Dashboard", icon: LayoutDashboard },
44+
{ href: "/dashboard/projects", label: t.nav.projects || "Projects", icon: FolderKanban },
45+
{ href: "/dashboard/collaborators", label: t.projects?.collaborators || "Collaborators", icon: Users },
46+
{ href: "/dashboard/chat", label: t.chat?.title || "Chat", icon: MessageCircle },
47+
{ href: "/dashboard/whiteboard", label: t.whiteboard?.title || "Whiteboard", icon: Palette },
48+
{ href: "/dashboard/todo", label: t.todo?.title || "To Do", icon: CheckSquare },
49+
{ href: "/dashboard/meeting", label: t.meeting?.title || "Meeting", icon: Calendar },
50+
{ href: "/dashboard/planning", label: t.planning?.title || "Planning", icon: ClipboardList },
51+
{ href: "/dashboard/diagrams", label: t.diagrams?.title || "Flow & Diagrams", icon: Workflow },
52+
{ href: "/dashboard/files", label: t.files?.title || "Files", icon: FileText },
53+
{ href: "/dashboard/wiki", label: t.wiki?.title || "Knowledge Base", icon: BookOpen },
54+
{ href: "/dashboard/community", label: t.community?.title || "Community", icon: MessageSquare },
55+
{ href: "/dashboard/entertainment", label: t.landing?.community?.title || "Entertainment", icon: Gamepad2 },
56+
{ href: "/dashboard/ai-tools", label: t.nav.aiTools || "AI Tools", icon: Sparkles },
57+
{ href: "/dashboard/support", label: "Live Support", icon: Headphones },
58+
{ href: "/dashboard/settings", label: t.nav.settings || "Settings", icon: Settings },
59+
]
60+
5761
useEffect(() => {
5862
const currentUser = getCurrentUser()
5963
if (!currentUser) {
@@ -197,7 +201,7 @@ export function DashboardSidebar() {
197201
<div className="p-1.5 border border-border group-hover:border-red-500 transition-colors">
198202
<LogOut className="h-4 w-4 group-hover:text-red-500 transition-colors" />
199203
</div>
200-
<span>Log Out</span>
204+
<span>{t.nav.signOut || "Log Out"}</span>
201205
</div>
202206
</button>
203207
</div>

components/language-switcher.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,14 @@ export function LanguageSwitcher() {
1818
setUserLanguage(lang)
1919
setCurrentLang(lang)
2020
setIsOpen(false)
21-
// Reload to apply language changes
22-
window.location.reload()
21+
// Notify other parts of the app in the same window to update without a full reload
22+
try {
23+
const evt = new CustomEvent("lab68_language_change", { detail: { lang } })
24+
window.dispatchEvent(evt)
25+
} catch (e) {
26+
// fallback to reload if CustomEvent isn't available
27+
window.location.reload()
28+
}
2329
}
2430

2531
return (

lib/i18n.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3795,8 +3795,25 @@ export function useLanguage() {
37953795
}
37963796
}
37973797

3798+
// Listen for in-window language change events (dispatched by LanguageSwitcher)
3799+
const handleCustomEvent = (e: Event) => {
3800+
try {
3801+
// support CustomEvent with detail
3802+
const ce = e as CustomEvent
3803+
const newLang = (ce?.detail?.lang as Language) || getUserLanguage()
3804+
setLanguage(newLang)
3805+
setTranslations(getTranslations(newLang))
3806+
} catch (err) {
3807+
// ignore
3808+
}
3809+
}
3810+
37983811
window.addEventListener("storage", handleStorageChange)
3799-
return () => window.removeEventListener("storage", handleStorageChange)
3812+
window.addEventListener("lab68_language_change", handleCustomEvent)
3813+
return () => {
3814+
window.removeEventListener("storage", handleStorageChange)
3815+
window.removeEventListener("lab68_language_change", handleCustomEvent)
3816+
}
38003817
}, [])
38013818

38023819
return {

0 commit comments

Comments
 (0)