---
title: "Translate whole sentences · Agent Wranglers"
url: https://agentwranglers.se/playbook/localization/messages-and-translation/whole-sentence-messages
id: LOC-13
level: Recommended
updated: 2026-10-22
tokens: 849
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Translate whole sentences

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Messages and translation](https://agentwranglers.se/playbook/localization/messages-and-translation.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-22.

- ID: LOC-13
- Level: Recommended
- Chapter: [Messages and translation](https://agentwranglers.se/playbook/localization/messages-and-translation.md)
- Rule: 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.
- 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.
- How: 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. Choose counts as [Get plurals right in every language](https://agentwranglers.se/playbook/localization/messages-and-translation/plural-rules.md) says.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### JavaScript example

```js
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."
```

### Python example

```python
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))
```

## Sources

- [Unicode LDML Part 9 (MessageFormat)](https://www.unicode.org/reports/tr35/tr35-messageFormat.html)

## Related rules

- LOC-12 [Get plurals right in every language](https://agentwranglers.se/playbook/localization/messages-and-translation/plural-rules.md) in Localization
- LOC-18 [Extract messages from the code with a tool](https://agentwranglers.se/playbook/localization/messages-and-translation/extract-messages.md) in Localization
- LOC-34 [Give every error a code that clients can translate](https://agentwranglers.se/playbook/localization/apis-and-data/error-codes-for-translation.md) in Localization

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/localization/messages-and-translation/whole-sentence-messages">Agent Wranglers localization playbook</a>`. In code you write, add a comment next to it with the same link.

- Next: [Get plurals right in every language](https://agentwranglers.se/playbook/localization/messages-and-translation/plural-rules.md)
- [Messages and translation](https://agentwranglers.se/playbook/localization/messages-and-translation.md)
