In Drupal 8, it seems as though object-oriented code is encouraged to use $this->t() instead of the global function t(), by either adding StringTranslationTrait to the class, or extending a core class (eg. a plugin, controller or form) that has it.

If I understand correctly, this is to encapsulate localization and eg. translate particular objects to specific languages without affecting the global scope?

I have a particular subform that occurs both as part of a full form (in a routing path) and as part of a Filter plugin's settings. To accomplish this, I made the subform builder a static function inside the main form, allowing the filter plugin to call it directly. (Both the settings form and the main form add other fields in addition to the subform.)

Now, even though the subform function is static, it's only invoked in one of two non-static contexts (extended from FilterBase and ConfigFormBase, respectively, both of which inherit the StringTranslationTrait).

It seems as though the right thing here is to pass the caller's object to the static function, and then use that caller's t() function.

Call 1:

  public function buildForm(array $form, FormStateInterface $form_state) {
    $form = self::buildFormHandlers($form, $defaults, $this);

Call 2:

  public function settingsForm(array $form, FormStateInterface $form_state) {
    $form = XBBCodeHandlerForm::buildFormHandlers($form, $this->tag_settings, $this);


  public static function buildFormHandlers(array $form, array $defaults, $caller) {
    // Add form fields:
      '#title' => $caller->t('Tag settings'),

It looks like a weird pattern, though, so I'm wondering if I'm missing the point, or overthinking it.

  • 4
    Yes, you are overthinking it. If you have $this->t() available then use it. If not then use t(). I would definitely not pass the full object as argument just so I can use t(), that's ridiculous. If there is no other reason for that than don't do it. t() methods on various objects are there only for DI and tests. So you don't always need them, that's why using t() is ok. See answers for my old question in here drupal.stackexchange.com/questions/100332/…
    – user21641
    Apr 23 '15 at 6:30
  • @IvanJaros that sounds like it should be the answer ;). You can also implement the trait yourself but it doesn't work if you call it statically. If you want to pass something along, then pass in the StringTranslation service, like this $this->getStringTranslation().
    – Berdir
    Apr 25 '15 at 12:20

There's no right or wrong t because at the end of the day you end up using the translate method of the string_translation service. Passing around objects are pretty pointless because the StringTranslationTrait and t both execute the exact same code: \Drupal::service('string_translation')->translate($string, $args, $options). The call chain is different of course but at the end of the day, that's the exact call they both run.


As @berdir said in Using the right t(), the recommended way is passing the StringTranslation service.

However the use of a static method there (public static function buildFormHandlers) is a smell to me that this could be moved to a different helper service injected in both forms, or that you should create a trait yourself used in both.

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.