Skip to content Skip to sidebar

This is the technical support forum for WPML - the multilingual WordPress plugin.

Everyone can read, but only WPML clients can post here. WPML team is replying on the forum 6 days per week, 22 hours per day.

This topic contains 6 replies, has 0 voices.

Last updated by Otto 2 weeks, 1 day ago.

Assisted by: Otto.

Author Posts
October 3, 2025 at 10:36 am #17454068

Denis Papovic

We have a custom post type “People“ on our website. We have a translation manager, that we want to be able to assign the work to a translator, then when translator finishes the job, we want our translation manager to review translated post, and if everything is fine, to publish it. We manage to get it to work somehow, but the accessibility of the translation jobs from a view of translation manager is not so great, so we were wandering if there is something we can do about it, that’s integrated inside WPML settings.

OK let’s start from the beginning.

We want the scenario when translator finishes job, the newly translated post is not published, until translator manager reviews it.

The only way we manage to achieve this is by selecting “Save the translated post as a draft“ on “When you receive completed translations“ section. But this also means that when translator manager translates the page, or edit translated page, it also goes to draft. It would be really useful if we would have an option when translator finishes the job, status of that post inside Translation Management → Translation Jobs tab, goes to something like “Needs review“, and then when translator manager reviews it changes the state to publish. I saw that there is something similar in documentation, but we couldn’t find anywhere the way for our translated post to reach that status. After the job is done by the translator side, the status always goes to “Completed“. Can we also somehow make translated posts go to drafts only when assigned to a translator?

It’s hard to review translated posts from the Translation Jobs tab

At the moment for all our translated jobs, when you hover over it there is only one option - to view the original post. There is no other action that could be taken from there. This means that our translator manager needs to go to the original post, then add language extension to the page, then review the post, then edit the post, and finally publish it from the edit page backend. This is very impractical. We tried to make this cycle a bit shorter by adding a preview button into Translation jobs button Action column, which adds a language extension to the post, and opens translated version of a post.

php

// Enqueue JS on Translation Management pages only for allowed users
add_action('admin_enqueue_scripts', function($hook) {
   if (strpos($hook, 'tm/menu') === false) return;

   $current_user = wp_get_current_user();
   if (!in_array('administrator', $current_user->roles) &&
       !in_array('translation_manager', $current_user->roles) &&
       !is_super_admin($current_user->ID)
   ) {
       return;
   }

   wp_enqueue_script(
       'custom-wpml-actions',
       get_template_directory_uri() . 'https://cdn.wpml.org/assets/dist/js/wpml-job-actions.js',
       ['jquery'],
       '1.0',
       true
   );
});

// AJAX handler to return current user roles
add_action('wp_ajax_wpml_get_current_user_roles', function () {
   $current_user = wp_get_current_user();
   if (!$current_user) {
       wp_send_json_error(['message' => 'No user']);
   }
   wp_send_json_success([
       'roles' => (array) $current_user->roles,
   ]);
});

JS

jQuery(document).ready(function ($) {
   console.log("[WPML DEBUG] Custom script loaded");

   const langMap = {
       spanish: 'es',
       german: 'de',
       french: 'fr',
       italian: 'it',
       portuguese: 'pt'
   };

   const allowedRoles = ['administrator', 'translation_manager', 'super_admin'];

   // Check if user is allowed
   $.get(ajaxurl, { action: 'wpml_get_current_user_roles' }, function (response) {
       if (response.success) {
           const userAllowed = response.data.roles.some(role => allowedRoles.includes(role));
           console.log("[WPML DEBUG] User allowed:", userAllowed);
           if (userAllowed) setupButtons();
       }
   });

   function setupButtons() {
       function injectButtons() {
           $('tr.ant-table-row').each(function () {
               const row = $(this);
               const actionsCell = row.find('td.wpml-actions .ant-space');
               if (!actionsCell.length) return;
               if (actionsCell.find('.custom-preview-post').length > 0) return;

               const originalLink = row.find('td.wpml-title-column a[href]').attr('href') || '';
               const targetLangText = row.find('td.wpml-language-column .wpml-target-lang').text().trim().toLowerCase();
               const langCode = langMap[targetLangText];
               if (!originalLink || !targetLangText || !langCode) return;

               // Get status safely
               const statusText = row.find('td.wpml-status-column').text().trim().toLowerCase();
               if (!statusText.includes('completed')) return;

               // Build Preview URL
               let previewUrl = originalLink;
               if (/\/[a-z]{2}\//.test(originalLink)) {
                   previewUrl = originalLink.replace(/\/[a-z]{2}\//, '/' + langCode + '/');
               } else {
                   const urlParts = originalLink.split('/');
                   urlParts.splice(3, 0, langCode);
                   previewUrl = urlParts.join('/');
               }

               // Add Preview button
               const button = $('<button>')
                   .addClass('ant-btn ant-btn-primary custom-preview-post')
                   .text('Preview')
                   .on('click', function () {
                       window.open(previewUrl, '_blank');
                   });

               actionsCell.prepend($('<div class="ant-space-item">').append(button));
               console.log("[WPML DEBUG] Added Preview button →", previewUrl);
           });
       }

       // Initial run
       setTimeout(injectButtons, 200);

       // MutationObserver for dynamic updates
       const targetNode = document.querySelector('.ant-table-tbody');
       if (targetNode) {
           const observer = new MutationObserver(() => setTimeout(injectButtons, 100));
           observer.observe(targetNode, { childList: true, subtree: true });
           console.log("[WPML DEBUG] MutationObserver active");
       }
   }
});

But we are sure that there must be a way to make this better from the WPML setup console. Could you help us to get there?

Translator manager couldn’t tell from the Transaltion jobs tab which posts are reviewed and published and which one are drafted and needs to be reviewed.

All posts have the same status “Completed“ and translation manager could not tell which ones are finished and which ones are awaiting for a review. Is there something we can do to make this more accessible? And how we can make translated posts out of the queue? We don't want a translator access to the translation version of the post, and to be able to edit it, once the job is finished. Also how can we remove it from the translation jobs tab as well for translator manager.

If you need anything let me know.

Thank you,

Denis

October 3, 2025 at 3:03 pm #17454826

Otto
WPML Supporter since 09/2015

Languages: English (English ) Spanish (Español )

Timezone: America/Argentina/Buenos_Aires (GMT-03:00)

Hello,

To ensure the quickest and most accurate support, please provide your debug information so I can look at some of your configurations. We have an excellent article on how to locate it here: https://wpml.org/faq/provide-debug-information-faster-support/.

Let me check if I understood the problem:
You want a workflow for CPT People where translators can complete jobs but nothing is published until a translation manager reviews and approves it. The current workaround (“Save translated post as draft”) works but makes the manager’s own edits also land as drafts and gives poor visibility in Translation Jobs (everything says Completed). You also want a clean way—ideally inside WPML—for managers to see which items need to review, open the translated entry directly, approve/publish it, and keep translators from editing it after delivery.

WPML has a streamlined process to review translations:
https://wpml.org/documentation/reviewers/how-to-work-as-a-reviewer/

Please check if this flow is suitable for your use case:

❌ Please make a full website backup before proceeding ❌

* Go to **WPML → Settings → Automatic translation** and set **What should happen with your automatically translated content** to **Let me review it before it gets published**. This enables the **Pending review** workflow and the **Review** button in **WPML → Translations**.
* Ensure **CPT People** is set to *Translatable – only show translated items* in **WPML → Settings → Post Types Translation** so it shows in the queue filters.
* Assign **language pairs** to your Translation Manager (and to any reviewers) in **WPML → Translation Management → Translators**. Missing pairs often hide items from review lists.
* Translators complete jobs (ATE or human input). Items land in **WPML → Translations** with **Pending review**. The Manager opens **WPML → Translations**, filters **Status: Pending review**, **Post type: People**, clicks **Review**, adjusts if needed, then **Approve** (publishes) or **Send back**.
* If the review list is blank, but counts show pending, run the quick maintenance actions in **WPML → Support → Troubleshooting** (Clear cache, Remove ghost entries, Sync local job IDs, etc.), then reload the queue.

**Notes:**
• This keeps translators from publishing; **only approvals publish**.
• You can still assign jobs from **WPML → Translation Management → Translation Dashboard** and track them in **Jobs**, but the actual *review & publishing* happens in **WPML → Translations** (not in the Jobs tab).

Best Regards,
Otto

October 8, 2025 at 7:02 pm #17468714

Denis Papovic

I have a role of super admin, which means I am translator manager. I have assigned a bunch of tasks to a translators, but when I go to WPML → Translations, logged in as a translator manager, I can't see them. I see only one item that was previously assigned to me. When I go to translation jobs I can see them but with complete status. When I'm logged in as a translator, in WPML → Translations I see the jobs that are assigned to me.

My setting are set to match all that you described above inside WPML -> setttings.

Images attached are from translator manager WPML → Translations, trnalsation manager translation job, and regular translator WPML → Translations

08.10.2025_20.59.57_REC.png
08.10.2025_20.58.13_REC.png
08.10.2025_20.55.14_REC.png
October 8, 2025 at 7:35 pm #17468857

Otto
WPML Supporter since 09/2015

Languages: English (English ) Spanish (Español )

Timezone: America/Argentina/Buenos_Aires (GMT-03:00)

Hello,

Is the super admin also an admin in the sub-site?

I am not sure if I am getting the problem :(, please apologize.

I created a clean installation of WordPress, WPML, and all necessary WPML add-ons. I enabled ATE and automatic translation (with a dummy engine), in case you need it. May I kindly ask you to reproduce the problem with a minimal setup? I think the flow you are looking for is not related with the CPT, so you can use post or pages.

You can access the WordPress dashboard using the link below:
hidden link

Thanks!

Best Regards,
Otto

October 13, 2025 at 3:22 pm #17480426

Denis Papovic

OK, let's go step by step. We have custom post type people that we are translating. translators are people who are hired to translate assigned post, and don't have access to anything else other than translation tasks(under "Translations" tab). How can I, as a translator manager, remove translation tasks from translator list (job list that appears under translations tab, when logged in as a translator), once the post is translated by the translator and approved by translator manager?

October 14, 2025 at 3:16 pm #17484669

Denis Papovic

Any feedback on this one?

October 14, 2025 at 3:57 pm #17484836

Otto
WPML Supporter since 09/2015

Languages: English (English ) Spanish (Español )

Timezone: America/Argentina/Buenos_Aires (GMT-03:00)

Hello,

Thanks for the explanation.

It's expected that jobs don't go away from the Translation Manager view of the jobs list. The TM should use the filters to see what's missing and what's completed.

You don't want that the translator can edit the translation once it's finished, right? This feature was discussed a while ago, and it was decided to leave it as it is now, because in most cases translators are requested to edit translations after they are completed and, in general, translator don't edit the jobs after they are done.

As a workaround, after the translation is completed, send it again to translation and assign it to the TM. This will remove it from the Translator jobs list.

I understand that this is not convenient, but the feature you need is not currently available.

Best Regards,
Otto