Skip to content

Internationalization (i18n) ​

Send locale-specific email templates based on user language preferences.

Configuration ​

Add i18n options to your module configuration:

typescript
MailerModule.forRoot({
  transport: { host: 'smtp.example.com', port: 587 },
  template: {
    dir: join(__dirname, 'templates'),
    adapter: new HandlebarsAdapter(),
  },
  i18n: {
    defaultLocale: 'en',
    templateDirPattern: '{{locale}}/',
    fallback: true,
  },
})

Directory Structure ​

Organize your templates by locale:

templates/
  en/
    welcome.hbs
    reset-password.hbs
  es/
    welcome.hbs
    reset-password.hbs
  fr/
    welcome.hbs

Sending Localized Emails ​

Pass the locale option in sendMail():

typescript
// Sends using templates/es/welcome.hbs
await this.mailerService.sendMail({
  to: 'user@example.com',
  subject: 'Bienvenido',
  template: 'welcome',
  locale: 'es',
  context: { name: 'Juan' },
});

Fallback Behavior ​

A locale with a region falls back to its language first: for locale: 'es-CO' the mailer uses templates/es-CO/welcome.hbs if it exists, otherwise templates/es/welcome.hbs (new in v4). Both - and _ separate the region (pt_BR → pt). Templates of every bundled adapter are detected, .mjml included.

typescript
// templates/es-CO/welcome.hbs doesn't exist, templates/es/welcome.hbs does
await this.mailerService.sendMail({
  to: 'user@example.com',
  template: 'welcome',
  locale: 'es-CO',
  context: { name: 'Juan' },
});

If neither exists and fallback: true (default), the system falls back to defaultLocale:

typescript
// templates/fr/reset-password.hbs doesn't exist
// Falls back to templates/en/reset-password.hbs
await this.mailerService.sendMail({
  to: 'user@example.com',
  template: 'reset-password',
  locale: 'fr',
  context: { resetLink: 'https://...' },
});

Custom Pattern ​

The templateDirPattern controls how locale maps to the directory structure:

typescript
// Default: '{{locale}}/' → templates/es/welcome.hbs
// Custom:  '{{locale}}-templates/' → templates/es-templates/welcome.hbs
i18n: {
  defaultLocale: 'en',
  templateDirPattern: '{{locale}}-templates/',
}

TIP

  • Works with all template adapters (Handlebars, Pug, EJS, Nunjucks, Liquid, MJML)
  • If no locale is provided, the template is resolved normally (no i18n prefix)
  • Set fallback: false to throw an error when a locale template is missing
  • A locale that is not a language tag (letters, digits, - and _ only, such as en, es-CO, zh_Hant_TW) is ignored with a warning and defaultLocale is used, so user input never shapes a file path
  • Localized templates are looked up in template.dir only, not in the extra template.dirs
  • Mail classes receive the locale in render(), so they can translate the subject too

Released under the MIT License.