Using the Translation Service

Objectives
  • You'll learn about the translation service.
  • You'll learn about functions that are globally available.

The Translation Service

The translation service is part of the Localization API. It lets you localize text strings: it adds your text strings to a set of translatable strings so people who install Drupal in a different language, or sites that provide language switchers, can easily provide a translation for your text.

When we talk about translatable text strings we refer to things like:

  • Status/warning/error messages
  • The "submit" and "search" labels on buttons
  • The "Forgot Password?" link

In other words, relatively short bits of text that make up the site's interface rather than the actual content.

Drupal also has a separate content translation mechanism you can install and configure to maintain translations of nodes, blocks, terms, menus and other things. That content translation mechanism is not related to the translation service we're discussing in this chapter.

The translation service only deals with translating interface text. It does not deal with content translation.

Using the Translation Service

You can access the translation service in three different ways:

  • via a globally available function
  • via your object
  • via the service container

Utility functions are similar to services in that they provide helpful functionality. Some utility functions, such as the t() function used for translation are available nearly everywhere, including outside your class. However, they are not available in special cases such as when automated tests are running

Let's have a look at them:

via the function t()

$message = t("Hello world.");

Via your Object

$message = $this->t("Hello world.");

Via the Service Container

$trans = \Drupal::translation();
$message = $trans->translate("Hello world.");

Which one should you use?

When you are within a class where the translation method is available, you should use $this->t().

When you are not within a class where the translation method is available, or not in a class at all, you should use t().

There's no common reason why you would use \Drupal::translation()->translate("hello") at all, except in specific cases where t() is not globally available, such as during automated testing. We will not cover these special cases here, as you're highly unlikely to encounter them at this stage/

Decoupling

t()is a kind of alias or wrapper function for \Drupal::translation()->translate(). If Drupal ever decides to change the underlying translation mechanism, t() will point to this new mechanism, and you will never need to change your own code. You just keep using t() and don't worry about the underlying implementation details.

However, if you use \Drupal::translation()->translate(), and Drupal decides to change that to, for instance, \Drupal::localization()->translate(), you would have to update your code in many places.

The same goes for $this->t(): Drupal could change the underlying implementation of the translation service, or you yourself could override and replace the mechanism for your own classes. If you keep using $this->t() you don't need to update any of these translation service calls when the underlying implementation of the translation service changes.

Decoupling is a more advanced concept. Don't worry if you don't fully grasp what's going on. Just now that it's good practice to use these wrapper functions or wrapper methods available in your class when you can, and don't use the underlying methods for which they are a wrapper.

How does it work?

When you provide a text string wrapped in the t() function, two things happen:

  • The string gets added to a set of translatable strings.
  • When the string is printed on screen, Drupal checks the site's active language and tries to retrieve the translated string. If no translation exists, the untranslated source string will be returned.

By convention, all source strings are assumed to be in American English (EN-US).
This means you should never do the following:

// DO NOT DO THIS:
$message = \Drupal::translation()->translate("Bonjour monde.");

Instead, do this...

$message = \Drupal::translation()->translate("Hello world.");

... and provide a French translation using the Translation User Interface that's available when you set up multiple languages for your site.