payloadcms / payloadcms/payload

Duplicate Selected Locales: content is empty when the admin active locale is not among the selected locales (remaining case after #15849)

Open
#17,562 3 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

(Select all that apply) area: localization area: localization
Dominant language
TypeScript
Stars
44.8k
Forks
4.2k
Avg merge
2d 21h
Merged PRs (30d)
53

Description

Describe the Bug

Follow-up to #15847 / #15849 (fixed in v3.83.0) and #15655. Those fixed the filtering so localized block content is no longer dropped. A related case remains on v3.86.0:

"Duplicate Selected Locales" produces a document with empty localized content whenever the admin's active locale is NOT one of the selected locales.

Root cause

In packages/payload/src/duplicateDocument/index.ts (getDuplicateDocumentData), the source doc is first correctly narrowed to the selected locales:

duplicatedFromDocWithLocales = filterDataToSelectedLocales({
  configBlockReferences: payload.config.blocks,
  docWithLocales: duplicatedFromDocWithLocales,
  fields: collectionConfig.fields,
  selectedLocales,
})

I verified this step is correct now — for selectedLocales: ['en'] it preserves content: { en: [...] } with all inner block values intact.

The problem is the next step, which resolves that already-filtered doc back to a single locale:

const duplicatedFromDoc = await afterRead({
  ...
  doc: deepCopyObjectSimple(duplicatedFromDocWithLocales),
  locale: req.locale,       // the admin's ACTIVE locale
  fallbackLocale: null,     // hardcoded — ignores the configured fallback
  ...
})

When req.locale (the admin's active locale) is not in selectedLocales, the with-locales doc no longer contains req.locale (it was just filtered out), and with fallbackLocale: null there is no fallback — so every localized field resolves to empty. The new document is created with empty content.

This is independent of field type; it affects any localized field and is fully determined by whether req.locale ∈ selectedLocales.

Link to the code that reproduces this issue

Same setup as #15847 — https://github.com/jakobpevec/payload-issue-repro — with one added step: change the admin's active locale to a locale you do not select.

Reproduction Steps

Collection with a localized blocks (or richText) field and ≥2 locales (e.g. en, de), and a document with content in both.

  1. Open the document.
  2. In the admin, switch the active locale (top-right locale selector) to de.
  3. Open Duplicate → Duplicate Selected Locales and select only en.
  4. Duplicate.

Actual: the duplicated document's localized content is empty.
Expected: the duplicated document contains the en content.

Control (proves the rule): with the active locale set to en (active locale ∈ selected), the same steps copy the content correctly. Verified across a full matrix — content is preserved iff the active locale is one of the selected locales:

active locale selected content copied
en [en]
de [en] ❌ empty
de [de]
en [de] ❌ empty
en [en, de]
de [en, de]
fr [en, de] ❌ empty
Suggested fix

Resolve afterRead with a locale guaranteed to survive the filter — e.g. use req.locale when it is in selectedLocales, otherwise the first selected locale — and/or honor the configured fallback instead of hardcoding fallbackLocale: null.

Which area(s) are affected? (Select all that apply)

area: localization, area: admin

Environment Info
  • Payload version: 3.86.0
  • Database adapter: @payloadcms/db-postgres
  • Node.js: 22

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in packages/payload/src/duplicateDocument/index.ts at getDuplicateDocumentData and trace the filterDataToSelectedLocales and afterRead calls. Reproduce the issue with the linked setup by selecting only en while the active locale is de; done means Duplicate Selected Locales preserves the selected locale's localized content regardless of the active locale.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend-api-design, localization
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.