Drupal - Best practice: $this->t() versus t()

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.

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.



I18N L10N