Point 47 - GymNet Import Localization

Problem

Das Import Log Fenster beim Import von GymNet war noch nicht lokalisiert. Die "Import Information" Sektion und die Progress-Meldungen hatten hardcodierte englische und deutsche Texte.

Lösung

1. Import Information Box (Yellow Info Box)

Vorher (hardcodiert):

<h4>Import Information</h4>
<li>• Event information will be extracted and created</li>
<li>• Competitions and disciplines will be imported</li>
<li>• Participants will be added to the database</li>
<li>• Existing clubs will be updated if found</li>
<li>• Existing participants will be updated if found</li>

Nachher (lokalisiert):

<h4>{t('events.import.information.title')}</h4>
<li> {t('events.import.information.eventInfo')}</li>
<li> {t('events.import.information.competitions')}</li>
<li> {t('events.import.information.participants')}</li>
<li> {t('events.import.information.clubsUpdate')}</li>
<li> {t('events.import.information.participantsUpdate')}</li>

2. Import Progress Messages

Vorher (hardcodiert):

setImportProgress({ step: 'Import completed successfully!', progress: 100 })
setImportProgress({ step: `Import failed: ${errorMessage}`, progress: 0 })
summary = `\n🎪 Event Created: "${result.createdEvent.name}" (ID: ${result.createdEvent.id})${summary}`
summary += '\n\n💾 Database Import Results:\n'
summary += `  🏛️ Clubs: ${clubResults.inserted} new, ${clubResults.updated} updated, ${clubResults.errors} errors\n`

Nachher (lokalisiert):

setImportProgress({ step: t('events.import.progress.completed'), progress: 100 })
setImportProgress({ step: `${t('events.import.progress.failed')} ${errorMessage}`, progress: 0 })
summary = `\n🎪 ${t('events.import.progress.eventCreated', { name: result.createdEvent.name, id: result.createdEvent.id })}${summary}`
summary += `\n\n💾 ${t('events.import.progress.databaseResults')}\n`
summary += `  🏛️ ${t('events.import.progress.clubs', { inserted: clubResults.inserted, updated: clubResults.updated, errors: clubResults.errors })}\n`

Translation Keys

Deutsche Übersetzungen (de.json)

"import": {
  // ... existing keys ...
  "information": {
    "title": "Import-Informationen",
    "eventInfo": "Veranstaltungsinformationen werden extrahiert und erstellt",
    "competitions": "Wettkämpfe und Disziplinen werden importiert",
    "participants": "Teilnehmer werden zur Datenbank hinzugefügt",
    "clubsUpdate": "Bestehende Vereine werden aktualisiert, falls vorhanden",
    "participantsUpdate": "Bestehende Teilnehmer werden aktualisiert, falls vorhanden"
  },
  "progress": {
    "completed": "Import erfolgreich abgeschlossen!",
    "failed": "Import fehlgeschlagen:",
    "eventCreated": "Veranstaltung erstellt: \"{name}\" (ID: {id})",
    "databaseResults": "Datenbank-Import-Ergebnisse:",
    "clubs": "Vereine: {inserted} neu, {updated} aktualisiert, {errors} Fehler",
    "participants": "Teilnehmer: {inserted} neu, {updated} aktualisiert, {errors} Fehler",
    "competitions": "Wettkämpfe: {inserted} neu, {updated} aktualisiert, {errors} Fehler",
    "disciplines": "Disziplinen: {inserted} neu, {updated} aktualisiert, {errors} Fehler"
  }
}

Englische Übersetzungen (en.json)

"import": {
  // ... existing keys ...
  "information": {
    "title": "Import Information",
    "eventInfo": "Event information will be extracted and created",
    "competitions": "Competitions and disciplines will be imported",
    "participants": "Participants will be added to the database",
    "clubsUpdate": "Existing clubs will be updated if found",
    "participantsUpdate": "Existing participants will be updated if found"
  },
  "progress": {
    "completed": "Import completed successfully!",
    "failed": "Import failed:",
    "eventCreated": "Event Created: \"{name}\" (ID: {id})",
    "databaseResults": "Database Import Results:",
    "clubs": "Clubs: {inserted} new, {updated} updated, {errors} errors",
    "participants": "Participants: {inserted} new, {updated} updated, {errors} errors",
    "competitions": "Competitions: {inserted} new, {updated} updated, {errors} errors",
    "disciplines": "Disciplines: {inserted} new, {updated} updated, {errors} errors"
  }
}

String Interpolation

Die Progress-Messages verwenden i18next String-Interpolation für dynamische Werte:

// Beispiel: Event Creation
t('events.import.progress.eventCreated', { 
  name: result.createdEvent.name, 
  id: result.createdEvent.id 
})
// Output (DE): Veranstaltung erstellt: "TestEvent" (ID: 123)
// Output (EN): Event Created: "TestEvent" (ID: 123)

// Beispiel: Database Results
t('events.import.progress.clubs', { 
  inserted: 5, 
  updated: 3, 
  errors: 0 
})
// Output (DE): Vereine: 5 neu, 3 aktualisiert, 0 Fehler
// Output (EN): Clubs: 5 new, 3 updated, 0 errors

Betroffene Komponenten

client/src/pages/Events.tsx

  • Import Information Box: Zeilen 854-862
  • handleImportFile Success: Zeilen 371-393
  • handleImportFile Error: Zeilen 410-414

client/src/i18n/locales/de.json

  • events.import.information: 6 neue Keys
  • events.import.progress: 8 neue Keys

client/src/i18n/locales/en.json

  • events.import.information: 6 neue Keys
  • events.import.progress: 8 neue Keys

Testing

Manuelles Testing

  1. Open Events page: http://localhost:5173/events
  2. Click "Veranstaltung importieren" / "Import Event"
  3. Verify Import Information Box ist lokalisiert:
  4. Header zeigt "Import-Informationen" (DE) oder "Import Information" (EN)
  5. Alle 5 Bullet Points sind übersetzt
  6. Select a Gymnet XML file
  7. Fill in event name and click "Importieren" / "Import"
  8. Verify Progress Messages sind lokalisiert:
  9. Success message: "Import erfolgreich abgeschlossen!" (DE) / "Import completed successfully!" (EN)
  10. Event creation: "Veranstaltung erstellt: ..." (DE) / "Event Created: ..." (EN)
  11. Database results header: "Datenbank-Import-Ergebnisse:" (DE) / "Database Import Results:" (EN)
  12. Result lines: "Vereine: X neu, Y aktualisiert, Z Fehler" (DE) / "Clubs: X new, Y updated, Z errors" (EN)
  13. Test Error Case: Use invalid XML file
  14. Verify error message: "Import fehlgeschlagen: ..." (DE) / "Import failed: ..." (EN)

Language Switching

  1. Start with German (default)
  2. Verify all texts in German
  3. Switch to English via language selector
  4. Verify all texts in English
  5. Import another file
  6. Verify progress messages in English

Ergebnis

Vollständig lokalisiert: - Import Information Box (5 Texte) - Progress Messages (Success) - Progress Messages (Error) - Event Creation Message - Database Import Results (4 Kategorien mit Zählern)

Build Status: - Client kompiliert ohne Fehler - Keine TypeScript-Fehler - Build-Zeit: 6.69s

Translation Coverage: - 14 neue Translation Keys hinzugefügt - Alle Keys in DE und EN vorhanden - String-Interpolation funktioniert korrekt

Vorteile

  1. Konsistenz: Alle Texte verwenden das zentrale Translation-System
  2. Wartbarkeit: Änderungen an Texten nur in JSON-Dateien nötig
  3. Erweiterbarkeit: Weitere Sprachen können einfach hinzugefügt werden
  4. Benutzererfahrung: Import-Prozess vollständig in Benutzersprache
  5. Professionalität: Keine gemischten Sprachen mehr im UI

Hinweis

Die Server-seitigen Import-Log-Nachrichten (in server/src/routes/events.ts) bleiben auf Deutsch, da sie: - Nur im Server-Log erscheinen (nicht im UI) - Für Debugging-Zwecke gedacht sind - Nicht vom Endbenutzer gesehen werden

Falls gewünscht, können diese später ebenfalls lokalisiert werden, aber das ist nicht Teil von Point 47.