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:
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:
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
{
"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" }
]
}
| Field | What it carries |
|---|---|
version | Schema version. The CLI accepts 1 and ignores anything else. |
generator | The package and version that wrote the file, echoed in the CLI's log line. |
appDir | The app's root directory. |
defaultLocale | i18n.defaultLocale, or en when the block sets none. |
fallbackLocale | Exactly 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. |
localeFileFormat | json. The only format the module publishes. |
locales | One entry per locale, each with code, language, file and an optional name. |
layers | Every 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,languageandfileare published per entry, so a locale reference resolves without knowing@nuxtjs/i18n's field names. Entries missing acodeor afileare dropped, and duplicates bycodeare 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.
localeDiris reported only when the resolved directory exists and contains at least one.jsonfile; 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
rootDirrelative 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, noprotectedLocales, noorphanScan. Those live ini18n-kit.config.tsor.i18n-mcp.jsonand 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 module | With the module, artifact present | |
|---|---|---|
| Layer graph and locale table | Resolved by calling loadNuxt from the project's own @nuxt/kit | Read from .nuxt/i18n-kit.json |
@nuxt/kit installed | Required | Not needed for that app |
A nuxt.config.ts that needs environment variables | Has to evaluate | Not evaluated |
| Adapter chosen | Nuxt, by detection | Nuxt, by the same detection — the artifact is read inside that adapter |
| Layer names | Derived by the CLI | Derived by the CLI, identically |
| Kit policy | Read from your config file | Read from your config file |
Locale list narrowed by locales in your config | Yes | Rejected 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.