Riepilogo
DiscourseAi::Translation::PostLocalizer (localizzazione dei contenuti) produce occasionalmente
traduzioni tronche senza registrare alcun errore (log di Rails,
log di Sidekiq, code di retry/dead di Sidekiq). La troncatura avviene a metà frase,
in modo silenzioso, e il risultato parziale viene salvato come se fosse una traduzione
completa e riuscita.
Osservato su: Discourse core + discourse-ai 46bea6613 (2026-07-09), LLM:
Gemini 2.5 Flash tramite provider Google.
Prove di riproduzione
Due casi reali sulla nostra istanza:
- Un post tedesco di ~2090 caratteri tradotto in spagnolo ha prodotto solo 50 caratteri,
interrompendosi immediatamente prima di una parola tra virgolette (“aufwendiger”) nel testo
sorgente. - Un post tedesco di ~1830 caratteri tradotto in inglese (83 caratteri) e slovacco
(97 caratteri) — entrambi si sono interrotti nello stesso punto esatto della frase,
immediatamente prima di uno shortcode emoji (
) nel testo sorgente.
Tutte le altre lingue (fr, it, pt, ru, he) per lo stesso post sono state
tradotte completamente (1600–1950 caratteri).
Causa principale (per quanto riesco a rintracciare)
In lib/completions/structured_output.rb, StructuredOutput#read_buffered_property
ricade su DiscourseAi::Utils::BestEffortJsonParser.extract_key ogni volta
che @partial_json_tracker.broken? è true. Questo fallback restituisce qualsiasi cosa sia
stata parsata prima che il flusso JSON si interrompesse — senza eccezioni, senza avvisi, senza
alcuna indicazione che l’output sia incompleto. In
lib/translation/base_translator.rb#get_translation, questo valore viene utilizzato così com’è
come traduzione finale e persistito tramite PostLocalization#save!.
I punti di troncatura nei nostri dati cadono immediatamente prima di un carattere “speciale”
nel testo sorgente (una virgoleta dritta, uno shortcode emoji),
suggerendo che il tracker del flusso JSON si confonda per determinati
caratteri/sequenze nell’output streaming del modello e marchi il flusso
come interrotto (broken?) prematuramente.
Impatto
I contenuti vengono pubblicati con traduzioni visibilmente incomplete, a volte prive di senso,
e non c’è alcun segnale operativo (log, job morto, notifica admin)
per rilevarlo. L’abbiamo scoperto solo perché un membro della comunità
ha notato del testo incomprensibile a metà frase nell’interfaccia utente.
Correzioni suggerite
- Segnala un avviso/errore (Rails.logger + Discourse-error-log) ogni volta
che StructuredOutput#broken? è true e viene utilizzato il fallback best-effort, in modo
che gli amministratori possano rilevare il problema invece di pubblicare in silenzio contenuti parziali. - Considera la validazione della lunghezza della traduzione rispetto a una soglia di sanità mentale relativa
alla lunghezza del testo sorgente prima di salvare una PostLocalization.
Disponibile a fornire coppie complete di testo greco/tradotto in privato se utile per
debuggare il tracker JSON.