If you upgraded to WordPress 6.8 and suddenly started seeing this notice:
Notice: Function _load_textdomain_just_in_time was called incorrectly…
you’re not alone.
Starting in WordPress 6.7 and continuing in 6.8, core became stricter about when translations are loaded and now surfaces a developer notice whenever a theme or plugin loads a text domain too early in the request lifecycle. (WordPress.org)
The good news: this is not a fatal error. It’s a warning that something in your code is running at the wrong time. In this guide, you’ll learn what the notice means and multiple safe ways to fix (or, if necessary, temporarily silence) it.
Notice: This issue is one we’ve personally encountered. You can explore similar cases and their solutions in our WordPress Bug Fixing category.
Table of Contents
What the “Function _load_textdomain_just_in_time was called incorrectly” Notice Means
_load_textdomain_just_in_time() is part of WordPress’s internationalization (i18n) system. Its job is to load translation files only when a given text domain is actually used, instead of eagerly loading all .mo files. This “just in time” loading improves performance and memory usage. (WordPress Developer Resources)
The notice usually looks like this:
Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the {your-domain} 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. (This message was added in version 6.7.0.)
In plain English:
- A theme or plugin is causing translations for a text domain to load before WordPress is ready (i.e., before hooks like
initare fired). - WordPress now warns you so you can move that code to the correct hook and avoid subtle bugs.
Common triggers:
- Calling
load_plugin_textdomain()orload_theme_textdomain()too early. - Using
__(),_e(), etc. in code that runs beforeinit(for example, in plugin bootstrap files or early hooks). - Calling
load_textdomain()directly with a custom path. - Using APIs that translate strings too early, such as some
get_plugin_data()usages with translation enabled.
Why You See This More in WordPress 6.7–6.8
WordPress 6.7 introduced several i18n changes:
- Just-in-time loading is stricter about when translations are loaded.
- A new developer notice was added for domains loaded too early, with the “added in version 6.7.0” message.
- Themes and plugins that were “quietly wrong” for years now log notices as soon as you enable debugging.
When you upgrade to 6.8, the same checks continue, so any plugin or theme that hasn’t been updated will still trigger the warning.
Quick Overview of Fixes
In most cases, you’ll fix this by:
- Loading plugin translations in
plugins_loadedorinit. - Loading theme translations in
after_setup_theme(orinitfor some setups). - Ensuring text domains, file names, and paths match.
- Avoiding direct
load_textdomain()unless you really need it. - Optionally, using an MU plugin to mute this one deprecation notice while you clean things up.
Let’s walk through each method.
Method 1: Use WP_DEBUG to Find Exactly Where the Notice Comes From
Before you change anything, it’s worth confirming which plugin or theme is responsible.
Step 1: Enable debugging (preferably on a staging site)
Edit wp-config.php and make sure you’re not doing this on a live site unless you hide error output.
A safe debugging setup is: (WordPress Developer Resources)
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_DISPLAY', false );
define( 'WP_DEBUG_LOG', true );
This will:
- Turn on WordPress debugging.
- Hide notices from visitors.
- Log all notices and warnings to
wp-content/debug.log.
Tip: Always debug on a staging or local site where possible, or at least keep
WP_DEBUG_DISPLAYset tofalsein production.
Step 2: Trigger the notice
- Visit both the front end and wp-admin while logged in.
- Then open
wp-content/debug.logand search for_load_textdomain_just_in_time.
The log line typically includes:
- The text domain that’s being loaded too early.
- A stack trace with the file and line responsible (e.g.
wp-content/plugins/some-plugin/some-file.php).
Once you know who causes it, you can apply the relevant fix below.
Method 2: Load Plugin Translations on the Correct Hook
If the notice points to a plugin domain (e.g. woocommerce, my-plugin, titan-security, etc.), you likely need to move or wrap your load_plugin_textdomain() call.
Bad pattern (too early)
// my-plugin/my-plugin.php
load_plugin_textdomain(
'my-textdomain',
false,
dirname( plugin_basename( __FILE__ ) ) . '/languages'
);
This runs as soon as the file is included, which is often earlier than WordPress expects.
Recommended pattern
// my-plugin/my-plugin.php
add_action( 'plugins_loaded', 'myplugin_load_textdomain' );
function myplugin_load_textdomain() {
load_plugin_textdomain(
'my-textdomain',
false,
dirname( plugin_basename( __FILE__ ) ) . '/languages'
);
}
Steps:
- Open your plugin’s main PHP file (the one with the plugin header).
- Wrap your
load_plugin_textdomain()call in a function. - Hook that function to
plugins_loaded(orinitif you need the current user set before translations are used). - Make sure your
.mofiles actually exist in either:wp-content/languages/plugins/, orwp-content/plugins/your-plugin/languages/.
Why it works:
plugins_loadedfires after all active plugins are included, but before most of WordPress starts outputting anything.- This gives WordPress time to set up the internal registry so
_load_textdomain_just_in_time()can do its job without complaining.
Method 3: Load Theme Translations on the Correct Hook
For themes, the same idea applies, but the recommended hook is usually after_setup_theme.
Bad pattern
// functions.php
load_theme_textdomain( 'mytheme', get_template_directory() . '/languages' );
Recommended pattern
// functions.php
add_action( 'after_setup_theme', 'mytheme_load_textdomain' );
function mytheme_load_textdomain() {
load_theme_textdomain(
'mytheme',
get_template_directory() . '/languages'
);
}
Steps:
- Open your theme’s
functions.php. - Wrap
load_theme_textdomain()in a function. - Hook it into
after_setup_theme(orinitif you have a special setup). - Ensure your
.mofiles live in:wp-content/languages/themes/, orwp-content/themes/your-theme/languages/.
For child themes, use load_child_theme_textdomain() on the same hook:
add_action( 'after_setup_theme', 'my_child_theme_setup' );
function my_child_theme_setup() {
load_child_theme_textdomain(
'parent-theme-slug',
get_stylesheet_directory() . '/languages'
);
}
Method 4: Check Text Domains, File Names, and Locations
Even if you load translations at the right time, mistakes in file names or domains can still cause warnings and missing translations.
1. File locations
- Plugins
- Recommended:
wp-content/languages/plugins/your-plugin-slug-locale.mo - Fallback:
wp-content/plugins/your-plugin/languages/your-plugin-slug-locale.mo
- Recommended:
- Themes
- Recommended:
wp-content/languages/themes/your-theme-slug-locale.mo - Fallback:
wp-content/themes/your-theme/languages/locale.mo(no text domain prefix).
- Recommended:
2. File names
Use the pattern:
textdomain-locale.mo
Examples:
myplugin-en_US.momytheme-de_DE.mo
3. Text domain consistency
Whatever domain you use in load_plugin_textdomain() or load_theme_textdomain() must match the domain used in translation functions:
__( 'My string', 'myplugin' ); // OK
_e( 'My string', 'myplugin' ); // OK
Avoid:
__( 'My string', 'my-plugin' ); // mismatch
__( 'My string', 'MyPlugin' ); // mismatch
Mismatched domains mean WordPress can’t find the correct translation and may still log notices in debug mode.
Method 5: Avoid Direct load_textdomain() Calls
A common pattern in older codebases is:
load_textdomain(
'myplugin',
WP_PLUGIN_DIR . '/myplugin/languages/myplugin-en_US.mo'
);
This bypasses WordPress’s modern i18n system and is more likely to interact badly with the just-in-time loader, especially in 6.7+.
Instead, prefer the wrapper functions:
// Plugins
load_plugin_textdomain(
'myplugin',
false,
dirname( plugin_basename( __FILE__ ) ) . '/languages'
);
// Themes
load_theme_textdomain(
'mytheme',
get_template_directory() . '/languages'
);
These:
- Register the custom path with WordPress’s text domain registry.
- Work with core’s automatic translation loading.
- Reduce the chance of conflicting with
_load_textdomain_just_in_time().
Method 6: (Advanced) Temporarily Silence the Notice via MU Plugin
If you’re dealing with a legacy or abandoned plugin that you can’t easily fix (for example, no access to its source code, or updates will overwrite your changes), you may choose to mute only this specific deprecation notice to keep logs and front-end output clean.
Important: this does not fix the underlying timing issue. It only hides the
_load_textdomain_just_in_time“doing it wrong” notice so you can keep working without noisy logs. Similar approaches are already used in the community as a workaround. (iTomation)
Step 1: Define a toggle constant (optional but recommended)
In wp-config.php, above the “That’s all, stop editing!” line, add:
define( 'DISABLE_DEPRECATION_NOTICE_LOAD_TEXTDOMAIN', true );
This lets you turn the suppression on/off without removing the file.
Step 2: Create an MU plugin
Create the file:
wp-content/mu-plugins/silence-jit-i18n-notice.php
Add this code:
<?php
/**
* Mute the '_load_textdomain_just_in_time' deprecation warning.
*/
if ( defined( 'DISABLE_DEPRECATION_NOTICE_LOAD_TEXTDOMAIN' ) && DISABLE_DEPRECATION_NOTICE_LOAD_TEXTDOMAIN ) {
add_filter(
'doing_it_wrong_trigger_error',
fn( $doing_it_wrong, $function_name ) => $function_name !== '_load_textdomain_just_in_time' ? $doing_it_wrong : false,
10,
2
);
}
What this does:
- Hooks into the
doing_it_wrong_trigger_errorfilter, which controls whether “doing it wrong” notices become PHP warnings. - If the offending function is
_load_textdomain_just_in_time, it returnsfalse, preventing the notice from being triggered. - Because it’s an MU plugin, it loads automatically on every request.
Again: use this as a temporary shield, not a permanent solution. You should still fix or replace the plugins/themes that load translations too early where possible.
Best Practices to Avoid Translation Errors in WordPress 6.7+ and 6.8
To future-proof your code against similar issues:
- Use the right hooks
- Plugins: register translation paths early, but make sure real translation usage (or anything that triggers
_load_textdomain_just_in_time) happens no earlier thaninit. In practice,plugins_loadedorinitis a safe place for loading plugin text domains. - Themes: load text domains in
after_setup_theme(classic/child themes) or rely on core’s automatic loading for properly configured block themes.
- Plugins: register translation paths early, but make sure real translation usage (or anything that triggers
- Keep translations in the expected locations
Usewp-content/languages/plugins/andwp-content/languages/themes/for production translations wherever possible. - Use consistent text domains
Match the text domain used in headers,load_*_textdomain()calls, and translation functions (__(),_e(), etc.). - Don’t expose notices on live sites
On production, keep:define( 'WP_DEBUG', true ); define( 'WP_DEBUG_DISPLAY', false ); define( 'WP_DEBUG_LOG', true );so notices go to logs instead of visitors’ screens. - Test updates in a staging environment
When upgrading WordPress (especially major versions like 6.7 or 6.8), test your stack in a staging copy first and inspectdebug.logfor new notices.
Final Thoughts
The “Function _load_textdomain_just_in_time was called incorrectly” notice is WordPress nudging you toward better translation loading practices, not a sign that your site is broken.
If you:
- Move translation loading into the proper hooks,
- Ensure your text domains and file paths are correct,
- Avoid direct
load_textdomain()where possible, and - Optionally use an MU plugin to mute this one deprecation notice while you refactor legacy code,
you’ll eliminate the warning and be better aligned with the modern i18n system shipped in WordPress 6.7 and 6.8.


