9

I'm looking for a best practice: should contributed modules use $this->t() or t()?

  • I prefer using StringTranslationTrait:t because it is easier to mock the string_translation service. – mradcliffe Jan 5 '17 at 14:03
20

Best practice depends on where the code is placed.

OOP Code

Use $this->t().

If you extend a drupal base class like a controller or a plugin the t() function is provided as class method $this->t() out of the box and you should use it. This makes your code testable.

For most tasks you'll find a suitable drupal class to extend from which has $this->t() defined, but if you need to build your own class from scratch best practice would be to use the string translation trait and inject this as service if you use this class in a service context:

use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
class MyClass {
  use StringTranslationTrait;

  /**
   * Constructs a MyClass object.
   *
   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
   *   The string translation service.
   */
  public function __construct(TranslationInterface $string_translation) {
    // You can skip injecting this service, the trait will fall back to \Drupal::translation()
    // but it is recommended to do so, for easier testability,
    $this->stringTranslation = $string_translation;
  }

  /**
   * Does something.
   */
  public function doSth() {
    // ...
    $string = $this->t('Something');
    // ...
  }

}

Source: https://www.drupal.org/docs/8/api/translation-api-code-text

Procedural Code

Use t().

If you have procedural code, for example a hook, then use t(), which is a global function.

Not best practice would be to use the procedural t() in OOP Code.

  • Note that by extending some types of classes, for example extending ControllerBase when creating a controller, $this->t() is already provided without needing to use the StringTranslationTrait. – Jaypan Jan 5 '17 at 14:29
  • Yes, there are plenty of base classes that provide $this->t() out of the box, there are over hundred in core. The code example is only needed, if you don't extend from one of these classes. – 4k4 Jan 5 '17 at 14:59
  • And what about the case when we develop drush command? Should we use StringTranslationTrait or drush specific function dt()? – Артем Ильин Sep 17 '18 at 10:04
  • that's a great explanation. Why do we need this use StringTranslationTrait; within class? – David Mar 12 at 14:09
  • It's better to use $this->setStringTranslation($string_translation); – mpp Apr 8 at 9:17
4

The best practice is to use $this->t(), rather than t(). Usage of the module will not change, however, with the advent of Drupal 8, we now have PHPUnit testing built into core. PHPUnit testing allows for tests to be written to confirm everything works, so that anytime code is changed, the tests can be run to ensure nothing has been broken. The relevance of this is that PHPUnit testing tests only against a single class (aka a unit), meaning that core is not bootstrapped for these tests. Global functions such as t() therefore do not exist, and they will throw an error, preventing the tests from being run.

If you never create any unit tests, then you will never see the difference between using t() and $this->t(), however creating tests is also a best practice, and therefore if you really want to be doing things right, you should be using $this->t(), and creating Unit tests for each of your classes.

* Edit *

Updating after reading 4k4's post.

My comments above only relate to OOP code, not procedural code. Procedural code is not unit tested, nor does it have the $this constructor. In procedural code, t() is correct.

  • Excellent explanation! BTW, looking forward to reading your book. – No Sssweat Jan 9 '17 at 0:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.