d0b454e7c8
- 统一 localStorage key:LanguageSwitcher 同时保存到 i18n_language 和 i18nextLng - 优化 API 请求拦截器:添加 getCurrentLanguage() 函数,优先从 localStorage 读取最新语言设置 - 支持兼容性:同时读取 i18n_language 和 i18nextLng(i18next 默认 key) - 规范化语言格式:确保返回正确的语言代码(zh-CN, zh-TW, en)
55 lines
1.6 KiB
TypeScript
55 lines
1.6 KiB
TypeScript
import { useState, useEffect } from 'react'
|
||
import { Select, Space } from 'antd'
|
||
import { GlobalOutlined } from '@ant-design/icons'
|
||
import { useTranslation } from 'react-i18next'
|
||
import { useMediaQuery } from 'react-responsive'
|
||
|
||
const LanguageSwitcher: React.FC = () => {
|
||
const { i18n } = useTranslation()
|
||
const isMobile = useMediaQuery({ maxWidth: 768 })
|
||
const [currentLang, setCurrentLang] = useState<string>(i18n.language || 'en')
|
||
|
||
useEffect(() => {
|
||
setCurrentLang(i18n.language || 'en')
|
||
}, [i18n.language])
|
||
|
||
const languages = [
|
||
{ value: 'zh-CN', label: '简体中文' },
|
||
{ value: 'zh-TW', label: '繁體中文' },
|
||
{ value: 'en', label: 'English' }
|
||
]
|
||
|
||
const handleChange = async (value: string) => {
|
||
setCurrentLang(value)
|
||
await i18n.changeLanguage(value)
|
||
// 保存到 localStorage(统一使用 i18n_language)
|
||
localStorage.setItem('i18n_language', value)
|
||
// 同时保存到 i18nextLng(i18next 默认使用的 key,用于兼容)
|
||
localStorage.setItem('i18nextLng', value)
|
||
// 刷新页面以应用 Ant Design 的 locale 和所有翻译
|
||
window.location.reload()
|
||
}
|
||
|
||
return (
|
||
<Space>
|
||
<GlobalOutlined style={{ color: '#fff', fontSize: isMobile ? '14px' : '16px' }} />
|
||
<Select
|
||
value={currentLang}
|
||
onChange={handleChange}
|
||
options={languages}
|
||
style={{
|
||
width: isMobile ? 100 : 120,
|
||
color: '#fff'
|
||
}}
|
||
dropdownStyle={{
|
||
minWidth: 120
|
||
}}
|
||
bordered={false}
|
||
size={isMobile ? 'small' : 'middle'}
|
||
/>
|
||
</Space>
|
||
)
|
||
}
|
||
|
||
export default LanguageSwitcher
|