Tagged: theme Toggle Comment Threads | Keyboard Shortcuts

  • Thorsten Frommen 2:53 pm on 2015/02/11 Permalink | Reply
    Tags: theme   

    How to get translations programmatically 

    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. See the post about Language negotiation for an explanation.
    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: Screenshot

    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.

     
  • Thorsten Frommen 6:17 am on 2014/04/02 Permalink | Reply
    Tags: , theme   

    Create a custom language switcher 

    We offer a widget and the “quick links” to show links to translations, but many users need a custom solution at other places or in a formatting we just don’t give them (yet).

    There is a handy helper function to get all the links as an array: mlp_get_interlinked_permalinks(). It returns an array with the text (human readable language name), the permalink to the other site’s translation and an entry lang (the language code) – for each single translation.

    You can use that to create your own language switcher. The following function creates a string that might look like this:

    EN | DE | RU

    Add it to your theme’s functions.php.

    /**
     * Create a navigation between translations
     *
     * @param  string $between  Separator between items
     * @param  string $before   HTML before items
     * @param  string $after    HTML after items
     * @return string
     */
    function mlp_navigation(
        $between = ' | ',
        $before  = '<p class="mlp-lang-nav">',
        $after   = '</p>'
    )
    {
        $links = (array) mlp_get_interlinked_permalinks();
    
        if ( empty ( $links ) )
            return '';
    
        $items = array ();
    
        foreach ( $links as $link ) {
            if ( isset ( $link['text'] ) ) {
                $text = $link['text'];
            }
            else {
                // take just the main code
                $first = strtok( $link['lang'], '_' );
                $text  = mb_strtoupper( $first );
            }
    
            $items[] = sprintf(
                '<a href="%1$s" hreflang="%2$s" rel="alternate">%3$s</a>',
                esc_url( $link['permalink'] ),
                esc_attr( $link['lang'] ),
                $text
            );
        }
    
        return $before . join( $between, $items ) . $after;
    }

    Now you can call the function wherever you need it without any arguments:

    echo mlp_navigation();

    Don’t forget the closing semicolon!

    If you want to get a list, you can change the parameters:

    echo mlp_navigation(
        '</li><li>', // between items
        '<ul class="mlp-lang-nav"><li>', // before
        '</li></ul>' // after
    );

    We will add support for custom menus in one of the next versions of Multilingual Press, so you can create your own menus with drag and drop.

     
    • Piet 4:31 am on 2014/07/02 Permalink | Reply

      Thanks for the tutorial, I will try to implement this. I noticed though that although Posts and Pages are perfectly linked together across languages, Categories are not. If I am looking at a Category Archive the language switcher links to the homepage of the resp. languages. Is there a way to fix this?
      Thanks,
      Piet

      • Thomas Scholz 5:47 am on 2014/07/02 Permalink | Reply

        This part is not completed – yet. We will add taxonomy support in version 2.1.

    • Jorge Díaz 11:39 pm on 2014/09/26 Permalink | Reply

      Hi, I think that the answer to this question is going to be pretty obvios, but when you want to print the code in a page you have to write the code using if that is correct I used it but I don’t know what is happening because is not showing the language switcher.

      • Thomas Scholz 12:00 am on 2014/09/27 Permalink | Reply

        Is there something missing in your comment? I’m not sure what exactly you are asking. :)

        • Jorge Díaz 1:20 am on 2014/09/28 Permalink | Reply

          Hi, thanks for your answer, actually yes the PHP tags are missing, but I finally did it, now I have other question. Multilingual Press works with multisite, I have multisite setup and 2 sites the second is cloned from the first one so I have the same data in both (pages and post) Priority of first language (site for first site) is 10 and second language(site) is 9. But how do I create the relationships between the pages from the first language to the pages in second language, because when I click the check button it creates a page in the same site as draft, so I don’t know what I am missing.

          • Thomas Scholz 1:46 am on 2014/09/28 Permalink | Reply

            Use the button Change Relationship to find the other post or page. It is right below the editor for the translation in MultilingualPress Pro. See our docs for screenshots.

            • Jorge Díaz 2:25 am on 2014/09/28 Permalink

              Hi, thanks for you answer, I am using the free version, I think that custom relationships are not available for the free version, now I managed to create a widget are as you can see here http://prntscr.com/4qzg2n it looks like the same widget from social icon, now my question is, is it possible at least to leave the widget as it is (because if I uncheck the “trasnlate this post option” it disappear) but linking to home page, because now it links to a page that doesn’t exist. Sorry to bother you. :(

            • Thomas Scholz 2:05 pm on 2014/09/28 Permalink

              If it links to the wrong page, it’s a bug. You should uncheck the option Show widget for translated content only. in the widget settings to get it on all pages.

              I have extended our language API in version 2.1, so you can create a much more granular language switcher now. I hope to find the time for a post about that next week.

            • Jorge Díaz 7:21 pm on 2014/09/28 Permalink

              Actually that option is unchecked :(

            • Jorge Díaz 7:29 pm on 2014/09/28 Permalink

              I have unchecked “show current site” and “show widget for translated content only” and now it appears just the flag for the other site in both site, but it’s linking to a page that don’t exist :S for example if the page is the home (domain.com) it’s linking to domain.com/lang/home-2/ and if I go to domain.com/about it links to domain.com/lang/about-2 so I don’t really understand what is happening.

c
Compose new post
j
Next post/Next comment
k
Previous post/Previous comment
r
Reply
e
Edit
o
Show/Hide comments
t
Go to top
l
Go to login
h
Show/Hide help
shift + esc
Cancel