Nuxt i18n
Composables

defineI18nLocale

The defineI18nLocale() composable is used to define a function to dynamically load locale messages used for lazy-loading translations.

The defineI18nLocale() composable is used to define a function to dynamically load locale messages used for lazy-loading translations.

The loader function needs to return a Promise that resolves a messages object.

Type

declare function defineI18nLocale<Messages = LocaleMessages<DefineLocaleMessage>, Locales = Locale>(
  loader: (locale: Locales) => Messages | Promise<Messages>
): (locale: Locales) => Messages | Promise<Messages>

Parameters

loader

A function that is the dynamic locale messages loading, that has the following parameters:

  • locale
    Type: Locale
    A target locale that is passed from nuxt i18n module. That is passed when the locale is switched in the following cases:
    • when you switch the locale with setLocale().
    • when the locale is switched with <NuxtLink>. for example, the route path resolved by useSwitchLocalePath() or $switchLocalePath().

Usage

An example of a loader function using a fetch request to load locale messages:

export default defineI18nLocale(locale => {
  return $fetch(`https://your-company-product/api/${locale}`)
})

Where the loader runs

A loader runs on the server as well as in the browser. In a production build the server runs it outside the Nuxt app - that is what lets its messages be served from the messages endpoint - so it can only use APIs that exist in both places, such as $fetch() and useRuntimeConfig(). Nitro-only APIs (the h3 utilities, useStorage()) are not available in the browser, or in development where loaders always run in the Nuxt app.

Nuxt app composables (useNuxtApp(), useState(), useCookie(), useRequestHeaders(), ...) are the exception: a locale file calling one keeps its loader inside the Nuxt app instead, and is loaded there on both server and client. That is decided at build time, by reading the calls the locale file makes itself. A composable reached through an imported helper is not visible, and fails when the server loads that locale - call it in the locale file to make it detectable.

i18n/locales/en.ts
export default defineI18nLocale(async locale => {
  // loaded in the Nuxt app, not through the messages endpoint
  const { $tenant } = useNuxtApp()
  return $fetch(`/api/messages/${$tenant.id}/${locale}`)
})
Messages for such a locale are produced per request during SSR and again in the browser, and the locale file ships in the client bundle. A loader that reads server-only resources (a database, an internal service) must not use these composables - keep it loadable by the server.
Copyright © 2026