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:
locale is missing, the resolver falls back to the defaultLocale control.
Email Template Example
Mount in your bridge
Testing
- Sync the workflow:
npx novu@latest sync --bridge-url ... --secret-key ... - Create or update subscribers with different locales:
- Trigger:
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
saveMissingandmissingKeyHandler— 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/intlfor ICU MessageFormat support- A simple
Record<Locale, Record<Key, string>>lookup if you only need a few strings