DeesseJS Collections

Internationalization

Native i18n support for collections and fields

Internationalization

@deessejs/collections has native, first-class support for internationalization. All user-facing strings can be translated without external i18n libraries.

Configuration

Set up supported locales in your configuration:

// config/database.ts
export const { collections } = defineConfig({
  database: { url: process.env.DATABASE_URL! },

  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'fr', 'es', 'de'],
    fallbackLocale: 'en'
  },

  collections: [posts, users]
})

Collection Translations

Collections support translated labels and descriptions:

// collections/posts.ts
export const posts = collection({
  slug: 'posts',

  // Translated labels
  label: {
    en: 'Blog Post',
    fr: 'Article de Blog',
    es: 'Artículo de Blog',
    de: 'Blog-Beitrag'
  },

  // Plural labels
  plural: {
    en: 'Blog Posts',
    fr: 'Articles de Blog',
    es: 'Artículos de Blog',
    de: 'Blog-Beiträge'
  },

  // Description
  description: {
    en: 'Blog posts and articles',
    fr: 'Articles de blog',
    es: 'Artículos de blog',
    de: 'Blog-Artikel'
  },

  fields: { ... }
})

Field Translations

Field Labels and Descriptions

fields: {
  title: field({
    type: text(),

    // Translated label
    label: {
      en: 'Title',
      fr: 'Titre',
      es: 'Título',
      de: 'Titel'
    },

    // Translated description
    description: {
      en: 'The title of your post',
      fr: 'Le titre de votre article',
      es: 'El título de tu entrada',
      de: 'Der Titel Ihres Beitrags'
    }
  })
}

Validation Messages

fields: {
  email: field({
    type: email(),

    messages: {
      required: {
        en: 'Email is required',
        fr: 'Email est requis',
        es: 'El correo electrónico es obligatorio',
        de: 'E-Mail ist erforderlich'
      },

      invalid: {
        en: 'Invalid email format',
        fr: 'Format d\'email invalide',
        es: 'Formato de correo electrónico no válido',
        de: 'Ungültiges E-Mail-Format'
      }
    }
  })
}

Modifiers with Translations

fields: {
  username: field({
    type: text({ min: 3, max: 20 }),

    messages: {
      tooShort: {
        en: 'Username must be at least 3 characters',
        fr: 'Le nom d\'utilisateur doit comporter au moins 3 caractères'
      },

      tooLong: {
        en: 'Username must be at most 20 characters',
        fr: 'Le nom d\'utilisateur ne peut pas dépasser 20 caractères'
      }
    }
  })
}

Enum Value Labels

Translate enum values for better UX:

fields: {
  status: field({
    type: enumField(['draft', 'published', 'archived']),

    // Translated enum values
    enumLabels: {
      draft: {
        en: 'Draft',
        fr: 'Brouillon',
        es: 'Borrador',
        de: 'Entwurf'
      },
      published: {
        en: 'Published',
        fr: 'Publié',
        es: 'Publicado',
        de: 'Veröffentlicht'
      },
      archived: {
        en: 'Archived',
        fr: 'Archivé',
        es: 'Archivado',
        de: 'Archiviert'
      }
    }
  })
}

Using Translations

Set Locale for Operations

// Set locale for specific operation
const post = await collections.posts.create({
  data: { title: 'Hello' },
  locale: 'fr' // Error messages in French
})

Get Translated Labels

// Get translated label for a field
const label = collections.posts.fields.title.getLabel('fr')
// Returns: 'Titre'

// Get all labels for a locale
const labels = collections.posts.getLabels('es')

Runtime Error Messages

Validation errors automatically respect the current locale:

try {
  await collections.users.create({
    data: {
      username: 'ab' // Too short
    }
  })
} catch (error) {
  // If locale is 'fr':
  // "Le nom d'utilisateur doit comporter au moins 3 caractères"
}

Missing Translations

When a translation is missing, the framework falls back to the default locale:

label: {
  en: 'Title',    // Default
  fr: 'Titre',    // Available
  // es: missing, falls back to 'en'
  de: 'Titel'     // Available
}

// Requesting 'es' returns 'Title' (default)

Type Safety: All locales are type-checked. Only defined locales can be used in defineConfig, providing compile-time safety.

Next Steps

On this page