---
title: "Payload CMS locale 'all': Fetch every language in one query"
slug: "payload-locale-all-fetch-every-language"
published: "2026-03-17"
updated: "2026-04-06"
categories:
  - "Payload"
tags:
  - "payload cms locale all"
  - "generateStaticParams"
  - "multilingual sitemap generation"
  - "query localized slug payload"
  - "Payload CMS locale all bug"
  - "Next.js i18n"
  - "getPayload"
  - "fallbackLocale"
  - "static path generation"
  - "localized relationship null error"
llm-intent: "reference"
audience-level: "intermediate"
framework-versions:
  - "payload@2"
  - "next.js@15"
  - "typescript@5"
  - "next-intl@5"
status: "stable"
llm-purpose: "Payload CMS locale 'all' returns every locale in one query for static paths and sitemaps; avoid localized 'where' bugs—learn the correct patterns now."
llm-prereqs:
  - "Access to Payload CMS"
  - "Access to Next.js"
  - "Access to TypeScript"
  - "Access to getPayload"
  - "Access to next-intl"
llm-outputs:
  - "Completed outcome: Payload CMS locale 'all' returns every locale in one query for static paths and sitemaps; avoid localized 'where' bugs—learn the correct patterns now."
---

**Summary Triples**
- (payload.find with locale:'all', returns, localized fields as objects keyed by locale codes (e.g., title: { en: 'X', de: 'Y' }); non-localized fields remain normal values)
- (use-case, benefit, collapses N queries (one per locale) into a single query—ideal for generateStaticParams and multilingual sitemaps)
- (where clause + locale:'all', behavior, differs from single-locale queries — filtering on localized fields requires different patterns and can produce null/relationship errors if done incorrectly)
- (safe pattern, when filtering, filtering on non-localized fields works normally with locale:'all'; for localized fields target locale-specific keys (e.g., slug.en) or use per-locale queries)
- (common bug, symptom, localized 'where' misuse can lead to unexpected nulls (e.g., 'localized relationship null' errors) — debug by inspecting raw locale:'all' response shapes)
- (recommended workflow, steps, query once with locale:'all', iterate localized field objects to build per-locale paths or sitemap entries; if filtering first, either use locale-specific where paths or run per-locale queries)

### {GOAL}
Payload CMS locale 'all' returns every locale in one query for static paths and sitemaps; avoid localized 'where' bugs—learn the correct patterns now.

### {PREREQS}
- Access to Payload CMS
- Access to Next.js
- Access to TypeScript
- Access to getPayload
- Access to next-intl

### {STEPS}
1. Understand locale 'all' response shape
2. Identify ideal use cases
3. Avoid filtering localized fields with 'all'
4. Query by specific locale for slugs
5. Generate multilingual sitemap entries
6. Mitigate null localized relationship errors

<!-- llm:goal="Payload CMS locale 'all' returns every locale in one query for static paths and sitemaps; avoid localized 'where' bugs—learn the correct patterns now." -->
<!-- llm:prereq="Access to Payload CMS" -->
<!-- llm:prereq="Access to Next.js" -->
<!-- llm:prereq="Access to TypeScript" -->
<!-- llm:prereq="Access to getPayload" -->
<!-- llm:prereq="Access to next-intl" -->
<!-- llm:output="Completed outcome: Payload CMS locale 'all' returns every locale in one query for static paths and sitemaps; avoid localized 'where' bugs—learn the correct patterns now." -->

# Payload CMS locale 'all': Fetch every language in one query
> Payload CMS locale 'all' returns every locale in one query for static paths and sitemaps; avoid localized 'where' bugs—learn the correct patterns now.
Matija Žiberna · 2026-03-17

Most Payload CMS localization tutorials show you how to fetch content in a single locale: pass `locale: 'en'` to `payload.find()`, get English back. Pass `locale: 'de'`, get German. Simple enough.

But there's a less documented parameter that changes the query entirely: `locale: 'all'`. Instead of returning content in one language, it returns every locale's data in a single request — fields come back as objects keyed by locale rather than single translated values.

This matters most in two situations: building static paths for CMS-driven pages at build time, and generating sitemaps that need every language variant of every URL. In both cases, the naive approach is N queries per locale. `locale: 'all'` collapses that into one.

There's a catch, though. The parameter works differently depending on whether you combine it with a `where` clause — and getting that wrong leads to a bug that's hard to diagnose. This guide covers both cases with confirmed patterns from the Payload community.

## What `locale: 'all'` Actually Returns

When you pass a specific locale to `payload.find()`, localized fields return as plain values:

```typescript
// locale: 'en' — field returns a string
{
  id: '123',
  title: 'Our Services',
  slug: 'services',
}
```

When you pass `locale: 'all'`, localized fields return as objects keyed by locale code. Non-localized fields return as normal values:

```typescript
// locale: 'all' — localized fields return as keyed objects
{
  id: '123',          // non-localized — returns as normal value
  title: {            // localized: true — returns as keyed object
    en: 'Our Services',
    de: 'Unsere Leistungen',
    sl: 'Naše storitve',
  },
  slug: {             // localized: true — returns as keyed object
    en: 'services',
    de: 'leistungen',
    sl: 'storitve',
  },
  price: 499,         // non-localized — returns as normal value
}
```

This is confirmed in the Payload docs: *"The response will be structured so that field values come back as the full objects keyed for each locale instead of the single, translated value."*

The same parameter works in the REST API as `?locale=all` or `?locale=*`:

```bash
curl "https://localhost:3000/api/services?locale=all&limit=100"
```

## When to Use It: Simple Collection Fetching

`locale: 'all'` works cleanly when you're fetching documents without filtering on a localized field. The most common use case is pulling all documents from a collection to extract slugs for static generation or sitemap building.

```typescript
// File: src/lib/payload/getAllServices.ts
import { getPayload } from 'payload'
import config from '@payload-config'

export async function getAllServicesAllLocales() {
  const payload = await getPayload({ config })

  const result = await payload.find({
    collection: 'services',
    locale: 'all',
    draft: false,
    limit: 1000,
    pagination: false,
  })

  return result.docs
}
```

Each document comes back with localized fields as keyed objects. You then loop over your locales to extract the values you need:

```typescript
// File: src/app/[locale]/services/[slug]/page.tsx
import { routing } from '@/i18n/routing'
import { getAllServicesAllLocales } from '@/lib/payload/getAllServices'

export async function generateStaticParams() {
  const services = await getAllServicesAllLocales()

  const params: { locale: string; slug: string }[] = []

  for (const service of services) {
    // slug is a localized field — comes back as { en: '...', de: '...', sl: '...' }
    const slugField = service.slug as Record<string, string> | undefined

    if (!slugField) continue

    for (const locale of routing.locales) {
      const slug = slugField[locale]
      if (slug) {
        params.push({ locale, slug })
      }
    }
  }

  return params
}
```

One query, every locale, every slug. At build time this means Next.js has everything it needs to pre-render `/en/services/services`, `/de/services/leistungen`, and `/sl/services/storitve` without any additional API calls.

## When NOT to Use It: Filtering on a Localized Field

Here's where developers get burned. If you try to combine `locale: 'all'` with a `where` clause that filters on a localized field — like finding a document by its slug — the results are unreliable.

Issue #11212 in the Payload repository exists specifically because of this. The problem is that `locale: 'all'` changes the internal structure of fields, and `where` queries on those fields behave inconsistently when the field is stored as a locale-keyed object rather than a plain value.

Do not do this:

```typescript
// ⚠️ Unreliable — where on a localized field with locale: 'all'
const result = await payload.find({
  collection: 'services',
  locale: 'all',
  where: {
    slug: { equals: 'leistungen' }, // localized field — unreliable with locale: 'all'
  },
})
```

The confirmed working pattern from the Payload community for querying by localized slug is to use a specific locale per query, not `locale: 'all'`.

## The Correct Pattern: Querying by Localized Slug

When you need to find a document by its slug in a specific locale — which is what every `[slug]/page.tsx` does at request time — query with the exact locale, not `'all'`:

```typescript
// File: src/lib/payload/getServiceBySlug.ts
import { getPayload } from 'payload'
import config from '@payload-config'
import type { Locale } from '@/i18n/routing'

export async function getServiceBySlug(slug: string, locale: Locale) {
  const payload = await getPayload({ config })

  const result = await payload.find({
    collection: 'services',
    locale,               // specific locale — reliable with where clause
    fallbackLocale: 'en',
    draft: false,
    limit: 1,
    where: {
      slug: { equals: slug },
    },
  })

  return result.docs[0] ?? null
}
```

```typescript
// File: src/app/[locale]/services/[slug]/page.tsx
import { setRequestLocale } from 'next-intl/server'
import { getServiceBySlug } from '@/lib/payload/getServiceBySlug'
import { notFound } from 'next/navigation'
import type { Locale } from '@/i18n/routing'

export default async function ServicePage({
  params,
}: {
  params: Promise<{ locale: Locale; slug: string }>
}) {
  const { locale, slug } = await params

  setRequestLocale(locale)

  const service = await getServiceBySlug(slug, locale)

  if (!service) {
    notFound()
  }

  return (
    <article>
      <h1>{service.title}</h1>
    </article>
  )
}
```

The split is clean: `locale: 'all'` in `generateStaticParams` to build the path list at build time, specific locale in the page component to fetch the actual document at render time.

## Sitemap Generation

The other place `locale: 'all'` earns its keep is sitemap generation. A multilingual sitemap needs every URL variant for every document — and doing that with per-locale queries multiplies your API calls by the number of locales you support.

```typescript
// File: src/app/sitemap.ts
import { getPayload } from 'payload'
import config from '@payload-config'
import { routing } from '@/i18n/routing'
import type { MetadataRoute } from 'next'

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const payload = await getPayload({ config })
  const baseUrl = process.env.NEXT_PUBLIC_SERVER_URL!

  const services = await payload.find({
    collection: 'services',
    locale: 'all',
    draft: false,
    limit: 1000,
    pagination: false,
  })

  const entries: MetadataRoute.Sitemap = []

  for (const service of services.docs) {
    const slugField = service.slug as Record<string, string> | undefined

    if (!slugField) continue

    for (const locale of routing.locales) {
      const slug = slugField[locale]
      if (!slug) continue

      entries.push({
        url: `${baseUrl}/${locale}/services/${slug}`,
        lastModified: service.updatedAt,
        alternates: {
          languages: Object.fromEntries(
            routing.locales
              .filter((l) => slugField[l])
              .map((l) => [l, `${baseUrl}/${l}/services/${slugField[l]}`])
          ),
        },
      })
    }
  }

  return entries
}
```

One query for all services, all locales, all slug variants. The `alternates.languages` object gives search engines the hreflang data they need to understand the relationship between language versions.

## Known Bug: Null Localized Relationships

One active issue worth knowing about before shipping to production: if a localized relationship field has been removed from a document and left null in the database, querying with `locale: 'all'` throws a 500 error in Payload 3.28.

The error is:
```
Cannot read properties of null (reading 'relationTo')
```

This was reported in issue #11864 against both the REST and Local APIs. If your collections have relationship fields marked as `localized: true`, audit them for null values before relying on `locale: 'all'` in production. Either ensure the field always has a value, or add error handling around the query until the fix lands.

## The Pattern in Summary

Use `locale: 'all'` when:
- Fetching a collection without filtering on localized fields
- Building static paths in `generateStaticParams`
- Generating sitemaps that need all URL variants

Use a specific locale when:
- Querying with `where` on a localized field like `slug`
- Rendering page content at request time
- Any situation where you need reliable filtering on translated values

The two patterns work together: `locale: 'all'` at build time to enumerate paths, specific locale at render time to fetch the right content. Keep them in separate functions and the distinction stays clear.

Let me know in the comments if you run into edge cases with this — particularly around relationship fields and `locale: 'all'`, which seems to be where most of the rough edges are. Subscribe for more practical development guides.

Thanks, Matija

## LLM Response Snippet
```json
{
  "goal": "Payload CMS locale 'all' returns every locale in one query for static paths and sitemaps; avoid localized 'where' bugs—learn the correct patterns now.",
  "responses": [
    {
      "question": "What does the article \"Payload CMS locale 'all': Fetch every language in one query\" cover?",
      "answer": "Payload CMS locale 'all' returns every locale in one query for static paths and sitemaps; avoid localized 'where' bugs—learn the correct patterns now."
    }
  ]
}
```