To make custom types in WordPress multilingual, your custom types need to be declared according to the recommended WordPress procedure:

  1. Make sure they’re registered on the ‘init‘ hook
  2. Never use a GetText call for the custom post type
  3. Always use the constants TRUE and FALSE. 0 and 1 may not work.
  4. Check the WordPress Codex for complete documentation –

Here is a working example that we use on our own website.

add_action('init', 'icl_theme_register_custom', 0);
function icl_theme_register_custom() {
        array('post', 'page'),
            'hierarchical' => true,
            'label' => 'Service type',
            'query_var' => true,
            'rewrite' => true

        register_post_type( 'testimonial',
            'description' => __( 'Testimonials.' ),
            'labels' => array(
                'name' => __( 'Testimonials' ),
                'singular_name' => __( 'Testimonial' ),
                'add_new' => __( 'Add New' ),
                'add_new_item' => __( 'Add New Testimonial' ),
                'edit' => __( 'Edit' ),
                'edit_item' => __( 'Edit Testimonial' ),
                'new_item' => __( 'New Testimonial' ),
                'view' => __( 'View Testimonial' ),

Then, you can choose if these custom types are translatable or not.

If you are using the Translation Management module, go to WPML->Translation Management and click on the Multilingual Content Setup tab. Otherwise, without the Translation Management module, you will find these options under WPML->Translation Options.

Multilingual Content Setup at the Bottom of Edit Screens

When custom types are translatable, they have language attributes. Each entry will appear for a specific language only and you can translate them to other languages.

WPML will filter the entires per language when you use the WordPress API calls to load them.

When not translatable, WPML doesn’t filter the custom type and entries will appear for all languages. This is useful if the data is not unique per language.