Complete translation implementation for admin interface

- Fixed all hardcoded strings in admin components to use t() function
- Updated BrandingPage.tsx to use translations for watermark settings
- Updated EventsListPage.tsx to use translations for status labels
- Added missing translation keys to both en.json and de.json
- Fixed translations for:
  - System settings (general, storage, categories tabs)
  - Branding page (watermark settings, positions, opacity)
  - Email configuration and templates
  - Event list view (status labels, filters, actions)
  - Event detail view (all sections properly translated)
- Added comprehensive German translations for all new keys
- Ensured consistent translation usage across all admin pages

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-07-08 17:41:02 +02:00
parent d594d00227
commit 1bc9b547c7
11 changed files with 491 additions and 356 deletions
+12 -10
View File
@@ -6,6 +6,7 @@ import { api } from '../../config/api';
import { toast } from 'react-toastify';
import { useQuery } from '@tanstack/react-query';
import { categoriesService } from '../../services/categories.service';
import { useTranslation } from 'react-i18next';
interface PhotoUploadProps {
eventId: number;
@@ -13,6 +14,7 @@ interface PhotoUploadProps {
}
export const PhotoUpload: React.FC<PhotoUploadProps> = ({ eventId, onUploadComplete }) => {
const { t } = useTranslation();
const [isUploading, setIsUploading] = useState(false);
const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
const [uploadProgress, setUploadProgress] = useState(0);
@@ -79,7 +81,7 @@ export const PhotoUpload: React.FC<PhotoUploadProps> = ({ eventId, onUploadCompl
}
// Show success message
toast.success(`Successfully uploaded ${selectedFiles.length} photo${selectedFiles.length > 1 ? 's' : ''}`);
toast.success(t('toast.uploadSuccess'));
// Call callback
if (onUploadComplete) {
@@ -87,7 +89,7 @@ export const PhotoUpload: React.FC<PhotoUploadProps> = ({ eventId, onUploadCompl
}
} catch (error: any) {
console.error('Upload error:', error);
toast.error(error.response?.data?.error || 'Failed to upload photos');
toast.error(error.response?.data?.error || t('toast.uploadError'));
} finally {
setIsUploading(false);
setUploadProgress(0);
@@ -105,17 +107,17 @@ export const PhotoUpload: React.FC<PhotoUploadProps> = ({ eventId, onUploadCompl
{/* Category Selection */}
<div>
<label className="block text-sm font-medium text-neutral-700 mb-2">
Photo Category
{t('upload.photoCategory')}
</label>
<select
value={selectedCategoryId || ''}
onChange={(e) => setSelectedCategoryId(e.target.value ? Number(e.target.value) : null)}
className="w-full px-3 py-2 border border-neutral-300 rounded-lg focus:ring-2 focus:ring-primary-500"
>
<option value="">No category</option>
<option value="">{t('upload.noCategory')}</option>
{categories.map((category) => (
<option key={category.id} value={category.id}>
{category.name} {!category.is_global && '(Event specific)'}
{category.name} {!category.is_global && t('upload.eventSpecific')}
</option>
))}
</select>
@@ -132,10 +134,10 @@ export const PhotoUpload: React.FC<PhotoUploadProps> = ({ eventId, onUploadCompl
>
<Upload className="w-12 h-12 mx-auto text-neutral-400 mb-4" />
<p className="text-neutral-700 font-medium mb-1">
Click to upload or drag and drop
{t('upload.clickToUpload')}
</p>
<p className="text-sm text-neutral-500">
JPEG, PNG or WebP (max 50MB per file)
{t('upload.fileRequirements')}
</p>
<input
ref={fileInputRef}
@@ -151,7 +153,7 @@ export const PhotoUpload: React.FC<PhotoUploadProps> = ({ eventId, onUploadCompl
{selectedFiles.length > 0 && (
<div className="space-y-2">
<p className="text-sm font-medium text-neutral-700">
Selected files ({selectedFiles.length})
{t('upload.selectedFiles')} ({selectedFiles.length})
</p>
<div className="max-h-48 overflow-y-auto space-y-2">
{selectedFiles.map((file, index) => (
@@ -193,7 +195,7 @@ export const PhotoUpload: React.FC<PhotoUploadProps> = ({ eventId, onUploadCompl
disabled={selectedFiles.length === 0 || isUploading}
leftIcon={isUploading ? <Loader2 className="w-4 h-4 animate-spin" /> : <Upload className="w-4 h-4" />}
>
{isUploading ? 'Uploading...' : `Upload ${selectedFiles.length} Photo${selectedFiles.length !== 1 ? 's' : ''}`}
{isUploading ? t('upload.uploading') : t('common.upload') + ` ${selectedFiles.length} ${t(selectedFiles.length === 1 ? 'common.photo' : 'common.photos')}`}
</Button>
</div>
@@ -201,7 +203,7 @@ export const PhotoUpload: React.FC<PhotoUploadProps> = ({ eventId, onUploadCompl
{isUploading && (
<div className="mt-4">
<div className="flex justify-between text-sm text-neutral-600 mb-1">
<span>Uploading...</span>
<span>{t('upload.uploading')}</span>
<span>{uploadProgress}%</span>
</div>
<div className="w-full bg-neutral-200 rounded-full h-2">