Atlas CMS
Use Cases

Multi-Language

Build a localized website that serves content in multiple languages using Next.js i18n routing and the Atlas CMS locale parameter.

Multi-Language Site

Atlas CMS supports field-level localization out of the box. You can request translated content simply by appending ?locale=fr to your API calls. Atlas will merge the translations over your default locale, ensuring that untranslated fields gracefully fall back.

In this guide, we'll implement a localized Next.js app using App Router's [locale] dynamic segment.

What We're Building

app/
  [locale]/
    layout.tsx    ← Wraps the app and provides the current locale
    page.tsx      ← Fetches localized homepage content

1. API Helper

We will add a locale parameter to our fetch functions.

lib/atlas.ts
const BASE = process.env.ATLAS_BASE_URL + '/api/v1/public'
const headers = { 'X-API-Key': process.env.ATLAS_API_KEY! }

export async function getLocalizedPage(slug: string, locale: string) {
  // Pass the locale as a query parameter
  const res = await fetch(`${BASE}/pages/${slug}?locale=${locale}`, {
    headers,
    next: { revalidate: 60 },
  })
  
  if (!res.ok) return null
  const { data } = await res.json()
  return data
}

2. Localized Route

Next.js allows you to capture the locale from the URL (e.g., /en, /fr, /id) using a dynamic folder name like [locale].

app/[locale]/page.tsx
import { notFound } from 'next/navigation'
import { getLocalizedPage } from '@/lib/atlas'

type Props = {
  params: Promise<{ locale: string }>
}

export default async function LocalizedHomePage({ params }: Props) {
  const { locale } = await params
  
  // Fetch the 'home' page translated into the active locale
  const pageData = await getLocalizedPage('home', locale)

  if (!pageData) notFound()

  const { seo } = pageData.page

  return (
    <main className="container py-20 text-center">
      <h1 className="text-5xl font-bold mb-4">{seo.title}</h1>
      <p className="text-xl text-gray-600">{seo.description}</p>
      
      {/* 
        You would typically pass pageData.blocks to a BlockRenderer here.
        Because you passed ?locale=, the block data will already be translated!
      */}
    </main>
  )
}

3. Language Switcher

To switch languages, build a component that updates the URL segment.

components/LanguageSwitcher.tsx
'use client'

import { usePathname, useRouter } from 'next/navigation'

export function LanguageSwitcher() {
  const router = useRouter()
  const pathname = usePathname() // e.g. "/en/about"

  const switchLanguage = (newLocale: string) => {
    // Replace the first path segment with the new locale
    const newPath = pathname.replace(/^\/[^\/]+/, `/${newLocale}`)
    router.push(newPath)
  }

  return (
    <select onChange={(e) => switchLanguage(e.target.value)} className="border p-1 rounded">
      <option value="en">English</option>
      <option value="fr">Français</option>
      <option value="id">Bahasa Indonesia</option>
    </select>
  )
}

Next Steps

  • Read the detailed Localization reference to understand how locale fallback behaves in the API.
  • Explore Next.js official internationalization (i18n) docs for advanced middleware setup.

On this page