Languages and regions Recommended
Translate whole sentences
On sites with several languages, or one planned, keep every visible text in a message file. Use one entry per whole sentence with named placeholders, and never build a sentence from translated pieces.
How to do it
Give each sentence one key, and put values in named placeholders such as {name}, so translators can move them. Use ICU MessageFormat or gettext, which handle plurals inside the sentence. Never join strings such as "Booked by " plus a name, because word order differs between languages. Add a short note for translators to each key.
Example
import { IntlMessageFormat } from 'intl-messageformat';
const booked = new IntlMessageFormat('{name} booked {count, plural, one {# room} other {# rooms}}.', 'en');
booked.format({ name: 'Ana', count: 2 }); // "Ana booked 2 rooms."
import gettext
translation = gettext.translation("messages", localedir="locale", languages=["sv"], fallback=True)
count = 2
text = translation.ngettext("{name} booked one room.", "{name} booked {count} rooms.", count)
print(text.format(name="Ana", count=count))
How to check
A lint rule finds no text in templates outside the message calls. A test finds no message that is joined to another with + or string formatting.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers website playbook: https://agentwranglers.se/playbook/website/languages-and-regions/whole-sentence-messages.