@@ -4,16 +4,37 @@ import { Languages } from 'lucide-react';
44import { useRouter , usePathname } from 'next/navigation' ;
55import { useLocale } from 'next-intl' ;
66import { useState , useEffect } from 'react' ;
7+ import { locales } from '@/i18n' ;
8+
9+ // Helper function to get language name from messages
10+ const getLanguageName = async ( localeCode : string ) : Promise < string > => {
11+ try {
12+ const messages = await import ( `../../messages/${ localeCode } .json` ) ;
13+ return messages . default . language ?. name || localeCode ;
14+ } catch {
15+ return localeCode ;
16+ }
17+ } ;
718
819export function LanguageToggle ( ) {
920 const router = useRouter ( ) ;
1021 const pathname = usePathname ( ) ;
1122 const locale = useLocale ( ) ;
1223 const [ isOpen , setIsOpen ] = useState ( false ) ;
1324 const [ mounted , setMounted ] = useState ( false ) ;
25+ const [ languageNames , setLanguageNames ] = useState < Record < string , string > > ( { } ) ;
1426
15- // Only enable client-side features after hydration
27+ // Load language names from i18n messages
1628 useEffect ( ( ) => {
29+ const loadLanguageNames = async ( ) => {
30+ const names : Record < string , string > = { } ;
31+ for ( const localeCode of locales ) {
32+ names [ localeCode ] = await getLanguageName ( localeCode ) ;
33+ }
34+ setLanguageNames ( names ) ;
35+ } ;
36+
37+ loadLanguageNames ( ) ;
1738 setMounted ( true ) ;
1839 } , [ ] ) ;
1940
@@ -31,7 +52,7 @@ export function LanguageToggle() {
3152 < div className = "relative" >
3253 < button
3354 onClick = { ( ) => mounted && setIsOpen ( ! isOpen ) }
34- className = "group w-9 h-9 rounded-full flex items-center justify-center border border-border/20 hover:border-border/40 backdrop-blur-sm hover:backdrop-blur-md hover:bg-accent/10 transition-all duration-300"
55+ className = "group w-9 h-9 rounded-full flex items-center justify-center border border-border/20 hover:border-border/40 backdrop-blur-sm hover:backdrop-blur-md hover:bg-accent/10 transition-all duration-300 cursor-pointer disabled:cursor-default "
3556 aria-label = "Toggle language"
3657 disabled = { ! mounted }
3758 >
@@ -44,24 +65,24 @@ export function LanguageToggle() {
4465 className = "fixed inset-0 z-10"
4566 onClick = { ( ) => setIsOpen ( false ) }
4667 />
47- < div className = "absolute right-0 top-full mt-2 w-32 backdrop-blur-md border border-border/30 rounded-xl shadow-2xl z-20 overflow-hidden bg-background/80 " >
48- < button
49- onClick = { ( ) => toggleLanguage ( 'en' ) }
50- className = { `w-full px-4 py-3 text-left text-sm hover:bg-accent/50 transition-all duration-200 ${
51- locale === 'en' ? 'text-foreground font-medium bg-accent/20' : 'text-muted-foreground'
52- } ` }
53- >
54- English
55- </ button >
56- < div className = "w-full h-px bg-border/30" > </ div >
57- < button
58- onClick = { ( ) => toggleLanguage ( 'zh' ) }
59- className = { `w-full px-4 py-3 text-left text-sm hover:bg-accent/50 transition-all duration-200 ${
60- locale === 'zh' ? 'text-foreground font-medium bg-accent/20' : 'text-muted-foreground'
61- } ` }
62- >
63- 中文
64- </ button >
68+ < div className = "absolute right-0 top-full mt-2 w-32 backdrop-blur-md border border-border/30 rounded-xl shadow-2xl z-20 overflow-hidden bg-background/95 " >
69+ { locales . map ( ( localeCode , index ) => (
70+ < div key = { localeCode } >
71+ < button
72+ onClick = { ( ) => toggleLanguage ( localeCode ) }
73+ className = { `w-full px-4 py-3 text-left text-sm transition-all duration-200 cursor-pointer hover:bg-slate-100 dark:hover:bg-slate-800 hover:text-slate-900 dark:hover:text-slate-100 ${
74+ locale === localeCode
75+ ? 'text-foreground font-semibold bg-slate-200 dark:bg-slate-700'
76+ : 'text-muted-foreground'
77+ } ` }
78+ >
79+ { languageNames [ localeCode ] || localeCode }
80+ </ button >
81+ { index < locales . length - 1 && (
82+ < div className = "w-full h-px bg-border/30" > </ div >
83+ ) }
84+ </ div >
85+ ) ) }
6586 </ div >
6687 </ >
6788 ) }
0 commit comments