24

In this is guest post, Michael Wassmer explains how to build a multilingual product catalog using WordPress.

The idea for this post came from a discussion in the forum about sharing custom fields and media between translations.

The goal –  a multilingual product catalog with WordPress

To set up my small bilingual shop I didn’t want to use a complex e-commerce CMS, WordPress was just the right thing for what I needed. Also I was looking forward to testing the WPML plugin on a slightly more complex project than the usual classical blog or website.

So, in my English/French online catalog, the products are each described in a dedicated post. To add a product I simply add a post in the back-end of WordPress, giving it the name of my product as title, typing the description in the content text-area, uploading the products photos to the images gallery of the post, and using the custom fields for values like price, reference and size.

Here’s how a product post in English (the default language) would look :

post_example

Now, after creating the original post for a product, how do I create the translated (French) version of it? Following WPML’s instruction, I simply click on the Language box under the post content window, click on “show” next to “Translations” and then click on “add”. It opens up a new post page where I can type in all the translated informations of my product : French title, French description, etc.

Problem – translations duplicate product information

But wait! Here is the annoying thing. I also have to type in again the custom fields values: reference, price and size. In my case those values are the same in any language so it makes no sense having to enter them twice. This is an obvious problem that would make me lose a lot of time if I had to type in the same information multiple times for each product post translation.

It’s the same issue with the product images, I don’t want to upload all the product photos a second time for the same product in it’s translated version. Logically, product photos are the same in any language, so I should be able to upload them only once.

So, let’s save the translated post just like this, without typing in a translation for the custom fields and without uploading the product images.

Ok, now let’s have a look at some code. Here’s a very basic example of a product listing page for a category (usually the archive.php file of your WP theme) :

<?php while (have_posts()) : the_post(); ?>
  <ul class = "product">
    <li class = "title"><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></li>
    <li class = "ref"><?php echo get_post_meta($post->ID, 'Reference', true); ?></li>
    <li class = "price"><?php echo get_post_meta($post->ID, 'Price', true); ?></li>
  </ul>
<?php endwhile; ?>

That’s the classical loop. It shows a list of my products and the associated custom field values – Price and Reference.

Now if I click on another language in the language selector on the front-end of my website (French in my case), it shows the translation of the articles title, but it doesn’t show the reference and the price value. That’s normal, remember we didn’t enter them in the translated post..

So, how do I get WordPress to show the custom values I entered in the original English post ?

Solution – sharing custom fields between translations

Well, WPML is a powerful plugin that provides us with a very useful function to fetch those values from the original post, even on the translated pages.

We are going to use the icl_object_id() function and replace the previous code by the following :

<?php while (have_posts()) : the_post(); ?>
<?php
  // Get the original post ID (in my case the english one)
  $o_ID = icl_object_id($post->ID, 'post', false, 'en'); ?>
  <ul class= "product">
    <li class = "title"><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></li>
    <li class = "ref"><?php echo get_post_meta($o_ID, 'Reference', true); ?></li>
    <li class = "price"><?php echo get_post_meta($o_ID, 'Price', true); ?></li>
  </ul>
<?php endwhile; ?>

Basically what we did was to retrieve the ID of the original post corresponding to any translated post, and using this ID to get the custom values. Depending on the original language of your posts, you can change the last parameter of icl_object_id (‘de’ for German, ‘fr’ for French, etc.). You can get more information about the other parameters of this function here and a list of other functions in the coding API page.

That was for the custom fields, now how do I do the same with the image gallery?

Let’s take our first example and also show three thumbnails images for each post in the list:

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

<?php
  // Get the original post ID (in my case the english one)
  $o_ID = icl_object_id($post->ID, 'post', false, 'en'); ?>

  <ul class= "product">
    <li class = "title"><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></li>
    <li class = "ref"><?php echo get_post_meta($o_ID, 'Reference', true); ?></li>
    <li class = "price"><?php echo get_post_meta($o_ID, 'Price', true); ?></li>

<?php

  // Get 3 thumbnails from the original post
  $args = array('post_type' => 'attachment','numberposts' => 3,'post_status' => null,'post_parent' => $o_ID);
  $attachments = get_posts($args);
  if ($attachments) {
    foreach ($attachments as $attachment) {
      echo '<li class="thumbnail">'.wp_get_attachment_image($attachment->ID).'</li>';
    }
  }
?>
</ul>

<?php endwhile; ?>

Summary

You can easily customize this little script to fit your needs, showing more (or less) images or different sizes.

That’s it. Now we can show our product list in any language, and it will always contain all the product custom fields and images, even if technically these are only stored in the original post.

This gets really interesting for bigger catalogs with more languages. Imagine you have to change the price of a product in five languages. With the normal method you would have to edit all five posts. With this easy method you always have one “master” language with its posts containing the complete information about your products and translations reusing it.

Michael Wassmer is a freelance web designer based in Barcelona, Spain. You can contact him at mike@michaelwassmer.net

24 Responses to “Creating a multilingual product catalog”

  1. Thanks for your work. 🙂

    Still one problem: I can see the thumnbails but can’t click them to enlarge. How could I make them klickable? Thanks. 🙂

  2. Hi, how did you get WP to do a product catalog? I am doing a project right now where I need to make a product catalog with WP and could really use some help on how you got to where you were in your first post screenshot showing price. Thanks!

  3. Great!
    I had not thought of using custom fields in such a way but you put the idea in my mind in a very nice way.
    With such kinds of modifications on my site sure I can build great websites through simple modifications of the themes.
    If you do know good resources on creating custom forms for posts that enable you to add the product fields all at a time rather than having to memorize all the custom fields and adding them to each post you specify as a product.
    Appreciated Thanks

  4. Hi there,

    Is there a similar way to gather all meta data/attachments from a translation group?

    What I mean to say is that this solution will only work if you always include a translation in the default language (which is English in your case).

    What if you don’t include a translation in the default language, but have translations in multiple other languages and want the meta data/attachments to be the same for all these translations?

    Yours,

    • I’m not sure I understand the question. Best to post it in our forum with an example of what you’re trying to get.

  5. I was looking for a way to use the same “Featured image” from WordPress 3.0 across all translations of a page or posts. This seems to work. All I have to do is select a featured image in my original post (English).

    In case anyone else is trying to achieve the same result, here is the code I used to display the featured image in the header:


    ID, 'post', false, 'en');
    $image = wp_get_attachment_image_src( get_post_thumbnail_id( $o_ID ), 'post-thumbnail');
    list($src, $width, $height) = $image;
    if ( is_singular() && has_post_thumbnail( $o_ID ) && $width >= HEADER_IMAGE_WIDTH ) :
    echo get_the_post_thumbnail( $o_ID, 'post-thumbnail' );
    else : ?>
    <img class="wp-post-image" src="" width="" height="" alt="" />
    ?>

  6. CODE CORRECTION FROM PREVIOUS COMMENT

    I was looking for a way to use the same “Featured image” from WordPress 3.0 across all translations of a page or posts. This seems to work. All I have to do is select a featured image in my original post (English).

    In case anyone else is trying to achieve the same result, here is the code I used to display the featured image in the header:


    $o_ID = icl_object_id($post->ID, 'post', false, 'en');
    $image = wp_get_attachment_image_src( get_post_thumbnail_id( $o_ID ), 'post-thumbnail');
    list($src, $width, $height) = $image;
    if ( is_singular() && has_post_thumbnail( $o_ID ) && $width >= HEADER_IMAGE_WIDTH ) :
    echo get_the_post_thumbnail( $o_ID, 'post-thumbnail' );
    else : ?>

  7. Hi, I’m using worpdress 3 b2 with wpml dev

    I have tried the technique to display french (default language) from a specific french category but the wp_query returns nothing in other languages

    $daily = new WP_Query();
    $daily->query('cat=' . icl_object_id(array(3),'category',true, 'fr') . "&suppress_filters=1" );

    the following works in the default language but not in aother languages


    $daily->have_posts())

    is there anything I miss ?

    thanks

  8. Moïse: you saved my day!! awesome man!

    even if a think wpml is a great plugin, it lacks of a few features like an ability to copy content from other languages by default.

  9. Great writeup, but I am still struggling with this.

    I like to include the WP gallery into my page, so I think I should be able to use this too.

    In my page template I call the gallery shortcode (which needs the post ID), but it doesn’t work if I do:

    // Get the post ID (http://wpml.org/2009/09/creating-a-multilingual-product-catalog/)
    $o_ID = icl_object_id($post->ID, 'page', false, 'en');

    echo do_shortcode('[gallery id="' . intval( $o_ID->post_parent ) . '", columns="3", size="thumbnail", orderby="menu_order ASC", link="file"]');

    Anyone knows how to accomplish this correctly?

  10. Nice post!

    I would like to list all my products on one page only, with a custom page template.

    I’m trying to modify the thumbnail section a little bit to save some space in the design.
    I only want to show the first attached image of the 3 as a link. The link then opens up a modal box with all the images in a bigger format. With Next and Prev navigation of course.

    I’m using the Lightbox Plus plugin and it works, but it shows all the 3 thumbnails on the product page of course.

    Any way to get it to only show the first attached image from the array?

  11. This helped me a lot! I’m building a real estate website in Dutch, English and German languages and with posts as living spaces, this comes very handy. Especially for the images!

  12. Hi!

    I’m trying to solve the same problem, but “…usually the archive.php file of your WP theme)….” is not on this archive…. where can I found?

  13. Great article. Thanks.

    What about taxonomies/terms?

    A scenario:
    Blog in English and French. The administrator edits a English post by selecting/deselecting a term from a taxonomy. How can the french post get this update as well?

    • Actually, we are going to update this tutorial soon and show new techniques for building more modern project catalogs. This will include custom fields, taxonomy, parametric searches and even product comparisons. All multilingual. I’ll write about it in our blog as soon as it’s ready.