How to get translations programmatically

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

The most important API in MultilingualPress for you is probably the Language API. This API has a method get_translations() that you can use to get a prepared set of translations for posts of any post type, terms of any taxonomy, a search term, the front page or a blog page.

You can access that API with a filter:

$mlp_language_api = apply_filters( 'mlp_language_api', NULL );

MultilingualPress will transform that NULL value now into an instance of the class Mlp_Language_Api. In other words: The variable $mlp_language_api is an object now. But you should still test that, just in case the user has deactivated MultilingualPress:

$mlp_language_api = apply_filters( 'mlp_language_api', NULL );

if ( ! is_a( $mlp_language_api, 'Mlp_Language_Api_Interface' ) )
	return;

As you can see, you should test against the Interface Mlp_Language_Api_Interface, not against the concrete class. This enables other plugins to replace our implementation with a custom translation handler.

Today, we are looking just at $mlp_language_api->get_translations( $args );

Arguments for Mlp_Language_Api::get_translations()

$args is an array, we can pass some options here to tweak the results.

Name Type Description
site_id int Base site. Usually the current site.
content_id int post or term_taxonomy ID, not term ID.
type string Either post, term, post_type_archive, search or front_page.
strict bool When TRUE (default) only matching exact translations will be included.
search_term string If you want to translate a search.
post_type string For post type archives.
include_base bool Include the base site in returned list.

All parameters are optional. MultilingualPress will try to find proper values for them. We recommend to set the content_id for terms and posts though, because that is not always available, at least not in a reliable way.

Now let’s see how our code could look like:

$mlp_language_api = apply_filters( 'mlp_language_api', NULL );

if ( ! is_a( $mlp_language_api, 'Mlp_Language_Api_Interface' ) )
	return;

$args = array (
	'strict'               => TRUE,
	'include_base'         => TRUE
);

/** @var Mlp_Language_Api_Interface $mlp_language_api */
$translations = $mlp_language_api->get_translations( $args );

if ( empty ( $translations ) )
	return;

Note that $mlp_language_api->get_translations( $args ) will return an empty array if there are no translations even when we set include_base to TRUE.

Now, let’s say the translations are not empty. We get an array of objects, each an instance of Mlp_Translation which implements the Mlp_Translation_Interface. That sounds complicated, but it just means that we have a set of methods on each object to get information about the translation.

Methods for Mlp_Translation

Method Return type Description
get_source_site_id() int The site ID the translation is based on.
get_target_site_id() int The ID of the site where the translation can be found.
get_page_type() string Either post, term, post_type_archive, search or front_page.
get_icon_url() Mlp_Url_Interface An object, an instance of a class implementing the Mlp_Url_Interface. It has a magic method __toString(), so we can cast it to a string and get an escaped URL.
get_target_title() string The title of the translation, for example the post title or the term name.
get_target_content_id() int The term_taxonomy_id or the post id. This is empty for other translation types like post type archives or search.
get_remote_url() string The URL for the translation.
get_language() Mlp_Language_Interface An object, an instance of a class implementing the Mlp_Language_Interface.

The Mlp_Translation::get_language() object deserves an explanation. It has three public methods.

Methods for Mlp_Language

Method Return type Description
get_priority() int A number between 0 and 10.
is_rtl() bool Whether the translation is in a right-to-left language (like Hebrew) or not.
get_name( $name ) string Different representations of the language. Default is the language in its native writing, eg. Deutsch for German. We strongly recommend to use that, because that’s most easily to recognize for your readers.
Other allowed parameters are english to get the English name, http to get the HTTP value (for example de-AT) or custom to get the custom name you have set in the site properties.
You can also use language_short to get just the first part of a language code with subsets, eg. just de.

Example: Add translation links to the post content

Let’s see what we can do with all this code. The following example adds very simple translation links to the post content. It uses the first part of the language code and sets it to uppercase. The images are used too, if they are available.

add_filter( 'the_content', function( $content ) {

    if ( ! is_singular() )
        return $content;

    $mlp_language_api = apply_filters( 'mlp_language_api', NULL );

    if ( ! is_a( $mlp_language_api, 'Mlp_Language_Api_Interface' ) )
        return $content;

    $args = array (
        'strict'               => TRUE,
        'include_base'         => TRUE
    );

    /** @var Mlp_Language_Api_Interface $mlp_language_api */
    $translations = $mlp_language_api->get_translations( $args );

    if ( empty ( $translations ) )
        return $content;

    $links = array();

    /** @type Mlp_Translation_Interface $translation */
    foreach ( $translations as $translation ) {

        $current = $img = '';

        if ( $translation->get_target_site_id() === get_current_blog_id() )
            $current = ' class="current"';

        $img_url = $translation->get_icon_url();

        if ( '' !== (string) $img_url )
            $img = "<img src='$img_url' alt=''> ";

        $text = $translation->get_language()->get_name( 'language_short' );
        $text = mb_strtoupper( $text, 'UTF-8' );

        $links[] = sprintf(
            '<a href="%1$s" title="%2$s" %3$s>%4$s</a>',
            $translation->get_remote_url(),
            esc_attr( $translation->get_target_title() ),
            $current,
            $img . $text
        );
    }

    $links = '<p class="translations">'
        . join( ' <span class="separator">|</span> ', $links )
        . '</p>';

    return $content . $links;
});

The result should look like this:

Theme integration

You can use such a function in other places too, of course. In a theme you should add a custom action wherever you need it and assign a callback handler to that action. This way, your theme will not break when the user deactivates MultilingualPress.

So in a template file add this line:

do_action( 'translation_box' );

And in your functions.php create a callback function and register it for that action:

add_action( 'translation_box', 'show_mlp_translation' );

function show_mlp_translation() {
    // find and print translation links
}

Any questions or suggestions? Or do you have used this tutorial successfully? Please let me know.


Build the perfect multilingual webshop with WooCommerce and our plugins MultilingualPress and CentralStock!