Bug Description
When using strapi-plugin-publisher with Strapi v5's i18n plugin, scheduled publish/unpublish actions are shared across all locales of the same document. Setting a publish timer on one locale (e.g., Japanese) causes the timer to appear on other locales (e.g., English) as well, preventing locale-specific scheduling.
Steps to Reproduce
- Enable i18n and publisher plugins on a content type
- Open an entry in locale A (e.g.,
ja) and set a publish timer
- Switch to locale B (e.g.,
en) of the same document
- Observe that the timer from locale A is displayed, and you cannot set a separate timer for locale B
Expected Behavior
Each locale should have independent publish/unpublish timers. Setting a timer on one locale should not affect other locales.
Root Cause Analysis
There are three issues:
1. locale attribute missing from action schema
The action content type schema does not include a locale field, so there is no way to store which locale a scheduled action belongs to.
2. Strapi v5 sanitizeQuery strips locale from attribute filters
Even if locale is added to the schema and passed as filters[locale]=ja from the frontend, Strapi v5's core controller sanitizeQuery treats locale as a system-level i18n parameter and removes it from the attribute filters. This means the default find controller ignores the locale filter entirely.
3. Frontend does not pass locale to the action query
The getAction() hook does not include locale in the filters passed to the API, nor in the React Query cache key. This means all locales share the same cached result.
Suggested Fix
- Add
locale to the action content type schema (type: 'string', required: false)
- Override
find in actionController to restore the locale filter after sanitizeQuery:
const actionController = factories.createCoreController('plugin::publisher.action', ({ strapi }) => ({
async find(ctx) {
const sanitizedQuery = await this.sanitizeQuery(ctx);
const { filters: rawFilters } = ctx.query || {};
if (rawFilters?.locale !== undefined) {
const { locale } = rawFilters;
if (locale === null || locale === '' || locale === 'null') {
if (!sanitizedQuery.filters) sanitizedQuery.filters = {};
sanitizedQuery.filters.locale = null;
} else if (typeof locale === 'string') {
if (!sanitizedQuery.filters) sanitizedQuery.filters = {};
sanitizedQuery.filters.locale = locale;
}
}
const { results, pagination } = await strapi.plugin('publisher').service('action').find(sanitizedQuery);
const sanitizedResults = await this.sanitizeOutput(results, ctx);
return this.transformResponse(sanitizedResults, { pagination });
}
}));
- Pass
locale to getAction() filters and include it in the React Query cache key to ensure locale-specific caching.
Environment
- Strapi: v5.x
- strapi-plugin-publisher: 2.0.9
- i18n plugin: enabled
Additional Context
We are currently using patch-package to work around this issue. Happy to submit a PR if the maintainers agree with the approach above.
Bug Description
When using
strapi-plugin-publisherwith Strapi v5's i18n plugin, scheduled publish/unpublish actions are shared across all locales of the same document. Setting a publish timer on one locale (e.g., Japanese) causes the timer to appear on other locales (e.g., English) as well, preventing locale-specific scheduling.Steps to Reproduce
ja) and set a publish timeren) of the same documentExpected Behavior
Each locale should have independent publish/unpublish timers. Setting a timer on one locale should not affect other locales.
Root Cause Analysis
There are three issues:
1.
localeattribute missing from action schemaThe
actioncontent type schema does not include alocalefield, so there is no way to store which locale a scheduled action belongs to.2. Strapi v5
sanitizeQuerystripslocalefrom attribute filtersEven if
localeis added to the schema and passed asfilters[locale]=jafrom the frontend, Strapi v5's core controllersanitizeQuerytreatslocaleas a system-level i18n parameter and removes it from the attribute filters. This means the defaultfindcontroller ignores the locale filter entirely.3. Frontend does not pass
localeto the action queryThe
getAction()hook does not includelocalein the filters passed to the API, nor in the React Query cache key. This means all locales share the same cached result.Suggested Fix
localeto the action content type schema (type: 'string', required: false)findinactionControllerto restore thelocalefilter aftersanitizeQuery:localetogetAction()filters and include it in the React Query cache key to ensure locale-specific caching.Environment
Additional Context
We are currently using
patch-packageto work around this issue. Happy to submit a PR if the maintainers agree with the approach above.