Zum Inhalt springen

Mehrsprachigkeit der Records

Stand: 2026-10-26. Umgesetzt im Store (Lexicons, Indexer, Writer, AppView); in test ausgeschaltet (APPVIEW_TRANSLATE_ENABLED=false). Rechtsgrundlage: VERFASSUNG Art. 35 (maschinelle Übersetzungen sind abgeleitet, massgebend ist das Original). Die Übersetzung der Oberfläche und der CMS-Inhalte ist Sache des Clients.

Eine Liste für alle Dienste des Stores: ATVOTO_LANGUAGES (Standard de-CH,fr-CH,it-CH,rm,en-GB, BCP-47). Der Client übernimmt sie (ARCHITECTURE_SPLIT §5.5). Eine Sprache hinzufügen heisst: Liste erweitern, Dienste neu starten; bestehende Records bekommen die fehlende Sprache beim nächsten Lauf des Workers.

Pro Vorlage kann der Client die Sprachen einschränken: langs bei createDossier/updateDossier (gespeichert in app_dossier_meta.langs, leer = alle). Der Worker übersetzt Argumente, Kommentare und Themen einer Vorlage nur in diese Sprachen. Kommt eine Sprache später dazu, holt der Worker sie beim nächsten Lauf nach; fällt eine weg, bleiben vorhandene Übersetzungen stehen.

Inhalt Wo liegt die Übersetzung Warum
Argument inline im Record: translations[] (lang, title, body, source = manual/ai, model, translatedAt) Die kanonische Kopie gehört dem Community-Konto, der Store darf sie ergänzen
Kommentar eigener Record ch.atvoto.dossier.commentTranslation im Community-Konto, rkey {commentRkey}-{lang} Der Kommentar liegt im Repo der Person; dort darf der Store nicht schreiben
Themen (Taxonomie) direkt in der DB (Knoten des Themenbaums) kein eigener Record pro Knoten
Vorlage im CMS des Clients Redaktion beim Client (Art. 18)
Offizielle Argumente wie Argumente inline; putOfficialArgument nimmt neben dem Original optional translations[] (lang, title, body) an und schreibt sie mit source=manual, die fehlenden Sprachen übersetzt der Worker Herausgeber ist der Client, die Kopie liegt im Community-Konto; amtliche Übersetzungen (Abstimmungsbüchlein) gehen maschinellen vor

langs am Record nennt die Sprache des Originals.

  1. Der Indexer projiziert den Record und setzt translation_status: pending (keine), partial (einige), complete (alle Sprachen), manual_only (alle, nur manuell; der Worker rührt sie nicht an). Gezählt wird gegen ATVOTO_LANGUAGES: Ein Record einer Vorlage mit weniger Sprachen bleibt partial.
  2. Der Worker im Writer (services/writer/src/translation/translator.py) holt pending/partial, denen eine Sprache ihrer Vorlage fehlt, übersetzt diese per LLM (Infomaniak, Standard swiss-ai/Apertus-70B-Instruct-2509) und schreibt zurück: bei Argumenten putRecord auf die kanonische Kopie, bei Kommentaren einen commentTranslation-Record.
  3. Über den Firehose kommt die Änderung zurück in den Index.
  4. Die AppView liefert mit ?lang= die gewünschte Sprache, sonst das Original (services/appview/src/routes/participation/_lang.py).
Variable (Writer) Standard Bedeutung
APPVIEW_TRANSLATE_ENABLED false Worker an/aus
APPVIEW_TRANSLATE_COMMENTS_ENABLED false auch Kommentare
APPVIEW_TRANSLATE_TOPICS_ENABLED true auch Themen
APPVIEW_TRANSLATE_MODEL, …_BASE_URL Apertus, Infomaniak LLM
APPVIEW_TRANSLATE_BATCH_SIZE, …_POLL_INTERVAL_SECONDS 20, 30 Takt
  • Ein putRecord auf die kanonische Kopie ändert ihren CID. Verweise mit CID (strongRef, z.B. Bewertungen) zeigen danach auf eine ältere Fassung; der Text des Originals bleibt gleich.
  • Übersetzungen eines gelöschten Kommentars bleiben als Records im Community-Konto stehen, bis sie aufgeräumt werden (vgl. ACCOUNT_DELETION.md).