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:
@@ -14,6 +14,8 @@ import {
|
||||
Typography,
|
||||
styled
|
||||
} from '@mui/material';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import LanguageSwitcher from '../components/LanguageSwitcher';
|
||||
|
||||
const StyledCard = styled(Card)({
|
||||
height: '100%',
|
||||
@@ -93,8 +95,18 @@ const recentQueries = [
|
||||
];
|
||||
|
||||
const Home = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Box className="p-6">
|
||||
{/* Header with Language Switcher */}
|
||||
<Box className="flex justify-between items-center mb-6">
|
||||
<Typography variant="h4" className="font-bold text-gray-800">
|
||||
{t('navigation.dashboard')}
|
||||
</Typography>
|
||||
<LanguageSwitcher />
|
||||
</Box>
|
||||
|
||||
<Grid container spacing={3}>
|
||||
{/* Knowledge Base Status Card */}
|
||||
<Grid size={{ xs: 12, md: 6, lg: 4 }}>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user