Skip to content

Tutorial 5 Localization de

James Morris edited this page Jul 29, 2026 · 1 revision

Tutorial 5 · Lokalisierung (i18n)

🌎 Sprache: Deutschalle 33 Sprachen ansehen

Ziel: verstehen, wie LockedIn CLI 33 Sprachen spricht — und üben, einen Agenten dabei anzuleiten, noch eine hinzuzufügen. Lokalisierung ist eine hervorragende Aufgabe für einen Agenten: mechanisch genug zum Delegieren, aber mit echten Einschränkungen (Test-Gate, Layout-Regeln, Grammatik-Review), die dir beibringen zu reviewen.

← Zurück: Tutorial 4 Prompts formulieren und prüfen · Zurück zu Start


Was „lokalisiert“ hier bedeutet

Starte die CLI auf Spanisch, Hindi, Japanisch, vereinfachtem Chinesisch oder einer anderen mitgelieferten Sprache, und alles ändert sich — der Splash, die Hilfetabelle, die Ausgabe jedes Commands, die Chat-Session, sogar das rechtliche Kleingedruckte. Nicht nur die Witze: die gesamte sichtbare Oberfläche.

lockedin --lang de post
LOCKEDIN_LANG=hi lockedin
lockedin --lang zh aura

Die Sprache wird beim Start automatisch erkannt, in dieser Prioritätsreihenfolge:

  1. das Flag --lang (--lang de, --lang=fr, -l ja)
  2. die Umgebungsvariable LOCKEDIN_LANG
  3. dein Locale (LC_ALL / LC_MESSAGES / LANG, dann das Locale von OS/Laufzeit)
  4. Englisch als Fallback

normalizeLang() verwendet normalerweise den primären Subtag des Locale. Das bedeutet: de-DE wählt de, aber tlh wird nicht versehentlich zu tl; die echten Aliasse fil und tgl mappen absichtlich auf Tagalog (tl), das norwegische nb und nn mappen auf no, das historische indonesische in mappt auf id, und das historische hebräische iw mappt auf he. Zwei Region-Codes bleiben wortwörtlich erhalten, statt auf ihren primären Subtag zurückzufallen: pt-BR/pt_BR wählen den kanonischen regionalen Code, während generisches pt das rückwärtskompatible brasilianisch-portugiesische Bundle bleibt (beide sind brasilianisches Portugiesisch und teilen sich dieselben Pools/UI), und en-SG/en_SG behalten Singlish (generisches en bleibt Englisch). Traditionelles Hongkong-Chinesisch ist dieselbe Art Ausnahme: zh-HK, zh_HK.UTF-8 und zh-Hant-HK wählen zh-HK, während generisches zh und Mainland-Tags vereinfachtes Chinesisch (zh) wählen.

Mitten im Flug umschalten — das /language-Panel. Die CLI konnte schon immer in einer anderen Sprache starten (--lang, LOCKEDIN_LANG); jetzt kannst du mitten in der Session umschalten. Tippe /language (Aliasse /lang und /languages), um alle 33 Sprachen nach Code aufzulisten, jeweils in ihrer eigenen Schrift; /language el schaltet für den Rest der Session um. Der Sinn ist die Rettungsleine: Nach einem Wechsel zeichnet die CLI in der neuen Sprache neu und druckt dann, in der Sprache, die du gerade verlassen hast, den exakten Weg zurück — /language en jetzt, lockedin --lang en beim nächsten Mal —, damit dich ein versehentlicher Abstecher nach 日本語 oder ಕನ್ನಡ nie stranden lässt. (Wenn du zweimal wechselst, wird auch die Sprache angeboten, auf die dein LOCKEDIN_LANG zeigt.) --lang und LOCKEDIN_LANG bleiben unverändert. Wie /a11y ist das ein aufrichtig nützliches Werkzeug, nicht Teil der Satire.

Die Idee: Sprach-Bundles

Jeder übersetzbare Text lebt in Bundles, eines pro Sprache, jeweils in dieser Form:

{ meta: { lang: 'de', name: 'Deutsch', dir: 'ltr' },
  pools: { HOOKS: [ /* ~25 */ ], LESSONS: [ /* ... */ ], /* ... */ },
  ui:    { buzzwordDensity: 'Buzzword-Dichte: ', /* labels, headings */ } }
  • pools sind die Inhalts-Arrays (die Witze), denen du in Kapitel 2 begegnet bist.
  • ui sind die Oberflächen-Strings: Labels, Überschriften und kleine Templates.

Englisch ist das Referenz-Bundle innerhalb von src/lockedin.js; die anderen 32 Bundle-Module leben in src/content/*.js: ar, bn, bo, de, el, en-SG, es, eu, fa, fi, fr, he, hi, id, is, it, ja, kn, ms, nl, no, pl, pt, pt-BR, ru, sv, tl, tr, uk, ur, zh und zh-HK (pt-BR verwendet die Pools/UI von pt wieder, wird aber separat registriert). Jedes davon ist in BUNDLES registriert; SUPPORTED_LANGS wird aus diesen Keys erzeugt, und renderHelp() gibt diese generierte Code-Liste aus. Kein UI-Bundle hartcodiert die Liste.

setLang('fr');       // richtet die aktive Sprache auf das französische Bundle
// L = aktive pools, U = aktive ui
pick(L.HOOKS)        // ein französischer Hook
U.buzzwordDensity    // "Densité de jargon : "

Weil jeder Renderer L und U liest (niemals einen hartcodierten String), ändert setLang allein das gesamte Erlebnis. Das ist der ganze Trick.

Das Sicherheitsnetz: Schlüsselparität

Hier ist die Invariante, die das Hinzufügen einer Sprache sicher macht:

Jedes Bundle muss exakt dieselben pools- und ui-Keys bereitstellen wie Englisch.

Ein Test erzwingt das für alle 33 Bundles. Wenn du in Englisch einen neuen UI-String hinzufügst und vergisst, ihn ins Ukrainische zu übersetzen, springt npm test auf Rot und sagt dir, welcher Key fehlt. Du kannst eine halb übersetzte Sprache nicht lautlos ausliefern.

Der schwierige Teil: Terminal-Layout

Sprachen belasten das Terminal-Layout auf unterschiedliche Weise:

  • Japanisch, vereinfachtes Chinesisch und traditionelles Hongkong-Chinesisch verwenden East-Asian-Wide-/Fullwidth-Zeichen. vw() zählt diese als zwei Spalten, und wrap() trennt lange Zeichenfolgen ohne Leerzeichen hart um, damit CJK-Text in Karten und Boxen bleibt.
  • Hindi und Kannada verwenden nichtabständige bzw. einschließende kombinierende Zeichen (Mn / Me), etwa Matras und Viramas. vw() zählt diese als null Spalten, damit sie die gemessene Breite nicht aufblasen.
  • box() umbrecht jede Body-Zeile vor dem Auffüllen, sodass ein langer übersetzter Banner den Rahmen nicht mehr durchschlagen kann.
  • Jedes Bundle setzt sentenceEnd und listSep (zum Beispiel . / , , / ), damit von Generatoren zusammengesetzte Sätze natürlich klingen.

Wenn du eine Sprache hinzufügst, müssen Kartenkopf-Strings (cardSubtitle, cardMeta, cardFooter) trotzdem in ≤ 60 sichtbare Spalten passen. Arabisch, Persisch, Hebräisch und Urdu setzen meta.dir: 'rtl'. Die Ausgabe enthält standardmäßig keine bidi-Steuerzeichen, weil einige Terminals sie als gerahmte Labels darstellen. LOCKEDIN_BIDI=on aktiviert explizit ausgeglichene Isolate nach dem Umbruch für Terminals, von denen bekannt ist, dass sie sie unterstützen, und bewahrt ANSI, ASCII-Commands und die logische Copy/Paste-Reihenfolge. Screenreader-Ausgabe entfernt diese Steuerzeichen immer. Ohne dieses Opt-in kann die gemischte RTL/LTR-Reihenfolge weniger ausgefeilt sein; Unterstützung wird nie sondiert oder geraten.

Der hinterhältige Teil: Grammatik rund um rohe Nutzereingaben

Einige UI-Templates fügen rohe Nutzerklauseln mit Platzhaltern wie {cap} ein. Übersetze sie nicht Slot für Slot. Der Satz muss grammatisch bleiben, wenn der Platzhalter eine Phrase ist, die der Nutzer eingegeben hat, und kein hübsches Substantiv.

Ein echter Warn-Bug: Japanische Templates, die direkt hinter {cap} setzen, können falsch klingen, wenn {cap} eine vollständige Klausel ist. Die Lösung ist nicht „härter übersetzen“, sondern das Template umzubauen (zum Beispiel einen Nominalisierer hinzuzufügen oder den Platzhalter zu verschieben), damit beliebige Nutzereingaben weiterhin passen.

✅ Probier es mit deinem Agenten aus — füge eine Sprache hinzu

Diese Übung funktioniert immer noch genau gleich. Such dir eine Sprache aus, die du grob gegenprüfen kannst (oder bitte den Agenten darum), und bring sie End-to-End ans Ziel. Schreib zuerst die Spezifikation:

Füge Dänisch (da) hinzu. Erstelle src/content/da.js als { meta, pools, ui }-Bundle mit den gleichen Keys wie Englisch und übersetze jeden Eintrag (Content-Pools mit jeweils ~25 Einträgen, alle UI-Strings). Registriere da in BUNDLES in src/lockedin.js. --lang da und ein da-*-Locale müssen es auswählen. Halte die Kartenkopf-Strings innerhalb der Breitenbegrenzung. npm test muss grün bleiben, und füge dänische Invarianten- und Erkennungstests hinzu, die den vorhandenen lokalisierten Tests entsprechen.

Führe dann den Loop aus Kapitel 3–4 aus:

  1. Zuerst planen. „Bevor du Code schreibst, sag mir, welche Dateien du ändern wirst und wie du die Schlüsselparität mit Englisch beibehältst.“
  2. Zuerst Tests. „Füge fehlschlagende Tests hinzu: da-Erkennung, Schlüsselparität für da und eine dänische Reflect-/Connect-Invariante. Erstelle das Bundle noch nicht.“
  3. Implementieren. „Erstelle jetzt src/content/da.js, indem du ein vorhandenes Bundle Key für Key übersetzt, registriere es und lass die Tests bestehen. Für Zufälligkeit nur pick/shuffle.“
  4. Gate + Review. npm test, dann lockedin --lang da post — und lies den Diff: Wurde jeder Key übersetzt? Sind die Kartenrahmen noch ausgerichtet? Überleben Templates mit {cap} rohe Nutzerklauseln?

Kleinere Aufwärmübungen, falls dir eine ganze Sprache zu viel ist:

  • „Füge allen 33 Sprach-Bundles ein weiteres TAGLINE hinzu und halte die Anzahlen gleich.“
  • „Prüfe, ob cardFooter in Kannada ≤ 60 sichtbare Spalten hat, und erkläre, wie kombinierende Zeichen gemessen wurden.“
  • „Zeig mir den Test, der fehlschlagen würde, wenn ich einen ui-Key aus ja.js löschen würde.“

Wohin du als Nächstes gehen kannst

  • Überflieg src/content/es.js — es ist immer noch eine freundliche Vorlage für ein neues Bundle.
  • Lies docs/HANDOFF.md → „Adding a language“ noch einmal.
  • Genieße die mehrsprachigen Witze in der Befehlsreferenz.

Damit ist das Tutorial komplett. Du kannst jetzt einen KI-Agenten anleiten, Features zu bauen und hinter einem Test-Gate zu lokalisieren — in 33 Sprachen und bereit für noch mehr. Stimmst du zu? 👇

📘 LockedIn CLI wiki

Tutorial

Reference


Satire · Sátira · 風刺. Not affiliated with LinkedIn. GPL-3.0-or-later.

Clone this wiki locally