- Payload localizeStatus: Per-Locale Draft Publishing Guide
Payload localizeStatus: Per-Locale Draft Publishing Guide
Setup, queries, and known bugs for per-locale publishing with Payload localizeStatus (v3.72+); practical workflow tips.

Moving to Next.js and Payload CMS? I offer advisory support on an hourly basis.
Book Hourly AdvisorylocalizeStatusOne of the most common requests I get from agency clients running multilingual sites is simple to explain but surprisingly hard to implement: "Can we launch the English site now and keep the German version in draft until we finish the translations?"
Before Payload v3.72.0, the answer involved workarounds — separate collections, custom status fields, or shipping incomplete content behind feature flags. As of January 2026, Payload has a native solution: localizeStatus. It lets you manage publication status independently per locale, so publishing English doesn't force German live, and unpublishing one language doesn't take down the others.
It's currently marked as experimental and beta, which means it works but you should test thoroughly before relying on it in production. This guide covers the setup, how it changes your data shape, how to query correctly with it enabled, and the known bugs worth knowing about before you ship.
localizeStatus EnabledWithout localizeStatus, a document's _status field is a single string representing one status across all locales:
// Default behavior — one status for all locales
{
id: '123',
title: 'Our Services',
_status: 'published',
}
With localizeStatus enabled, _status becomes an object keyed by locale — each language tracks its own publication state independently:
// With localizeStatus — status per locale
{
id: '123',
title: {
en: 'Our Services',
de: 'Unsere Leistungen',
sl: 'Naše storitve',
},
_status: {
en: 'published',
de: 'draft',
sl: 'published',
},
}
In the admin UI, the status indicator changes based on which locale the editor is currently viewing. Editors can publish, unpublish, or save as draft for just the locale they're working in without touching the others.
Enabling localizeStatus requires changes in two places. Missing either one means it won't work.
First, enable the experimental flag at the top-level Payload config:
// File: payload.config.ts
import { buildConfig } from 'payload'
export default buildConfig({
experimental: {
localizeStatus: true,
},
localization: {
locales: [
{ label: 'English', code: 'en' },
{ label: 'Deutsch', code: 'de' },
{ label: 'Slovenščina', code: 'sl' },
],
defaultLocale: 'en',
fallback: true,
},
// ... rest of config
})
Second, enable it per collection (or global) that needs per-locale status management:
// File: src/collections/Pages/index.ts
import type { CollectionConfig } from 'payload'
export const Pages: CollectionConfig = {
slug: 'pages',
versions: {
drafts: {
localizeStatus: true,
},
},
fields: [
{
name: 'title',
type: 'text',
localized: true,
},
{
name: 'content',
type: 'richText',
localized: true,
},
{
name: 'slug',
type: 'text',
localized: true,
},
],
}
Not every collection needs localizeStatus. Enable it only on collections where independent per-locale publishing is actually required. A settings collection shared across all languages probably doesn't need it. A pages collection where each market manages its own content does.
With localizeStatus enabled, the standard pattern for fetching published content combines locale with a _status filter. The Payload REST API docs show this pattern explicitly:
// File: src/lib/payload/getPages.ts
import { getPayload } from 'payload'
import config from '@payload-config'
import type { Locale } from '@/i18n/routing'
export async function getPublishedPages(locale: Locale) {
const payload = await getPayload({ config })
const result = await payload.find({
collection: 'pages',
locale,
fallbackLocale: 'en',
where: {
_status: { equals: 'published' },
},
})
return result.docs
}
Pass the locale from next-intl's routing and filter on _status: 'published' — Payload resolves the status check against the locale-specific status value. A German editor who has saved a page as draft won't surface it in the German frontend, while the English version of the same document remains live.
For draft preview mode, where you want editors to see unpublished content:
// File: src/lib/payload/getPageBySlug.ts
import { getPayload } from 'payload'
import config from '@payload-config'
import { draftMode } from 'next/headers'
import type { Locale } from '@/i18n/routing'
export async function getPageBySlug(slug: string, locale: Locale) {
const { isEnabled: isDraft } = await draftMode()
const payload = await getPayload({ config })
const result = await payload.find({
collection: 'pages',
locale,
fallbackLocale: 'en',
draft: isDraft,
limit: 1,
where: {
slug: { equals: slug },
...(!isDraft && { _status: { equals: 'published' } }),
},
})
return result.docs[0] ?? null
}
When draft mode is active, the _status filter is omitted so editors can preview unpublished content. In normal rendering, only published content surfaces.
The practical flow for a client launching English first and German second looks like this in Payload's admin:
The content team creates pages in English, fills in all the English fields, and publishes them locale by locale — each publish action affects only the currently selected locale. German fields exist in the document but remain in draft. The English frontend goes live. German editors then work through translations at their own pace, publishing German locale by locale as translations complete, without any risk of accidentally taking down English content or publishing incomplete German pages.
The admin UI handles this by always showing the status of the currently selected locale. An editor working in German who opens a page sees "Draft" even if the English version is published. When they're ready, they publish just the German locale.
localizeStatus was introduced as experimental in v3.72.0 and there are active bugs worth knowing about before committing it to a production project.
SQL error with join fields (issue #15248)
If your collection has a join field and you query with draft: true and a locale parameter, Payload generates an invalid SQL query on PostgreSQL:
invalid reference to FROM-clause entry for table '_r_v'
If you hit this, the reported workarounds are removing localizeStatus: true temporarily, or checking whether a defaultSort on a related collection is involved. This is an active open issue.
Unnamed group fields lose data on localized publish (issue #15642)
If your collection has a group field without a name property, any fields inside that group lose their data when you publish a single locale. This affects both localized and non-localized fields inside the unnamed group. A fix was committed (38b8c68) in a subsequent release — check that you're on a version after v3.76.1 where this was reported.
Unpublish dropdown visible without localizeStatus (issue #15291)
A minor UI issue: the "Unpublish in [locale]" dropdown button appears even when localizeStatus is not enabled on the collection. The Payload team acknowledged it and noted a design solution is coming. It's cosmetic and doesn't affect data, but worth flagging to clients who might be confused by it.
The honest answer is: carefully. The Payload docs themselves say to test thoroughly before using in production, and the active bugs above are real. If your project is on PostgreSQL with join fields, hold off until issue #15248 is resolved. If you're on MongoDB or your collections don't use join fields, the feature works well for its core purpose.
For new projects starting now, it's worth building with localizeStatus in mind even if you don't enable it immediately — making your fields localized: true from the start means you can turn on localizeStatus later without a migration.
The underlying workflow it enables — independent publication status per locale — is genuinely useful for agency work and something clients ask for. Worth keeping an eye on as it moves from experimental toward stable.
Let me know in the comments if you've hit other edge cases with localizeStatus in your projects. Subscribe for more practical development guides.
Thanks, Matija
Detailed Payload guides with field configuration examples, custom components, and workflow optimization tips to speed up your CMS development process.