feat: Add German translation support for MinIO WebUI
- Set up i18n infrastructure with react-i18next - Add German as default language with English fallback - Create comprehensive translation files for all UI components - Translate Dashboard, QuickStartWizard, Reports, and navigation - Add language switcher in app header - Maintain existing German email template in backend - Create modular translation structure with namespaces - Add testing checklist and implementation summary All user-facing strings in dashboard, quick wizard, and reports sections are now available in German, fulfilling the requirement for complete German localization. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
This commit is contained in:
@@ -17,6 +17,8 @@ import {
|
||||
Menu,
|
||||
MenuItem,
|
||||
Tooltip,
|
||||
Select,
|
||||
FormControl,
|
||||
} from '@mui/material';
|
||||
import {
|
||||
Menu as MenuIcon,
|
||||
@@ -28,7 +30,9 @@ import {
|
||||
Assessment as AssessmentIcon,
|
||||
Logout as LogoutIcon,
|
||||
AccountCircle as AccountCircleIcon,
|
||||
Language as LanguageIcon,
|
||||
} from '@mui/icons-material';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import useAuthStore from '../../store/authStore';
|
||||
|
||||
const drawerWidth = 240;
|
||||
@@ -37,23 +41,25 @@ interface NavItem {
|
||||
text: string;
|
||||
icon: React.ReactElement;
|
||||
path: string;
|
||||
translationKey: string;
|
||||
}
|
||||
|
||||
const navItems: NavItem[] = [
|
||||
{ text: 'Dashboard', icon: <DashboardIcon />, path: '/' },
|
||||
{ text: 'Buckets', icon: <StorageIcon />, path: '/buckets' },
|
||||
{ text: 'Users', icon: <PeopleIcon />, path: '/users' },
|
||||
{ text: 'Policies', icon: <PolicyIcon />, path: '/policies' },
|
||||
{ text: 'Reports', icon: <AssessmentIcon />, path: '/reports' },
|
||||
];
|
||||
|
||||
const Layout: React.FC = () => {
|
||||
const { t, i18n } = useTranslation(['common']);
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const { user, logout } = useAuthStore();
|
||||
const [open, setOpen] = useState(true);
|
||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||
|
||||
const navItems: NavItem[] = [
|
||||
{ text: 'Dashboard', icon: <DashboardIcon />, path: '/', translationKey: 'navigation.dashboard' },
|
||||
{ text: 'Buckets', icon: <StorageIcon />, path: '/buckets', translationKey: 'navigation.buckets' },
|
||||
{ text: 'Users', icon: <PeopleIcon />, path: '/users', translationKey: 'navigation.users' },
|
||||
{ text: 'Policies', icon: <PolicyIcon />, path: '/policies', translationKey: 'navigation.policies' },
|
||||
{ text: 'Reports', icon: <AssessmentIcon />, path: '/reports', translationKey: 'navigation.reports' },
|
||||
];
|
||||
|
||||
const handleDrawerToggle = () => {
|
||||
setOpen(!open);
|
||||
};
|
||||
@@ -71,6 +77,10 @@ const Layout: React.FC = () => {
|
||||
navigate('/login');
|
||||
};
|
||||
|
||||
const handleLanguageChange = (event: any) => {
|
||||
i18n.changeLanguage(event.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ display: 'flex', width: '100%' }}>
|
||||
<AppBar
|
||||
@@ -97,10 +107,37 @@ const Layout: React.FC = () => {
|
||||
</IconButton>
|
||||
|
||||
<Typography variant="h6" noWrap component="div" sx={{ flexGrow: 1 }}>
|
||||
MinIO WebUI
|
||||
{t('common:appName')}
|
||||
</Typography>
|
||||
|
||||
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
|
||||
<FormControl size="small" sx={{ minWidth: 120 }}>
|
||||
<Select
|
||||
value={i18n.language}
|
||||
onChange={handleLanguageChange}
|
||||
displayEmpty
|
||||
sx={{
|
||||
color: 'white',
|
||||
'& .MuiOutlinedInput-notchedOutline': {
|
||||
borderColor: 'rgba(255, 255, 255, 0.5)',
|
||||
},
|
||||
'&:hover .MuiOutlinedInput-notchedOutline': {
|
||||
borderColor: 'rgba(255, 255, 255, 0.8)',
|
||||
},
|
||||
'&.Mui-focused .MuiOutlinedInput-notchedOutline': {
|
||||
borderColor: 'white',
|
||||
},
|
||||
'& .MuiSvgIcon-root': {
|
||||
color: 'white',
|
||||
},
|
||||
}}
|
||||
startAdornment={<LanguageIcon sx={{ mr: 1, color: 'white' }} />}
|
||||
>
|
||||
<MenuItem value="de">Deutsch</MenuItem>
|
||||
<MenuItem value="en">English</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<Tooltip title="Account">
|
||||
<IconButton
|
||||
onClick={handleMenuOpen}
|
||||
@@ -150,7 +187,7 @@ const Layout: React.FC = () => {
|
||||
<ListItemIcon>
|
||||
<LogoutIcon fontSize="small" />
|
||||
</ListItemIcon>
|
||||
Logout
|
||||
{t('common:navigation.logout')}
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</Toolbar>
|
||||
@@ -191,7 +228,7 @@ const Layout: React.FC = () => {
|
||||
onClick={() => navigate(item.path)}
|
||||
>
|
||||
<ListItemIcon>{item.icon}</ListItemIcon>
|
||||
<ListItemText primary={item.text} />
|
||||
<ListItemText primary={t(`common:${item.translationKey}`)} />
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user