Internationalization
Multi-language support with @nuxtjs/i18n in the Nuxt template.
Internationalization is Integrated with @nuxtjs/i18n. The template ships
English and Chinese application messages, locale-aware navigation, and separate
Nuxt Content collections for each language.
Configuration
app/config/i18n.nuxt.config.ts is passed to the i18n block in
nuxt.config.ts:
| Setting | Value |
|---|---|
| Locales | en (en-US, en-us.json) and zh (zh-CN, zh-cn.json) |
| Message directory | app/i18n/locales/ |
| Default locale | en |
| Strategy | prefix_except_default |
| Browser detection | Disabled |
With prefix_except_default, English uses /docs and /blog; Chinese uses
/zh/docs and /zh/blog. Browser-language redirects are disabled, so a URL is
stable and explicit.
Application messages and links
Use useI18n() for reactive locale state and translations:
<script setup lang="ts">
const { t, locale } = useI18n()
</script>
<template>
<h1>{{ t("home.hero.title") }}</h1>
<span>{{ locale }}</span>
</template>Use NuxtLinkLocale in templates and useLocalePath() in script or middleware.
They retain the active prefix when users move between pages:
<NuxtLinkLocale to="/dashboard">{{ $t("nav.dashboard") }}</NuxtLinkLocale>Avoid hardcoding /zh or stripping it with a plain URL concatenation.
Content localization
Nuxt Content uses independent collections, not slug.zh.md pairs:
| Collection | Source |
|---|---|
docs_en / docs_zh | content/en/docs/** / content/zh/docs/** |
blog_en / blog_zh | content/en/blog/** / content/zh/blog/** |
legal_en / legal_zh | content/en/legal/** / content/zh/legal/** |
The collection selection happens in the docs/blog composables and pages. Keep
matching paths across locale directories when the same article exists in both.
Documentation navigation remains manual in docs-sidebar-config.ts.
Add a locale
Register it
Add the locale code, language tag, display name, and message filename to the
locales array in app/config/i18n.nuxt.config.ts.
Add application messages
Create the matching JSON file under app/i18n/locales/. Preserve the same key
shape as en-us.json so shared components do not fall back to raw keys.
Extend locale-keyed server code
Add the message import to messagesMap in server/email/index.ts. Search for
other explicit locale maps before considering the locale complete.
Add localized content
Create the locale's docs/blog/legal directories, add collections in
content.config.ts, select them in the content composables, and update language
switching and manual docs navigation as needed.
Verify
- Default-English URLs have no prefix; Chinese URLs use
/zh. - Header, footer, auth, forms, and validation copy switch language.
- Internal links preserve the active locale.
- Docs, blog, and legal pages query the intended collection.
- Contact email renders with the requested locale; Better Auth mail is explicitly passed a locale if bilingual auth email is required.
- Missing translation keys and locale-specific 404s are absent from logs.
