Nuxt Module

What It Publishes

During a Nuxt build, @the-i18n-kit/nuxt writes the layer graph and the locale table Nuxt resolved to .nuxt/i18n-kit.json, and the CLI reads them from there.

The Configuration It Replaces

Without the module, the CLI resolves your layer graph and locale table by loading your app through Nuxt, which needs @nuxt/kit installed and a nuxt.config.ts that evaluates with the environment the CLI happens to have. Where that is impractical — a CI job with no build secrets, a container with only the repository mounted — the way out has been to declare localeDirs and defaultLocale yourself:

i18n-kit.config.ts
import { defineI18nKitConfig } from '@the-i18n-kit/cli/config'

export default defineI18nKitConfig({
  defaultLocale: 'en',
  localeDirs: [
    { path: 'apps/admin/i18n/locales', layer: 'admin' },
    { path: 'layers/dashboard/i18n/locales', layer: 'dashboard' },
    { path: 'layers/booking/i18n/locales', layer: 'booking' },
    { path: 'packages/ui/i18n/locales', layer: 'ui' },
  ],
})

That is a second description of your layer graph, maintained by hand, and declaring both keys moves the project onto the generic adapter, so Nuxt's own resolution stops being consulted at all. A layer added to nuxt.config.ts and not to this list is then invisible: its keys are scanned against no source, which surfaces as orphan keys rather than as an error.

With the module, the same project declares neither key:

i18n-kit.config.ts
import { defineI18nKitConfig } from '@the-i18n-kit/cli/config'

export default defineI18nKitConfig({
  context: 'A B2B booking platform.',
  protectedLocales: ['de-formal'],
})

What is left is policy — the things the tool cannot see for itself. The layer graph and the locale table come from the build, which is where they were resolved. See Declared vs. Derived Configuration for the general form of this split, and the configuration field reference for the fields themselves.

What Is in the File

.nuxt/i18n-kit.json
{
  "version": 1,
  "generator": "@the-i18n-kit/nuxt@0.1.4",
  "appDir": "/repo/apps/admin",
  "defaultLocale": "en",
  "fallbackLocale": "en",
  "localeFileFormat": "json",
  "locales": [
    { "code": "en", "language": "en-US", "file": "en.json", "name": "English" },
    { "code": "de-formal", "language": "de-DE", "file": "de-formal.json" }
  ],
  "layers": [
    { "rootDir": "/repo/apps/admin", "localeDir": "/repo/apps/admin/i18n/locales" },
    { "rootDir": "/repo/layers/dashboard" },
    { "rootDir": "/repo/packages/ui", "localeDir": "/repo/packages/ui/i18n/locales" }
  ]
}
FieldWhat it carries
versionSchema version. The CLI accepts 1 and ignores anything else.
generatorThe package and version that wrote the file, echoed in the CLI's log line.
appDirThe app's root directory.
defaultLocalei18n.defaultLocale, or en when the block sets none.
fallbackLocaleExactly as Nuxt resolved it — a string, an array, a per-locale map, or null. The CLI normalizes it, so one implementation serves both this path and the fallback path.
localeFileFormatjson. The only format the module publishes.
localesOne entry per locale, each with code, language, file and an optional name.
layersEvery layer Nuxt resolved, in Nuxt's order, each with its rootDir and — when it has one — its localeDir.

Three details are worth stating outright:

  • Locales carry all three reference forms. code, language and file are published per entry, so a locale reference resolves without knowing @nuxtjs/i18n's field names. Entries missing a code or a file are dropped, and duplicates by code are removed.
  • Layer order is precedence, not alphabetical. The app's own layer comes first, then what it extends, in the order Nuxt resolved.
  • Layers without translations stay in the list. localeDir is reported only when the resolved directory exists and contains at least one .json file; a layer that carries source code but no translations keeps its entry without one, so it is still scanned for key usage.

localeDir is resolved per layer as <rootDir>/<restructureDir>/<langDir>, honoring a layer's own i18n block where it sets one, and defaulting to i18n and locales — the same resolution the Nuxt adapter performs from outside.

What the Artifact Does Not Contain

  • Layer names. The CLI derives them from each rootDir relative to the directory it was pointed at, so a layer's name depends on where you run the CLI from, not on which app published the artifact.
  • Kit policy. No glossary, no context, no protectedLocales, no orphanScan. Those live in i18n-kit.config.ts or .i18n-mcp.json and are read directly from disk, so they apply before anything has been built.

What Changes for the CLI

The module changes where the facts come from, not what the kit does with them.

Without the moduleWith the module, artifact present
Layer graph and locale tableResolved by calling loadNuxt from the project's own @nuxt/kitRead from .nuxt/i18n-kit.json
@nuxt/kit installedRequiredNot needed for that app
A nuxt.config.ts that needs environment variablesHas to evaluateNot evaluated
Adapter chosenNuxt, by detectionNuxt, by the same detection — the artifact is read inside that adapter
Layer namesDerived by the CLIDerived by the CLI, identically
Kit policyRead from your config fileRead from your config file
Locale list narrowed by locales in your configYesRejected at build time; narrow with the Nuxt config instead

Installing the module does not move a project between adapters: the Nuxt adapter is chosen by looking for a nuxt.config, not by looking for the artifact.

Every reason the artifact is not used — absent, unparseable, an unknown shape, older than a nuxt.config it describes, or describing no locale directory at all — falls back to loading the app, with a warning where there is something to say. Limits lists each case.

Copyright © 2026