load_plugin_textdomain( string $domain, string|false $deprecated = false, string|false $plugin_rel_path = false ): bool

Loads a plugin’s translated strings.

Description

If the path is not given then it will be the root of the plugin directory.

The .mo file should be named based on the text domain with a dash, and then the locale exactly.

Parameters

$domainstringrequired
Unique identifier for retrieving translated strings
$deprecatedstring|falseoptional
Deprecated. Use the $plugin_rel_path parameter instead.

Default:false

$plugin_rel_pathstring|falseoptional
Relative path to WP_PLUGIN_DIR where the .mo file resides.

Default:false

Return

bool True when textdomain is successfully loaded, false otherwise.

Source

 *                                      Default false.
 * @param string|false $plugin_rel_path Optional. Relative path to WP_PLUGIN_DIR where the .mo file resides.
 *                                      Default false.
 * @return bool True when textdomain is successfully loaded, false otherwise.
 */
function load_plugin_textdomain( $domain, $deprecated = false, $plugin_rel_path = false ) {
	/** @var WP_Textdomain_Registry $wp_textdomain_registry */
	/** @var array<string, WP_Translations|NOOP_Translations> $l10n */
	global $wp_textdomain_registry, $l10n;

	if ( ! is_string( $domain ) ) {
		return false;
	}

	if ( false !== $plugin_rel_path ) {
		$path = WP_PLUGIN_DIR . '/' . trim( $plugin_rel_path, '/' );
	} elseif ( false !== $deprecated ) {
		_deprecated_argument( __FUNCTION__, '2.7.0' );
		$path = ABSPATH . trim( $deprecated, '/' );
	} else {
		$path = WP_PLUGIN_DIR;
	}

	$wp_textdomain_registry->set_custom_path( $domain, $path );

	// If just-in-time loading was triggered before, reset the entry so it can be tried again.
	if ( isset( $l10n[ $domain ] ) && $l10n[ $domain ] instanceof NOOP_Translations ) {
		unset( $l10n[ $domain ] );
	}

	return true;
}

/**
 * Loads the translated strings for a plugin residing in the mu-plugins directory.
 *
 * @since 3.0.0
 * @since 4.6.0 The function now tries to load the .mo file from the languages directory first.

Changelog

VersionDescription
4.6.0The function now tries to load the .mo file from the languages directory first.
1.5.0Introduced.

User Contributed Notes

  1. Skip to note 9 content

    Loading the plugin translations should not be done during plugins_loaded action since that is too early and prevent other language related plugins from correctly hooking up with load_textdomain() function and doing whatever they want to do.
    Calling load_plugin_textdomain() should be delayed until init action.

    add_action( 'init', 'wpdocs_load_textdomain' );
     
    /**
     * Load plugin textdomain.
     */
    function wpdocs_load_textdomain() {
      load_plugin_textdomain( 'wpdocs_textdomain', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' ); 
    }
  2. Skip to note 11 content

    The text domain name must use dashes and not underscores, be lower case, and have no spaces.

    Source: https://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/

    So use ‘wpdocs-textdomain’ instead of ‘wpdocs_textdomain’, e.g.

    load_plugin_textdomain( 'wpdocs-textdomain', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );

  3. Skip to note 12 content

    load_plugin_textdomain() is no longer necessary for plugins hosted on WordPress.org. Since WordPress 4.6, translations are automatically loaded from the languages directory, and since 6.7, a just-in-time loading system is used. Calling this function manually is now discouraged. It’s recommended to just use proper text domains in your __() , _e() , and other translation functions, and place .mo files in the standard plugin languages folder.

  4. Skip to note 13 content

    WordPress 6.7.0 has started showing following notice if load_plugin_textdomain is loaded with plugins_loaded hook.

    PHP Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the xyz-plugin/theme 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.

    As mentioned in this documentation/notes, use init hook instead of plugins_loaded to fix it.

    Example:

    function wpdocs_init() {
        load_plugin_textdomain( 'wpdocs-textdomain', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' ); 
    }
    add_action( 'plugins_loaded', 'wpdocs_init' );
  5. Skip to note 14 content

    If you are using the widgets_init hook in a plugin, I’d suggest setting the priority to 0 when using add_action to run the load_plugin_textdomain function. For example:

    add_action( 'init', 'my_load_plugin_textdomain_function', 0 );

    The reason for this is that the widgets_init action runs as a result of a priority 1 init hook. In your extended WP_Widget class you might use l10n functions such as __() to label or describe the widget. This therefore needs to happen after load_plugin_textdomain is called.

    Use of __() prior to using the load_plugin_textdomain function will result in subsequent translations failing for that registered domain.

  6. Skip to note 15 content

    Plugin Text domain load

    function my_plugin_init() {
        load_plugin_textdomain( 'my-textdomain', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' ); 
    }
    add_action( 'plugins_loaded', 'my_plugin_init' );
  7. Skip to note 16 content


    /**
    * Load plugin textdomain.
    */
    function load_translation() {
    load_plugin_textdomain( 'your-plugin-textdomain', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
    }
    add_action( 'plugins_loaded', 'load_translation' );

    The plugins_loaded hook is more appropriate than the init hook for loading translations because it ensures that all plugins are fully loaded before your plugin’s text domain is registered. This avoids potential issues with translation files being loaded too early.

    plugins_loaded hook: This hook fires after all active plugins have been loaded. It’s the recommended place for loading the text domain since all necessary plugin files will be available by then.

    init hook: While it can work, it’s fired earlier than plugins_loaded, and loading the text domain here may result in translations not being fully registered, especially if your plugin depends on other plugins being loaded.

    Therefore, using plugins_loaded is the best practice for ensuring reliable translation loading.

You must log in before being able to contribute a note or feedback.