Make WordPress Core

Opened 4 months ago

Closed 3 months ago

Last modified 2 months ago

#63185 closed defect (bug) (wontfix)

Function _load_textdomain_just_in_time was called incorrectly in WP v6.8-RC1

Reported by: jorgedelcampo's profile jorgedelcampo Owned by:
Milestone: Priority: normal
Severity: normal Version: trunk
Component: I18N Keywords:
Focuses: Cc:

Description

Hi everyone.

After update to WordPress 6.8-RC1, I recieved this message in many plugins and themes.

Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the acf 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. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in C:\MAMP\htdocs\my-site\wp-includes\functions.php on line 6121

The same message appears for many of my plugins and my own custom theme.

Affected textdomains: js_composer, acf, gp-limit-submissions, happy-elementor-addons and others, including my own custom theme.

If I back to wp 6.7.2, the message desappears.

Change History (13)

#1 @swissspidy
4 months ago

  • Milestone Awaiting Review deleted
  • Resolution set to wontfix
  • Status changed from new to closed

Hi there and welcome to WordPress Trac

As the message says: 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. I suggest reaching out to the plugin developer and pointing them to https://make.wordpress.org/core/2024/10/21/i18n-improvements-6-7/

#2 @westguard
4 months ago

Something as simple as this throws this same warning in 6.8 RC2:

<?php

	/**
	 * @wordpress-plugin
	 * Plugin Name: Test plugin
	 * Text Domain: test-domain
	 */

	$test = __('Test', 'test-domain');

This ticket was mentioned in Slack in #core by westguard. View the logs.


4 months ago

#5 @westguard
4 months ago

That makes sense, thanks for your help!

#6 @kevinB
3 months ago

  • Component changed from Administration to I18N
  • Resolution wontfix deleted
  • Status changed from closed to reopened

@swissspidy The WP 6.8 release has caused a long list of prominent plugins to be pegged with this "_load_textdomain_just_in_time was called incorrectly" notice. But in the case of Pods, I find that the problematic code is this addition to wp-settings.php:

https://core.trac.wordpress.org/changeset?sfp_email=&sfph_mail=&reponame=&new=59461%40trunk%2Fsrc%2Fwp-settings.php&old=59132%40trunk%2Fsrc%2Fwp-settings.php

The plugin is not calling load_textdomain() early. Instead, its textdomain is being auto-registered early by wp-settings.php based on the plugin file's "Text Domain" tag:

<?php
$plugin_data = get_plugin_data( $plugin, false, false );

$textdomain = $plugin_data['TextDomain'];
if ( $textdomain ) {
        if ( $plugin_data['DomainPath'] ) {
                $GLOBALS['wp_textdomain_registry']->set_custom_path( $textdomain, dirname( $plugin ) . $plugin_data['DomainPath'] );
        } else {
                $GLOBALS['wp_textdomain_registry']->set_custom_path( $textdomain, dirname( $plugin ) );
        }
}

As a result, some plugin string initialization gets triggered by do_action('setup_theme') or downstream actions, leading to the _load_textdomain_just_in_time() notice.

Can you explain what's going on here and detail the new implications and requirements for plugins? It seems like the plugins are being called out for textdomain loading they're not responsible for.

#7 @sc0ttkclark
3 months ago

@kevinB There are indeed some occurrences in Pods that we have fixed in the upcoming release. But it could be that what you've found is in addition to that. I'm not 100% sure.

#8 @kevinB
3 months ago

@sc0ttkclark It seems that previously, any early plugin translation calls were quietly ignored as long as the plugin did not also load the textdomain too early. But now, Core's early auto-registration of the textdomain makes those same calls problematic. Is this an intentional move to flush out the mistimed plugin translation calls? If not, what is the rationale for registering the textdomain before it is allowed to be used?

Last edited 3 months ago by kevinB (previous) (diff)

#9 @swissspidy
3 months ago

  • Resolution set to wontfix
  • Status changed from reopened to closed

The plugin is not calling load_textdomain() early. Instead, its textdomain is being auto-registered early by wp-settings.php based on the plugin file's "Text Domain" tag

Can you explain what's going on here and detail the new implications and requirements for plugins? It seems like the plugins are being called out for textdomain loading they're not responsible for.

This _doing_it_wrong notice is not about calling load_textdomain() specifically. It's about triggering translation loading, for example by calling __(), too early.

While this message was already introduced in 6.7, there were some edge cases where it didn't fire. In 6.8 that's not the case anymore thanks to that wp-settings.php change.

Is this an intentional move to flush out the mistimed plugin translation calls?

Yes. Again, see https://make.wordpress.org/core/2024/10/21/i18n-improvements-6-7/ and https://make.wordpress.org/core/2025/03/12/i18n-improvements-6-8/. They contain some good examples and explanation why loading translations too early is bad.


If you have a plugin doing it wrong in the repo or on GitHub, I am happy to take a look and point out why it might happen in your case.

You're definitely not expected to do things like did_action( 'init' ) in your code à la https://github.com/pods-framework/pods/pull/7398/commits/7b93ffdb353183f3713cf3fc9751deb13f8d6cdc. That could just make things worse by unintentionally removing any user-facing texts. Instead you should figure out why your whole code is loaded too early and what you can do to avoid that.


PS. There is no reason to reopen the ticket. Discussions can continue even on closed tickets. So let's do that please :)

#10 @kevinB
3 months ago

You're definitely not expected to do things like did_action( 'init' ) in your code

@swissspidy Pods is not my code; I just pointed it out as an example. But I will assert a notice on your blanket statement about did_action('init') based on consideration of my own case.

PublishPress Revisions filters the cron_schedules filter, adding this item to the array:

<?php
$schedules['two_minutes'] = array(
        'interval' => 120,
        'display'  => esc_html__( 'Every 2 Minutes', 'revisionary' )
);

This implementation conforms to wordpress.org documentation for the cron_schedules filter.

Now I find that because another plugin calls wp_schedule_event() prior to the the init action, Revisions is flagged with a notice for its proper filtering of cron_schedules. How are we supposed to resolve this if did_action( 'init' ) is bad form?

This also raises a question about your _doing_it_wrong notice strategy. The wp-settings.php change causes another plugin's early wp_schedule_event() to flag Revisions with a _load_textdomain_just_in_time notice. Do you see how this newly aggressive flagging has actually confused the situation by blaming the wrong plugin? To avoid side effects like this, you would need to apply a similar _doing_it_wrong notice to every function in the code base that should not be called prior to init, as well as every action and filter that should not be applied prior to init. If not, would you agree that it is understandable for plugins to begin wrapping their translation strings in did_action( 'init' ) checks to avoid false accusations which can lead to the very real consequences of diminished confidence or negative reviews?

A simpler alternative would be to revert the wp-settings.php change so plugins once again have the jurisdiction to register their textdomain at the proper time. Then if another plugin's function call triggers an extra execution of some of my plugin's __() calls prior to the init action, those will once again be disregarded without harm or false alarm.

Last edited 3 months ago by kevinB (previous) (diff)

#11 @swissspidy
3 months ago

Now I find that because another plugin calls wp_schedule_event() prior to the the init action, Revisions is flagged with a notice for its proper filtering of cron_schedules. How are we supposed to resolve this if did_action( 'init' ) is bad form?

Ideally that other plugin would be fixed, to prevent it from triggering this notice for everyone else.

Related: https://core.trac.wordpress.org/ticket/62462#comment:21

[...] those will once again be disregarded without harm or false alarm.

That would just cause early user-facing messages to not be properly translated again, which is the whole issue this notice aims to address.

#12 @kevinB
3 months ago

That would just cause early user-facing messages to not be properly translated again, which is the whole issue this notice aims to address.

@swissspidy In this case of function wp_schedule_event(), the string in question is not even used. It calls wp_get_schedules(), but only accesses the 'interval' array element. However, the cron_schedules filter does not provide that context. So in reality, there was never a user-facing string going untranslated.

You might think that is an edge case to disregard, but what is the harm in just allowing the functional effect of an actual untranslated string be the signal that triggers users to report an issue? Then if there is a real concern, it will naturally be reported to the correct support channel, followed by another plugin author being notified if needed.

Your early auto-registration of plugin textdomains is instead forcing me to bear the burden of explaining and troubleshooting other plugins' issues even if there is no real impact on my own users. At minimum, instead of shrugging off the potential for false blame about who is doing_it_wrong, please consider rephrasing the PHP Notice to communicate some uncertainty about what has caused this plugin's translation call to happen too early.

Last edited 3 months ago by kevinB (previous) (diff)

#13 @davidbaumwald
2 months ago

#63435 was marked as a duplicate.

Note: See TracTickets for help on using tickets.