Tuesday, October 15, 2013

Wordpress: Making a multilingual website with Polylang

There are multiple solutions to make a Wordpress website multilingual :-) Up to now I had some experience with Polylang, let me share a few things about it that I find important to know.

Preparation

First, define the texdomain for your theme in the functions.php by adding this code:

 load_theme_textdomain( 'theme_name', TEMPLATEPATH.'/languages' );  

Installing

Download and install Polylang the usual way...

Polylang
http://wordpress.org/plugins/polylang/

Settings

After installing first add your languages in wp-admin at Settings > Languages. After that you will have more tabs available here. On the Settings tab, set your default language and convert your already recorded posts and pages to that language. On the String translation tab you can translate a few important bits like the title of the web page.

Basic usage

From now on you will be able to set the language of individual posts and pages. You can also create pages that are linked to their different language counterparts. This is useful if you want to be able to directly switch from an article to it's foreign language counterpart.

In the posts and pages lists you can either create new items the usual way, or you can click on the plus sign in the language column to add a different language version of an already existing item. This works at various other places like cathegories and tags too.

You can also edit a post/page and manually enter the counterpart items IDs...

Admin bar addition

There is a new option in the admin bar which allows you to show all elements in your posts/pages lists or only those of a specific language. This is very useful when managing content.

Widgets

Managing which widgets to show is really easy as now you can choose to make your widget appear only in case of a specific language. A new select for this function is available at the bottom of the widget editor.

Menus

The menu editor will offer new locations in the theme to place your menus, so you just have to create the counterparts of your already existing menus in the new languages. You don't have to modify your theme source.

The only problem it might cause is that it changes the container id of your menu in the html source, so it is a good idea to always put your menu in a wrapper div or <nav> and use it as the base of the menu css code instead of the menu div inside.

Setting the home page

I wrote about this in a previous post, but basically the deal is that you can set a page to be the home page and it will use the page.php in your theme. However, when you try to go to the home using a different language, there will be no post id to load. You can use this and modify this code at the begining of page.php:

 <?php get_header(); ?>  
      <?php if (have_posts()) : while (have_posts()) : the_post(); ?>  

To something like this:

 <?php get_header(); ?>  
       <?php   
         if(get_the_ID() == '') {   
            if(pll_current_language() == 'de') {   
              $wp_query = new WP_Query( 'page_id=20' );   
            };   
            if(pll_current_language() == 'fr') {   
              $wp_query = new WP_Query( 'page_id=40' );   
            };   
         };   
       ?>   
      <?php if (have_posts()) : while (have_posts()) : the_post(); ?>  

Language switcher

Polylang has a built-in language switcher, but I found a really simple plugin that produces just what I need:

Simple Language Switcher

After installing it, you can set it up in the wp-admin settings area. You can add the desired languages to be displayed and set up the way you want them displayed. Very simple and intuitive.

You might need to go into the plugin directory to extract more flag icons. The plugin contains the famfamfam flag icons pack in a compressed archive, but only a few of them are extracted by default.

You can find more information about it on it's home page here:

The plugin contains a widget, but you can also insert the switcher in your theme with this code: 

 <?php if( function_exists( 'simple_language_switcher' ) ) { ?>  
 <div id="simple-language-switcher"><?php simple_language_switcher(); ?></div>  
 <?php } ?>  

The basic css rules that you need to add and modify are these:

 #page{position:relative;}  
 #simple-language-switcher{position:absolute;right:50px;top:10px;}  


Custom language switcher

This is just a basic stupid code that can be extended to be exactly what you need:
(The default language in this example was 'hu')

 <?php   
      global $polylang;  
      if (isset($polylang)) {  
       $languages = $polylang->get_languages_list();  
      }  
      foreach($languages as $lang) {  
           if($lang->slug == 'hu') {  
                echo '<a ';  
                if(pll_current_language() == $lang->slug) {  
                     echo 'class="active"';  
                }  
                echo 'href="'.get_bloginfo('wpurl').'">'.$lang->slug.'</a>';  
           } else {  
                echo '<a ';  
                if(pll_current_language() == $lang->slug) {  
                     echo 'class="active"';  
                }  
                echo 'href="'.get_bloginfo('wpurl').'/'.$lang->slug.'">'.$lang->slug.'</a>';  
           };  
      }  
 ?>  

What is the current language?

It is very simple to check or print the current language whith the built in function:
 <?php echo pll_current_language(); ?>  

Custom Fields

Custom fields in posts and pages gave me a real headache the first time I tried them with polylang as the default settings synchronize the custom fields - just not how I expected.

For example we have an About us page with the custom field of Phone. When I add the alternative language counterpart to this page, the custom field is already there and already filled in. I thought that I just have to change it's value and I'll be set, but no, the two pages have a common custom field now and if I change the value it will be overwritten on the default page too.

You can either turn off the custom field synchronisation or add a new custom field with a localized label and query it like this:

 <?php $phone = get_post_meta($values->ID, __(‘Phone’, ‘domain’), true); ?>  

Next time I will most probably just turn off the sync...

Query example

A simple example to query hungarian language posts of a custom post type only sorted alphabetically:

 <ul>  
   <?php  
     global $post;  
     $tmp_post = $post;  
     $args = array( 'lang' => 'hu', 'numberposts' => 0, 'post_type' => 'Apps', 'order'=> 'ASC', 'orderby' => 'title' );  
     $myposts = get_posts( $args );  
     foreach( $myposts as $post ) : setup_postdata($post); ?>  
       <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>  
       <?php  
         $post_meta = get_post_meta(get_the_ID());  
         print_r($post_meta);  
       ?>  
     <?php endforeach; ?>  
   <?php $post = $tmp_post; ?>  
 </ul>  


Further information

See the official documentation here:
http://polylang.wordpress.com/documentation/documentation-for-developers/