{"id":333807,"date":"2026-07-01T12:55:52","date_gmt":"2026-07-01T12:55:52","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/wpml-translation-cleaner\/"},"modified":"2026-07-01T12:55:18","modified_gmt":"2026-07-01T12:55:18","slug":"translation-cleaner-for-wpml","status":"publish","type":"plugin","link":"https:\/\/srd.wordpress.org\/plugins\/translation-cleaner-for-wpml\/","author":15452977,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0.0","stable_tag":"1.0.0","tested":"7.0","requires":"5.9","requires_php":"7.4","requires_plugins":null,"header_name":"Translation Cleaner for WPML","header_author":"Klemens Hechenberger","header_description":"Safely identify and clean WPML translation issues \u2014 orphan translations, broken groups, and more.","assets_banners_color":"014e86","last_updated":"2026-07-01 12:55:18","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/hechenbros.ch\/plugins\/translation-cleaner-for-wpml\/","header_author_uri":"https:\/\/hechenbros.ch","rating":0,"author_block_rating":0,"active_installs":0,"downloads":39,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.0":{"tag":"1.0.0","author":"klemensh","date":"2026-07-01 12:55:18"}},"upgrade_notice":{"1.0.0":"<p>Initial release.<\/p>"},"ratings":[],"assets_icons":[],"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3592691,"resolution":"1544x500","location":"assets","locale":"","width":2203,"height":714}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.0"],"block_files":[],"assets_screenshots":[],"screenshots":{"1":"Module overview \u2014 three cards for Orphan Translations, Misplaced Originals, and Swapped Originals","2":"Orphan Translations scan results with reason codes and bulk actions","3":"Misplaced Originals results with per-row language reassignment dropdown","4":"Swapped Originals results with per-row Fix Original action"}},"plugin_section":[],"plugin_tags":[3786,732,99,2333,103],"plugin_category":[48,52],"plugin_contributors":[269729],"plugin_business_model":[],"class_list":["post-333807","plugin","type-plugin","status-publish","hentry","plugin_tags-cleanup","plugin_tags-maintenance","plugin_tags-multilingual","plugin_tags-translation","plugin_tags-wpml","plugin_category-language-tools","plugin_category-performance","plugin_contributors-klemensh","plugin_committers-klemensh"],"banners":[],"icons":{"svg":false,"icon":"https:\/\/s.w.org\/plugins\/geopattern-icon\/translation-cleaner-for-wpml_014e86.svg","icon_2x":false,"generated":true},"screenshots":[],"raw_content":"<!--section=description-->\n<p>Translation Cleaner for WPML helps you keep your multilingual WordPress site clean by identifying and fixing three common categories of WPML data corruption, all from a single admin tool under <strong>Tools \u2192 Translation Cleaner for WPML<\/strong>.<\/p>\n\n<p><strong>Module 1 \u2014 Orphan Translations<\/strong><\/p>\n\n<p>Finds translated posts whose main-language counterpart no longer exists (deleted or trashed). These orphaned records consume storage, clutter your admin, and break WPML's translation groups.<\/p>\n\n<ul>\n<li>Bulk action: Move to Trash (reversible) or Permanently Delete<\/li>\n<li>Reason codes per row: <em>Missing original<\/em>, <em>Original deleted<\/em>, <em>Original trashed<\/em><\/li>\n<li>Every deletion is re-validated immediately before execution \u2014 if the original was restored since the scan, the item is skipped<\/li>\n<\/ul>\n\n<p><strong>Module 2 \u2014 Misplaced Originals<\/strong><\/p>\n\n<p>Finds posts that WPML treats as originals (<code>source_language_code = NULL<\/code>) but are registered under a language that is not your main language \u2014 with no main-language version in that translation group at all.<\/p>\n\n<p>This typically happens when content is created directly in a secondary language without going through the main language first. Left uncorrected, these posts can cause translation workflow issues and incorrect language flags.<\/p>\n\n<ul>\n<li>Per-row fix: select the post's actual language from a dropdown and reassign it \u2014 no bulk guessing<\/li>\n<\/ul>\n\n<p><strong>Module 3 \u2014 Swapped Originals<\/strong><\/p>\n\n<p>Finds cases where a secondary-language post carries the \"original\" flag while a live main-language version exists in the same translation group. WPML incorrectly treats the secondary post as the source, which inverts the translation relationship for both posts.<\/p>\n\n<ul>\n<li>Per-row fix: one click to promote the main-language post to original and demote the secondary to a translation \u2014 the trid (translation group) is preserved<\/li>\n<\/ul>\n\n<p><strong>Common features across all modules<\/strong><\/p>\n\n<ul>\n<li>Scan all WPML-tracked post types, including non-public types like <code>nav_menu_item<\/code><\/li>\n<li>Filter by post type and main language<\/li>\n<li>Detailed results table with sort, search, and pagination<\/li>\n<li>Export results to CSV before taking any action<\/li>\n<li>Developer hooks: <code>wmtc_protected_post_ids<\/code>, <code>wmtc_orphan_results<\/code>, <code>wmtc_before_delete<\/code>, <code>wmtc_after_delete<\/code><\/li>\n<\/ul>\n\n<p><strong>Requirements<\/strong><\/p>\n\n<ul>\n<li>WPML must be installed and active<\/li>\n<\/ul>\n\n<!--section=installation-->\n<ol>\n<li>Upload the <code>wpml-translation-cleaner<\/code> folder to <code>\/wp-content\/plugins\/<\/code><\/li>\n<li>Activate the plugin through <strong>Plugins \u2192 Installed Plugins<\/strong><\/li>\n<li>Navigate to <strong>Tools \u2192 Translation Cleaner for WPML<\/strong><\/li>\n<li>Select a module, choose your main language and post types, then click <strong>Run Scan<\/strong><\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20this%20work%20with%20woocommerce%20multilingual%20%28wcml%29%3F\"><h3>Does this work with WooCommerce Multilingual (WCML)?<\/h3><\/dt>\n<dd><p>Yes. The scanners detect issues regardless of how WPML or WCML registered the content, including products managed in WCML's independent mode.<\/p><\/dd>\n<dt id=\"will%20it%20delete%20or%20modify%20content%20incorrectly%3F\"><h3>Will it delete or modify content incorrectly?<\/h3><\/dt>\n<dd><p>For orphan deletions, every item is re-validated against a fresh database scan immediately before the action runs. For reassignment actions (Misplaced Originals, Swapped Originals), the fix is performed via WPML's own <code>wpml_set_element_language_details<\/code> API \u2014 no raw data is modified outside of WPML's own logic.<\/p><\/dd>\n<dt id=\"can%20i%20undo%20a%20deletion%3F\"><h3>Can I undo a deletion?<\/h3><\/dt>\n<dd><p>Use <strong>Move to Trash<\/strong> for reversible cleanup. <strong>Permanently Delete<\/strong> is irreversible \u2014 always export a CSV and back up your database first.<\/p><\/dd>\n<dt id=\"can%20i%20undo%20a%20language%20reassignment%3F\"><h3>Can I undo a language reassignment?<\/h3><\/dt>\n<dd><p>Not automatically. Before running fixes in bulk, export a CSV so you have a record of the original state. The CSV can be used as a reference to manually revert if needed.<\/p><\/dd>\n<dt id=\"what%20post%20types%20are%20scanned%3F\"><h3>What post types are scanned?<\/h3><\/dt>\n<dd><p>All post types that WPML is tracking in <code>icl_translations<\/code>, including <code>nav_menu_item<\/code> which is a common source of orphaned translations invisible to standard WordPress post type queries.<\/p><\/dd>\n<dt id=\"how%20do%20i%20exclude%20specific%20posts%20from%20cleanup%3F\"><h3>How do I exclude specific posts from cleanup?<\/h3><\/dt>\n<dd><p>Use the <code>wmtc_protected_post_ids<\/code> filter:<\/p>\n\n<pre><code>add_filter( 'wmtc_protected_post_ids', function( $ids ) { $ids[] = 42; return $ids; } );\n<\/code><\/pre><\/dd>\n<dt id=\"is%20this%20plugin%20affiliated%20with%20wpml%20or%20onthegosystems%3F\"><h3>Is this plugin affiliated with WPML or OnTheGoSystems?<\/h3><\/dt>\n<dd><p>No. This is an independent tool built to work alongside WPML. WPML is a trademark of OnTheGoSystems.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release<\/li>\n<li>Module: Orphan Translations \u2014 find and delete orphaned translation posts<\/li>\n<li>Module: Misplaced Originals \u2014 find and reassign posts flagged as originals in the wrong language<\/li>\n<li>Module: Swapped Originals \u2014 fix inverted original\/translation relationships within a translation group<\/li>\n<\/ul>","raw_excerpt":"Find and fix WPML data issues \u2014 orphaned translations, misplaced originals, and swapped original flags.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/srd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/333807","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/srd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/srd.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/srd.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=333807"}],"author":[{"embeddable":true,"href":"https:\/\/srd.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/klemensh"}],"wp:attachment":[{"href":"https:\/\/srd.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=333807"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/srd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=333807"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/srd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=333807"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/srd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=333807"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/srd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=333807"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/srd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=333807"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}