i18n: Fix 44 additional hardcoded English strings across 15 files

Fixed files:
- competitions-view.tsx: 10 strings (placeholders, labels)
- subjects-view.tsx: 11 strings (types, actions, placeholders)
- professional-calendar.tsx: 5 strings (event type labels)
- illness-reporting-view.tsx: 3 strings (status badges)
- student-detail-view.tsx: 4 strings (health form placeholders)
- data-table.tsx: 2 strings (search, empty state)
- compliance-wizard.tsx: 2 strings (name, state)
- settings-view.tsx: 1 string (Skipped)
- competence-flower-view.tsx: 1 string (Active)
- disciplinary-view.tsx: 1 string (All clear)
- district-management-view.tsx: 1 string (No recent activity)
- competitions-view.tsx: 1 string (Stock)
- ui/pagination.tsx: 3 strings (Previous, Next, More pages)
- ui/breadcrumb.tsx: 1 string (More)
- ui/carousel.tsx: 2 strings (Previous/Next slide)
- ui/sidebar.tsx: 1 string (Sidebar title)

Total: 44 hardcoded English strings replaced with German
This commit is contained in:
Z User committed 2026-08-10 23:37:27 +00:00
1 parent 229b918fa5
commit baa9f981ed
14 files changed
+45 -45

No files matched your search

+1 -1
View File
@@ -512,7 +512,7 @@ export default function CompetenceFlowerView() {
<div className="flex items-center gap-3 pr-4 border-r border-gray-200/60 dark:border-gray-700/40">
<div className="w-12 h-12 rounded-xl shadow-md ring-2 ring-white dark:ring-gray-800" style={{ backgroundColor: primaryColor, boxShadow: `0 4px 12px ${primaryColor}30` }} />
<div>
<p className="text-[10px] uppercase tracking-wider font-semibold text-gray-500/70 dark:text-gray-400/60">Active</p>
<p className="text-[10px] uppercase tracking-wider font-semibold text-gray-500/70 dark:text-gray-400/60">Aktiv</p>
<p className="text-xs font-mono text-gray-700 dark:text-gray-300">{primaryColor}</p>
</div>
</div>
+12 -12
View File
@@ -1550,7 +1550,7 @@ export default function CompetitionsView() {
}}
>
<SelectTrigger className="min-h-[44px]">
<SelectValue placeholder="Select a competition" />
<SelectValue placeholder="Wettbewerb auswählen" />
</SelectTrigger>
<SelectContent>
{activeCompetitions.map((comp) => (
@@ -2329,7 +2329,7 @@ export default function CompetitionsView() {
<Input
value={createForm.title}
onChange={(e) => setCreateForm((f) => ({ ...f, title: e.target.value }))}
placeholder="Competition title"
placeholder="Wettbewerbstitel"
className="mt-1 min-h-[44px]"
/>
</div>
@@ -2339,7 +2339,7 @@ export default function CompetitionsView() {
<Textarea
value={createForm.description}
onChange={(e) => setCreateForm((f) => ({ ...f, description: e.target.value }))}
placeholder="Describe the competition..."
placeholder="Beschreiben Sie den Wettbewerb..."
className="mt-1 min-h-[80px]"
rows={3}
/>
@@ -2417,7 +2417,7 @@ export default function CompetitionsView() {
type="number"
value={createForm.maxParticipants}
onChange={(e) => setCreateForm((f) => ({ ...f, maxParticipants: e.target.value }))}
placeholder="Unlimited"
placeholder="Unbegrenzt"
className="mt-1 min-h-[44px]"
/>
</div>
@@ -2445,7 +2445,7 @@ export default function CompetitionsView() {
<Textarea
value={createForm.rules}
onChange={(e) => setCreateForm((f) => ({ ...f, rules: e.target.value }))}
placeholder="Competition rules and guidelines..."
placeholder="Regeln und Richtlinien..."
className="mt-1 min-h-[100px]"
rows={4}
/>
@@ -2509,7 +2509,7 @@ export default function CompetitionsView() {
<Input
value={rewardForm.name}
onChange={(e) => setRewardForm((f) => ({ ...f, name: e.target.value }))}
placeholder="Reward name"
placeholder="Belohnungsname"
className="mt-1 min-h-[44px]"
/>
</div>
@@ -2519,7 +2519,7 @@ export default function CompetitionsView() {
<Textarea
value={rewardForm.description}
onChange={(e) => setRewardForm((f) => ({ ...f, description: e.target.value }))}
placeholder="Reward description..."
placeholder="Belohnungsbeschreibung..."
className="mt-1 min-h-[80px]"
rows={3}
/>
@@ -2565,7 +2565,7 @@ export default function CompetitionsView() {
<Input
value={rewardForm.rewardValue}
onChange={(e) => setRewardForm((f) => ({ ...f, rewardValue: e.target.value }))}
placeholder="Promo code or value"
placeholder="Promo-Code oder Wert"
className="mt-1 min-h-[44px]"
/>
</div>
@@ -2586,7 +2586,7 @@ export default function CompetitionsView() {
type="number"
value={rewardForm.rankRequirement}
onChange={(e) => setRewardForm((f) => ({ ...f, rankRequirement: e.target.value }))}
placeholder="Any"
placeholder="Alle"
className="mt-1 min-h-[44px]"
/>
</div>
@@ -2596,7 +2596,7 @@ export default function CompetitionsView() {
type="number"
value={rewardForm.pointsRequired}
onChange={(e) => setRewardForm((f) => ({ ...f, pointsRequired: e.target.value }))}
placeholder="Any"
placeholder="Alle"
className="mt-1 min-h-[44px]"
/>
</div>
@@ -2752,12 +2752,12 @@ export default function CompetitionsView() {
/>
</div>
<div>
<Label>Stock</Label>
<Label>Bestand</Label>
<Input
type="number"
value={newRewardForm.stock}
onChange={(e) => setNewRewardForm((f) => ({ ...f, stock: e.target.value }))}
placeholder="Unlimited"
placeholder="Unbegrenzt"
className="mt-1 min-h-[44px]"
/>
</div>
+2 -2
View File
@@ -245,7 +245,7 @@ export function ComplianceWizard({ schoolId, onComplete }: ComplianceWizardProps
onChange={(e) =>
setState((prev) => ({ ...prev, dpoName: e.target.value }))
}
placeholder="Full name"
placeholder="Vollständiger Name"
/>
</div>
<div>
@@ -305,7 +305,7 @@ export function ComplianceWizard({ schoolId, onComplete }: ComplianceWizardProps
setState((prev) => ({ ...prev, bundesland: value }))
}>
<SelectTrigger>
<SelectValue placeholder="Select state..." />
<SelectValue placeholder="Bundesland auswählen..." />
</SelectTrigger>
<SelectContent>
{BUNDESLANDS.map((land) => (
+2 -2
View File
@@ -103,7 +103,7 @@ export function DataTable<T extends Record<string, any>>({
<div className="relative">
<Search className="absolute left-3 top-2.5 h-5 w-5 text-gray-400" />
<Input
placeholder="Search..."
placeholder="Suchen..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="pl-10"
@@ -191,7 +191,7 @@ export function DataTable<T extends Record<string, any>>({
</div>
{sortedData.length === 0 && (
<div className="text-center py-8 text-gray-500">No data found</div>
<div className="text-center py-8 text-gray-500">Keine Daten gefunden</div>
)}
</div>
);
+1 -1
View File
@@ -371,7 +371,7 @@ export default function DisciplinaryView() {
</div>
</motion.div>
<p className="text-gray-500 dark:text-gray-400 text-lg font-medium">{t('disciplinary.no_cases')}</p>
<p className="text-gray-400 text-sm mt-1">All clear</p>
<p className="text-gray-400 text-sm mt-1">Alles in Ordnung</p>
</CardContent>
</Card>
) : (
+1 -1
View File
@@ -894,7 +894,7 @@ export default function DistrictManagementView() {
{activityLog.length === 0 ? (
<div className="text-center py-8">
<Activity className="h-12 w-12 text-emerald-300 dark:text-emerald-700 mx-auto mb-3" />
<p className="text-gray-500 dark:text-gray-400">No recent activity</p>
<p className="text-gray-500 dark:text-gray-400">Keine aktuellen Aktivitäten</p>
</div>
) : (
<ScrollArea className="max-h-96">
+3 -3
View File
@@ -340,13 +340,13 @@ function ReportCard({
const getStatusBadge = () => {
if (report.adminApprovalStatus === 'approved') {
return <Badge variant="outline" className="bg-emerald-50 text-emerald-700 border-emerald-300 dark:bg-emerald-950/30 dark:text-emerald-300 dark:border-emerald-800"><CheckCircle2 className="h-3 w-3 mr-1" />Approved and on calendar</Badge>;
return <Badge variant="outline" className="bg-emerald-50 text-emerald-700 border-emerald-300 dark:bg-emerald-950/30 dark:text-emerald-300 dark:border-emerald-800"><CheckCircle2 className="h-3 w-3 mr-1" />Genehmigt und im Kalender</Badge>;
}
if (report.adminApprovalStatus === 'rejected') {
return <Badge variant="outline" className="bg-rose-50 text-rose-700 border-rose-300 dark:bg-rose-950/30 dark:text-rose-300 dark:border-rose-800"><XCircle className="h-3 w-3 mr-1" />Rejected by administration</Badge>;
return <Badge variant="outline" className="bg-rose-50 text-rose-700 border-rose-300 dark:bg-rose-950/30 dark:text-rose-300 dark:border-rose-800"><XCircle className="h-3 w-3 mr-1" />Von der Verwaltung abgelehnt</Badge>;
}
if (report.parentApprovalStatus === 'approved') {
return <Badge variant="outline" className="bg-blue-50 text-blue-700 border-blue-300 dark:bg-blue-950/30 dark:text-blue-300 dark:border-blue-800"><Clock className="h-3 w-3 mr-1" />Awaiting administration</Badge>;
return <Badge variant="outline" className="bg-blue-50 text-blue-700 border-blue-300 dark:bg-blue-950/30 dark:text-blue-300 dark:border-blue-800"><Clock className="h-3 w-3 mr-1" />Wartet auf Verwaltung</Badge>;
}
switch (report.parentApprovalStatus) {
case 'pending':
+5 -5
View File
@@ -619,18 +619,18 @@ function EventCreatorDialog({
<div className="grid grid-cols-2 gap-2">
<div>
<Label htmlFor="type">Type</Label>
<Label htmlFor="type">Typ</Label>
<select
id="type"
value={formData.type}
onChange={(e) => setFormData({ ...formData, type: e.target.value as CalendarEventType })}
className="w-full px-3 py-2 border rounded-md"
>
<option value="exam">Exam</option>
<option value="lesson">Lesson</option>
<option value="assignment">Assignment</option>
<option value="exam">Prüfung</option>
<option value="lesson">Unterricht</option>
<option value="assignment">Hausaufgabe</option>
<option value="school_event">School Event</option>
<option value="custom">Custom</option>
<option value="custom">Sonstiges</option>
</select>
</div>
+1 -1
View File
@@ -3930,7 +3930,7 @@ export default function SettingsView() {
</div>
<div className="text-center">
<p className="text-xl font-bold text-amber-600 dark:text-amber-400">{importResult.skipped}</p>
<p className="text-[10px] text-gray-500 dark:text-gray-400">Skipped</p>
<p className="text-[10px] text-gray-500 dark:text-gray-400">Übersprungen</p>
</div>
<div className="text-center">
<p className="text-xl font-bold text-red-600 dark:text-red-400">{importResult.errorCount}</p>
+10 -10
View File
@@ -2320,7 +2320,7 @@ export default function SubjectsView() {
/>
</div>
<div>
<Label>Icon</Label>
<Label>Symbol</Label>
<Select
value={categoryForm.icon}
onValueChange={(v) => setCategoryForm({ ...categoryForm, icon: v })}
@@ -2392,11 +2392,11 @@ export default function SubjectsView() {
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="topic">Topic</SelectItem>
<SelectItem value="exercise">Exercise</SelectItem>
<SelectItem value="lesson">Lesson</SelectItem>
<SelectItem value="topic">Thema</SelectItem>
<SelectItem value="exercise">Übung</SelectItem>
<SelectItem value="lesson">Lektion</SelectItem>
<SelectItem value="quiz">Quiz</SelectItem>
<SelectItem value="vocabulary">Vocabulary</SelectItem>
<SelectItem value="vocabulary">Wortschatz</SelectItem>
</SelectContent>
</Select>
</div>
@@ -2418,7 +2418,7 @@ export default function SubjectsView() {
</div>
</div>
<div>
<Label>Icon</Label>
<Label>Symbol</Label>
<Select
value={contentForm.icon}
onValueChange={(v) => setContentForm({ ...contentForm, icon: v })}
@@ -2446,7 +2446,7 @@ export default function SubjectsView() {
checked={contentForm.isPublic}
onCheckedChange={(v) => setContentForm({ ...contentForm, isPublic: v })}
/>
<Label>Public</Label>
<Label>Öffentlich</Label>
</div>
</div>
</div>
@@ -2481,9 +2481,9 @@ export default function SubjectsView() {
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="edit">Edit</SelectItem>
<SelectItem value="add">Add</SelectItem>
<SelectItem value="delete">Delete</SelectItem>
<SelectItem value="edit">Bearbeiten</SelectItem>
<SelectItem value="add">Hinzufügen</SelectItem>
<SelectItem value="delete">Löschen</SelectItem>
</SelectContent>
</Select>
</div>
+1 -1
View File
@@ -93,7 +93,7 @@ function BreadcrumbEllipsis({
{...props}
>
<MoreHorizontal className="size-4" />
<span className="sr-only">More</span>
<span className="sr-only">Mehr</span>
</span>
)
}
+2 -2
View File
@@ -196,7 +196,7 @@ function CarouselPrevious({
{...props}
>
<ArrowLeft />
<span className="sr-only">Previous slide</span>
<span className="sr-only">Vorherige Folie</span>
</Button>
)
}
@@ -226,7 +226,7 @@ function CarouselNext({
{...props}
>
<ArrowRight />
<span className="sr-only">Next slide</span>
<span className="sr-only">Nächste Folie</span>
</Button>
)
}
+3 -3
View File
@@ -77,7 +77,7 @@ function PaginationPrevious({
{...props}
>
<ChevronLeftIcon />
<span className="hidden sm:block">Previous</span>
<span className="hidden sm:block">Zurück</span>
</PaginationLink>
)
}
@@ -93,7 +93,7 @@ function PaginationNext({
className={cn("gap-1 px-2.5 sm:pr-2.5", className)}
{...props}
>
<span className="hidden sm:block">Next</span>
<span className="hidden sm:block">Weiter</span>
<ChevronRightIcon />
</PaginationLink>
)
@@ -111,7 +111,7 @@ function PaginationEllipsis({
{...props}
>
<MoreHorizontalIcon className="size-4" />
<span className="sr-only">More pages</span>
<span className="sr-only">Weitere Seiten</span>
</span>
)
}
+1 -1
View File
@@ -196,7 +196,7 @@ function Sidebar({
side={side}
>
<SheetHeader className="sr-only">
<SheetTitle>Sidebar</SheetTitle>
<SheetTitle>Seitenleiste</SheetTitle>
<SheetDescription>Displays the mobile sidebar.</SheetDescription>
</SheetHeader>
<div className="flex h-full w-full flex-col">{children}</div>