feat(i18n): migrate hardcoded German strings to t() across 104 components/pages — AST-based batch with re-parse gate, 423 new de.json keys; tsc clean; vitest failures byte-identical to clean-tree baseline (pre-existing)

This commit is contained in:
Agent Zero
2026-08-27 01:43:06 +02:00
parent 5680179260
commit 4cb5298768
105 changed files with 1204 additions and 459 deletions
@@ -4,6 +4,7 @@
import React, { useState } from 'react';
import { Bookmark, Check, Folder, Filter, Group as GroupIcon, ArrowDownAZ, LayoutGrid } from 'lucide-react';
import { useTranslation } from 'react-i18next';
export interface SaveViewSelection {
folder: boolean;
@@ -32,6 +33,7 @@ const defaultSelection: SaveViewSelection = {
};
export function SaveViewDialog({ open, onClose, onSave, hasFilter, hasGroup, hasSort, hasFolder }: SaveViewDialogProps) {
const { t } = useTranslation();
const [name, setName] = useState('');
const [selection, setSelection] = useState<SaveViewSelection>(defaultSelection);
@@ -66,19 +68,19 @@ export function SaveViewDialog({ open, onClose, onSave, hasFilter, hasGroup, has
{/* Header */}
<div className="flex items-center gap-2 px-5 py-4 border-b border-secondary-100">
<Bookmark className="w-5 h-5 text-primary-600" strokeWidth={2} />
<h2 className="text-base font-semibold text-secondary-800">Ansicht speichern</h2>
<h2 className="text-base font-semibold text-secondary-800">{t('saveViewDialog.ansichtspeichern')}</h2>
</div>
{/* Body */}
<div className="px-5 py-4 space-y-4">
{/* Name input */}
<div>
<label className="block text-xs font-medium text-secondary-600 mb-1">Name der Ansicht</label>
<label className="block text-xs font-medium text-secondary-600 mb-1">{t('saveViewDialog.namederansicht')}</label>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="z.B. Meine Firmen-Kontakte"
placeholder={t('saveViewDialog.zbmeinefirmenkontakte')}
autoFocus
onKeyDown={(e) => { if (e.key === 'Enter') handleSave(); }}
className="w-full px-3 py-2 text-sm border border-secondary-200 rounded-md focus:outline-none focus:border-primary-400 focus:ring-1 focus:ring-primary-300"
@@ -87,7 +89,7 @@ export function SaveViewDialog({ open, onClose, onSave, hasFilter, hasGroup, has
{/* Component selection */}
<div>
<label className="block text-xs font-medium text-secondary-600 mb-2">Was soll gespeichert werden?</label>
<label className="block text-xs font-medium text-secondary-600 mb-2">{t('saveViewDialog.wassollgespeichertwerden')}</label>
<div className="space-y-1.5">
{options.map((opt) => (
<label
@@ -112,7 +114,7 @@ export function SaveViewDialog({ open, onClose, onSave, hasFilter, hasGroup, has
</div>
</span>
{!opt.available && (
<span className="text-[10px] text-secondary-400 italic">nicht aktiv</span>
<span className="text-[10px] text-secondary-400 italic">{t('saveViewDialog.nichtaktiv')}</span>
)}
</label>
))}