Support continuous job

Created on 7 March 2023, over 1 year ago
Updated 25 April 2023, over 1 year ago

Problem/Motivation

When Transifex provider is used in a continuous job, it doesn't work as expected. Continuous job should create a translation job item and send them immeadiately to transifex (or on cron run, depending on settings).

Currently after adding e.g. a node, an error message appears:

Warning: Attempt to read property "attributes" on null in Drupal\tmgmt_transifex\Transifex\TransifexApi->getStats() (line 158 of modules/contrib/tmgmt_transifex/src/Transifex/TransifexAPI.php).
Drupal\tmgmt_transifex\Transifex\TransifexApi->getStats('txdrupal__txsep__44__txsep__node', 'hu') (Line: 315)

Missing resource with slug: txdrupal__txsep__44__txsep__node
Basic page Test continuous job has been created.

The job is created, but it is "inactive" and doesn't created a related resource in the related Transifex project. And you cannot even create the resource later, because the resource creation function is not called in any later events (for example updating the job doesn't create the resource, and gives the same error message as above).



🐛 Bug report
Status

Active

Version

2.0

Component

Code

Created by

🇭🇺Hungary suchdavid

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @suchdavid
  • 🇭🇺Hungary suchdavid

    Created a patch

  • 🇭🇺Hungary suchdavid

    It seems that using the continuous job integration breaks updating the node edit submit, when "mark translations as outdated" is checked. To prevent this, there is patch for ignoring the outdated field. (But unfortunately this results in not starting a new job for the given translations).
    https://www.drupal.org/project/tmgmt/issues/3063378

  • 🇭🇺Hungary suchdavid

    Continuous updating may be treated with a custom modul, where hook_entity_update realizes the reactivating of job items.

    <?php
    /**
     * @file
     * Module.
     */
    
    use Drupal\Core\Entity\EntityInterface;
    use Drupal\Core\Entity\ContentEntityInterface;
    use Drupal\tmgmt\Entity\Job;
    use Drupal\tmgmt\Entity\JobItem;
    use Drupal\tmgmt_transifex\Transifex\TransifexApi;
    use Drupal\tmgmt_transifex\Utils\Helpers;
    
    /**
     * Implements hook_entity_update().
     */
    function mymodule_transifex_entity_update(EntityInterface $entity) {
      if ($entity instanceof ContentEntityInterface
        && $entity->isTranslatable()
        && !$entity->getEntityType()->get('entity_revision_parent_type_field')) {
    
        $entity = $entity->getUntranslated();
        $source_langcode = $entity->language()->getId();
        $current_job_items = _mymodule_transifex_load_continuous('content', $entity->getEntityTypeId(), $entity->id(), $source_langcode);
    
        if ($current_job_items) {
          $job = reset($current_job_items)->getJob();
          $translator = $job->getTranslator();
          $tx = new TransifexApi($translator);
    
          $translation_manager = \Drupal::service('content_translation.manager');
          $translation = $entity->hasTranslation($job->getTargetLangcode()) ? $entity->getTranslation($job->getTargetLangcode()) : NULL;
          $metadata = isset($translation) ? $translation_manager->getTranslationMetadata($translation) : NULL;
          $metadata->isOutdated();
    
          foreach ($current_job_items as $job_item) {
            // Reactivate old job if new translation arrives.
            $job_item->resetData();
            $job_item->getData();
            $job_item->active();
    
            $title = $job_item->label();
            $slug = Helpers::slugForItem($job_item);
    
            $strings = Helpers::extractStringsFromNode($job_item);
            $payload = Helpers::renderHTMLFromStrings($strings);
            $res = $tx->upsertResource($slug, $title, $job->id(), $payload);
    
            \Drupal::messenger()->addMessage('Added ' . strval($res->strings_created) . ' strings to resource named: ' . $title, 'status');
            $job_item->active();
          }
        }
      }
    }
    
    /**
     * Loads active job entities that have a job item with the identifiers.
     *
     * @param $plugin
     *   The source plugin.
     * @param $item_type
     *   The source item type.
     * @param $item_id
     *   The source item id.
     * @param string $source_language
     *   The source language of the item.
     *
     * @return \Drupal\tmgmt\Entity\JobItem[]
     *   An array of job item entities.
     */
    function _mymodule_transifex_load_continuous($plugin, $item_type, $item_id, $source_language) {
      $query = \Drupal::database()->select('tmgmt_job_item', 'tji');
      $query->innerJoin('tmgmt_job', 'tj', 'tj.tjid = tji.tjid');
      $result = $query->condition('tj.source_language', $source_language)
        // Only query for jobs that are currently active.
        ->condition('tj.state',Job::STATE_CONTINUOUS)
        ->condition('tj.translator','transifex')
        ->condition('tji.plugin', $plugin)
        ->condition('tji.item_type', $item_type)
        ->condition('tji.item_id', $item_id)
        ->fields('tji', array('tjiid'))
        ->fields('tj', array('target_language'))
        ->orderBy('tji.changed', 'DESC')
        ->groupBy('tj.target_language')
        ->groupBy('tji.tjiid')
        ->groupBy('tji.changed')
        ->execute();
      if ($items = $result->fetchAllKeyed()) {
        $return = array();
        foreach (JobItem::loadMultiple(array_keys($items)) as $key => $item) {
          $return[$items[$key]] = $item;
        }
        return $return;
      }
      return FALSE;
    }
    
  • Hi suchdavid,

    After conducting further investigation on our end, here are our findings:

    Issue #1: Whenever new content is created in Drupal, a job is created but remains inactive. This results in no translations being sent to Transifex for translation.

    → We are currently working on a fix for this issue, which will be released soon.

    ------------------------------------------------------------------------
    Issue #2: When content previously sent for translation is updated, no job is automatically created through the continuous jobs feature.

    → After fixing continuous jobs in our module, it appears that content updates are still not sent by the continuous jobs feature. This seems to be a Drupal/Tmgmt limitation. Is this your take as well? Is this why you suggest utilizing a custom module that implements hook_entity_update to re-enable job items?

  • Hi suchdavid,

    The fixes for issue #1 are included in our latest release: https://www.drupal.org/project/tmgmt_transifex/releases/2.0.7

Production build 0.71.5 2024