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.