The WordPress _load_textdomain_just_in_time function is called any time a plugin uses __() , the text translation loader for polyglot support, which means ALL text loading needs to happen after the WordPress :: init hook is called.
Many places in our plugin code is calling text string support way before WordPress init has finished.
This now throws warnings in WP 6.7+
Hooks Order of Precedence
This is very much related to the hooks & filters order of precedence.
As a reminder, here are the initial hook orders:
- WordPress : muplugins_loaded
- WordPress : registered_taxonomy
- WordPress : registered_post_type
- WordPress : plugins_loaded
- WordPress : set_current_user
- WordPress : init <—— all __() calls should come at/AFTER this
- SLP : slp_init_complete
Notice
Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the store-locator-le domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later.
Reproduction
SLP , Power, Experience, Premier when running on WP 6.7+ – like on the QC site
Research & Development
Power
Errors after SLP updates…
Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the slp-power domain was triggered too early.
Experience
Errors after SLP updates…
Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the slp-experience domain was triggered too early.
Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the store-locator-le domain was triggered too early.
Fatal error: Uncaught Error: Attempt to assign property "add_to_settings_tab" on null in /var/www/html/wp-content/plugins/slp-experience/include/module/options/SLP_Experience_Options.php:243
Fatal Error : add_to_settings_tab
Resolved
SLP_Experience_Options::view() was turning on the “add_to_settings_tab” property on various SLP settings, which were not active yet. Updated SLP to always put those settings on the tabs and drop the view() method.
Note: It is still very likely that SLP_Experience_Options is being initialized way too early...
Yes, the invocation is in \SLP_BaseClass_Addon::create_object_option_manager() which sets up add on options as soon as the plugins are loaded.
Update the main SLP plugin to only call the add on options object creation via slp_init_complete not on plugin loading / initialization.
SLP Plugin
Load Order
- slp_setup_environment()
via loader.php called from store-locator-plus.php- \SLPlus::initialize()
via require_once( SLPLUS_PLUGINDIR . ‘include/SLPlus.php’ ) from slp_setup_environment() last line of class file.- SLP_Actions::get_instance() – will load plugin textdomain on init order #11
- new SLPlus_Location — FIXED move first textdomain reference out of constructor
- …
- $this->add_object( SLP_SmartOptions::get_instance() ); — ERROR: loading lots of text early
- \SLPlus::initialize()
Adding A Location
Fatal error: Uncaught Error: Call to a member function get_option() on null in /var/www/html/wp-content/plugins/store-locator-plus/include/module/admin/SLP_Admin_Locations.php:1273
Resolved: WP_List_Table current_screen action hook appears to no longer be valid in WP 6.7+
add_object( SLP_SmartOptions::get_instance() )
- set SLP_Actions::get_instance() – will load plugin textdomain on init precedence #9
- move all the create*options() calls that were in \SLP_SmartOptions::initialize() into WordPress::init hook \SLP_SmartOptions::run_during_init() run at precedence #11
- move \SLP_SmartOptions::set_text_string_defaults() out of \SLPlus::initialize_after_plugins_loaded() and into new \SLP_SmartOptions::run_during_init()
place at bottom after settings are created otherwise the settings are null - \SLPlus::recenter_map() is being called too early.
Warning: Undefined array key “” in /var/www/html/wp-content/plugins/store-locator-plus/include/SLPlus.php on line 605… plus others- called from
- \SLP_SmartOptions::slp_init_complete() via hook on slp_init_complete fired in \SLP_Actions::init() after text domain loaded fires…
- \SLP_SmartOptions::slp_specific_setup()
- \SLP_SmartOptions::slp_init_complete() via hook on slp_init_complete fired in \SLP_Actions::init() after text domain loaded fires…
- called from
What appears to be happening here…
- \SLP_Actions::init() is called on the WordPress::init hook with precedence #9
- This the fires do_action() for slp_init_complete
- Which then calls \SLP_SmartOptions::slp_specific_setup() at that point (wp::init#9)
- However the full setup of SmartOptions settings does NOT happen until wp::init#10 per the \SLP_SmartOptions::initialize() execution.
As such none of the settings are ready yet. Instead of running the option setup in wp::init#10 we need to move it into the slp_init_complete routine so it runs on wp::init#9 but AFTER the SLP_Actions::init has loaded the text domain.
Resolved: re-sorted invocation stack.
new \SLPlus_Location from \SLPlus::initialize()
\SLPlus_Location::__construct() called __() far too early.
It is opened with a new SLPlus_Location() call in \SLPlus::initialize() which is called as soon as the plugin is read (wp_loaded).
Resolution
did not need to init the ‘draft’ string in the constructor, move it to \SLPlus_Location::set_PageData() which is called later.