How to add icons to the language nav menu items

This tutorial is part of our MultilingualPress 2 documentation. In case you are using the newer version 3, please switch to MultilingualPress 3.

By default, our language navigation menus show the language name in its native spelling. This intended: We want to discourage the use of flags for languages. But we do offer the option to use a custom image for each site, and if you want to use that, you can add it to the link text.

The hook for that is mlp_prepare_nav_menu_item_output. You get two variables as input:

  1. $item: The nav menu item, an instance of the class WP_Post with some extra properties.
  2. $translation: An instance of an implementation of the Mlp_Translation_Interface. If we couldn’t find a translation for some reason, this variable is NULL, so you have to test it before you work with it.

The $translation has a method get_icon_url() which is again an object: an instance of the Mlp_Url_Interface. It can be casted to a string to get the URL. Another way is calling the method __toString() directly. If there is an icon, the escaped URL is returned. You get an empty string otherwise.

Here is how you can use it:

/**
 * Adds an icon to the menu text
 *
 * $item is passed as an object handle, so this function can change it directly
 * and doesn't have to return anything.
 * We still return a string value to make unit tests easier.
 *
 * @wp-hook mlp_prepare_nav_menu_item_output
 * @param   WP_Post                        $item
 * @param   Mlp_Translation_Interface|NULL $translation Might be NULL
 *                       if there is no translation for the item or
 *                       the other site is not linked to the current
 *                       site.
 * @return  string  When and why we stopped.
 */
function mlp_add_icons_to_menu( WP_Post $item, $translation = NULL ) {

	if ( ! is_object( $translation ) )
		return 'no translation object';

	if ( ! class_implements( $translation, 'Mlp_Translation_Interface' ) )
		return 'invalid translation object';

	if ( FALSE !== strpos( $item->title, '<img' ) )
		return 'icon already present';

	/* $translation->get_icon_url() returns an instance of
	 * Mlp_Url_Interface, so we have to cast it to a string
	 * before we check it with empty().
	 * @see Mlp_Url_Interface
	 */
	$icon_url = (string) $translation->get_icon_url();

	if ( empty ( $icon_url ) )
		return 'no icon available';

	$item->title = "<img src='$icon_url' alt=''> $item->title";

	return 'success';
}

add_action(
	'mlp_prepare_nav_menu_item_output', // hook
	'mlp_add_icons_to_menu',            // callback
	10,                                 // priority
	2                                   // number of accepted arguments
);

Download as plugin: MultilingualPress Addon: Nav Menu Icons. Activate it as a network plugin, and it will just work without further configuration.
You might have to adjust the image position in your stylesheet. Example:

.mlp-language-nav-item img {
    vertical-align: middle;
}

Here is a screenshot of such a changed menu with our built-in flags. Again: please do not use these flags. 🙂 Navigation menu with icons

Always add an alt attribute, but leave its value empty if you still have text, so users with screen readers don’t have to waste their time with it. The item text is good enough.