Skip to content

I18N: Fix PHPStan errors for literal strings in nooped plurals - #14088

Closed
westonruter wants to merge 3 commits into
WordPress:trunkfrom
westonruter:fix/phpstan-i18n-literal-string-followup
Closed

westonruter wants to merge 3 commits into
WordPress:trunkfrom
westonruter:fix/phpstan-i18n-literal-string-followup

Conversation

@westonruter

@westonruter westonruter commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

✅ Committed in r64234 (80c6c39).


Follow-up to r64232 (#14079), which made the localization API require literal strings. That left five PHPStan errors on trunk, reported as warnings on PRs that touch the affected files:

src/wp-includes/post.php:1506              _n_noop() $singular and $plural expect literal-string, mixed given
src/wp-includes/category-template.php:899  _n_noop() $singular and $plural expect literal-string, mixed given
src/wp-admin/includes/media.php:2898       translate_nooped_plural() expects the literal-string nooped plural shape, array given

Post mime types. get_post_mime_types() documented the third element of each mime type as a bare array, so the literal types returned by _n_noop() were lost before media.php passed them to translate_nooped_plural(). The nooped plural shape is now declared in a @phpstan-return for get_post_mime_types(), a @phpstan-param for the post_mime_types filter (whose documented type is what PHPStan uses for the filtered return value), and a @phpstan-return for wp_edit_attachments_query(), which passes the mime types through.

Runtime strings passed to _n_noop(). register_post_status() builds its default label_count from the status label, and wp_generate_tag_cloud() supports the old-style single_text and multiple_text arguments. Both pass runtime values to _n_noop() only to build the nooped plural structure, so there is nothing to extract for translation. These are intentional for back-compat, so the errors are ignored inline with the reason, next to the existing phpcs:ignore for the corresponding I18n sniffs. Each line lists argument.type twice, since one ignore covers one error and there is one each for $singular and $plural.

Building the nooped plural arrays by hand instead was tried in one commit and reverted in the next: it duplicated the structure returned by _n_noop() and only hid the runtime strings from static analysis, without making them literal.

The nested nooped plural shape is repeated in three places. A shared type alias is being discussed in #13890 (comment) and is left for later.

PHPStan with phpstan.neon.dist now reports no errors, and the inline ignores also match at level 10, so reportUnmatchedIgnoredErrors reports nothing.

Trac ticket: https://core.trac.wordpress.org/ticket/65817

Use of AI Tools

AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5.5
Used for: Reproducing the CI warnings, writing the type and code changes, and verifying them with PHPStan, PHPCS, and WP-CLI; the approach was directed and reviewed by me.


This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.

🤖 Generated with Claude Code

westonruter and others added 3 commits October 7, 2026 13:21
`translate_nooped_plural()` now requires a nooped plural whose strings
are literal, but `get_post_mime_types()` documented the third element of
each mime type as a bare `array`. The literal types returned by
`_n_noop()` were therefore lost before the counts on the media library
screen were translated in `media.php`.

The nooped plural shape is now declared in the return type of
`get_post_mime_types()`, in the `post_mime_types` filter, whose
documented parameter type is what PHPStan uses for the filtered return
value, and in the return type of `wp_edit_attachments_query()`, which
passes the mime types through.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`_n_noop()` marks strings for extraction into translation files, so it
now requires literal strings. Two callers passed runtime values instead,
only to build the nooped plural structure: the default `label_count` in
`register_post_status()`, which reuses the status label, and the
old-style `single_text` and `multiple_text` arguments of
`wp_generate_tag_cloud()`.

Both now build the same array directly, so the result is unchanged.
This also removes the `phpcs:ignore` comments that were needed for
passing non-literal strings to `_n_noop()`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The previous commit built the nooped plurals in `register_post_status()`
and `wp_generate_tag_cloud()` by hand, so that runtime values were no
longer passed to `_n_noop()`. That duplicated the structure returned by
`_n_noop()`, and it did not make the strings literal: it only hid them
from static analysis, while they still reach `translate_nooped_plural()`.

The `_n_noop()` calls are restored, and the `literal-string` errors are
ignored inline with the reason, next to the existing `phpcs:ignore` for
the corresponding I18n sniffs. This keeps the deviation visible where
the runtime values enter the nooped plural. Each line ignores
`argument.type` twice, once for `$singular` and once for `$plural`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@westonruter
westonruter marked this pull request as ready for review October 7, 2026 20:40
@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props westonruter.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

wporg-sync pushed a commit that referenced this pull request Oct 7, 2026
Since r64232 the localization API requires literal strings, which surfaced five new PHPStan errors. The nooped plurals in the post mime types lost the literal types returned by `_n_noop()` before reaching `translate_nooped_plural()`, because `get_post_mime_types()` documented each one as a bare `array`. Their shape is now declared, including on the `post_mime_types` filter, whose documented type determines the type of the filtered return value.

Two callers pass runtime values to `_n_noop()` for back-compat: the default `label_count` in `register_post_status()` and the old-style `single_text` and `multiple_text` arguments of `wp_generate_tag_cloud()`. There is nothing to extract for translation in either case, so the errors are ignored inline. Building the nooped plural by hand instead would duplicate its structure and only hide the runtime strings from static analysis.

Developed in #14088.
Follow-up to r27376, r40516, r64232.

See #65817.


git-svn-id: https://develop.svn.wordpress.org/trunk@64234 602fd350-edb4-49c9-b593-d223f7449a82
@westonruter westonruter closed this Oct 7, 2026
wporg-sync pushed a commit to WordPress/WordPress that referenced this pull request Oct 7, 2026
Since r64232 the localization API requires literal strings, which surfaced five new PHPStan errors. The nooped plurals in the post mime types lost the literal types returned by `_n_noop()` before reaching `translate_nooped_plural()`, because `get_post_mime_types()` documented each one as a bare `array`. Their shape is now declared, including on the `post_mime_types` filter, whose documented type determines the type of the filtered return value.

Two callers pass runtime values to `_n_noop()` for back-compat: the default `label_count` in `register_post_status()` and the old-style `single_text` and `multiple_text` arguments of `wp_generate_tag_cloud()`. There is nothing to extract for translation in either case, so the errors are ignored inline. Building the nooped plural by hand instead would duplicate its structure and only hide the runtime strings from static analysis.

Developed in WordPress/wordpress-develop#14088.
Follow-up to r27376, r40516, r64232.

See #65817.

Built from https://develop.svn.wordpress.org/trunk@64234


git-svn-id: http://core.svn.wordpress.org/trunk@63385 1a063a9b-81f0-0310-95a4-ce76da25c4cd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant