payloadcms / payloadcms/payload
bug: plugin-ecommerce overwrites user i18n overrides in plugin-ecommerce namespace
@paulpopus is already working on this.
Since May 6, 2026.
- Dominant language
- TypeScript
- Stars
- 44.8k
- Forks
- 4.2k
- Avg merge
- 2d 21h
- Merged PRs (30d)
- 53
Description
Describe the Bug
When a user supplies translations for the plugin-ecommerce namespace via Payload's top-level i18n.translations config (e.g. to localise a label like cart), the ecommerce plugin silently discards them at config-build time.
The plugin first deep-merges the user's translations into the plugin defaults (good), but then immediately overwrites the entire plugin-ecommerce namespace per locale with only its own defaults (bad), losing every user override.
In node_modules/@payloadcms/plugin-ecommerce/dist/index.js (v3.84.1), lines 208 and 214–230:
// line 208 — first this is fine: user overrides survive deepMerge
incomingConfig.i18n.translations = deepMergeSimple(translations, incomingConfig.i18n?.translations);
// lines 214-230 — then this loop wipes them out
Object.entries(translations).forEach(([locale, pluginI18nObject]) => {
const typedLocale = locale;
if (!incomingConfig.i18n.translations) {
incomingConfig.i18n.translations = {};
}
if (!(typedLocale in incomingConfig.i18n.translations)) {
incomingConfig.i18n.translations[typedLocale] = {};
}
if (!('plugin-ecommerce' in incomingConfig.i18n.translations[typedLocale])) {
incomingConfig.i18n.translations[typedLocale]['plugin-ecommerce'] = {};
}
// wholesale assignment — discards anything merged in above
incomingConfig.i18n.translations[typedLocale]['plugin-ecommerce'] = {
...pluginI18nObject.translations['plugin-ecommerce'],
};
});
The result is that incomingConfig.i18n.translations[locale]['plugin-ecommerce'] always equals the plugin's bundled defaults, regardless of what the user passed in.
Plugin source on GitHub: https://github.com/payloadcms/payload/blob/main/packages/plugin-ecommerce/src/index.ts (the equivalent of dist/index.js:227-229 in the published 3.84.1 build).
Suggested Fix
Replace the wholesale assignment with a merge that lets user overrides win, e.g.:
incomingConfig.i18n.translations[typedLocale]['plugin-ecommerce'] = {
...pluginI18nObject.translations['plugin-ecommerce'],
...incomingConfig.i18n.translations[typedLocale]['plugin-ecommerce'],
};
…or simply remove the second loop entirely, since the deepMergeSimple call on line 208 already correctly merges plugin defaults with user overrides (with user overrides winning).
Link to the code that reproduces this issue
https://github.com/jhb-dev/payload-ecommerce-i18n-overwrite
Reproduction Steps
- Clone the reproduction repository and run the development server.
- The reproduction's
payload.config.tspasses a top-leveli18nwithtranslations.de['plugin-ecommerce'].cart = 'MEIN KORB (user override)'. - The
onInithook reads backpayload.config.i18n.translations.de['plugin-ecommerce'].cartand logs the resolved value. - Hit any API route to trigger initialisation:
curl http://localhost:3000/api/users. - Expected: the log prints
MEIN KORB (user override). - Actual: the log prints
Warenkorb(the plugin default), proving the user override was overwritten.
Captured server output:
[i18n-repro] de.plugin-ecommerce.cart resolved to: "Warenkorb"
[i18n-repro] expected: "MEIN KORB (user override)"
[i18n-repro] BUG REPRODUCED — user i18n override for plugin-ecommerce was overwritten by plugin defaults
Which area(s) are affected?
plugin: ecommerce
Environment Info
Binaries:
Node: 24.3.0
npm: 11.4.2
pnpm: 10.33.0
Relevant Packages:
payload: 3.84.1
next: 15.4.11
@payloadcms/db-mongodb: 3.84.1
@payloadcms/plugin-ecommerce: 3.84.1
@payloadcms/translations: 3.84.1
react: 19.2.1
react-dom: 19.2.1
Operating System:
Platform: darwin
Arch: arm64
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.
Assessment
This issue has not been assessed yet.