Created on 8 February 2024, 10 months ago
Updated 13 September 2024, 3 months ago

WEB-T is an open source free automated website translation tool developed for European Commission. It has built-in integration with eTranslation MT API. This module uses Drupal core localization modules to automatically translate website content - articles, pages, comments, taxonomy terms, configuration & UI strings.

More information: https://website-translation.language-tools.ec.europa.eu/solutions/web-t-drupal_en

Project link

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

📌 Task
Status

Fixed

Component

module

Created by

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

Comments & Activities

  • Issue created by @dragels
  • 🇮🇳India vishal.kadam Mumbai

    Thank you for applying!

    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 run phpcs --standard=Drupal,DrupalPractice on the project, which alone fixes most of what reviewers would report.
    • 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 won't be changed by this application and no other user will be able to opt projects into security advisory policy.
    • 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 Code Review Administrator before commenting on newly created applications. Code Review Administrators will do some preliminary checks that are necessary before any change on the project files is suggested.
    • Reviewers should show the output of a CLI tool only once per application.
    • It may be best to have the applicant fix things before further review.

    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 .

  • Status changed to Needs work 10 months ago
  • 🇮🇳India vishal.kadam Mumbai

    Release branch names always end with the literal .x as described in Release branches . The only exception is for the main branch, which is actually not fully supported on drupal.org and should be avoided.

  • Update branch name in this issue and in code repository.

  • Status changed to Needs review 10 months ago
  • Status changed to Needs work 10 months ago
  • 🇮🇳India vishal.kadam Mumbai

    1. Move all files outside folder and delete "webt" folder

    2. Fix phpcs issues.

    phpcs --standard=Drupal,DrupalPractice --extensions=php,module,inc,install,test,profile,theme,css,info,txt,md,yml webt
    
    FILE: /home/vishalkadam/DRUPAL-REVIEW/webt/Notice.txt
    ----------------------------------------------------------------------
    FOUND 1 ERROR AFFECTING 1 LINE
    ----------------------------------------------------------------------
     23 | ERROR | [x] Expected 1 newline at end of file; 2 found
    ----------------------------------------------------------------------
    PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY
    ----------------------------------------------------------------------
    
    
    FILE: /home/vishalkadam/DRUPAL-REVIEW/webt/License.txt
    ----------------------------------------------------------------------
    FOUND 1 ERROR AFFECTING 1 LINE
    ----------------------------------------------------------------------
     339 | ERROR | [x] Expected 1 newline at end of file; 0 found
    ----------------------------------------------------------------------
    PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY
    ----------------------------------------------------------------------
    
    
    FILE: /home/vishalkadam/DRUPAL-REVIEW/webt/webt/src/Form/PretranslationForm.php
    --------------------------------------------------------------------------------
    FOUND 1 ERROR AND 7 WARNINGS AFFECTING 8 LINES
    --------------------------------------------------------------------------------
     300 | ERROR   | The array declaration extends to column 83 (the limit is 80). The array content should be split up over multiple lines
     349 | WARNING | Only string literals should be passed to t() where possible
     548 | WARNING | Only string literals should be passed to t() where possible
     587 | WARNING | Only string literals should be passed to t() where possible
     592 | WARNING | Only string literals should be passed to t() where possible
     597 | WARNING | Only string literals should be passed to t() where possible
     620 | WARNING | Only string literals should be passed to t() where possible
     659 | WARNING | Only string literals should be passed to t() where possible
    --------------------------------------------------------------------------------
    
    
    FILE: /home/vishalkadam/DRUPAL-REVIEW/webt/webt/src/Form/TranslationProviderForm.php
    --------------------------------------------------------------------------------
    FOUND 0 ERRORS AND 1 WARNING AFFECTING 1 LINE
    --------------------------------------------------------------------------------
     520 | WARNING | Only string literals should be passed to t() where possible
    --------------------------------------------------------------------------------

    3. FILE: webt/webt.info.yml

    core_version_requirement: ^8 || ^9 || ^10

    The Drupal Core versions before 8.7.7 do not recognize the core_version_requirement: key.

  • @vishal.kadam Thanks for the quick review, I have made required changes in WEB-T project's Drupalcode repository.

  • Status changed to Needs review 10 months ago
  • Changing the issue priority as per issue priorities .

  • Status changed to Needs work 9 months ago
  • 🇮🇹Italy apaderno Brescia, 🇮🇹
    • The following points are just a start and don't necessarily encompass all of the changes that may be necessary
    • A specific point may just be an example and may apply in other places
    • A review is about code that doesn't follow the coding standards, contains possible security issue, or doesn't correctly use the Drupal API; the single points aren't ordered, not even by importance

    src/Controller/EtranslationCallbackController.php

    $this->logger->info("Received late translation ($request_id)");

    The first argument must be a literal string, not a concatenation of strings. If there is part of the string that is dynamic, the literal string needs to use placeholders.

    src/Controller/AboutTabController.php

          $this->t("See how to <a target='_blank' href='@link'>configure and use this plugin</a>."),
          [
            '@link' => 'https://website-translation.language-tools.ec.europa.eu/solutions/drupal_en',
          ]
        );
    

    The correct placeholder for URLs starts with a colon, such as :link which must be surrounded by double quote characters.

        $text = "
    			<h5>$about_heading</h5>
    			<p>
    				$about_content
    			</p>
    			<p>
    				$configure_content
    			</p>
    			<h5>$more_info_heading</h5>
    			<p>
    				$more_info_content (<a target='_blank' href='$learn_more_link'>$learn_more</a>).
    			</p>
    			<p>
    				<img alt='EC logotype' class='logotypes' src='$ec_logotype_url' />
    				<img alt='WEBT logotype' class='logotypes' src='$webt_logotype_url' id='webt_logtype' />
    			</p>
    			";
    
        return [
          '#markup'   => $text,
          '#attached' => [
            'library' => [
              'webt/about_tab.style',
            ],
          ],
        ];
    

    Drupal has other way to output complex markup. #markup for simple markup, not markup with images and links.

    Also, what shown in the user interface must be translatable.

      /**
       * {@inheritdoc}
       *
       * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
       *   The Drupal service container.
       *
       * @return static
       */
      public static function create(ContainerInterface $container) {
        return new static(
          $container->get('webt.asset_manager')
        );
      }
    

    The fist line in the documentation comment is sufficient. If the documentation comment describes parameters and return value, using {@inheritdoc} does not have any pro.

    src/Controller/AboutTabController.php

        $configure_content = new FormattableMarkup(
          $this->t("See how to <a target='_blank' href='@link'>configure and use this plugin</a>."),
          [
            '@link' => 'https://website-translation.language-tools.ec.europa.eu/solutions/drupal_en',
          ]
        );
    

    For translatable markup, there is the TranslatableMarkup, but there is no need to explicitly create an instance of that class, since it is already returned from $this->t().

    src/Form/TranslationProviderForm.php

    If the form is used to save values in a configuration object, its parent class needs to be ConfigFormBase.

  • Status changed to Needs review 7 months ago
  • @apaderno Thanks for the review, I have fixed these types of issues in my latest commits.

  • Status changed to Needs work 6 months ago
  • 🇮🇹Italy apaderno Brescia, 🇮🇹

    webt.module

    /**
     * Perform scheduled translations for entity to be loaded.
     *
     * @param \Drupal\Core\Entity\Entity $e
     *   Entity.
     */
    function webt_entity_load($e) {
      $entity = \Drupal::state()->get("webt_update_entity");
      if ($entity) {
        \Drupal::state()->delete("webt_update_entity");
        $translation_manager = \Drupal::service('webt.translation_manager');
        $translation_manager->entityUpdateAllTranslations($entity);
      }
    }
    

    Hook implementations use a different documentation comment.
    Entity hooks like this one needs to use the entity passed as parameter, not an entity stored somewhere. If an entity must the flagged for translation, a dynamic property needs to be set for that entity. (The ContentEntityBase class implements the __get() and __set() magic methods.

      if (method_exists($entity, 'isTranslatable') && $entity->isTranslatable() && array_key_exists('default_langcode', $entity->toArray()) && $entity->default_langcode &&
          $entity->default_langcode[0]->value && \Drupal::service('webt.translation_manager')->entityTranslatableContentChanged($entity)) {
        \Drupal::state()->set("webt_update_entity", $entity);
      }
    

    Instead of verifying a method exists, the code needs to verify the object implements Drupal\Core\TypedData\TranslatableInterface.

    src/Controller/AboutTabController.php

            'configure_content' => [
              '#type' => 'html_tag',
              '#tag' => 'p',
              '#value' => Markup::create($this->t('See how to <a target="_blank" href=":link">configure and use this plugin</a>.', [
                ':link' => 'https://website-translation.language-tools.ec.europa.eu/solutions/drupal_en',
              ])),
    

    The Drupal\Core\Render\Markup class is internal and must not be used by contributed modules. In this case, it is not even necessary to use that class, since $this->t() already returns an object that implements \Drupal\Component\Render\MarkupInterface.

      /**
       * The request stack service.
       *
       * @var \Symfony\Component\HttpFoundation\RequestStack
       */
      protected $requestStack;
    

    There is not need to add request_stack as dependency and use that property, since:

    Additionally, if a parameter is typed to one of the following special classes the system will pass those values as well.

    • \Symfony\Component\HttpFoundation\Request: The raw Symfony request object. It is generally only useful if the controller needs access to the query parameters of the request. By convention, this parameter is usually named $request.
    • \Psr\Http\Message\ServerRequestInterface: The raw request, represented using the PSR-7 ServerRequest format. This object is derived as necessary from the Symfony request, so if either will suffice the Symfony request will be slightly more performant. By convention this parameter is usually named $request.
    • \Drupal\Core\Routing\RouteMatchInterface: The "route match" data from this request. This object contains various standard data derived from the request and routing process. Consult the interface for details.

    (Routing API / Route controllers for simple routes)

      /**
       * The cache service.
       *
       * @var \Drupal\Core\Cache\CacheBackendInterface
       */
      protected $cache;
    

    There is no need to use that property, since the parent class has cache().

      /**
       * The language manager service.
       *
       * @var \Drupal\Core\Language\LanguageManagerInterface
       */
      protected $languageManager;
    

    There is no need to use that property, since the parent class has languageManager().

      /**
       * The logger service.
       *
       * @var \Psr\Log\LoggerInterface
       */
      protected $logger;
    
      /**
       * Entity type manager service.
       *
       * @var \Drupal\Core\Entity\EntityTypeManagerInterface
       */
      protected $entityTypeManager;
    

    Similarly, there is no need to define those properties, for the same reason. Check which methods must be called to initialize the parent properties.

    src/Controller/PretranslationProgressController.php

      use LoggerChannelTrait;
    

    That trait is already used from the parent class, together other traits.

        use AutowireTrait;
        use LoggerChannelTrait;
        use MessengerTrait;
        use RedirectDestinationTrait;
        use StringTranslationTrait;
    

    None of those traits needs to be used from ControllerBase child classes.

      /**
       * Messenger.
       *
       * @var Drupal\Core\Messenger\MessengerInterface
       */
      protected $messenger;
    

    The parent class has methods to use the messenger. Check also which methods must be called to initialize the parent properties.

        $logs = Link::fromTextAndUrl('logs', Url::fromRoute('dblog.overview'));
        $this->messenger->addError($this->t("Backend translation process was aborted! Check @logs for errors or try increasing website's PHP max_execution_time.", ['@logs' => $logs->toString()]));
        return new Response();
    

    The correct code to add a link in a translatable string is similar to the following code, which uses the url_generator service (which exists also in Drupal 11).

    $message = $this->t('Operating in maintenance mode. <a href=":url">Go online.</a>', [':url' => $this->urlGenerator->generate('system.site_maintenance_mode')]);
    
    $this->messenger->addMessage($message, 'status', FALSE);
    

    src/Form/PretranslationForm.php

    The class defines properties that are not necessary because the parent class already define the necessary methods; it also include methods that child classes need to call to initialize the parent properties.
    For inherited methods, the documentation comments are different from the documentation comments this class uses.

      public function submitForm(array &$form, FormStateInterface $form_state) {
        $this->messenger->deleteAll();
        $config = $this->configFactory->getEditable('webt.settings');
        $types  = StringType::getAllTypes();
        foreach ($types as $type) {
          $selected = $form_state->getValue('advanced')[$type];
          $config->set('translate_' . $type, $selected);
        }
        $config->save();
        $this->messenger->addStatus($this->t('Affected content type selection saved'));
      }
    

    Submission form handlers do not need to remove messages from the messenger.

  • Status changed to Needs review 6 months ago
  • Thanks for the review, I have updated the code. Regarding the idea of using __set() method to mark entity for translation - this did not seem to work. I tried:
    1. Using __set() without $entity->save() - dynamic field was not preserved in hook_entity_load method
    2. Using __set() with $entity->save() - I get 'Update existing 'node' entity revision while changing the revision ID is not supported.' error
    3. Calling __set() from hook_entity_presave instead of hook_entity_update or hook_entity_insert, so that entity is saved afterwards.

    However, I refactored the method, so that it uses the entity list provided as parameter.

  • 🇮🇹Italy apaderno Brescia, 🇮🇹

    Thank you for your contribution and for your patience with the review process!

    I updated your account so you can now opt into security advisory coverage for any project you created and every project you will create.

    These are some recommended readings to help you with maintainership:

    You can find more contributors chatting on Slack or IRC in #drupal-contribute. So, come hang out and stay involved !
    Anyone is welcome to participate in the review process. Please consider reviewing other projects that are pending review . I encourage you to learn more about that process and join the group of reviewers.

    I thank the dedicated reviewers as well.

  • Assigned to apaderno
  • Status changed to Fixed 4 months ago
  • 🇮🇹Italy apaderno Brescia, 🇮🇹
  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024