feat(i18n): add internationalization support with i18next

- Add i18next and related dependencies for internationalization
- Implement language switcher component with English and Chinese support
- Create translation files for English and Chinese locales
- Update login and home pages to use translations
- Configure i18n initialization with language detection
- Add dayjs locale synchronization with i18n language changes
- Update tsconfig and eslint to ignore new locales directory
- Remove unused App.css and simplify index.css
- Update npmrc with mirror configuration
This commit is contained in:
2025-10-10 11:15:56 +08:00
parent a1e8f47ed4
commit 8cf7a4e5d5
16 changed files with 1430 additions and 138 deletions

View File

@@ -1,5 +1,6 @@
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import {
Box,
Button,
@@ -14,8 +15,10 @@ import {
Card,
CardContent
} from '@mui/material';
import LanguageSwitcher from '../components/LanguageSwitcher';
const Login = () => {
const { t } = useTranslation();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [rememberEmail, setRememberEmail] = useState(false);
@@ -24,6 +27,8 @@ const Login = () => {
const [passwordError, setPasswordError] = useState(false);
const navigate = useNavigate();
console.log(t, t('en'), t('login'));
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
@@ -44,7 +49,7 @@ const Login = () => {
<Box sx={{ minHeight: '100vh', width: '100vw', bgcolor: 'background.default', display: 'flex', flexDirection: 'column' }}>
{/* 顶部栏使用主题主色 */}
<AppBar position="static" color="primary" enableColorOnDark>
<Toolbar sx={{ minHeight: 60 }}>
<Toolbar sx={{ minHeight: 60, justifyContent: 'space-between' }}>
<Box
sx={{
width: 40,
@@ -62,6 +67,7 @@ const Login = () => {
>
T
</Box>
<LanguageSwitcher />
</Toolbar>
</AppBar>
@@ -69,12 +75,12 @@ const Login = () => {
<Container maxWidth="sm" sx={{ flex: 1, display: 'flex', alignItems: 'center' }}>
<Card sx={{ width: '100%' }}>
<CardContent sx={{ p: 4 }}>
<Typography variant="caption" color="text.secondary" sx={{ mb: 1, display: 'block' }}>
Servicename
<Typography variant="subtitle1" color="text.secondary" sx={{ mb: 1, display: 'block' }}>
T-Systems Enterprise RAG Empowerment System
</Typography>
<Typography variant="h5" fontWeight={700} sx={{ mb: 2 }}>
Enter Login
<br /> Email & Password
{t('login.login')}
<br /> {t('login.emailLabel')} & {t('login.passwordLabel')}
</Typography>
<Box component="form" onSubmit={handleSubmit} noValidate>
@@ -83,7 +89,7 @@ const Login = () => {
id="email"
name="email"
type="email"
placeholder="Email"
placeholder={t('login.emailPlaceholder')}
autoComplete="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
@@ -97,7 +103,7 @@ const Login = () => {
id="password"
name="password"
type="password"
placeholder="Password"
placeholder={t('login.passwordPlaceholder')}
autoComplete="current-password"
value={password}
onChange={(e) => setPassword(e.target.value)}
@@ -115,23 +121,18 @@ const Login = () => {
id="rememberEmail"
/>
}
label="Remember email"
label={t('login.rememberMe')}
/>
<Link href="#" variant="caption">
Forgot your username or password?
</Link>
</Box>
<Button type="submit" variant="contained" fullWidth disabled={isSubmitting}>
{isSubmitting ? 'Processing...' : 'Login'}
{isSubmitting ? 'Processing...' : t('login.login')}
</Button>
</Box>
<Box sx={{ mt: 2, textAlign: 'center' }}>
<Link href="#">Do you need help?</Link>
<Box mt={0.5}>
{/* 保留说明文案,去掉社交登录 */}
No account? <Link href="#">Sign up</Link>.
{t('login.signInTip')} <Link href="#">{t('login.signUp')}</Link>.
</Box>
</Box>
</CardContent>