Languages and translation
A workflow that serves customers in several countries has to answer three questions: which language a model
writes in, how to translate a text without breaking what a later step still needs — a name, a code, a marker —
and how each language writes a date, an amount, a time. Models handle the first two well when they are told
exactly what to do; the third is better left to Format as Text, which writes
18. Oktober 2026 and 12,50 € the same way every time.
Subtitles have their own page: Translating captions translates timed captions line by line without touching the timing, with glossaries and a repair round. This page is about the text around them.
Which language a model writes in
Section titled “Which language a model writes in”- Say it, in the system prompt: “Write in German”. A model asked in English for a text about Italy may otherwise answer in either.
- Or follow the reader: “reply in the language the customer wrote in”. In the
email-sorting lab an email in Italian got its reply in
Italian, one in English in English. Ask for the language code as well (
"reply_language": "it"), so the rest of the workflow can choose the right template or voice for it. - Or pass it as data: a locale that comes with an order (
de-CH) goes into the prompt through a template — “Write in the language of this locale: [locale]” — and into Format as Text, so the words and the figures agree.
Translating with a model
Section titled “Translating with a model”Text Generation translates well when the system prompt says what a translator would ask:
- Translate the meaning and the tone, not word by word: a notice should read as if it had been written in that language.
- What is never translated: the brand, product and place names, codes. List them.
- What a later step fills in: keep every
[marker]exactly as written, and say what each marker will hold. A translator who sees[date]cannot know that it becomes “domenica 18 ottobre 2026”; in the lab the Italian translation wrote “del [date]”, which is correct for “del 18 ottobre” and wrong for “del domenica 18 ottobre”. Asking harder did not fix it; choosing a form that fits every language did — the date without the weekday.
And keep data out of the text. A source that says “on Saturday 18 October … a refund of EUR 12.50” is translated around those words; the lab’s first attempt, told to keep dates and prices as written, left “Saturday 18 October” in English inside the Italian, German and French notices, and “EUR 12.50” with a decimal point. Write the source with markers — “on [date] … a refund of [refund]” — and fill them after the translation with values that Format as Text writes in each language. The date, the amount and the code then cannot be mistranslated, and they are the same in every language because they come from the same data.
Before filling, check that the markers survived: a Replace Text with
use_regex, find \[(booking_code|date|refund)\] and replace_with $0 leaves the text unchanged and counts the
markers on count — 3 in every language of the lab.
Several languages at once
Section titled “Several languages at once”| Pattern | How | Use it when |
|---|---|---|
| One answer, a key per language | Text Generation in JSON mode returns {"it": …, "de": …, "fr": …}; Extract reads each |
short texts in a few languages: one call, the same terms in every language, the cheapest |
| One step per language | the list of languages is enumerated and Text Generation runs once per language | long texts, many languages, or a different model or brief per language |
| One template per language | the texts are written once by people; Select by Key picks the template by locale | legal lines, confirmations, anything that must not vary — no model at all |
Many workflows combine them: fixed sentences from per-language templates, a model only for the part that must be written, and Format as Text for every figure.
Language settings on other nodes
Section titled “Language settings on other nodes”| Node | Setting | Note |
|---|---|---|
| Format as Text | locale and currency, also as inputs |
numbers, money, percentages and dates in the reader’s conventions |
| Product Description | language: en, it, de, fr, es, pt, nl, pl, ja, ko, zh |
writes the listing directly in that language |
| Caption Translation | target_language, glossary |
timed captions; see Translating captions |
| Speech to Text | the spoken language, or detection | see Transcription and captions |
Try it: a notice in three languages
Section titled “Try it: a notice in three languages”A ferry company on an Alpine lake cancels a crossing because of the wind and tells each booked passenger in their language. The notice is written once in English, with markers; one Text Generation step translates it into Italian, German and French in one JSON answer; a Replace counts the markers in each translation; Format as Text writes the date and the refund in each language; a template fills the markers.
The source:
Dear passenger, because of strong wind the 14:20 crossing from Bellano Pier to Varenna Pier on [date] will not run.Your booking [booking_code] has been moved to the 15:05 crossing on the Aurora, at no extra cost. If that time doesnot suit you, you can change it for free until 13:00, or ask for a full refund of [refund] at any ticket office. Weare sorry for the inconvenience. Lake Line Ferrieswith date 2026-10-18, refund 12.5, booking_code LLF-7Q42. The results:
it — Gentile passeggero, a causa del forte vento la traversata delle 14:20 da Bellano Pier a Varenna Pier del 18 ottobre 2026 non verrà effettuata. La prenotazione LLF-7Q42 è stata spostata sulla traversata delle 15:05 a bordo dell’Aurora, senza costi aggiuntivi. […] richiedere un rimborso completo di 12,50 € presso qualsiasi biglietteria.
de — Sehr geehrter Fahrgast, aufgrund starken Windes fällt die Überfahrt um 14:20 Uhr von Bellano Pier nach Varenna Pier am 18. Oktober 2026 aus. Ihre Buchung LLF-7Q42 wurde ohne Aufpreis auf die Überfahrt um 15:05 Uhr mit der Aurora umgebucht. […] eine vollständige Rückerstattung von 12,50 € beantragen.
fr — Cher passager, en raison de vents violents, la traversée de 14 h 20 de Bellano Pier à Varenna Pier le 18 octobre 2026 n’aura pas lieu. Votre réservation LLF-7Q42 a été reportée sur la traversée de 15 h 05 à bord de l’Aurora, sans frais supplémentaires. […] demander le remboursement intégral de 12,50 € à n’importe quelle billetterie.
- The names stayed as they are; the times follow each language (14:20 Uhr, 14 h 20), as the brief asked.
- The date and the refund were never seen by the model: Format as Text wrote 18 ottobre 2026, 18. Oktober 2026, 18 octobre 2026 and 12,50 €.
- It took three runs to get here, and each taught one rule of this page: the first left “Saturday 18 October” and “EUR 12.50” untranslated (keep data out of the text); the second and third wrote “del domenica” (choose a form that fits every language).
- A model is a fluent translator, not a native one: the German used “an jeder Fahrkartenschalterstelle”, a word a German speaker would not write. Have a native speaker read the first notices of a new template.
The run costs about 0.04 credits: one call for the three languages.
node madoo-install-example.mjs lab-languages --api <your Madoo API URL> --key <key.json> --runWhen something goes wrong
Section titled “When something goes wrong”| Symptom | Cause | What to do |
|---|---|---|
| A date or an amount stays in the source language or format | it was in the text, and the model was told to keep it | write it as a marker and fill it with Format as Text per language |
A marker is missing or translated ([datum]) |
the model rewrote it | say in the system prompt to keep every [marker] exactly as written; count them with Replace before filling |
| A sentence does not agree with the value filled in | the translator did not know what the marker holds | say what each marker holds; choose a form that fits every language |
| The answer is in the wrong language | the language was not stated | state it in the system prompt, or ask for the customer’s language and its code |
| A name was translated | it was not listed as untranslatable | list brand, product and place names in the system prompt |
| A word reads oddly to a native speaker | a model’s fluency is not a native’s | have the first texts of a new template read by a native speaker |