t()
, TranslationManager::translate()
and StringTranslationTrait::t()
now return a TranslatableMarkup
object instead of a string.
The actual translation will only be performed whenever the object is casted to string or whenever the TranslatableMarkup
object is rendered.
This means module code will have to be reviewed for any instances of the output of t()
appearing in array keys and in strpos()
:
1. Array keys
As PHP does not allow us to use objects as array keys, all instances where t() is used in an array key will need to be explicitly cast to string. In most cases this will be about the labels for <optgroup>
elements in #options
.
$form['foo']['#options'][t('Bar')]['baz'];
// Becomes:
$form['foo']['#options'][(string) t('Bar')]['baz'];
2. strpos()
Similarly, this applies to when used as the second argument for strpos() as well:
strpos('foobar', t('foo'));
// becomes:
strpos('foobar', (string) t('foo'));
Note: since t()
gets translated it is really not recommended to use it in strpos
as the results are unpredictable.
3. Automated tests
Some strict equality checks in automated tests may fail. If your module has tests, do a full test run and cast any output of t() to string where necessary. Testbase
and KernelTest
has the castSafeStrings()
helper method provided by AssertHelperTrait
, which will cast all elements of an array that implement MarkupInterface
for you. This is especially useful when using TestBase::assertIdentical()
or KernelTestBase::assertSame()
4. Access characters of a string
$var = t('foo');
$first_letter = $var[0];
// becomes:
$var = (string) t('foo');
$first_letter = $var[0];
Note: since t()
gets translated it is really not recommended to use it character by character as the results are not predictable.