chatbot-ui/components/ui/language-switcher.tsx

79 lines
2.5 KiB
TypeScript

'use client'
import i18nConfig from '@/i18nConfig'
import { usePathname, useRouter } from 'next/navigation'
import { useEffect, useTransition } from 'react'
import { Globe } from 'lucide-react'
export function LanguageSwitcher() {
const router = useRouter()
const pathname = usePathname()
const [isPending, startTransition] = useTransition()
const currentLocale = pathname.split('/')[1] || i18nConfig.defaultLocale
useEffect(() => {
// 只在加载时检查,避免多次保存 cookie
if (typeof window !== 'undefined') {
const saved = localStorage.getItem('preferred-language')
const isLocaleInPath = i18nConfig.locales.includes(currentLocale as any)
// 只有在 URL 中没有 locale 前缀时才进行处理
if (!isLocaleInPath && saved !== currentLocale) {
// 不做 cookie 写入,除非用户选择语言
console.log('[LanguageSwitcher] No need to update cookie, currentLocale:', currentLocale)
}
}
}, [currentLocale])
const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
const newLocale = e.target.value
// 仅在用户选择语言后保存 cookie
document.cookie = `preferred-language=${newLocale}; path=/; max-age=31536000`
// 验证 cookie 是否成功写入
const cookieValue = document.cookie
console.log('[LanguageSwitcher] Cookie set to:', cookieValue)
let segments = pathname === '/' ? [] : pathname.split('/').filter(Boolean)
const isLocaleInPath = i18nConfig.locales.includes(segments[0] as any)
if (isLocaleInPath) {
segments[0] = newLocale
} else {
segments.unshift(newLocale)
}
const newPath = '/' + segments.join('/')
// 延迟跳转,确保 cookie 写入完成
setTimeout(() => {
startTransition(() => {
if (pathname !== newPath) {
router.push(newPath)
} else {
router.refresh()
}
})
}, 0)
}
return (
<div className="absolute top-4 right-4 z-50 flex items-center gap-2">
<Globe size={18} className="text-muted-foreground" />
<select
className="rounded-md border px-2 py-1 text-sm bg-background text-foreground"
value={currentLocale}
onChange={handleChange}
disabled={isPending}
>
{i18nConfig.locales.map(locale => (
<option key={locale} value={locale}>
{i18nConfig.languageNames[locale] || locale.toUpperCase()}
</option>
))}
</select>
</div>
)
}