4

In Drupal 7 t() this warning was present:

You should never use t() to translate variables

In Drupal 8, well, it's Drupal 8, who knows where to even look?

I tried

and haven't found a similar warning. But absence of evidence is not evidence of absence. Is it OK now to use a variable?

  • I think this is because Drupal localize (the translations site) cannot detect variabeles, only predefined strings. So while it would probably work, the translated values would not appear in the translation file. So in order to have a tranlslation, it has to be defined. – Neograph734 Aug 24 '18 at 16:08
10

The advice is the same, it's just moved. The docs for t() say:

See \Drupal\Core\StringTranslation\TranslatableMarkup::__construct()for important security information and usage guidelines.

On that page you'll find familiar advice:

Translating Variables $string should always be an English literal string.

$string should never contain a variable, such as:

new TranslatableMarkup($text);

...

So generally speaking no, it's not OK to pass a variable as the first argument to t() in Drupal 8. Always use a literal string.

If you need to use variables for t(), pass a literal string containing placeholders, and a second argument containing their replacements. For example:

new TranslatableMarkup("@name's blog", [
  '@name' => $account
    ->getDisplayName(),
]);
  • So we are still parsing the codebase and not using {locales_source} as the source of truth? If we do, does it crawl phpstorage? Or what's the reason for the variable ban? – Smartsheet eng Aug 24 '18 at 18:38
  • The 2 reasons I've heard down the years are what you mentioned (for localize.drupal.org), and security. The latter being that blindly translating user-input can potentially introduce XSS and other problems – Clive Aug 24 '18 at 19:03
  • 3
    Yes. It "works" for your own site just fine (security problems aside, which are actually much worse in D8 because the string is marked as safe explicitly). This documentation and warninng is mostly about core/contrib code that is parsed by potx for localize.drupal.org. There is no locales_source table to look at there, the only source it can look at is the code – Berdir Aug 24 '18 at 20:07
6

Same as in Drupal 7. Drupal will always record a new t() source string dynamically when it encounters it. So this will of course work:

$string = 'Source string';
t($string);

The reason we advise against this strongly is:

  1. Often you end up translating twice, so t($var) and then some bunch of code and then t($whole_string) that contains t($var) output, etc. Can pollute the source string database.
  2. Often people ended up with $string = $count . ' apples'; t($string) which could grow your locale sources indefinitely and consequently make your locale cache unusable.
  3. Similar problem for t($userinput) which could also quickly become a security issue.

Telling people they should trace their code so the variable is surely not user input and does not contain dynamic portions and is surely not translated already is not a simple advice. But basically you could use dynamic strings as long as they are actually static strings.

And then when people want to publish this same code on drupal.org none of the clever dynamic static techniques you used would work since localize.drupal.org would need to parse the source code without running it, so it would need to be statically analysable or it is not translatable.

Applying that best practice regardless of who you are developing for is most consistent to document. Then you don't grow bad habits when developing in-house code and will not submit wrong patches or modules to drupal.org.

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.