Ich entwickle NeatPass, eine iOS-App, größtenteils allein. Irgendwann stößt jeder Solo-Entwickler an dieselbe Wand: Das Produkt ist bereit für mehr Menschen, aber diese Menschen sprechen Sprachen, die ich nicht beherrsche. Ich spreche ein paar, meine Nutzer sprechen Dutzende. Ich wollte, dass sich NeatPass für viel mehr von ihnen heimisch anfühlt, als ich jemals von Hand übersetzen könnte.
Also habe ich ein kleines Tool gebaut, um diese Lücke zu schließen, und es dann als Open Source veröffentlicht. Es heißt XCStringsTranslator und macht genau eine Sache: Es nimmt Apples Lokalisierungsdateien im Format .xcstrings und übersetzt jeden String in die gewünschten Sprachen, mit einem Sprachmodell deiner Wahl.
Warum es das brauchte
Apples modernes Dateiformat .xcstrings ist super, um Strings zu organisieren, aber mühsam, wenn man es gut übersetzen will. Die Strings sind über eine große JSON-Datei verstreut, viele enthalten Format-Platzhalter wie %@ oder %lld, die die Übersetzung unbedingt überleben müssen, und ein Großteil der UI-Texte ist ohne Kontext bedeutungslos. „Open" kann ein Verb oder ein Adjektiv sein, und das Modell hat keine Chance zu wissen, welches, solange du es ihm nicht sagst.
Naive maschinelle Übersetzung scheitert genau an diesen Stellen. Sie zerstört Platzhalter, ignoriert den Ton, den du im Rest der App etabliert hast, und übersetzt jeden String isoliert, als wäre er ein Wörterbucheintrag. Für eine App, bei der die Wortwahl Teil des Gefühls ist, reicht das nicht.
Und für jede kleine Textänderung in jeder unterstützten Sprache einen professionellen Übersetzer zu bezahlen, skaliert für eine Person, die alle paar Wochen Updates veröffentlicht, einfach nicht. Ich brauchte etwas, das mich in Minuten zu 90 Prozent ans Ziel bringt, damit der verbleibende Feinschliff das Einzige ist, das menschliche Aufmerksamkeit braucht.
Was ich gebaut habe
XCStringsTranslator ist eine Python-CLI. Du zeigst auf eine Datei im Format .xcstrings, wählst deine Zielsprachen, und es schickt die Strings gebündelt an ein LLM und schreibt die Übersetzungen direkt zurück in die Datei. Die Designziele waren bewusst langweilig: genau sein, sicher mit der Formatierung umgehen und niemanden an einen einzigen Anbieter binden.
- Multi-Provider. Funktioniert mit Claude, GPT und Gemini, plus OpenRouter, um über das von dir bevorzugte Modell zu routen. Tausche das Modell, behalte den Workflow.
- Kontextbewusst. Es übergibt vorhandene Übersetzungen und eine optionale Datei namens
context.mdan das Modell, sodass Ton und app-spezifische Bedeutung erhalten bleiben, statt String für String geraten zu werden. - Formatsicher. Format-Platzhalter wie
%@bleiben erhalten, damit deine interpolierten Strings in anderen Sprachen nicht kaputtgehen. - Für Umfang gebaut. Über 35 Sprachen, rekursive Verzeichnisverarbeitung und parallele Anfragen (standardmäßig 32 gleichzeitig), damit ein kompletter Lokalisierungsdurchlauf schnell fertig ist.
Wie es in der Praxis läuft
Das Ganze ist ein Einzeiler, sobald dein API-Key gesetzt ist. Installieren, auf die Datei zeigen, Sprachen auflisten, los. Es gibt ein Flag namens --dry-run, das die Kosten schätzt, bevor du etwas ausgibst, und ein Flag namens --fill-missing, das automatisch erkennt, welche Sprachen unvollständig sind, und nur die Lücken übersetzt.
Im Hintergrund gruppiert es die Strings in Batches, schickt sie mit dem umgebenden Kontext, validiert das Ergebnis und führt alles wieder in die ursprüngliche Dateistruktur zusammen. Die vorhandenen Übersetzungen dienen als Few-Shot-Beispiele, und genau das lässt das Ergebnis konsistent mit dem Rest der App wirken, statt wie ein frischer Auswurf einer Übersetzungs-API.
Speziell für NeatPass hat das die Lokalisierung von einer gefürchteten Pflicht in etwas verwandelt, das ich fast nebenbei ausführe. Ich schreibe den Text einmal auf Englisch, lasse das Tool laufen, überfliege die Ergebnisse und veröffentliche.
Veröffentlichen, als würde es zählen
XCStringsTranslator wird als Open-Source-Paket auf PyPI veröffentlicht, und dabei wurde mir klar, was einem bei Solo-Projekten niemand sagt: Die Disziplin, die bei einem echten Team die Releases sauber hält, ist schlicht nicht da, wenn man um 1 Uhr nachts allein arbeitet. Man vergisst, die Version hochzuzählen, überspringt das Changelog, vertippt sich beim Veröffentlichen. Statt mich auf Disziplin zu verlassen, die ich nicht zuverlässig habe, habe ich das Repo so verdrahtet, dass die langweiligen Teile von allein passieren.
Alles hängt an meinen Commit-Nachrichten. Ein Hook namens commit-msg erzwingt lokal Conventional Commits, ein Workflow prüft den PR-Titel nach denselben Regeln, und release-please liest diese Historie, um einen Release-PR zu öffnen. Beim Mergen setzt es das Tag und schreibt CHANGELOG.md neu; das daraus entstehende GitHub-Release löst eine Veröffentlichung auf PyPI über OIDC Trusted Publishing aus, sodass nirgends ein API-Token liegt, der leaken könnte.
- Ein stiller Trick. Der Release-PR wird von einem GitHub-App-Token geöffnet, nicht vom standardmäßigen
GITHUB_TOKEN. PRs, die vomGITHUB_TOKENerstellt werden, lösen keine anderen Workflows aus, also würde die erforderliche CI ausgerechnet beim wichtigsten PR im Repo nie laufen. Das App-Token behebt das. - Das lokale Tor spiegelt die CI. Pre-commit lässt
rufflinten und formatieren, blockiert versehentlich committete Private Keys und fängt zu große Dateien ab. Die CI führt danach exakt dieselben Prüfungen pluspytestüber Python 3.11, 3.12 und 3.13 aus, damit nichts Überraschendes aufmainlandet. - Lieferkette abgesichert. Jede GitHub-Action ist auf einen vollen Commit-SHA gepinnt statt auf ein verschiebbares Tag, jeder Workflow bekommt minimale
permissions, und Dependabot schlägt wöchentlich gruppierte Updates vor, damit die Pins nicht veralten. - Sicherheit auf Autopilot. CodeQL, OSSF Scorecard, ein Dependency-Review-Gate auf PRs und
pip-auditin der CI laufen alle, ohne dass ich daran denken muss. Für ein Tool, das deine API-Keys in der Hand hat, fühlte sich das wie das Minimum an.
Nichts davon ist für sich genommen neu. Der Punkt ist, dass alles automatisiert ist, sodass ein Ein-Personen-Projekt die Release-Hygiene eines ernsthaften bekommt, ohne dass ich mir auch nur einen einzigen Schritt merken muss.
Dem Review-Bot beibringen, wo die Leichen im Keller liegen
Jeder PR wird zusätzlich von einer KI geprüft, CodeRabbit. Von Haus aus sind solche Bots laut und melden Stil-Kleinigkeiten, die niemanden interessieren. Der nützliche Schritt war das Gegenteil von generisch: Ich habe die Nörgeleien abgeschaltet und stattdessen pro Datei aufgeschrieben, woran dieser Code konkret kaputtgeht.
Die Konfiguration enthält Anweisungen in natürlicher Sprache, die an jeden Pfad gebunden sind. Der Übersetzer darf Apples Format-Platzhalter wie %@, %lld oder %1$@ niemals verlieren oder umsortieren und muss Plural-Varianten beim Round-Trip erhalten. Die Pydantic-Modelle, die Apples JSON nachbilden, müssen ohne Verlust oder Umsortierung von Schlüsseln zurückserialisieren, denn die Treue zur Originaldatei ist der ganze Sinn. Der Preis-Abruf hat ein bewusst breites except, das die CLI niemals abstürzen lassen darf, also wird dem Bot gesagt, er solle nicht vorschlagen, es einzuengen. Nebenläufiger Code wird auf Races am gemeinsamen Statistik-Objekt geprüft.
Das ist die eigentliche Lehre hier. Das Wirkungsvollste, was du einem KI-Reviewer geben kannst, ist kein Style-Guide, sondern eine Karte der Fallstricke deiner Domäne. Und es liegt eine schöne Symmetrie darin: ein Tool, das Sprachmodelle zum Übersetzen nutzt, geprüft von einem Sprachmodell, das weiß, wo es schiefzugehen pflegt.
Was es nicht ist
Das will ich ehrlich sagen, weil es wichtig ist: XCStringsTranslator ist kein Ersatz für einen professionellen menschlichen Übersetzer. Es ist ein Werkzeug für Breite und Geschwindigkeit. Es bringt genaue, kontextbewusste Entwürfe schnell in viele Sprachen, und genau das brauchen ein Solo-Entwickler oder ein kleines Team, um mehr Menschen ohne Lokalisierungsbudget zu erreichen.
Für veröffentlichungskritische Texte, Rechtstexte oder jeden Markt, in dem Nuancen sich wirklich auszahlen, willst du weiterhin einen Muttersprachler drüberschauen lassen. Das richtige Bild ist: Dieses Tool nimmt die Fleißarbeit ab, damit ein menschlicher Prüfer seine Zeit mit Urteilsvermögen statt mit Tippen verbringt. So eingesetzt ist es ein Hebel, keine Abkürzung, die Qualität vortäuscht.
Ausprobieren
Es ist Open Source und nur ein pip install xcstrings-translator entfernt. Der Code, die vollständige Flag-Referenz und die unterstützten Modelle findest du im GitHub-Repository. Wenn du eine App mit Dateien im Format .xcstrings veröffentlichst und die Lokalisierung vor dir herschiebst, ist das der Anstoß. Und falls dich interessiert, wo es mit NeatPass weiterging: Ich habe darüber geschrieben, wie ich damit in einem deutschen IT-Security-Podcast gelandet bin.

