News
The app now speaks English
Menu language belongs to the person, content language belongs to the project. You can work in English and publish in French — or the other way around.
The app used to be in French, hard-coded into the components. That was deliberate: a single-language tool for a French team. Then it had to open up, and a question landed immediately — which of the two languages, exactly? The one in the menus, or the one in the posts?
Two settings, because they’re two different things
Interface language belongs to the person. Content language belongs to the project.
The first lives in your account: “Interface language”, with a useful clarification right underneath — “Menus, messages and emails. The language of generated content is set per project.” The choice is stored on the account, not in the browser: you find it again elsewhere, and the emails the app sends you follow it.
The second lives in the project settings, “Content language”, across thirty-eight languages — the seven most common first, then the rest of Europe. Its subtitle is just as blunt: “Used by every generation, whatever the interface language. Changing it doesn’t translate existing content.”
So an agency can work in English on a project that publishes in French, and on another that publishes in Spanish, without the two contaminating each other.
The French text is the key
Translation follows one founding decision: the French text is itself the identifier. There is no French catalog, because there is no key to invent — nothing abstract to chase three screens away just to learn what shows up. What you write is what you read.
The English catalog does exist: twenty-three files, one per area of the app, where every French string points to its translation. Plurals have their own function — French treats zero and one as singular, English doesn’t. Ambiguous strings carry a context: “Edited” doesn’t mean the same thing in a post’s history and on a provenance badge.
A test that refuses to let anything through
This is the part that holds the whole thing together. On every pnpm test, a check reads the source code, collects every translation call and demands: an English translation for each one, no unused entry in the catalog, identical parameters on both sides, no dynamic template as a source string, and no contradictory translations of the same text.
In practice: changing a French sentence without touching its translation breaks the build. You can’t forget.
American English, down to the dates
Choosing “English” isn’t only about translating words. Every date, time and number goes through the locale: fr-FR on one side, en-US on the other. So the month before the day, and a twelve-hour clock. “jeu. 24 sept. · 12 h 30” becomes “Thu, Sep 24 · 12:30 PM”. That was a decision, made on Sep 17, 2026: the product’s English is American, not British.
On the server, the language is resolved in order: the request context, then the account, then the header the app sends, then the browser’s. And a scheduled job writing to a whole team writes to each person in their own language — a reminder email isn’t translated on the fly, it’s composed once per recipient.
Content language, enforced by the server
The most important part is invisible. A project’s AI routes don’t trust the language the browser sends: they read the project’s own language from the database and impose it on the brief, the document and the profile they receive. A tab opened before the change, a post written three weeks ago, a brand profile still empty — all of them come back in the right language.
What’s written for you, on the other hand — the rationale behind a generation, a review, an assistant summary — follows the interface language. AI talks to you in your language and writes your posts in the project’s.
And handles, while we’re at it
Same family of problem: an account name isn’t the same on every platform. So the brand profile offers “One handle for all platforms” or “One handle per platform”. In the second case, each post shows the handle for its platform, and a platform without one falls back to the default.
The handle isn’t frozen when the post is created: it’s resolved at render time, from the post’s platform. A post adapted for LinkedIn therefore shows the LinkedIn handle, on its slides and in its export, without any operation having had to replace it.



