What the kit ships
Writing a locale is the walkthrough, catalog keys is the grammar you are filling in, checking your coverage is how you know you are done, and the i18n reference has the config.
| Locale | State |
|---|---|
en | Complete. The source language |
es | An unreviewed first pass, and it says so in its own files |
That second row is the honest one. The Spanish is a first pass nobody has reviewed, and the marker at the head of each catalog file states it rather than leaving you to find out.
Adding one is two steps
i18n({
supportedLocales: ["en", "es", "fr"],
messages: {
fr: { "app/board.title": "Tableau" },
},
})Ship the least specific tag that is true — es, not es-ES.
The catalog locale falls back and the formatting locale does not, so an es-AR reader already gets Argentine dates from a plain es catalog. Writing es-AR buys you nothing unless the words differ.
The default locale must be one of the supported ones, and the config refuses otherwise.
What you are covering
For an error, the key is the code. So the kit’s closed error union is the exact checklist a locale has to cover — there is no second identifier to keep in sync.
Beyond that: each capability’s own <name>/ keys, and your own domain’s.
The marker a translated file carries
Within its first 25 lines, exactly:
// LOCALE es — an unreviewed first pass. Not American English by design.Two facts, both load-bearing: the locale it is written in, and that the copy is an unreviewed first pass.
It exempts the file’s quoted values, not the file. A catalog is not written in Spanish — its values are. Everything around them is a docblock, an import and an identifier: ordinary English prose, and as subject to a prose rule as any other file’s.
A run is one line’s worth. The census reads line by line, and a quote that never closes on its line opens no value — so the inner lines of a multi-line template literal are read as prose.
What the send Worker carries
The kit’s own email copy, in every language the kit is written in, built into its bundle.
So adding a locale the kit ships costs you a package upgrade and no configuration at all.
What still travels as configuration is your diff — the email/ sentences you changed, one variable per locale, and nothing if you changed none.
A Cloudflare Worker variable holds 5,120 bytes, and provisioning refuses an override set that outgrows one, naming the language and the byte count rather than truncating — because a shortened catalog is a letter half in Spanish and half in English with nothing failing to say so.
What is not bounded that way
Screens are negotiated in the browser and fetched one locale at a time as their own chunk.
Errors carry their English on the wire and are translated by the client from a catalog it already holds.