• Home
BuildWithMatija
Get In Touch
  1. Home
  2. Blog
  3. Payload
  4. 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.

16th March 2026·Updated on:2nd March 2026·MŽMatija Žiberna·
Payload
Payload localizeStatus: Per-Locale Draft Publishing Guide

Need Help Making the Switch?

Moving to Next.js and Payload CMS? I offer advisory support on an hourly basis.

Book Hourly Advisory

One 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.

What Changes With localizeStatus Enabled

Without 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.

Setup: Two Places, Both Required

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.

Querying Published Content Per Locale

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 Agency Workflow This Enables

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.

Known Bugs Before You Ship

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.

Is It Ready for Production?

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

📚 Comprehensive Payload CMS Guides

Detailed Payload guides with field configuration examples, custom components, and workflow optimization tips to speed up your CMS development process.

No spam. Unsubscribe anytime.

📄View markdown version
0

Frequently Asked Questions

Comments

Leave a Comment

Your email will not be published

Stay updated! Get our weekly digest with the latest learnings on NextJS, React, AI, and web development tips delivered straight to your inbox.

10-2000 characters

• Comments are automatically approved and will appear immediately

• Your name and email will be saved for future comments

• Be respectful and constructive in your feedback

• No spam, self-promotion, or off-topic content

Matija Žiberna
Matija Žiberna
Full-stack developer, co-founder

I'm Matija Žiberna, a self-taught full-stack developer and co-founder passionate about building products, writing clean code, and figuring out how to turn ideas into businesses. I write about web development with Next.js, lessons from entrepreneurship, and the journey of learning by doing. My goal is to provide value through code—whether it's through tools, content, or real-world software.

Table of Contents

  • What Changes With `localizeStatus` Enabled
  • Setup: Two Places, Both Required
  • Querying Published Content Per Locale
  • The Agency Workflow This Enables
  • Known Bugs Before You Ship
  • Is It Ready for Production?
On this page:
  • What Changes With `localizeStatus` Enabled
  • Setup: Two Places, Both Required
  • Querying Published Content Per Locale
  • The Agency Workflow This Enables
  • Known Bugs Before You Ship
Build With Matija Logo

Build with Matija

Matija Žiberna

I turn scattered business knowledge into one usable system. End-to-end system architecture, AI integration, and development.

Quick Links

Payload CMS Websites
  • Bespoke AI Applications
  • Projects
  • How I Work
  • Blog
  • Payload CMS

    • Migration
    • Pricing

    Get in Touch

    Have a project in mind? Let's discuss how we can help your business grow.

    Contact me →
    © 2026BuildWithMatija•Principal-led system architecture•All rights reserved