Lokalisierung der Engine
Der menschenlesbare Text der Engine liegt in 17 Sprachen neben Englisch vor: nl, pl, pt-BR, pt-PT, fi, sv, da, nb, cs, uk, ru, de, fr, es, et, ja, zh-Hans. Englisch ist die Quelle; en-XA ist eine Pseudo-Locale, die jede Meldung mit Akzenten, Klammern und Füllzeichen versieht, sodass ein Test erkennen kann, ob Text in den Katalog verlagert wurde. Das Framework ist Project Fluent (fluent-bundle, unic-langid); der Code ist src/i18n/.
Was lokalisiert wird und was nie#
| Lokalisiert (ein Mensch liest es) | Nie lokalisiert (ein Programm liest es) |
|---|---|
| Meldungen und Fehler der Befehlszeile | JSON-Schlüssel und -Werte von result.json und report.json |
| die Zusammenfassungszeile jedes Laufs | CSV-Kopfzeilen und -Zeilen |
| der Text von SVG-Diagrammen (Titel, Achsen, Legenden, Beschriftungen) | Dateinamen |
report.html: Überschriften, Tabellen, Hinweise, Beschriftungen |
Fehlercodes (E-CLOCK-VERSION) |
| Urteilswörter (VALIDATED, MODELLED, PARTIAL) | die Verifikationsmatrix, Einheitendefinitionen, Herkunftsangaben |
die Beschreibungen der Szenarioarten (list_kinds(lang)) |
|
Hinweise, Haftungsausschlüsse und Mitteilungen (engine-legal-*) |
dieselben Texte innerhalb von JSON, die Englisch bleiben |
report.html der iq-Kampagne, die Vergleichsseite der Studie, die Bestenliste des Benchmarks, der Resilienzbericht |
summary.html eines Nachweispakets und das PNG des Observatoriums: Beide werden in ein Manifest gehasht (das des Pakets ist zusätzlich signiert), daher werden sie unabhängig von der Sprache auf Englisch erstellt |
Zahlen in Fließtext verwenden das Dezimalzeichen der Sprache (ein Komma in 15 der 18 Sprachen; einen Punkt in en, ja, zh-Hans und en-XA). Zahlen in maschinenlesbaren Dateien verwenden immer den Punkt. Eine Anzahl (eine Variable namens n, count, n_*, num_* oder *_count) erreicht Fluent als Zahl, sodass eine Übersetzung { $n -> [one] ... [few] ... *[other] ... } schreiben darf.
Die Sprache wählen#
- Befehlszeile:
--lang <tag>, dannKSHANA_LANG,LC_ALL,LC_MESSAGES,LANG, dann Englisch.ptist pt-BR; nurpt-PTist das Portugiesisch Portugals.zhist vereinfacht; Traditionell wird mit der Liste der unterstützten Tags abgelehnt. - Bibliothek:
api::run_toml_lang(toml, lang),run_toml_bilingual,run_toml_human,run_scenario_lang,list_scenario_kinds_json_lang(lang). - Python:
lang=Nonebeirun,run_full,run_typed,validate_toml,error_kind,list_kinds,scenario_kinds;run_human(toml, lang);error_info(toml, lang). - WebAssembly: ein optionales nachgestelltes
langbeirun_typed,run,chart_svg,summary,table_csv,run_all,error_kind,list_kinds,scenario_kinds;run_human(toml, lang);error_info(toml, lang);register_catalogue(tag, ftl_text). - MCP:
langbeirun_scenarioundlist_scenario_kinds.
Fehler und ihre Codes#
Jede Fehlermeldung hat einen stabilen Code, die Meldungskennung in Großbuchstaben (e-clock-version ist E-CLOCK-VERSION), in jeder Sprache gleich. Der englische Text der Befehlszeile bleibt unverändert. In einer anderen Sprache lautet die Zeile text [E-CODE]; mit --verbose folgt in jeder Sprache eine zweite Zeile code: E-CODE. Die API liefert KshanaError::code() und error_info ({kind, code, message}); MCP-Fehler tragen {kind, code, message} als Fehlerdaten. Prüfen Sie auf den Code, nie auf den Text.
Wie ein Lauf in einer anderen Sprache abläuft (die Regel des doppelten Laufs)#
Eine maschinenlesbare Datei darf nicht von der Sprache abhängen. Ein Lauf in einer anderen Sprache führt das Szenario deshalb zweimal aus: einmal auf Englisch, dessen result.json, report.json und CSV die maschinenlesbaren Dateien sind, und einmal in der Sprache der Nutzerin oder des Nutzers, für die Zusammenfassung, das Diagramm und report.html. Englisch ist ein Lauf, Byte für Byte, wie er vorher war.
Gemessen, nativ, Release-Build, Englisch dann --lang de (Sekunden): leo-navmsg-fit-interval-trade 9,2 -> 17,9, cislunar-arc-recovery 7,8 -> 14,1, lunar-station-coverage 7,8 -> 15,0, clock-ensemble 5,8 -> 11,6, leo-navmsg-model-comparison 5,1 -> 10,5, leo-ppp-convergence 2,8 -> 6,2; jedes andere mitgelieferte Szenario liegt unter 4 s; die 173 Szenarien, die bei dieser Messung mitgeliefert waren, brauchten auf Englisch zusammen 64 s. Der Aufwand ist für eine andere Sprache genau doppelt. WebAssembly wurde nicht gemessen (hier gibt es kein wasm-bindgen); beim Browserfaktor von etwa 4 ist es für die langsamste Art eine Minute.
Eine Seite vermeidet das Warten, indem sie das englische Ergebnis sofort zeigt und danach run_human(toml, lang) aufruft: Das ist allein der zweite Lauf, er liefert {summary, svg}, und das Studio kann „Wird übersetzt …“ anzeigen, bis es eintrifft.
Punkt für 0,41: ein Lauf. Beide aus einer Aufzeichnung von (message id, arguments) rendern. Es wurde beurteilt und nicht gebaut: Die Ergebnisse von t! werden nach ihrer Erzeugung geprüft, gemessen und gehasht (Textbreiten in Diagrammen, Herkunfts-Hashes über Ausgabetext), und num() formatiert an der Aufrufstelle, sodass eine Aufzeichnung Platzhalter-Token in maschinenlesbare Dateien schreiben und deren Bytes von der Wiedergabe abhängig machen würde. Es braucht Token liefernde t!/num, einen Finalisierer an jedem Schreiber und einen Nachweis der Byte-Identität je Schreiber.
WebAssembly#
Der Wasm-Build bettet nur den englischen Katalog ein. Die übrigen sechzehn würden je etwa 150 kB gzip hinzufügen. Eine Seite lädt bei einer Sprachwahl i18n/<lang>/engine.ftl und ruft register_catalogue(tag, text) auf; schlägt das Laden oder die Registrierung fehl, bleibt die Seite auf Englisch. Nativ betten die Befehlszeile und das Python-Wheel alle 18 ein.
Größe, nicht optimierte .wasm aus cargo build --release --target wasm32-unknown-unknown --features wasm --lib (vor wasm-bindgen und wasm-opt), Basis bc04e98f gegenüber diesem Zweig: 18,71 MB -> 19,88 MB roh, 5,43 MB -> 5,79 MB gzip, +357 kB gzip. Der englische Katalog hat 521 kB roh, davon 153 kB gzip; der Rest ist fluent-bundle und seine Abhängigkeiten. Das wird wie gemessen akzeptiert.
Der Katalog#
i18n/<tag>/engine.ftl enthält die Meldungen, Kennungen mit dem Präfix engine-. i18n/en/engine.ftl ist die Quelle; die anderen Dateien gehören den Übersetzern und können Meldungen vermissen lassen (jede fällt je Meldung auf Englisch zurück). Begleitlisten in i18n/en/: engine-counts.txt (Meldungen mit Zählvariablen, für Pluralformen), engine-numbers.txt (als Platzhalter übergebene Zahlen), engine-fragments.txt (Meldungen, die Teile eines zur Laufzeit zusammengesetzten Satzes sind: in ganze Sätze zusammenzuführen, nie anwachsen zu lassen).
Tests#
tests/i18n_catalogue.rs beweist Englisch: Jede Meldung hat eine aufgezeichnete ursprüngliche Vorlage und wird genau zu diesem Text gerendert; jede Kennung wird verwendet; die Variablen stimmen überein; die Pseudo-Locale rendert jede Meldung. i18n_api.rs, i18n_kinds.rs, i18n_legal.rs decken die Einstiegspunkte, die Beschreibungen der Arten und die Rechtstexte ab. i18n_ratchet.rs schlägt fehl, wenn ein neues Zeichenkettenliteral, das ein Mensch lesen würde, den Katalog umgeht: Erlaubnis je Datei in tests/fixtures/i18n/allow.json, die sinken, aber nie steigen darf. scripts/i18n_compare.py führt ganze Szenarien mit einer Basis-Binärdatei und der aktuellen aus und vergleicht jede Ausgabedatei.
Wie eine Zeichenkette in den Katalog verschoben wird: docs/design/i18n-migration.md.
Abhängigkeiten und Lizenzen#
Das Framework fügt fluent-bundle 0,16 (Apache-2.0 OR MIT) und unic-langid 0,9 (MIT OR Apache-2.0) hinzu, mit ihren transitiven Crates: fluent-syntax und fluent-langneg (Apache-2.0 OR MIT), intl-memoizer (Apache-2.0 OR MIT), intl_pluralrules (Apache-2.0/MIT), type-map (MIT/Apache-2.0), self_cell (Apache-2.0 OR GPL-2.0-only: Die verwendete Alternative ist Apache-2.0, die deny.toml erlaubt), tinystr und zerovec (Unicode-3.0), rustc-hash, smallvec, thiserror, displaydoc (MIT OR Apache-2.0). Jede ist permissiv nach der Liste allow in deny.toml; thiserror erscheint in zwei Versionen (1 und 2), was multiple-versions = "warn" nur meldet. Die Lizenzliste wurde aus cargo metadata gelesen; cargo deny check ist in der Autorenumgebung nicht installiert und läuft in der Integrations-CI.