Skip to content

i18n ​

Okapi provides English titles and messages by default. Pass i18n options to a mapper factory or core mapping function to replace them with static translations or resolve them at runtime.

ts
import { createAxiosErrorMapper } from '@alexovn/okapi/axios'

const mapAxiosError = createAxiosErrorMapper({
  i18n: {
    titles: { network: 'Connection problem' },
    messages: { network: 'Check your internet connection and try again.' },
  },
})

The same i18n object is available through the shared OkapiErrorOptions, MapOkapiErrorOptions, and OkapiErrorAdapterOptions types. See Types.

Types ​

OkapiErrorI18nOptions ​

Options for customizing mapped error titles and messages.

ts
interface OkapiErrorI18nOptions<
  TCustomKind extends string = never,
  TValidationErrors = ApiValidationErrors,
> {
  titles?: OkapiErrorTitles<TCustomKind>
  statusTitles?: OkapiErrorStatusTitles
  messages?: OkapiErrorMessages<TCustomKind>
  statusMessages?: OkapiErrorStatusMessages
  resolveTitle?: OkapiErrorTitleResolver<TCustomKind, TValidationErrors>
  resolveMessage?: OkapiErrorMessageResolver<TCustomKind, TValidationErrors>
}

Static Translations ​

Use static translations when the translated strings are known while configuring the mapper. Kind-based values provide general copy for an error category; status-based values override that copy for a specific HTTP response.

titles ​

Custom titles keyed by built-in or application-specific error kind.

  • Type:
ts
type OkapiErrorTitles<TCustomKind extends string = never> = Partial<
  Record<OkapiErrorKind<TCustomKind>, string>
>

statusTitles ​

Custom titles keyed by HTTP status code.

  • Type:
ts
type OkapiErrorStatusTitles = Partial<Record<number, string>>

messages ​

Custom messages keyed by built-in or application-specific error kind.

  • Type:
ts
type OkapiErrorMessages<TCustomKind extends string = never> = Partial<
  Record<OkapiErrorKind<TCustomKind>, string>
>

statusMessages ​

Custom messages keyed by HTTP status code.

  • Type:
ts
type OkapiErrorStatusMessages = Partial<Record<number, string>>

Example ​

ts
import type { OkapiErrorAdapterOptions } from '@alexovn/okapi'

const options: OkapiErrorAdapterOptions = {
  i18n: {
    titles: {
      'not-found': 'Not found',
      network: 'Connection problem',
    },
    statusTitles: {
      503: 'Temporarily unavailable',
    },
    messages: {
      'not-found': 'The requested resource was not found.',
      network: 'Check your internet connection and try again.',
    },
    statusMessages: {
      503: 'The service is temporarily unavailable. Please try again later.',
    },
  },
}

Dynamic Translations ​

Use resolvers when translation depends on runtime data or an i18n library. Each resolver receives the complete normalized OkapiError, including its kind, source, statusCode, raw response, and original cause.

resolveTitle ​

A function that derives a custom title from a normalized error.

  • Type:
ts
type OkapiErrorTitleResolver<
  TCustomKind extends string = never,
  TValidationErrors = ApiValidationErrors,
> = (error: OkapiError<TCustomKind, TValidationErrors>) => string | undefined

resolveMessage ​

A function that derives a custom message from a normalized error.

  • Type:
ts
type OkapiErrorMessageResolver<
  TCustomKind extends string = never,
  TValidationErrors = ApiValidationErrors,
> = (error: OkapiError<TCustomKind, TValidationErrors>) => string | undefined

Example ​

ts
import type { OkapiErrorAdapterOptions } from '@alexovn/okapi'

const options: OkapiErrorAdapterOptions = {
  i18n: {
    resolveTitle: ({ statusCode }) => {
      if (statusCode === 503) {
        return 'Temporarily unavailable'
      }

      return undefined
    },
    resolveMessage: ({ kind, statusCode }) => {
      if (statusCode !== undefined) {
        return translate(`errors.http.${statusCode}`)
      }

      return translate(`errors.api.${kind}`)
    },
  },
}

Translation Resolution Order ​

Titles are resolved in this order:

  1. i18n.resolveTitle
  2. i18n.statusTitles[statusCode]
  3. i18n.titles[kind]
  4. Built-in title

Messages are resolved in this order:

  1. i18n.resolveMessage
  2. i18n.statusMessages[statusCode]
  3. i18n.messages[kind]
  4. Built-in message

A resolver can return undefined to continue to the next fallback.