Retour aux articlesBack to articles

J'avais mis MultiChat de côté il y a quelques mois. Une messagerie qui traduit chaque message dans la langue de son destinataire, en adaptant le registre — décontracté entre amis, soutenu pour un échange professionnel. L'interface était là, le backend aussi, le dépôt avait sept étoiles.

Je suis revenu dessus cette semaine en pensant finir deux ou trois détails.

Ce que j'ai trouvé en ouvrant le capot

Le backend ne démarrait pas. Pas « mal » : pas du tout. Il tentait de joindre une base Postgres qui n'existait nulle part, et abandonnait avant de servir la moindre requête.

Une fois démarré, envoyer un message levait une exception — à chaque fois. Une requête écrite avec l'API d'une ancienne version de SQLAlchemy, qui n'existe plus dans la version utilisée. L'erreur était attrapée par un except et transformée en « traduction échouée ». Silencieusement, depuis le début.

Côté interface, deux écrans entiers — l'inscription, le mot de passe oublié — étaient écrits, complets, soignés… et injoignables. Ni exportés, ni reliés à une route.

Et surtout : il n'existait aucun moyen de démarrer une conversation. Pas de liste des échanges, pas de recherche d'utilisateur. Pour écrire à quelqu'un, il aurait fallu connaître son identifiant interne. Une messagerie dans laquelle on ne peut parler à personne.

Le compilateur TypeScript signalait 22 erreurs. Le build passait quand même : un commit avait remplacé tsc && vite build par vite build. La vérification de types retirée, au lieu des erreurs corrigées.

Le plus gênant

L'adaptation du registre — l'argument central du projet — était cassée par conception.

Le code préfixait "Hey, " au message avant de le faire traduire, puis tentait de retirer ce préfixe du résultat. Sauf que le traducteur traduit aussi le préfixe. Le texte revenait avec un « Salut, » que le code ne reconnaissait pas, et laissait donc dans le message final.

Ça ne pouvait pas marcher. Ça n'avait jamais marché.

Ce que ça m'a appris

Un projet peut paraître fini de l'extérieur et ne fonctionner sur aucun de ses axes. Ce qui m'a trompé, c'est que tout compilait, que tout semblait démarrer, et que l'interface était jolie. Trois signaux qui ne disent rien de ce que l'application fait réellement.

Les sept étoiles n'ont rien changé au code. Elles m'ont juste obligé à le relire.

Où ça en est

MultiChat fonctionne maintenant, et c'est vérifiable.

La traduction couvre neuf langues, avec trois registres réellement distincts. La même phrase française, envoyée à trois personnes : « Hey, can you send me the file by tonight? », « Hi, can you send me the file before tonight? », « Hello, could you please send me the file before this evening? »

S'y ajoutent les messages en temps réel avec indicateur de frappe et accusés de lecture, l'appel vidéo en pair-à-pair dont la signalisation passe par le WebSocket existant, une interface qui suit la langue du compte, un mode sombre, et une recherche pour — enfin — trouver quelqu'un à qui écrire.

Et 89 tests : 31 unitaires côté serveur, 42 côté interface, 16 de fumée qui s'exécutent aussi bien en local que contre la production.

C'est en ligne sur multichat-app.vercel.app, le code est sur GitHub.

Si vous voulez l'essayer, prenez deux comptes — un en français, un en anglais. C'est là que l'intérêt se voit.

I set MultiChat aside a few months ago. A messenger that translates every message into the recipient's language, adjusting the register along the way — casual among friends, formal for professional exchanges. The interface was there, so was the backend, and the repo had seven stars.

I came back to it this week expecting to wrap up two or three details.

What I found under the hood

The backend didn't start. Not "badly": not at all. It tried to reach a Postgres database that existed nowhere, and gave up before serving a single request.

Once running, sending a message raised an exception — every time. A query written against an older SQLAlchemy API that no longer exists in the version in use. The error was caught by an except and turned into "translation failed". Silently, from the very beginning.

On the interface side, two entire screens — sign-up and password reset — were written, complete, polished… and unreachable. Neither exported nor wired to a route.

And above all: there was no way to start a conversation. No list of threads, no user search. To write to someone, you would have needed their internal ID. A messenger in which you can talk to nobody.

The TypeScript compiler reported 22 errors. The build passed anyway: a commit had replaced tsc && vite build with vite build. Type checking removed, instead of the errors fixed.

The worst of it

Register adaptation — the whole point of the project — was broken by design.

The code prefixed "Hey, " to the message before sending it off to be translated, then tried to strip that prefix from the result. Except the translator translates the prefix too. The text came back with a "Salut," the code didn't recognise, and therefore left in the final message.

It could not have worked. It never had.

What it taught me

A project can look finished from the outside and work on none of its axes. What fooled me was that everything compiled, everything appeared to start, and the interface was pretty. Three signals that say nothing about what the application actually does.

The seven stars changed nothing in the code. They just forced me to read it again.

Where it stands

MultiChat works now, and that is verifiable.

Translation covers nine languages, with three genuinely distinct registers. The same French sentence, sent to three people: "Hey, can you send me the file by tonight?", "Hi, can you send me the file before tonight?", "Hello, could you please send me the file before this evening?"

On top of that: real-time messages with typing indicator and read receipts, peer-to-peer video calls whose signalling rides on the existing WebSocket, an interface that follows the account's language, a dark mode, and a search to — finally — find someone to write to.

And 89 tests: 31 unit tests on the server, 42 on the interface, and 16 smoke tests that run against local development as readily as against production.

It is live at multichat-app.vercel.app, and the code is on GitHub.

If you want to try it, take two accounts — one in French, one in English. That is where it gets interesting.