wxrks TMGMT Connector connects Drupal to wxrks, a context-first, AI-powered translation management platform. It adds wxrks as a translation provider in the Translation Management Tool (TMGMT), so site builders and content editors can submit content for translation, track job status, and receive translated content back in Drupal without leaving the site.

  • Submits TMGMT jobs (nodes, taxonomy terms and other TMGMT sources) to wxrks as translation projects.
  • Fetches delivered translations automatically on cron, on demand from the job page, or with the drush wxrks:fetch command.
  • Supports continuous jobs, so content changes are queued for re-translation.
  • Provides Views fields with the wxrks project name and last delivered workflow on the job items overview.

Project link

https://www.drupal.org/project/wxrks_tmgmt

Comments

guilhermesimbalista created an issue. See original summary.

avpaderno’s picture

Priority: Major » Normal
Issue summary: View changes
avpaderno’s picture

Thank you for applying!

Before giving links helpful to understand how the review process works, what to expect from a review, and what to do to avoid a review takes more time than needed, I would like to thank all the reviewers for the work they do.
These applications are volunters-driven, which also means it is not possible to predict when an application will be marked fixed and the applicant will get the permission to opt projects into security advisory policy. While we aim to make an application as quick as possible, it is also important for us that more people review the project used for an application. In this way, we make sure applications do not miss some important points that should be instead reported.
Applications are not meant to be complete debugging sessions that eliminate every existing bug, though. I apologize if sometimes applications seem to go into too-detailed reviews.

Please read Review process for security advisory coverage: What to expect for more details and Security advisory coverage application checklist to understand what reviewers look for. Tips for ensuring a smooth review gives some hints for a smoother review.

The important notes are the following.

  • If you have not done it yet, you should enable GitLab CI for the project and fix the PHP_CodeSniffer errors/warnings it reports.
  • For the time this application is open, only your commits are allowed.
  • The purpose of this application is giving you a new drupal.org role that allows you to opt projects into security advisory coverage, either projects you already created, or projects you will create. The project status will not be changed by this application; once this application is closed, you will be able to change the project status from Not covered to Opt into security advisory coverage. This is possible only 14 days after the project is created.

    Keep in mind that once the project is opted into security advisory coverage, only Security Team members may change coverage.
  • Only the person who created the application will get the permission to opt projects into security advisory coverage. No other person will get the same permission from the same application; that applies also to co-maintainers/maintainers of the project used for the application.
  • We only accept an application per user. If you change your mind about the project to use for this application, or it is necessary to use a different project for the application, please update the issue summary with the link to the correct project and the issue title with the project name and the branch to review.

To the reviewers

Please read How to review security advisory coverage applications, Application workflow, What to cover in an application review, and Tools to use for reviews.

The important notes are the following.

  • It is preferable to wait for a project moderator before posting the first comment on newly created applications. Project moderators will do some preliminary checks that are necessary before any change on the project files is suggested.
  • For the tools to use for reviewing a project, see Tools to use for reviews.
  • It may be best to have the applicant fix things before further reviews and avoid doing a review when another review is pending.

For new reviewers, I would also suggest to first read In which way the issue queue for coverage applications is different from other project queues.

avpaderno’s picture

As a side note, this application was unpublished by the anti-spam system that runs on drupal.org. That is why the first comment has been posted today.

vishal.kadam’s picture

Status: Needs review » Needs work

1. FILE: wxrks_tmgmt.module

For a new module that aims to be compatible with Drupal 10 and Drupal 11, I would rather implement hooks as class methods as described in Support for object oriented hook implementations using autowired services.

2. FILE: src/Plugin/QueueWorker/WxrksApiFetchQueueWorker.php, src/Plugin/QueueWorker/WxrksApiJobQueueWorker.php

Projects that are compatible with Drupal 10 or higher versions should use attributes instead of annotations.

guilhermesimbalista’s picture

Thanks for the review. Both points are fixed in the 1.0.x branch:

  1. Hooks: they are now methods of src/Hook/WxrksTmgmtHooks.php using #[Hook]. For Drupal 10, wxrks_tmgmt.module keeps procedural functions marked #[LegacyHook] that only delegate to that class.
  2. Attributes: both queue workers use #[QueueWorker]. The Views field plugins and the translator plugin now use attributes too.
guilhermesimbalista’s picture

Status: Needs work » Needs review
shaker-gspikes’s picture

Status: Needs review » Needs work

Manual review of 1.0.x at 7a4c2ec (9 October 2026). GitLab CI on that commit is green, phpcs (Drupal, DrupalPractice) is clean locally, and all commits are by the applicant. The fixes from #5 are in: hooks live in src/Hook/WxrksTmgmtHooks.php with #[LegacyHook] wrappers, and the queue workers, Views fields and translator use attributes.

Good things first: the module defines no routes or webhooks, TLS verification is never disabled, the auth token stays in memory and is never logged, remote UUIDs are validated before they are used in file paths, delivered ZIPs go to private:// (or temporary://) with size limits, the download URL is checked and fetched with allow_redirects => FALSE, the Views fields use #plain_text, and the XML is parsed with LIBXML_NONET.

Points to fix:

1. Credentials end up in exported configuration (src/WxrksTranslatorUi.php, config/schema/wxrks_tmgmt.schema.yml): accesskey and secretAccesskey are plain settings of the tmgmt.translator.* config entity, so drush config:export writes the secret key to the sync directory and into the site's repository. The usual workaround, a $config['tmgmt.translator.wxrks']['settings']['secretAccesskey'] override in settings.php, does not survive either: validateConfigurationForm() refills an empty password field from loadUnchangedTranslator(), which calls loadUnchanged(), and that applies config overrides. The next save of the translator form copies the overridden secret into active configuration. Store the key through the Key module (as other TMGMT providers do), or at least read the stored value with loadOverrideFree() and document the settings.php override in the README.

2. Aborting a job can fail half-way (src/Plugin/tmgmt/Translator/WxrksTranslator.php, abortTranslation()):
foreach ($job_items as $job_item) { $job_item->abortTranslation(); }
In TMGMT, JobItem::abortTranslation() throws TMGMTException('Cannot abort job item.') unless the item is active or needs review, while the job itself is still abortable. A job with one accepted item (common with auto-accept) therefore ends on an error page with some items aborted, the job state unchanged and the wxrks project never cancelled. Skip items where $job_item->isAbortable() is FALSE, and cancel the remote project regardless.

3. Connection errors are not caught (WxrksTranslator.php, doRequest() and the login request): both only catch BadResponseException, and getLanguagePairs() only catches TMGMTException. A DNS failure, refused connection or timeout throws a Guzzle ConnectException out of getSupportedTargetLanguages(), which TMGMT calls while checking out a job, so the checkout page returns a 500 error when the wxrks API is unreachable. Catch GuzzleException and rethrow it as TMGMTException; it would also help to set explicit connect_timeout/timeout options on these requests.

4. The cron queue worker can block cron for minutes (src/Plugin/QueueWorker/WxrksApiFetchQueueWorker.php): the worker declares cron: ['time' => 30], but cron only checks that budget between items. A single item goes through importTranslation() → downloadFilesAsync(), which polls for up to $maxTime = 180000 ms and then downloads with 'timeout' => 150. With automated cron that runs inside a visitor's request and can exceed max_execution_time, leaving the cron lock and the claimed item stuck. The "Fetch translations" button runs the same path in a normal web request. Throwing DelayedRequeueException while the export is still being prepared (instead of sleeping in a loop), and using the Batch API for the button, would keep each step short.

5. Pending re-translations are kept in the cache (src/Helper/QueueGateKeeper.php, cacheForFutureRequeue()): the list of nodes to re-queue is stored in cache.default with CACHE_PERMANENT. Any drush cache:rebuild (every deployment) silently drops it, and the read-modify-write without a lock loses entries when two workers run at the same time. This is state, not cache: the State API or a key/value collection fits better.

6. Continuous-job submissions are lost when the API call fails (src/Plugin/QueueWorker/WxrksApiJobQueueWorker.php): the worker saves a new job item, calls requestJobItemTranslation() (which catches every exception and only logs it), then removes the node from future re-queues, and processItem() also catches \Throwable. If the login fails, the queue item is deleted, the job item stays inactive and the change is never retried. Let the failure reach the queue as RequeueException or SuspendQueueException when the API is down.

Minor:
- wxrks_tmgmt.info.yml depends on tmgmt:tmgmt without a version, while composer.json requires ^1.18 (the first release with the TranslatorPlugin attribute). tmgmt:tmgmt (>=8.x-1.18) keeps tarball installs from enabling it on an older TMGMT.
- QueueGateKeeper queues every active or in-review job item for the fetch queue, not only items of wxrks translators, so the queue also fills with other providers' items.
- hook_uninstall() does not delete the two queues or the module's cache entries.

Status: Needs work (points 1 to 3).