WPML Cleanup and Duplicated Media Library: A Story from Experience

Removing the WPML (WordPress Multilingual Plugin) can leave behind unwanted remnants of content translations and duplicate images in your WordPress media library and posts. If you’ve encountered this issue, you know how frustrating it can be. Recently, I faced this issue on a client’s website and spent hours searching for a solution. In this article, I will provide step-by-step instructions on how I successfully removed these digital duplicates and cleaned up their website.

The Discovery of Duplicates:

A client has notified me that she deleted the WPML plugin and removed the posts in different languages. She encountered a perplexing issue after deactivating the WPML plugin. Upon checking the media library, she was taken aback to find that all the images had been replicated multiple times, creating a disorienting effect similar to that of a hall of mirrors.

WPML Cleanup and Duplicated Media Library: A Story from Experience

I looked at her website from the backend, and to my surprise, each media file had tripled in presence, and although each duplicate bore a unique identification, they all pointed to the same file URL. After further investigation, I found that the issue was caused by the WPML plugin’s database, which had created duplicates of all the website’s content, including media files for each language that was previously used. This resulted in a bloated database.

Preparation Is Key:

Before delving into any form of digital cleanup, I knew I had to safeguard the site. Backing up was not just a suggestion; it was a necessity. I used a trusted backup plugin to create a complete copy of the website, files, and database. I also set up a staging environment to test the cleanup script, ensuring the live site wouldn’t face downtime or data loss.

The Cleanup Script:

I came across a script on the WPML forum suggested by a user, Nigel. This script is to clean up WPML, and it gave me some much-needed relief. It was specifically crafted to remove all translated content and media in a way that left no trace. Below is the script.

 * Run snippet one-time to delete translated CONTENT (posts, media, taxonomies) when removing WPML from a site
 * You MUST have an up-to-date backup before running this code in case of unexpected results
global $wpdb;
/* Delete translated media posts */
// Get IDs of all translated media
$results = $wpdb->get_results( "SELECT element_id FROM {$wpdb->prefix}icl_translations WHERE element_type = 'post_attachment' AND source_language_code IS NOT null", OBJECT );
foreach ($results as $result){
    // delete the attachment post but not the media file
    // cannot use wp_delete_attachment because it deletes the media file
    // cannot use wp_delete_post because for attachments it switches to wp_delete_attachment
    // solution is to first switch post type to something else then use wp_delete_post
    // use direct query to avoid overhead of wp_update_post
        array( 'post_type' => 'for-deletion' ),
        array( 'ID' => $result->element_id ),
        array( '%s' ),
        array( '%d' )
    // delete safely using wp_delete_post
    wp_delete_post( $result->element_id, true );
/* Delete translated posts and pages */
// Get IDs of all translated posts
$results = $wpdb->get_results( "SELECT element_id FROM {$wpdb->prefix}icl_translations WHERE element_type IN ('post_post','post_page') AND source_language_code IS NOT null", OBJECT );
foreach ($results as $result){
    wp_delete_post( $result->element_id, true );
/** Taxonomies 
 * First delete the WPML taxonomy_priority terms
 * Then delete all translated terms
// Delete translation_priority terms
$terms = get_terms( array(
        'taxonomy' => 'translation_priority',
        'hide_empty' => false
foreach ( $terms as $term ) {
    wp_delete_term($term->term_id, 'translation_priority'); 
// Delete all translated categories and tags
// Get IDs of all translated categories and tags
$results = $wpdb->get_results( "SELECT element_id FROM {$wpdb->prefix}icl_translations WHERE element_type IN ('tax_category','tax_post_tag') AND source_language_code IS NOT null", OBJECT );
// Get an array of term ids along with their taxonomy, needed for wp_delete_term
$terms = $wpdb->get_results( "SELECT term_id,taxonomy FROM wp_term_taxonomy", OBJECT_K );
foreach ($results as $result){
    $term_id = $result->element_id;
    $taxonomy = $terms[$term_id]->taxonomy;
    wp_delete_term( $term_id, $taxonomy );  

Installing WP Code Snippets:

I added the script to my theme’s functions.php file, but if you are not a techie and don’t understand editing files on WordPress, I suggest you use the WP Code Snippet Plugin.

WPML Cleanup and Duplicated Media Library: A Story from Experience

With the script in hand, I installed the WP Code Snippets plugin and added a new script. Copy the above script and change the code type to PHP. Give a name to the snippet as I named it “WPML CLEANUP”.

WPML Cleanup and Duplicated Media Library: A Story from Experience

Click the toggle button to activate the snippet and click on update. The script will immediately run, and the magic will happen.

Post-Script Site Review:

Once the script completed its task, I checked the media library. The duplicates had been successfully removed, leaving behind a clean and orderly space. I conducted a detailed and comprehensive navigation of the site, making certain that all the functionalities were intact and working seamlessly.

Regeneration and Restoration:

After removing the duplicates, I generated thumbnails for the remaining media to ensure proper display on the site.

That’s it. My client was happy to see her media library clean and well organized again, and so am I.

Need Help?

Not everyone is comfortable wielding scripts. If that sounds like you, seek a professional. Then reach out to us at [email protected], and we would be more than happy to help you with this annoying issue.

Leave a Comment