Skip to main content
Every user-facing label, tooltip, placeholder, and notice in FlowDrop is rendered from a single typed Messages tree. You can override any subset by passing a messages callback to <App>. Wire that callback to your i18n library and locale changes propagate into FlowDrop without a subscription. FlowDrop is not an i18n library. It is a consumer of one. Translations live in your app, alongside the rest of your UI copy.

Quick start

Override a single string with a value:
messages is DeepPartial<Messages> — every key is optional, missing keys fall through to the English defaults. You can also pass a callback. The two forms are equivalent for static overrides; the callback is useful when your translations come from a function call you’d rather not invoke unless the prop is actually read:

Translating with paraglide-js

Paraglide-js compiles your .json translation files into typed message functions. Wire them into FlowDrop’s messages prop:
paraglide-js is one option — sveltekit-i18n, typesafe-i18n, or any reactive store will work. The contract is just: a callback returning a partial tree.
Passing messages as a callback (not a plain object) is what makes locale switching reactive. Paraglide’s reactive locale store causes Svelte to re-evaluate the expression; FlowDrop’s root then re-derives the merged message tree and re-renders.

The Messages shape

The full default tree lives at libs/flowdrop/src/lib/messages/defaults.ts and is exported as defaultMessages from @flowdrop/flowdrop/core. The shape is grouped by domain, not by component — file paths churn, domains don’t. Parameterised entries are functions, not template strings:
When you override a parameterised entry, you must supply a function with the same signature. Call sites invoke it with the params object, so a plain string would throw at runtime. If your translation doesn’t need the params, ignore them: ({ n: _n }) => 'Move up'.

Removed label props

Several components used to accept individual *Label props that duplicated the messages tree. These duplicates are removed — use the corresponding messages key instead: <FormToggle>’s onLabel/offLabel and <FormArray>’s addLabel are not removed. They express per-instance labels the global messages system cannot (a toggle’s “Hidden”/“Visible”, a schema-derived “Add Header” button) and are documented overrides. Workflow-level overrides on interrupt configs (config.confirmLabel, config.acceptAllLabel, etc.) are not removed either — those are runtime data from the workflow author, not component-prop API. They keep their priority over the messages defaults.

Components used outside the <App> provider

If you mount a flowdrop component (e.g. <SchemaForm> standalone, or a Storybook story) outside the root <App>, it falls back silently to the English defaultMessages. There is no error. The trade-off: a missing provider always renders English regardless of locale. To get translations in standalone usage, set up the messages context yourself:
setMessages accepts a getter so reactive overrides propagate the same way they do under <App>.

Reference

  • Defaults: libs/flowdrop/src/lib/messages/defaults.ts
  • Public types: Messages, MessagesOverride (re-exported from @flowdrop/flowdrop)
  • Source: libs/flowdrop/src/lib/messages/