payloadcms / payloadcms/payload
Duplicate Selected Locales: content is empty when the admin active locale is not among the selected locales (remaining case after #15849)
Nobody has claimed this yet.
- 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.
- Open the document.
- In the admin, switch the active locale (top-right locale selector) to
de. - Open Duplicate → Duplicate Selected Locales and select only
en. - 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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