Opened 7 weeks ago
Last modified 5 days ago
#64977 assigned defect (bug)
The `core/get-site-info` ability returns wrong locale code in the admin
| Reported by: |
|
Owned by: |
|
|---|---|---|---|
| Milestone: | 7.1 | Priority: | normal |
| Severity: | normal | Version: | 6.9 |
| Component: | Abilities API | Keywords: | abilities has-patch has-unit-tests commit |
| Focuses: | Cc: |
Description (last modified by )
Besides other site data, the core/get-site-info ability is supposed to return The site language locale code.
I would expect that to be the site language locale.
However, in the admin it returns the _user_locale which may not the same of the site locale.
Under the hood, the ability callback uses get_bloginfo().
That doesn't seem to be the right tool to retrieve the _site_ language locale code. In fact, get_bloginfo():
- can be passed a different language code by translators
- internally uses
determine_locale()which uses some logic that may return different results depending on (roughly):- whether the page is the login page
- whether is an admin or whether there are some get parameters related to user and locale _and_ it's a json request: in this case it returns the _user_locale
- other logic based on whether there is a 'language' request parameter or is installing
- finally fallbacks to
get_locale()which returns the _site_ locale
It is also worth considering what the ability should return in a multisite installation.
To reproduce:
- In WP Admin > Settings > General, set the Site Language to a language other than english e.g. Italian.
- In WP Admin > Users > Profile, set the Language to a different language e.g. Spanish.
- Place the following snippet in a template that outputs on the front end:
$ability = wp_get_ability( 'core/get-site-info' ); $result = $ability->execute(); var_dump( $result['language'] );
- Observe it returns
string(5) "it-IT", which is the expected site locale. - Place the same snippet into some admin page for example in
options-general.php. - Observe it returns
string(2) "es"which is not the expected locale. Actually, this is the _user_ locale. - Worth checking what is returned in a REST API call. As far as I see the returned language is correct. Tested with:
curl -X GET "http://localhost:8889/wp-json/wp-abilities/v1/abilities/core/get-site-info/run" \ -u "your-username:your-generated-application-password" \ -H "Content-Type: application/json"
Introduced in https://core.trac.wordpress.org/changeset/61063/
See https://core.trac.wordpress.org/ticket/64146
Change History (17)
This ticket was mentioned in PR #11388 on WordPress/wordpress-develop by @iamadisingh.
7 weeks ago
#2
- Keywords has-patch added
#3
@
7 weeks ago
- Milestone changed from Awaiting Review to 7.1
The PR looks good to me. Moving to milestone 7.1.
This ticket was mentioned in PR #11492 on WordPress/wordpress-develop by @sangu3105.
6 weeks ago
#4
The core/get-site-info ability should return the site locale, but currently returns the user locale in admin due to using get_bloginfo(), which relies on determine_locale().
This can vary based on context (admin, login, request params, JSON requests), making it unreliable for getting the actual site locale.
The site's language is stored directly as the WPLANG option. Reading it bypasses all the context-dependent filtering:
if ( 'language' === $field ) {
$result[ $field ] = str_replace( '_', '-', get_option( 'WPLANG' ) ?: 'en_US' );
}
get_option('WPLANG') returns the raw DB value — no context influence
The ?: 'en_US' handles the default English case where WPLANG is an empty string
str_replace('_', '-', ...) preserves the existing BCP 47 formatting (e.g. en-US, pt-BR)
Multisite Behavior
In multisite, get_option() already scopes to the current site (it internally routes through get_blog_option()), so no special handling is needed. Each site in the network correctly returns its own configured language. If you ever needed the network-level language, that would be get_network_option(null, 'WPLANG'), but that's not appropriate for core/get-site-info.
This ticket was mentioned in PR #11498 on WordPress/wordpress-develop by @sangu3105.
6 weeks ago
#5
The core/get-site-info ability should return the site locale, but currently returns the user locale in admin due to using get_bloginfo(), which relies on determine_locale().
This can vary based on context (admin, login, request params, JSON requests), making it unreliable for getting the actual site locale.
The site's language is stored directly as the WPLANG option. Reading it bypasses all the context-dependent filtering:
if ( 'language' === $field ) {
$result[ $field ] = str_replace( , '-', get_option( 'WPLANG' ) ?: 'en_US' );
}
get_option('WPLANG') returns the raw DB value — no context influence
The ?: 'en_US' handles the default English case where WPLANG is an empty string
str_replace(, '-', ...) preserves the existing BCP 47 formatting (e.g. en-US, pt-BR)
Multisite Behavior
In multisite, get_option() already scopes to the current site (it internally routes through get_blog_option()), so no special handling is needed. Each site in the network correctly returns its own configured language. If you ever needed the network-level language, that would be get_network_option(null, 'WPLANG'), but that's not appropriate for core/get-site-info.
This ticket was mentioned in PR #11502 on WordPress/wordpress-develop by @sangu3105.
6 weeks ago
#6
Ticket: 64977
Link: https://core.trac.wordpress.org/ticket/64977
The core/get-site-info ability should return the site locale, but currently returns the user locale in admin due to using get_bloginfo(), which relies on determine_locale().
This can vary based on context (admin, login, request params, JSON requests), making it unreliable for getting the actual site locale.
The site's language is stored directly as the WPLANG option. Reading it bypasses all the context-dependent filtering:
if ( 'language' === $field ) {
$result[ $field ] = str_replace( , '-', get_option( 'WPLANG' ) ?: 'en_US' );
}
get_option('WPLANG') returns the raw DB value — no context influence
The ?: 'en_US' handles the default English case where WPLANG is an empty string
str_replace(, '-', ...) preserves the existing BCP 47 formatting (e.g. en-US, pt-BR)
Multisite Behavior
In multisite, get_option() already scopes to the current site (it internally routes through get_blog_option()), so no special handling is needed. Each site in the network correctly returns its own configured language. If you ever needed the network-level language, that would be get_network_option(null, 'WPLANG'), but that's not appropriate for core/get-site-info.
#8
@
4 weeks ago
- Component changed from AI to Abilities API
Moving tickets related to the Abilities API to a new sub-component.
This ticket was mentioned in Slack in #core-test by nikunj8866. View the logs.
3 weeks ago
#10
@
2 weeks ago
Tested PR https://github.com/WordPress/wordpress-develop/pull/11388
In a local test environment, I set the site locale to it_IT and the admin user locale to es_ES.
Before the patch, wp_get_ability( 'core/get-site-info' )->execute() returned language => es in admin context.
After the patch, the same ability returned language => it-IT, matching the site locale instead of the user locale.
Patch tests well for me.
#11
@
2 weeks ago
Patch Testing Report
Patch Tested: https://github.com/WordPress/wordpress-develop/pull/11502
Environment
- WordPress: 7.1-alpha-62161-src
- PHP: 8.3.30
- Server: nginx/1.29.5
- Database: mysqli (Server: 8.4.8 / Client: mysqlnd 8.3.30)
- Browser: Chrome 147.0.0.0
- OS: Windows 10/11
- Theme: Twenty Twenty-Five 1.4
- MU Plugins: None activated
- Plugins:
- Test Reports 1.2.1
Steps taken
- In WP Admin > Settings > General, set the Site Language to a language other than English, e.g., Italian.
- In WP Admin > Users > Profile, set the Language to a different language e.g., French.
- Used the code provided by the reporter and created a plugin.
<?php /** * Plugin Name: Test Language Locale * Description: Difference in language locale * Version: 1.0 */ add_action( 'wp_footer', 'language_locale' ); add_action( 'admin_footer', 'language_locale' ); function language_locale () { $ability = wp_get_ability( 'core/get-site-info' ); $result = $ability->execute(); var_dump( $result['language'] ); }
- Head over to the footer of the site on the frontend and observe the returned language before and after the patch.
- Head over to the admin dashboard, scroll down to the end of the page and observe the returned language before and after the patch.
- ✅ Patch is solving the problem
Expected result
- The site locale should be returned in the admin dashboard instead of the user-specific admin locale.
Additional Notes
- None
Screenshots/Screencast with results
- Before:
- After:
@gziolo commented on PR #11388:
7 days ago
#12
@Adi-ty, this patch looks good. Would you mind adding a single unit test covering this edge case so it doesn't regress over time?
#13
@
7 days ago
I see multiple patches attached to this ticket. https://github.com/WordPress/wordpress-develop/pull/11388 looks the closest, but it still would benefit from a unit test that covers this edge case. https://github.com/WordPress/wordpress-develop/pull/11502 seems correct, but it uses a subset of functionality that the former covers through get_locale() call. @afercia, does it fix the issue for you as well?
@iamadisingh commented on PR #11388:
6 days ago
#15
@gziolo
Sure, I’ll add a unit test for this edge case as well
@iamadisingh commented on PR #11388:
6 days ago
#16
Added a unit test covering the edge case as well


This
core/get-site-infoability returned the wrong language value in admin context. It usedget_bloginfo( language ), which goes throughdetermine_locale()and may resolve to the current user locale in wp-admin. For a site-level ability, this is incorrect because the language field should represent the site locale consistently.Trac ticket: https://core.trac.wordpress.org/ticket/64977