XUnity.AutoTranslator übersetzt nicht
XUnity.AutoTranslator ist der beste Laufzeit-Übersetzer, den Unity hat, und wenn es still bleibt, liegt es fast immer an einer von fünf konkreten Sachen: Das Spiel ist ein IL2CPP-Build, der Text wird über einen Weg gesetzt, den der Hook nicht abfängt, das zeichnende UI-Framework ist nicht aktiviert, die Zeile ist länger als das Zeichenlimit, oder der Endpoint hat sich selbst abgeschaltet. So findest du heraus, welcher Fall vorliegt.
XUnity.AutoTranslator ist kostenlos, MIT-lizenziert, aktiv gepflegt und das mit Abstand beste Laufzeit-Übersetzungswerkzeug, das Unity hat. Es funktioniert, indem es sich in den Moment einklinkt, in dem ein Spiel einen String an eine Textkomponente übergibt, und die Übersetzung einsetzt, bevor gezeichnet wird. Genau dieser Entwurf ist der Grund, warum es überhaupt kein Wissen über die Dateiformate des Spiels braucht — und er ist auch der Grund, warum es lautlos scheitert, wenn es scheitert. Nichts stürzt ab. Das Spiel läuft einfach auf Japanisch weiter.
Die fünf Punkte unten erklären nahezu jede Meldung "es übersetzt nicht". Arbeite sie der Reihe nach ab; jeder hat eine andere Lösung, und zwischen ihnen zu raten kostet viele Abende.
Zuerst: Lies das Log, nicht den Bildschirm
Das Plugin ist laut darüber, was es tut, und das Log ist der einzige Ort, an dem es das sagt. Bei einer BepInEx-Installation schau in BepInEx/LogOutput.log. Unitys eigenes Log liegt daneben unter <Game>_Data/output_log.txt bei älteren Builds oder %APPDATA%/../LocalLow/<Company>/<Game>/Player.log bei neueren.
- Erwähnt das Log überhaupt, dass XUnity.AutoTranslator geladen wird? Wenn nicht, liegt das Problem beim Loader, nicht beim Übersetzer — dann bist du bei Fehlerursache eins.
- Nennt es einen initialisierten Endpoint und später einen, der nach wiederholten Fehlern abgeschaltet wurde? Das ist Fehlerursache fünf.
- Werden Übersetzungen nach
BepInEx/Translation/<lang>/Text/_AutoGeneratedTranslations.txtgeschrieben? Füllt sich diese Datei mit korrekten Übersetzungen, die nie auf dem Bildschirm auftauchen, ist die Netzwerkseite in Ordnung und die Anzeigeseite nicht. - Drücke im Spiel ALT+1, um das Fenster des Übersetzungs-Aggregators zu öffnen. Zeigt es die Zeilen, die du gerade siehst, sieht der Hook sie. Bleibt es leer, sieht der Hook sie nie.
Diese letzte Trennung — "übersetzt, aber nicht angezeigt" gegenüber "nie gesehen" — ist die Weggabelung. Alles Weitere hängt daran.
1. Das Spiel ist ein IL2CPP-Build
Unity liefert Spiele in zwei sehr unterschiedlichen Laufzeiten aus. Mono behält das C# des Spiels als gewöhnliche .NET-Assemblies in <Game>_Data/Managed/, darunter Assembly-CSharp.dll, mit vollständigen Typ- und Methodennamen. IL2CPP wandelt dieses C# vorab in C++ um und kompiliert es in eine native GameAssembly.dll; was vom Typsystem übrig bleibt, steckt in <Game>_Data/il2cpp_data/Metadata/global-metadata.dat.
Ein Laufzeit-Hook muss eine Methode finden und ersetzen. Auf Mono ist das ein normales Reflection-Problem. Auf IL2CPP gibt es keine verwaltete Methode, über die sich reflektieren ließe — der Code ist nativ, und der einzige Weg zurück zu Namen, Feldern und Methodenadressen führt über das Parsen von global-metadata.dat und das Rekonstruieren des Layouts. Das ist ein völlig anderer Loader, keine Einstellung.
- In fünf Sekunden erkannt: eine
GameAssembly.dllneben der Spiel-Exe plus einil2cpp_data-Ordner bedeutet IL2CPP. EinManaged/-Ordner voller DLLs bedeutet Mono. - IL2CPP braucht die IL2CPP-Variante von BepInEx und die passende, dagegen gebaute XUnity.AutoTranslator-Version. Der Mono-Build lädt nicht — er taucht schlicht nicht im Log auf, was sich genau wie "das Plugin ist kaputt" liest.
- Auch die Bit-Breite zählt. Ein 64-Bit-Spiel braucht den 64-Bit-Loader. Ein unpassendes Paar scheitert genauso still.
- Manche Spiele liefern eine nicht parsebare Metadaten-Datei aus. Packer und Anti-Tamper-Schichten verschlüsseln oder strukturieren
global-metadata.datum, und jedes Werkzeug, das auf dessen Lesen angewiesen ist — der Hook eingeschlossen —, endet dort.
2. Das Plugin lädt, und der Text erscheint nie
Das Plugin steht im Log, der Endpoint ist initialisiert, _AutoGeneratedTranslations.txt wächst — und der Bildschirm ändert sich nicht. Entweder übersetzt der Hook einen String, den das Spiel danach verwirft, oder das Spiel setzt Text über einen Weg, den der Hook nicht abfängt.
TextGetterCompatibilityMode
Viele Spiele lesen den Text, den sie gerade gesetzt haben, wieder zurück — um ihn zu vermessen, um etwas anzuhängen, um ihn mit etwas zu vergleichen. Sobald die Komponente einen übersetzten String hält, liefert dieses Zurücklesen die Übersetzung, die spieleigene Logik arbeitet auf Text, den sie nicht geschrieben hat, und das Ergebnis reicht von einer Zeile, die zurückspringt, bis zu einem Layout, das zusammenbricht. TextGetterCompatibilityMode in AutoTranslatorConfig.ini sorgt dafür, dass der Getter dem Spiel seinen ursprünglichen String zurückgibt, während der Spieler weiterhin den übersetzten sieht. Es ist standardmäßig aus, weil es bei jedem Lesen Arbeit kostet, und es ist der erste Schalter, den du probierst, wenn Text flackert, zurückspringt oder sich nicht halten will.
Die andere Hälfte dieser Kategorie ist Text, der von vornherein nie über eine gehookte API gesetzt wird: ein Spiel, das über seine eigene Text-Engine rendert, Zeichen direkt in ein Mesh streamt oder Dialoge in ein Sprite einbrennt. Dafür gibt es keine Einstellung — der Abfangpunkt existiert nicht. In Grafiken eingebrannter Text ist ein ganz eigenes Problem und braucht Bildübersetzung statt irgendeines Hooks.
3. Nur ein Teil des Textes wird übersetzt
Menüs werden übersetzt, Dialoge nicht. Oder Dialoge werden übersetzt und jede Schaltfläche bleibt japanisch. Das ist fast immer ein UI-Framework, das nicht aktiviert ist, denn das Plugin hookt jedes einzeln und nicht alle sind standardmäßig an.
- Standardmäßig an: UGUI (Unitys eingebaute UI), NGUI, TextMeshPro und UIElements (
EnableUGUI,EnableNGUI,EnableTextMeshPro,EnableUIElements). Zusammen decken sie die meisten modernen Spiele ab, auch Visual-Novel-Frameworks wie Utage, die durch sie zeichnen, statt einen eigenen Schalter mitzubringen. - Standardmäßig aus: IMGUI und die alte
TextMesh-Komponente. IMGUI ist Unitys Immediate-Mode-GUI — es zeichnet jeden Frame neu, ein Hook darauf bedeutet also Übersetzen in jedem Frame, und es ist aus Performance-Gründen deaktiviert, nicht weil es nicht funktioniert. - Die Schalter stehen in `AutoTranslatorConfig.ini` als
EnableIMGUI,EnableTextMeshund Verwandte. Setze den, den dein Spiel nutzt, aufTrueund starte neu. - Ältere und japanische Doujin-Unity-Spiele sind die üblichen IMGUI-Fälle. Ein Spiel, dessen Menüs wie schlichte graue Kästen im Standard-Stil aussehen, ist ein starker Hinweis.
Ändert das Aktivieren von allem nichts, kommt der Text gar nicht über eine Unity-Textkomponente — zurück zu Fehlerursache zwei.
4. Lange Zeilen werden übersprungen, nicht übersetzt
MaxCharactersPerTranslation steht standardmäßig auf 200. Alles Längere wird übersprungen. Nicht gekürzt, nicht erneut versucht, nicht so protokolliert, dass es beim Spielen auffiele — übersprungen, sodass die Zeile in der Originalsprache erscheint und nichts kaputt aussieht.
Das ist die Fehlerursache, nach der am längsten gesucht wird, weil die Indizien so schwach sind: Der Großteil des Spiels wird übersetzt, und dann ein Absatz nicht. Visual Novels trifft es am häufigsten — ein langer Erzählblock oder ein Monolog ohne Zeilenumbruch überschreitet 200 Zeichen mühelos, und es ist genau der Text, den du am dringendsten übersetzt haben wolltest.
Erhöhe den Wert in AutoTranslatorConfig.ini und starte neu. Bedenke, dass du damit auch erhöhst, was jede Anfrage kostet: Die kostenlosen Endpoints haben eigene Längengrenzen pro Anfrage und beginnen, Anfragen abzulehnen, die sie einzeln überschreiten — ein sehr hoher Wert tauscht also ein stilles Überspringen gegen einen sichtbaren Endpoint-Fehler. Irgendwo zwischen 500 und 1000 deckt gewöhnliche VN-Prosa ab.
5. Der Endpoint ist ausgefallen oder hat dich ausgebremst
XUnitys Standard-Endpoints sind kostenlose öffentliche Übersetzungsdienste, angesprochen so, wie ein Browser sie ansprechen würde. Sie sind nicht vertraglich zugesichert, und sie ändern sich. Wenn eine Reihe von Anfragen hintereinander fehlschlägt, schaltet das Plugin den Endpoint für den Rest der Sitzung ab, statt weiter darauf einzuhämmern — eine bewusste, gute Entscheidung, die zugleich bedeutet, dass alles danach still unübersetzt bleibt, bis du das Spiel neu startest.
- Suche im Log nach der Abschaltzeile. Steht sie da, ist die Lösung ein Neustart plus eine Änderung — nicht mehr Warten.
- Bremse die Warteschlange.
MaxTranslationsQueuedPerSecondund die Verzögerungseinstellungen gibt es, weil Stöße die Ratenbegrenzung auslösen. Schnelles Durchklicken einer VN schickt Hunderte Anfragen in Sekunden. - Wechsle den Endpoint. Wenn ein kostenloser Dienst einen schlechten Tag hat, hat ihn ein anderer meist nicht.
- Nutze einen Endpoint mit Schlüssel. Ein echter DeepL- oder kostenpflichtiger API-Schlüssel beseitigt die ganze Problemklasse, um den Preis eines kostenpflichtigen API-Schlüssels.
- Aktualisiere das Plugin. Wenn sich das Protokoll eines kostenlosen Endpoints ändert, kommt die Lösung als Release. Ein zwei Jahre alter Build gegen einen Dienst, der weitergezogen ist, ist eine häufige Ursache für "früher hat es funktioniert".
Bonus: Der Text wird übersetzt und erscheint als Kästchen
Das ist gar kein Übersetzungsfehler. Das Spiel hat einen Font-Atlas mitgeliefert, der genau die Glyphen enthält, die seine Originalsprache brauchte, und deine Zielsprache braucht Glyphen, die nicht darin sind — also wird jedes fehlende Zeichen als Kästchen oder Leerstelle gezeichnet. XUnity hat OverrideFont und OverrideFontTextMeshPro genau dafür. Achte auf den Fingerabdruck: Kästchen bedeuten eine fehlende Glyphe; buchstäbliche `?`-Zeichen bedeuten ein Kodierungsproblem weiter vorn in der Kette. Das sind verschiedene Fehler, und die Font-Einstellung behebt nur den ersten.
Die Reihenfolge zum Abarbeiten
- Kläre Mono gegen IL2CPP, indem du nach
GameAssembly.dllsuchst, und stelle sicher, dass du den passenden Loader installiert hast. - Öffne
BepInEx/LogOutput.logund prüfe, ob das Plugin geladen und ein Endpoint initialisiert wurde. - Drücke im Spiel ALT+0, um das eigene Fenster des Plugins zu öffnen — erscheint nichts, ist das Plugin nicht geladen. ALT+1 öffnet den Translation Aggregator: leer heißt, der Hook sieht den Text nie; gefüllt heißt, er sieht ihn.
- Sieht der Hook ihn, ändert sich aber der Bildschirm nicht, schalte
TextGetterCompatibilityModeein. - Wird nur ein Teil des Spiels übersetzt, aktiviere IMGUI und das alte TextMesh.
- Bleiben bestimmte lange Zeilen unübersetzt, erhöhe
MaxCharactersPerTranslationüber den Standardwert 200 hinaus. - Hat alles mitten in der Sitzung aufgehört, suche nach der Endpoint-Abschaltzeile und starte dann mit langsamerer Warteschlange oder einem anderen Endpoint neu.
Wenn ein Hook die falsche Form für die Aufgabe hat
Jeder der obigen Fehler geht auf dieselbe Wurzel zurück: Ein Laufzeit-Hook kann nur Text übersetzen, bei dessen Entstehung er anwesend ist. Setzt das Spiel den String nicht über eine API, die das Plugin kennt, oder wurde der Text gezeichnet, bevor das Plugin geladen war, oder legt die Laufzeit die zu hookende Methode nicht offen, gibt es nichts zu konfigurieren. Das Werkzeug macht seine Arbeit richtig, und der Text ist schlicht außer Reichweite.
Die strukturelle Alternative ist, an den Dateien statt am Frame zu arbeiten. Ein Werkzeug auf Dateiebene öffnet die spieleigenen Assets, holt die Strings heraus, übersetzt sie und schreibt eine übersetzte Kopie des Spiels — der Text liegt also schon in der Zielsprache vor, bevor die Engine ihn überhaupt lädt. Kein Hook, kein Abfangpunkt, kein Schalter pro Framework, und die Zeichengrenze ist das, was das Format hergibt. Genau das macht RuneTranslate, auf Unity und 16 weiteren Engines und Formaten.
Die Kompromisse sind real und gehen in die andere Richtung. Ein Werkzeug auf Dateiebene erreicht nur Text, der in den Dateien liegt — bei Unity heißt das TextAssets, MonoBehaviour-String-Felder, StreamingAssets-Skripte, Lokalisierungstabellen und Asset-Bundles, einschließlich AES-verschlüsselter Addressable-Bundles. Es braucht einen Export-Schritt vor dem Spielen, statt zu übersetzen, während du spielst. Und es kann nichts gegen Text ausrichten, den dein Spiel zur Laufzeit aus Fragmenten zusammensetzt. Unity ist genau deshalb eine Nach-bestem-Bemühen-Engine: Was ein bestimmtes Spiel externalisiert, schwankt enorm, und das Öffnen des Projekts ist, was dir sagt, was du hast.
- In C#-Code kompilierter Text ist die harte Grenze. Auf Mono-Builds liest RuneTranslate String-Literale mit einem mitgelieferten Sidecar aus der Assembly des Spiels, gefiltert danach, was die Aufrufstelle mit ihnen tut, sodass nie ein Szenenname oder ein Animator-Parameter übersetzt wird. Auf IL2CPP-Builds bleibt kompilierter Code außerhalb des Umfangs.
- IL2CPP-Asset-Text ist dagegen kein Problem. String-Felder von Komponenten werden auf IL2CPP gelesen, indem die Typinformationen aus den Metadaten des Spiels rekonstruiert werden — dieselbe
global-metadata.dat, die der Hook braucht, für einen anderen Zweck genutzt. - Es liest XUnitys eigene Ausgabe. Hast du bereits eine gefüllte
_AutoGeneratedTranslations.txt, zerlegt RuneTranslate diese Datei und kann die Werte darin übersetzen, ohne die Schlüssel anzurühren. Bereits geleistete Arbeit wird nicht weggeworfen. - Fonts werden beim Export behandelt, indem ein Fallback-Font-Asset ins Spiel injiziert wird, damit eine Zielsprache, die der Original-Font nie abdeckte, trotzdem dargestellt wird.
Neun Anbieter, drei davon ganz ohne API-Schlüssel — Google, das kostenlose DeepL und DeepLs Classic-/Next-Gen-Modelle — dazu DeepLs API, OpenAI, Anthropic, DeepSeek, jeder OpenAI-kompatible Endpunkt und ein lokales Modell über Ollama oder LM Studio. Die kostenlose Stufe schaltet jede Engine und jeden Anbieter frei; sie drosselt den Durchsatz und hält ein Projekt auf einmal. Windows 10/11 oder Linux und das Steam Deck über Wine oder Proton. Beim ersten Start ist eine kostenlose Patreon-Anmeldung nötig. Das Ergebnis ist ein spielbares übersetztes Build, das dir bleibt.
Kein Ansatz ist allgemein richtig. Ein Spiel, dessen ganzes Skript in einer gebündelten JSON-Tabelle steht, ist eine Aufgabe für die Dateiebene und war es immer. Ein Spiel, das seine Dialoge zur Laufzeit im Code zusammensetzt, ist eine Aufgabe für den Hook und wird es bleiben. Zu wissen, was du in der Hand hast, ist der Großteil der Arbeit.
Wie es weitergeht
- Ein Unity-Spiel übersetzen — die vollständige Anleitung, inklusive dem, was Unity externalisiert und was nicht.
- Die Unity-Engine-Seite — die unterstützten Formate und die aktuellen Grenzen an einem Ort.
- RuneTranslate vs. XUnity.AutoTranslator — die beiden Ansätze nebeneinander, mit den Fällen, die jeder für sich entscheidet.
- Den richtigen Übersetzungsanbieter wählen — welche Anbieter japanische Prosa gut bewältigen und welche nichts kosten.
- Glossar-Grundlagen — Figurennamen und Terminologie über ein ganzes Skript hinweg konsistent halten.
- Alle unterstützten Engines — falls sich herausstellt, dass das Spiel doch kein Unity ist.
Bereit, RuneTranslate auszuprobieren?
Der Free-Tarif schaltet jede Engine + jeden Übersetzungsanbieter frei. Supporter ($3/Mon.) schaltet volle Geschwindigkeit frei.
Für Windows herunterladen
