Override Composer Stager's TranslatableFactory to return Drupal's TranslatableMarkup

Created on 22 June 2023, over 1 year ago
Updated 19 July 2023, over 1 year ago

Problem/Motivation

  • Drupal's StringTranslationTrait::t() returns a Drupal\Core\StringTranslation\TranslatableMarkup object.
  • Composer Stager is designed to not depend on Drupal so its TranslatableAwareTrait::t() returns a PhpTuf\ComposerStager\API\Translation\Value\TranslatableInterface object.
  • Composer Stager's TranslatableAwareTrait::t() delegates to the TranslatableFactoryInterface service to instantiate the TranslatableInterface object, which means Drupal can override this service to instantiate and return a Drupal-suitable object.

Steps to reproduce

Proposed resolution

  • Create a class in Package Manager that's a subclass of Drupal\Core\StringTranslation\TranslatableMarkup that also implements PhpTuf\ComposerStager\API\Translation\Value\TranslatableInterface.
  • Implement a PhpTuf\ComposerStager\API\Translation\Factory\TranslatableFactoryInterface service that instantiates and returns an object of the above class.
  • Implementing TranslatableInterface means implementing the trans() method which takes the translator service as a parameter. This differs from TranslatableMarkup::render() which uses the translator passed to the constructor. A question to resolve is whether we want to allow trans() to be called with a different translator than TranslatableMarkup was constructed with and therefore potentially return a different string than render() would return.
    1. Option 1: Sure, why not allow it. Drupal doesn't call trans(), it uses only render(). Composer Stager itself doesn't call trans() either, since Composer Stager creates the messages but doesn't itself display them, it just models the API on Symfony's translation contracts. If a site adds some other code to the system that does call trans() on these messages, then assume it knows what it's doing and use the translator it passes even if it doesn't match the one that the TranslatableMarkup object was constructed with.
    2. Option 2: Nah, it's weird, so don't allow it. Add an assertion or exception to trans() that enforces that the translator passed in is the same one that was passed to the constructor. If we go with this option, then we'll need our factory to construct TranslatableMarkup objects with a string translation service that also implements PhpTuf\ComposerStager\API\Translation\Service\TranslatorInterface, which would require a subclass of or decorator around Drupal\Core\StringTranslation\TranslationManager. While not hard to create such a subclass/decorator, I'm not sure if this option is even desirable over option 1.

Remaining tasks

  • Write the patch.

User interface changes

API changes

Data model changes

📌 Task
Status

Fixed

Version

3.0

Component

Code

Created by

🇺🇸United States effulgentsia

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

Comments & Activities

Production build 0.71.5 2024