Five languages
The interface, the documentation and the pages of words are in English, German, French, Spanish and Italian, with the words in one typed catalogue and a build step that walks every language against English: same keys, same array lengths, nothing empty, the same placeholders. It found 192 missing keys on its first run.
The language is in the address — /de/docs, /fr/csv-to-markdown — and English keeps the bare paths, because sixty-eight pages were already indexed at them.
The switcher in the header names each language in itself — Deutsch, Français, Español, Italiano — because that is the only name a reader of it recognises. Choosing one takes you to the same page in that language, and it stays chosen.
The language is in the address
/de/docs, /fr/csv-to-markdown, /es/markdown-to-html: one address per page per language, which is what a search engine needs in order to offer somebody the right one. English deliberately keeps the bare paths. Sixty-eight pages were already indexed at them, and moving English under a prefix of its own would have traded everything a search engine knows about this site for a tidier scheme.
A browser asking for a language nobody has written here lands on English, rather than on a redirect to something it cannot read. Dates and month names are not translated by hand at all — Intl renders them, which is also why English here reads "8 September 2026" and not the American order.
One catalogue, checked by the build
Every sentence the interface says lives in one typed catalogue, with English as the source. A key added in English and forgotten in German does not compile, which removes the failure mode of every string table that is checked by hand.
Types cannot see everything, though. A list of three sections satisfies the same type as a list of five, so a translator who dropped a paragraph would ship a page missing it, in one language, silently. So a build step walks each language against English — same keys, same list lengths, nothing empty, the same placeholders — and it runs inside the build, so a language that does not line up stops a deploy instead of reaching a reader. It found 192 missing keys the first time it ran.
The blog is a different thing
An article is a file rather than a string, and a translation of one is another file beside it, so the blog is translated a piece at a time. English, German and French have all sixty-three. Where a language has nothing, it lists nothing, links to nothing and claims no hreflang for it: a heading over an empty index is worse than an honest absence.
What stays in English
The API's messages and the connector's, because an API answers in one language. The consent page an assistant sends you to, and the server's own copy of a shared document: both are rendered for a reader we know nothing about, at an address with no language in it, and guessing wrong on a consent screen is worse than English. The entries in this changelog are English too — a page like this one is written in another language when it is worth having in it.
Related: what a Markdown to HTML converter is for, and choosing among online document converters.