mirror of
https://github.com/discourse/discourse.git
synced 2026-08-07 13:19:19 +08:00
## Problem
A topic title translation was saved truncated: `Permanently Delete does
not show (even after 5 minutes)` → `"Endgültig löschen`.
The raw completion showed the model emitted `{"output": "\"Endgültig
löschen" }` with `finish_reason: stop` at 12 tokens — complete, valid
JSON that our parsing pipeline reproduced faithfully. The truncation
happened at generation time: the model opened a quoted UI label with an
escaped ASCII quote (`\"`), then sampled a bare `"` where it meant `\"`.
Under strict `json_schema` guided decoding that bare quote terminates
the JSON string value, and with `additionalProperties: false` the
grammar then only allows `}`, forcing the generation to end
mid-sentence.
Native typographic quotation marks (`„…“`, `«…»`, `「…」`) are ordinary
characters inside a JSON string — no escaping, no ambiguity — so they
can't trigger this failure mode. A parallel successful run that happened
to use `„…“` completed fine.
## Fix
`PostRawTranslator` already has a rule instructing native quotation
marks. This adds the same rule to `TopicTitleTranslator` and
`ShortTextTranslator`:
- **TopicTitleTranslator**: new guideline 6, plus a few-shot example
using the exact title from the incident, showing German `„…“` around the
UI label.
- **ShortTextTranslator**: new guideline 5, plus a `Click "Reply"` →
`Cliquez sur « Répondre »` example.
- **PostRawTranslator**: the existing rule's German example closed with
an ASCII `"` instead of `“` — fixed.
Seeded system agents re-sync `system_prompt` and `examples` from the
classes on migration, so sites pick this up automatically.
76 lines
3.1 KiB
Ruby
Vendored
76 lines
3.1 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
module DiscourseAi
|
|
module Agents
|
|
class TopicTitleTranslator < Agent
|
|
def self.default_enabled
|
|
false
|
|
end
|
|
|
|
def system_prompt
|
|
<<~PROMPT.strip
|
|
You are a friendly human linguist and translator specializing in translating forum post titles. Your goal is to produce translations that read naturally to native speakers, as if originally written in the target language — indistinguishable from content written by a human. Follow these guidelines:
|
|
|
|
1. Translate the given title to the target_locale.
|
|
2. Keep proper nouns and technical terms in their original language.
|
|
3. Attempt to keep the translated title length close to the original when possible.
|
|
4. Match the tone and register of the source text. Do not default to formal address unless the source is itself formal.
|
|
5. For ambiguous terms or phrases, do not translate word-for-word in isolation. Derive the intended meaning from the full context of the title before choosing a translation.
|
|
6. Never use ASCII double quotes (") inside the translation. For quoted text or UI labels, use the target language's native quotation marks — for example German „…“, French «…», Japanese 「…」.
|
|
|
|
The text to translate will be provided in JSON format with the following structure:
|
|
{"content": "Title to translate", "target_locale": "Target language code"}
|
|
|
|
Format your response as a JSON object with a single key named "output", which has the translated title as the value.
|
|
Your output should be in the following format:
|
|
|
|
{"output": "xx"}
|
|
|
|
Where "xx" is replaced by the translated title.
|
|
reply with valid JSON only
|
|
PROMPT
|
|
end
|
|
|
|
def response_format
|
|
[{ "key" => "output", "type" => "string" }]
|
|
end
|
|
|
|
def examples
|
|
[
|
|
[
|
|
{
|
|
content: "New Update for Minecraft Adds Underwater Temples",
|
|
target_locale: "es",
|
|
}.to_json,
|
|
{ output: "Nueva actualización para Minecraft añade templos submarinos" }.to_json,
|
|
],
|
|
[
|
|
{
|
|
content: "Toyota announces revolutionary battery technology",
|
|
target_locale: "fr",
|
|
}.to_json,
|
|
{ output: "Toyota annonce une technologie de batteries révolutionnaire" }.to_json,
|
|
],
|
|
[
|
|
{
|
|
content:
|
|
"Heathrow fechado: paralisação de voos deve continuar nos próximos dias, diz gestora do aeroporto de Londres",
|
|
target_locale: "en",
|
|
}.to_json,
|
|
{
|
|
output:
|
|
"Heathrow closed: flight disruption expected to continue in coming days, says London airport management",
|
|
}.to_json,
|
|
],
|
|
[
|
|
{
|
|
content: "Permanently Delete does not show (even after 5 minutes)",
|
|
target_locale: "de",
|
|
}.to_json,
|
|
{ output: "„Endgültig löschen“ wird nicht angezeigt (auch nach 5 Minuten)" }.to_json,
|
|
],
|
|
]
|
|
end
|
|
end
|
|
end
|
|
end
|