Opened 3 weeks ago
Last modified 6 days ago
#65666 new defect (bug)
both Upgrade buttons have the same value, potentially upgrading to wrong language
| Reported by: | o815 | Owned by: | |
|---|---|---|---|
| Priority: | low | Milestone: | Awaiting Review |
| Component: | Upgrade/Install | Version: | |
| Severity: | minor | Keywords: | has-patch |
| Cc: | Focuses: | ui |
Description
when an upgrade is available, there is a second upgrade button available that has the same text (value).
viewing the html source reveals the second button is sending with POST a different locale value "en-US", while the value indicates the locale is the current installed one (in this example de-DE).
while i never wanted to risk anything for a test, this indicates a potential issue upgrading to a wrong, not wanted localed version.
Attachments (1)
Change History (3)
This ticket was mentioned in PR #12824 on WordPress/wordpress-develop by @bejignesh.
6 days ago
#2
- Keywords has-patch added
When a localized site is offered both a localized and an en_US core update, and the en_US offer advertises a partial build matching the installed version, both buttons end up with the same label while posting different locales.
The second condition in list_core_update() matches for that offer, but only assigns a version string when it is the only update available:
} elseif ( 'en_US' === $update->locale && $update->packages->partial && $wp_version === $update->partial_version ) { $updates = get_core_updates(); if ( $updates && 1 === count( $updates ) ) { // If the only available update is a partial builds, it doesn't need a language-specific version string. $version_string = $update->current; } }
With more than one offer, nothing is assigned, so $version_string keeps the default set earlier in the function, which is built from get_locale() rather than from the offer's own locale. Because this is an elseif chain, the following condition that would have labelled it correctly is never reached.
### Reproduction
On a de_DE site, serving two offers, one de_DE and one en_US with a partial build matching the installed version:
| Button label | Posts locale
|
|---|---|
| Update to version 7.2–de_DE | de_DE
|
| Update to version 7.2–de_DE | en_US
|
Both buttons read the same, but the second posts locale=en_US and would install the English package. With this change:
| Button label | Posts locale
|
|---|---|
| Update to version 7.2–de_DE | de_DE
|
| Update to version 7.2–en_US | en_US
|
The added branch assigns the same string the following condition already uses for the non-partial case.
### Testing
- Checked the case the branch exists for, a single partial en_US offer, still renders
Update to version 7.2with no locale suffix. --group upgradepasses, 183 tests.--group adminpasses, 1016 tests, 0 failures. It reports 10 PHPUnit 10 deprecation warnings, which are identical on unmodified trunk.phpcsandphp -lclean.
No unit test is included. list_core_update() is defined in wp-admin/update-core.php, which runs page logic on include, so it cannot be exercised from PHPUnit without refactoring the function out of the page file. The reproduction above was done against the rendered admin screen.
## Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5
Used for: Drafting the patch and this description. I reproduced the mislabelled buttons on the rendered update screen before and after the change, confirmed the single-offer case still renders without a locale suffix, ran the upgrade and admin groups and checked the admin warnings against a trunk baseline, ran phpcs and php -l, and I take responsibility for the result.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)
it seems the issue is related to this code from update-core.php at line 43:
if ( 'en_US' === $update->locale && 'en_US' === get_locale() ) { $version_string = $update->current; } elseif ( 'en_US' === $update->locale && $update->packages->partial && $wp_version === $update->partial_version ) { $updates = get_core_updates(); if ( $updates && 1 === count( $updates ) ) { // If the only available update is a partial builds, it doesn't need a language-specific version string. $version_string = $update->current; } } elseif ( 'en_US' === $update->locale && 'en_US' !== get_locale() ) { $version_string = sprintf( '%s–%s', $update->current, $update->locale ); }When the second submit form and button is generated, the if else condition stopps at the second elseif because the updates locale is en_US, and it is a partial build and the version matches.
But it than fails at the inner if
because the count is 2.
in the end result all of the 3 if/elseif are never true and the $version_string is never set to en_US but keeps the previous value from get_locale()