Getting started
Languages and translations
Flowplan is available in three languages: German, English and French. Further languages can be added without changing the app's code – with any translation tool that understands JSON files.
Choosing a language
Flowplan follows your browser's language; languages Flowplan does not know show English. Under Settings → Appearance & language → Language you pick a language (with its flag) from the list – it then applies on all devices, also to e-mails and push notifications; Automatic (follows the browser) undoes the choice. On the sign-in page the small button at the bottom right (e.g. 🇬🇧 EN) opens a menu with all languages.
Dates, times and numbers follow the language (French: fr-FR, e.g. “15 oct. 2026” and “2 400,5”). Calculations in notes use the decimal comma in French as well.
What you create yourself – pages, databases, properties – stays in the language it was made in. Templates and example content exist in German and English; French accounts get the English ones.
How translation works
German and English sit side by side in the code. Every further language is a catalogue in the app's locales/ folder that maps the English text to its translation:
{
"Sign in": "Se connecter",
"{0} commented on “{1}”": "{0} a commenté « {1} »"
}locales/en.jsonlists every text of the app (more than 3,500) and is the source for translation tools. It is generated, not edited by hand.{0},{1}… stand for values such as names or numbers. They have to appear in the translation; their order may change.- An empty or missing entry shows the English text – so a language can grow step by step, and new texts in the app never break anything.
Adding a language
Create the catalogue, e.g. for Italian:
npm run i18n -- --add itThis creates
locales/it.jsonwith every text and empty translations.Translate – by hand or with a tool such as Weblate, Crowdin, POEditor or Lokalise (format “JSON key-value” or “i18next JSON”, source file
locales/en.json). Machine translation (e.g. DeepL) works as a draft; please keep placeholders and HTML tags unchanged.Register the language: in
lib/i18n.tsunderLANGUAGESwith its name and date format (it: { name: "Italiano", tag: "it-IT" }), and import the catalogue inlib/i18n-catalogs.ts.Check:
npm run i18n -- --check # progress and wrong placeholders npm run i18n -- --check --missing # what is still missing, with the place in the code
The language then appears in the choice on the sign-in page and in the profile, and browsers in that language get it automatically.
Keeping catalogues up to date
After texts change in the code, npm run i18n collects all texts again: new ones are added empty to every catalogue, unused ones drop out, existing translations stay. The tests only report missing translations; wrong placeholders make them fail.
In the code, texts are t("Deutsch", "English") in components, tr() outside of them and ct() for content the server creates. Tables of text pairs get a marker so npm run i18n finds them, e.g. // i18n-table: 1 for [German, English] pairs.
Text recognition
Text recognition for scanned PDFs and images is separate: it reads German and English, and French with FLOWPLAN_OCR_LANGS=fra,eng (see Configuration).