Prompt WordPress viewpoint: Multi-language web content and WordPress MultiLanguage (WPML)


We were recently asked to help a business that had used WordPress MultiLanguage (WPML) to set up a second language for its website. WPML is a commercial plugin, very reasonably priced for what you get, and extremely easy to use. If you’re planning to host web content in more than one language, then we highly recommend it. But what if your theme isn’t compatible with the way that WPML displays translated content?

The business in question already had most things working. Its marketing team had used WPML’s management tools to translate the content but there were two problems on the translated pages. Firstly, most of the pictures on the blog had disappeared and secondly, the main ‘recent posts’ widget on the home page wasn’t working.

Below is an overview of what we did and how we fixed it. If you want to learn more about WordPress, plugins and themes, then remember to sign up for our weekly WordPress tips, or sign up for our 60-day online WordPress course.

Broken pictures
After a quick trace of the HTML and into the theme’s functions and files, it became clear that this theme scaled most of the images on demand using its own scaling function. There is nothing wrong with that, and as an extra precaution the code always ensured that it would only scale images from the same domain as the blog (otherwise in theory you would be hosting a global image-scaling system on your WordPress server). WPML uses http://[your-site-url]/[two-letter-language-code]/[normal permalinks and slugs here] to serve the translated content. For example, http://www.example.com/my-great-blog-story becomes http://www.example.com/fr/mon-grand-blog. So now the image scaling code is trying to test for equality between the home_url() of your blog example.com/fr with the url of your image (which does not have a /fr in it). The solution is to edit the part of the code that tests for the home_url() and remove the /[two-letter-language code]

[code]
//need to strip the /fr/ from the home_url() to make the function work correctly
$my_home = home_url(); //the returned string includes the /fr/
//strip out everything after the first ‘/’ that appears after the ‘//’
$my_home = substr($my_home, 0, stripos($my_home,”/”,stripos($my_home,”//”)+2)+1);
//now test that the image $url is under your home url
if(strpos( $url, $my_home) === false) return false;
?>
[/code]


Recent Posts widget displays no posts on the translated page
To cut a long story short, both the WordPress documentation and the WPML documentation is excellent, but you need to read it carefully.

The root cause of the issue here was that the theme widget for displaying recent posts used the class WP_Query to directly query the WordPress database. This is valid but the direct query means WPML doesn’t get a look-in (WPML sits magically in the background using hooks and filters to ensure the correct language content is displayed, but if you query the database directly, WPML does not know about it). A better way to get posts for displaying anywhere in your blog outside the main loop is to use the function get_posts(). You can read all about it in the Codex, which also encourages you to use this function whenever you need to get posts.

So to create a fix we copied the entire existing widget code into the functions.php of the child theme (we always use child themes when we customize commercial themes so that the commercial theme can be updated separately without affecting the customizations). Once copied, we renamed the widget class, swapped the WP_Query code for get_posts() and we were almost there. WPML has a function called icl_object_id() to return the post ID of the translated blog content in the current language selected by your users, so the code looks like this – with two calls to get_posts()

[code]
global $post; //$post MUST BE THE GLOBAL
foreach ( $postslist as $post ) {

//get a translated post object
$__post = get_post(icl_object_id($post->ID, $post->post_type, false));
//make it global
$post = $__post;
//*now* set up the post data (on the ‘translated global $post’)
setup_postdata( $post );
//and now we can make the HTML:-
?>
[/code]


Want to learn about WordPress? Whether it’s a face-to-face training for you and your team, or our 60-day online training, our WordPress team is here to help you maximize your online visibility. Please visit our WordPress training page to register for a training today.