Posted on

WPML: Replacing posts with translations

Here’s a different approach to WPML searching. By default, you have two options. You can include posts in all languages in the results, or you can only use the current language.

This solution checks for matches also in other languages. If Relevanssi finds any, this script then replaces them with the translated posts. You get a wider range of results, but all in the current language.

This solution works best when all your posts appear in all languages.

To use this, add this code to your site:

remove_filter( 'relevanssi_hits_filter', 'relevanssi_wpml_filter' ); // Remove the original WPML filter.
add_filter( 'relevanssi_hits_filter', 'relevanssi_wpml_filter_show_translation' ); // Replace with our new filter.
function relevanssi_wpml_filter_show_translation( $data ) {
  $wpml_post_type_setting = apply_filters( 'wpml_setting', false, 'custom_posts_sync_option' );

  $current_blog_language = get_bloginfo( 'language' );
  $filtered_hits         = array();
  foreach ( $data[0] as $hit ) {
    $original_hit = $hit;

    $object_array = relevanssi_get_an_object( $hit );
    $hit          = $object_array['object'];
    $format       = $object_array['format'];

    if ( isset( $hit->blog_id ) ) {
      // This is a multisite search.
      switch_to_blog( $hit->blog_id );
      if ( function_exists( 'icl_object_id' ) ) {
        // Reset the WPML cache when blog is switched, otherwise WPML
        // will be confused.
        global $wpml_post_translations;
        $wpml_post_translations->reload();
      }
    }

    global $sitepress;

    // Check if WPML is used.
    if ( function_exists( 'icl_object_id' ) && ! function_exists( 'pll_is_translated_post_type' ) ) {
      if ( $sitepress->is_translated_post_type( $hit->post_type ) ) {
        $fallback_to_default = false;
        if ( isset( $wpml_post_type_setting[ $hit->post_type ] ) && '2' === $wpml_post_type_setting[ $hit->post_type ] ) {
          $fallback_to_default = true;
        }
        $id = apply_filters( 'wpml_object_id', $hit->ID, $hit->post_type, $fallback_to_default );
        // This is a post in a translated post type.
        if ( intval( $hit->ID ) === intval( $id ) ) {
          // The post is in the current language.
          if ( ! in_array( $id, wp_list_pluck( $filtered_hits, 'ID' ), false ) ) {
            $filtered_hits[] = $original_hit;
          }
        } elseif ( intval( $hit->ID ) !== intval( $id ) ) {
          // The post is in the other language, look for a translation.
          if ( ! in_array( strval( $id ), wp_list_pluck( $filtered_hits, 'ID' ), true ) ) {
            $_post = get_post( $id );
            if ( $_post ) {
              $filtered_hits[] = relevanssi_return_value( $_post, $format );
            }
          }
        }
      } else {
        // This is not a translated post type, so include all posts.
        $filtered_hits[] = $original_hit;
      }
    } elseif ( get_bloginfo( 'language' ) === $current_blog_language ) {
      // If there is no WPML but the target blog has identical language with current blog,
      // we use the hits. Note en-US is not identical to en-GB!
      $filtered_hits[] = $original_hit;
    }

    if ( isset( $hit->blog_id ) ) {
      restore_current_blog();
    }
  }

  // A bit of foolproofing, avoid a warning if someone passes this filter bad data.
  $query = '';
  if ( isset( $data[1] ) ) {
    $query = $data[1];
  }
  return array( $filtered_hits, $query );
}

This is almost the same as the default WPML compatibility in Relevanssi. Relevanssi checks if the post has a translation in the current language. Usually in that case Relevanssi discards the post, because it’s in the wrong language. Here Relevanssi adds the translation to the results instead.

Leave a Reply

Are you a Relevanssi Premium customer looking for support? Please use the Premium support form.

Your email address will not be published. Required fields are marked *