In Translate action, allow disabling token replacement through config form

Created on 22 October 2023, over 1 year ago

Problem/Motivation

I can't find a way to disable token replacement for Translate action.

Steps to reproduce

  1. Enable language, locale, and token modules.
  2. Enable French language (/admin/config/regional/language).
  3. Create a model (exported copy is attached):
  4. Add event: Prepare content entity form
    • Type: any
  5. Add action: Translate
    • Name of token: translated_message
    • Value to translate: Hello [current-user:display-name]!
  6. Add action: Display a message to the user
    • Message: [translated_message]
  7. Import the attached translation.fr.po file using drush (drush locale:import fr /path/to/translations.fr.po) or import UI (/admin/config/regional/translate/import). This would add the following translation entry:
    • Hello [current-user:display-name]! -> Bonjour [current-user:display-name] !
  8. Visit /fr/node/add/page

The following message is displayed (assuming the username is admin):
Hello admin!

My desired behavior is to use the translated message before token replacement:
Bonjour admin !

If you visit the User interface translation page (/admin/config/regional/translate), there should be an entry for translating the following string:
Hello admin!

If you log out and log back in as another user, say john, a new entry would be created for translating the following string:
Hello john!

Adding translations for each username is not practical.

Proposed resolution

The reason for this behavior seems to be that in the following lines tokens are automatically replaced:
Translate.php line 69: $value = $this->yamlParser->parse($value);

Translate.php line 78: $value = $token->getOrReplace($value);

It would be great to be able to turn off token replacement through the Translate action config form.

Remaining tasks

User interface changes

API changes

Data model changes

Feature request
Status

Active

Version

1.1

Component

Code

Created by

🇨🇦Canada druplr

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @druplr
  • 🇩🇪Germany jurgenhaas Gottmadingen

    I can see what you're trying to achieve and where that issue is coming from. But I am not convinced that the translation action should avoid replacing tokens because they would then never be replaced ever, if not by that action. Instead, we may have to provide an option to either replace and then translate, or to first translate and then replace.

  • 🇨🇦Canada druplr

    Thank you jurgenhaas for your prompt response!

    I didn't mean to avoid token replacement altogether. I meant to make it optional.

    The tokens can still be replaced in a subsequent action. In my example above, the Translate action is only responsible for the traslation; and it is the Display a message to the user action that replaces the token.

    However, the second alternative approach you provided should work:

    ...Instead, we may have to provide an option to either replace and then translate, or to first translate and then replace.

    • replace and then translate <- This is the current behavior as far as I understand.
    • first translate and then replace <- This should satisfy most cases including mine I think.
  • 🇨🇦Canada druplr

    Now that I re-read your last sentence, I am thinking you probably mean to allow the user select either of the options above in the Translate config form. If so, I can't think of a case that the first option (replace and then translate) be used. The second option (translate and then replace) however, would work similar to the t() function I think, which is more familiar to the developers.

  • 🇩🇪Germany jurgenhaas Gottmadingen

    The tokens can still be replaced in a subsequent action.

    That's the problem, as this would require recursive token replacement, which Drupal's token system doesn't allow. There will be a new action in ECA 2 which provides such functionality, but you will have to call that explicitly. For now, we shouldn't rely on that. And even later, each action with token replacement should go as far as it can on its own.

    Now that I re-read your last sentence, I am thinking you probably mean to allow the user select either of the options above in the Translate config form. If so, I can't think of a case that the first option (replace and then translate) be used. The second option (translate and then replace) however, would work similar to the t() function I think, which is more familiar to the developers.

    For 2 reasons, we need both options:

    • We need to remain backward compatible and don't want to break existing models
    • There can still be use cases for option 1, e.g. if someone composes a message from various parts in the model and has pre-made translations for each of the resulting strings after token replacement

    If anyone were to implement the suggested enhancement, this will have to go into 2.x

  • 🇩🇪Germany jurgenhaas Gottmadingen
  • 🇩🇪Germany geek-merlin Freiburg, Germany

    Note that according to function TranslatableMarkup::__construct | Drupal API the existing behavior of doing a

    t($value)
    • opens security risks
    • prevents template extraction
  • 🇩🇪Germany jurgenhaas Gottmadingen

    @geek-merlin do you have any recommendation on how to implement translation instead where the values that need to be translated are coming from the ECA model? In other words, those string only ever exist in a variable.

Production build 0.71.5 2024