Multilingual Email

Send emails in the recipient's preferred language using template translations.

Send emails in the recipient's preferred language using template translations.

Language resolution order

Owlat resolves the language for each email in this order:

  1. Explicit language param in the send request
  2. Contact preferred language stored on the contact record
  3. Template default language set when publishing
  4. Fallback default (en)

You can control language at different levels depending on your needs.

Option 1: Explicit language per request

Pass language directly when you know the user's locale:

import { Owlat } from '@owlat/sdk-js'

const owlat = new Owlat('lm_live_...')

await owlat.transactional.send({
  slug: 'welcome',
  email: 'mira@acme.io',
  dataVariables: { firstName: 'Mira' },
  language: 'de',
})
curl -X POST https://your-deployment.convex.site/api/v1/transactional \
  -H "Authorization: Bearer lm_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "slug": "welcome",
    "email": "mira@acme.io",
    "dataVariables": { "firstName": "Mira" },
    "language": "de"
  }'

Option 2: Contact preferred language

Set the language on the contact once, then send without specifying it each time:

// Set preferred language when creating the contact
await owlat.contacts.create({
  email: 'mira@acme.io',
  firstName: 'Mira',
  language: 'de',
})

// All future sends automatically use German
await owlat.transactional.send({
  slug: 'welcome',
  email: 'mira@acme.io',
  dataVariables: { firstName: 'Mira' },
  // No language param needed — uses contact preference
})

This is the cleanest approach for most applications. Set the language during signup and forget about it.

Full example: read locale from your database

A complete handler that reads the user's locale preference and sends in the right language:

import { Hono } from 'hono'
import { Owlat } from '@owlat/sdk-js'

const app = new Hono()
const owlat = new Owlat(process.env.OWLAT_API_KEY!)

app.post('/api/send-notification', async (c) => {
  const { userId, templateSlug, variables } = await c.req.json()

  // 1. Look up user locale from your database
  const user = await db.users.findUnique({
    where: { id: userId },
    select: { email: true, firstName: true, locale: true },
  })

  if (!user) return c.json({ error: 'User not found' }, 404)

  // 2. Send with the user's preferred language
  const result = await owlat.transactional.send({
    slug: templateSlug,
    email: user.email,
    dataVariables: {
      firstName: user.firstName,
      ...variables,
    },
    language: user.locale ?? undefined,
  })

  return c.json({ messageId: result.data.transactionalEmailId })
})
Supported languages

You need to add translations for each language in the Owlat dashboard before sending. If a requested language doesn't have a translation, the template default language is used. See Translations for setup instructions.

Next steps