Add warnings if loading translations too early
In my quick local testing I already identified a few plugins doing load_plugin_textdomain() wrong:
- [ ] RTL Tester
- Not really maintained anymore anyway
- [x] Two Factor
- https://github.com/WordPress/two-factor/pull/608
- [x] Elementor
- https://github.com/elementor/elementor/pull/27200
- [ ] Litespeed Cache
- https://github.com/litespeedtech/lscache_wp/pull/738
Plugins doing just-in-time loading wrong:
- [x] WooCommerce
- https://github.com/woocommerce/woocommerce/pull/47113
- [ ] BuddyPress
- Their theme integration also causes Twenty Twenty-Four translations to be loaded too early
To-do:
- Improve wording for the
_load_textdomain_just_in_timecase, mentioning that it's typically caused by unintended side effects in a plugin or theme. - What about themes? They usually do stuff in
after_setup_theme, which runs right beforeinitand current user setup. Probably all classic themes will be affected by this.
Strangely, when one of these plugins and Query Monitor is active, there is some sort of infinite loop happening and the site crashes with a 500. @johnbillion Any thoughts why QM might run in circles here?
Trac ticket: https://core.trac.wordpress.org/ticket/44937
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.
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 swissspidy, johnbillion.
To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.
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
- The Plugin and Theme Directories cannot be accessed within Playground.
- 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.
I'll take a look at what's happening in QM. I would recommend testing this out with some multilingual plugins if you haven't already. In particular WPML (and add-on plugins for it) has been a bit of a pain in the past with regard to loading translations too early.
I'm not seeing an infinite loop in my local testing with RTL Tester. I am concerned about calling __() from within the load textdomain functions though. Do we do that anywhere else?
OK here's how to reproduce the error. Even if you can't reproduce it so far, it seems logical:
- Set user profile to something else than en_US
- Activate RTL Tester
- Activate Query Monitor
- RTL Tester triggers the
_doing_it_wronginload_plugin_textdomain() - This calls
QM_Collector_Doing_It_Wrong::action_doing_it_wrong_run()which uses__() - This in turn triggers the
_doing_it_wrongin_load_textdomain_just_in_time() - This calls
QM_Collector_Doing_It_Wrong::action_doing_it_wrong_run()again...
Adding some caching to only warn about a specific text domain once would solve this. Like a _doing_it_wrong_once function or so.
I am concerned about calling
__()from within the load textdomain functions though. Do we do that anywhere else?
I don't think so. In theory it shouldn't cause any issues as the __() call and the load_*_textdomain() call use different domains. And the QM issue is only because it taps into the _doing_it_wrong.
Actually, it's more like QM would need to somehow unhook QM_Collector_Doing_It_Wrong in itself because it is triggering _doing_it_wrong itself.
Good spot, thanks. Temporarily unhooking itself is probably best otherwise there's no way to know what else might trigger a _doing_it_wrong call within any of the functions that are called from a doing it wrong handler.
Looking into warnings emitted by themes, such as twentytwentyone.
Some observations:
- Themes usually trigger just-in-time loading on
after_setup_theme - In the admin, the current user is set up right after
setup_themebecause of theload_default_textdomain()call inwp-settings.php - Checking for
after_setup_themeto emit a warning might be a better solution
I am concerned about calling
__()from within the load textdomain functions though.
At this point determine_locale() will already have been called, and the current user thus setup. So I don't see any other side effect happening because of this.
@ocean90 @SergeyBiryukov @johnbillion Is this something one of you could provide feedback on? I think it's a nice safeguard that could still land before the beta, but it also might be a bit noisy.
This could be noisy but it might be interesting to see if any feedback about that is raised during beta.
Committed in https://core.trac.wordpress.org/changeset/59127