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:
2025-07-23 21:39:55 +02:00
co-authored by Claude
parent c2469ba5e9
commit 09c1578d6c
20 changed files with 1056 additions and 265 deletions
+49 -12
View File
@@ -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>
))}