Skip to content

Scheduled actions are shared across locales — locale-aware filtering is needed #222

Description

@shoh7767

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

  1. Enable i18n and publisher plugins on a content type
  2. Open an entry in locale A (e.g., ja) and set a publish timer
  3. Switch to locale B (e.g., en) of the same document
  4. 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

  1. Add locale to the action content type schema (type: 'string', required: false)
  2. 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 });
      }
    }));
  3. 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.

Activity

  1. self-assigned this
    on May 29, 2026
  2. added theissue type on May 29, 2026
  3. TMSchipper commented on May 29, 2026

    @TMSchipper
    Contributor

    Hi @shoh7767 , thanks for putting the time into this and sorry for my late reply.

    The analysis is clear and the proposed fix is very helpful.

    I agree with the direction, and I’d be happy to review a PR if you’d like to contribute this upstream.

    I did a bit of local verification as well, and the main things we’d like to make sure the final implementation covers are:

    • preserve Strapi’s default query validation when overriding the action find
    • add locale as an optional field on publisher actions
    • safely restore filters.locale after sanitizeQuery
    • pass locale from the admin UI into getAction()
    • include locale in the React Query cache key and relevant invalidation paths
    • verify that non-localized publish/unpublish scheduling still works as before

    ^ These are mostly the extra checks/details needed to make it safe to merge.
    I’ve already set up a small local reproduction to verify the bug and validate the suggested approach. Let me know if you’d like to continue with a PR yourself, or if you’d prefer me to open one and tag you for feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions