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:

SettingValue
Localesen (en-US, en-us.json) and zh (zh-CN, zh-cn.json)
Message directoryapp/i18n/locales/
Default localeen
Strategyprefix_except_default
Browser detectionDisabled

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.

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:

CollectionSource
docs_en / docs_zhcontent/en/docs/** / content/zh/docs/**
blog_en / blog_zhcontent/en/blog/** / content/zh/blog/**
legal_en / legal_zhcontent/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.

On this page