Skip to main content

Translations (i18n)

@novu/framework workflows are code-first — content is rendered inside your bridge during workflow execution. That means i18n lives in your application layer: define translation keys in code (e.g. with i18next) and resolve them inside step resolvers using subscriber.locale.
The Novu Translation system on the Dashboard is intended for Dashboard-defined workflows. Framework workflows use your own i18n stack instead.

Setup with i18next

Install

Define translations

Use in a workflow

How subscriber.locale is set

locale comes from the subscriber record:
You can also pass it inline at trigger time:
If locale is missing, the resolver falls back to the defaultLocale control.

Email Template Example

Mount in your bridge

Testing

  1. Sync the workflow: npx novu@latest sync --bridge-url ... --secret-key ...
  2. Create or update subscribers with different locales:
  3. Trigger:
The user should receive their email in de_DE.

Tips

  • Use ISO 639-1 + ISO 3166-1 with underscore convention (en_US, de_DE, pt_BR).
  • Hard-fail on missing keys in development by setting i18next’s saveMissing and missingKeyHandler — this catches gaps in translations before deploy.
  • For digest emails, build a localized React component that takes a translation function as a prop and walks events.
  • Keep translation files separate from workflow code so your translation team can edit JSON without touching TypeScript.
  • Use i18next-http-backend + your CMS if translations should be edited by non-engineers without a code deploy.

Alternatives

i18next is just one option — any i18n library works:
  • react-i18next (React Email components support hooks via i18next provider patterns)
  • next-intl (server-side resolution works fine inside the bridge)
  • @formatjs/intl for ICU MessageFormat support
  • A simple Record<Locale, Record<Key, string>> lookup if you only need a few strings