Artikel

Wie ich einen Translator mit Symfony gebaut habe (1/3)

KISymfony

Architektur, Pipeline und Betrieb

Teil 1 von 3

Ausgangspunkt

Ich betreibe seit vielen Jahren den Null Papier Verlag. Der Schwerpunkt liegt auf gemeinfreien Texten, aber nicht nur im klassischen angelsächsischen Raum. Mich interessieren auch Werke aus Regionen, die im deutschsprachigen Markt unterrepräsentiert sind – etwa aus Japan, Lateinamerika oder kleineren europäischen Sprachräumen.

Sehr schnell wurde klar:
Ein einfacher „Übersetzen“-Prompt reicht dafür nicht aus.

Insbesondere bei Sprachen wie Japanisch stößt man mit Standard-Workflows an Grenzen. Kontext, Stil, Satzlogik und kulturelle Eigenheiten lassen sich nicht in einem einzigen KI-Aufruf sauber abbilden. Also habe ich begonnen, einen eigenen Übersetzer zu entwickeln – nicht als Tool, sondern als belastbares System.

Als technisches Fundament fiel die Wahl bewusst auf Symfony.


Warum kein Skript, sondern eine Architektur

Ein Verlag denkt in Büchern, Kapiteln, Fassungen und Revisionen. Genau so muss auch ein Übersetzer arbeiten.

Ich wollte:

  • mehrere Korrekturdurchläufe
  • jederzeit nachvollziehbare Zwischenstände
  • reproduzierbare Ergebnisse
  • saubere Abbrüche statt „irgendwie weiter“

Das Ergebnis ist keine lineare Übersetzung, sondern eine zustandsgetriebene Pipeline.


Grundstruktur des Systems

Die Anwendung ist klar getrennt in vier Ebenen:

  1. API
    Upload, Statusabfragen, Ergebnisdownload.
  2. Store
    Entitäten wie TranslationJob, Chapter, Chunk, Draft.
  3. Pipeline
    Orchestrierung der einzelnen Verarbeitungsschritte.
  4. Worker
    Asynchrone Ausführung über Symfony Messenger.

Wichtig war mir von Anfang an:
Kein KI-Aufruf darf einen HTTP-Request blockieren.


Der TranslationJob als zentrales Objekt

Alles hängt an einem TranslationJob. Diese Entität enthält ausschließlich Zustand, keine Logik.

Typische Informationen:

  • Ausgangs- und Zielsprache
  • aktueller Pipeline-Schritt
  • Status
  • Zeitstempel
  • Fehlerkennzeichen

Gerade bei komplexeren Sprachen wie Japanisch ist es essenziell, jederzeit zu wissen, wo ein Job steht und warum er ggf. gestoppt wurde.


Upload und Textgewinnung

Nach dem Upload:

  1. Validierung
  2. Extraktion in reinen Text
  3. Aufteilung in Kapitel
  4. Persistenz

Ab hier übernimmt der Messenger. Alles Weitere läuft im Hintergrund.

Das klingt banal, ist aber entscheidend:
Der Nutzer interagiert nur mit Zuständen, nicht mit Prozessen.


Zustände statt Prozessdenken

Ich habe früh gelernt:
Pipelines brechen ab. Worker stolper. Deployments scheitern.

Deshalb gilt:

  • Jeder Schritt prüft explizit seinen Input
  • Jeder Schritt ist idempotent
  • Kein Schritt verlässt sich auf vorherige In-Memory-Daten

Das System muss jederzeit fortsetzbar sein – auch nach Stunden oder Tagen.


Fazit Teil 1

Teil 1 beschreibt die Grundlage meines Übersetzers:

  • Verlagsperspektive statt Tool-Denken
  • zustandsbasierte Architektur
  • Symfony Messenger als Rückgrat

Im zweiten Teil geht es um den Kern: die eigentliche Übersetzungspipeline mit mehreren Korrekturstufen.

0 Kommentare