Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/_redirects
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
/api/components/prose=/docs/components/prose
/api/configuration=/docs/getting-started/configuration
/recipes/hooks=/docs/advanced/hooks
/docs/advanced/llms=/docs/integrations/llms

# Content v2 redirects
/guide/writing/content-directory=https://v2.content.nuxt.com/usage/content-directory
Expand Down
2 changes: 2 additions & 0 deletions docs/content/docs/7.integrations/.navigation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
title: Examples & Integrations
icon: i-lucide-cloud-upload
164 changes: 164 additions & 0 deletions docs/content/docs/7.integrations/01.i18n.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
---
title: I18n module
description: Learn how to create multi-language websites using Nuxt Content with the @nuxtjs/i18n module.
---

Nuxt Content integrates with [`@nuxtjs/i18n`](https://i18n.nuxtjs.org/) to create multi-language websites. When both modules are configured together, you can organize content by language and automatically serve the correct content based on the user's locale.

## Setup

::prose-steps
### Install the required module

```bash [terminal]
npm install @nuxtjs/i18n
```

### Configure your `nuxt.config.ts`

```ts [nuxt.config.ts]
export default defineNuxtConfig({
modules: ['@nuxt/content', '@nuxtjs/i18n'],
i18n: {
locales: [
{ code: 'en', name: 'English', language: 'en-US', dir: 'ltr' },
{ code: 'fr', name: 'French', language: 'fr-FR' },
{ code: 'fa', name: 'Farsi', language: 'fa-IR', dir: 'rtl' },
],
strategy: 'prefix_except_default',
defaultLocale: 'en',
}
})
```

### Define collections for each language

Create separate collections for each language in your `content.config.ts`:

```ts [content.config.ts]
const commonSchema = ...;

export default defineContentConfig({
collections: {
// English content collection
content_en: defineCollection({
type: 'page',
source: {
include: 'en/**',
prefix: '',
},
schema: commonSchema,
}),
// French content collection
content_fr: defineCollection({
type: 'page',
source: {
include: 'fr/**',
prefix: '',
},
schema: commonSchema,
}),
// Farsi content collection
content_fa: defineCollection({
type: 'page',
source: {
include: 'fa/**',
prefix: '',
},
schema: commonSchema,
}),
},
})
```

### Create dynamic pages

Create a catch-all page that fetches content based on the current locale:

```vue [pages/\[...slug\].vue]
<script setup lang="ts">
import { withLeadingSlash } from 'ufo'
import type { Collections } from '@nuxt/content'

const route = useRoute()
const { locale, localeProperties } = useI18n()
const slug = computed(() => withLeadingSlash(String(route.params.slug)))

const { data: page } = await useAsyncData('page-' + slug.value, async () => {
// Build collection name based on current locale
const collection = ('content_' + locale.value) as keyof Collections
const content = await queryCollection(collection).path(slug.value).first()

// Optional: fallback to default locale if content is missing
if (!content && locale.value !== 'en') {
return await queryCollection('content_en').path(slug.value).first()
}

return content
}, {
watch: [locale], // Refetch when locale changes
})
</script>

<template>
<ContentRenderer v-if="page" :value="page" />
<div v-else>
<h1>Page not found</h1>
<p>This page doesn't exist in {{ locale }} language.</p>
</div>
</template>
```
::

That's it! πŸš€ Your multi-language content site is ready.

## Content Structure

Organize your content files in language-specific folders to match your collections:

```
content/
en/
index.md
about.md
blog/
post-1.md
fr/
index.md
about.md
blog/
post-1.md
fa/
index.md
about.md
```

Each language folder should contain the same structure to ensure content parity across locales.

## Fallback Strategy

You can implement a fallback strategy to show content from the default locale when content is missing in the current locale:

```ts [pages/\[...slug\].vue]
const { data: page } = await useAsyncData('page-' + slug.value, async () => {
const collection = ('content_' + locale.value) as keyof Collections
let content = await queryCollection(collection).path(slug.value).first()

// Fallback to default locale if content is missing
if (!content && locale.value !== 'en') {
content = await queryCollection('content_en').path(slug.value).first()
}

return content
})
```

::prose-warning
Make sure to handle missing content gracefully and provide clear feedback to users when content is not available in their preferred language.
::

## Complete Examples

You can see a complete working example:
- **Source**: https://github.com/nuxt/content/tree/main/examples/i18n
- **Live Demo**: https://content3-i18n.nuxt.dev/
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: LLMs Integration
title: LLMs module
description: Learn how to generate AI-ready content files using Nuxt Content and
the Nuxt LLMs module.
---
Expand Down