$t
Bienvenue dans la visite des traductions. Every string in the
examples below is a _Translation row the docs seed (English,
French and Spanish), looked up by key with $t or
x-t.
This request resolved to
fr
because the controller called
$t.lang('fr')
for this request (drop it)
. Try
?lang=fr
or
?lang=es.
A key becomes a sentence
x-t sets an element's text from a key;
$t(key, vars) answers the string, with each
{name} filled from vars. The
controller and the template call the same function. A key with no row in your language falls
back to English, and a key nobody wrote shows the key itself, never a blank.
// blocks/translations.mjs
async $update() {
if (this.$req.query.lang) await $t.lang(this.$req.query.lang)
this.fromController = $t('tour.welcome')
}
<!-- blocks/translations.html -->
<span x-t="tour.welcome"></span>
<span x-text="$t('tour.hello', { name })"></span>
// seeds/_Translation.json
{ "locale": "fr", "key": "tour.hello", "value": "Bonjour {name}" }
- controller
- Bienvenue dans la visite des traductions
- x-t
- Bienvenue dans la visite des traductions
- with a var
- Bonjour Ada
- English only
- This sentence has no French yet, so French readers get it in English
- nobody wrote it
- tour.nobody.wrote.this
In the browser
The browser holds the catalogue too, so a count the server never saw fills in with no request, and a key built in the browser still resolves. Switch language and the whole page switches; the choice is kept in a cookie for the next request.
<span x-text="$t('tour.cart', { count })"></span>
<span x-text="$t('tour.status.' + status)"></span>
<button @click="switchTo('fr')">Français</button>
// a plain method: it runs in the browser
async switchTo(tag) {
await $t.lang(tag)
}
Dates and numbers follow the same locale
The locale that picks a string also formats dates, numbers and money in the same response, so
a French page never shows March 3, 2026. The controller passes no locale to
Intl; it gets the request's. The browser formats the same way, so
the text does not change when the page comes alive.
// No locale argument: the request's own.
new Date(instant).toLocaleDateString(undefined,
{ year: 'numeric', month: 'long', day: 'numeric' })
new Intl.NumberFormat().format(1234567.89)
new Intl.NumberFormat(undefined,
{ style: 'currency', currency: 'EUR' }).format(1234.5)
$t('tour.date', { date })
- a date
- 3 mars 2026
- in a sentence
- Nous sommes le 3 mars 2026
- a number
- 1 234 567,89
- money
- 1 234,50 €