2

I want to translate "You can only change the parent menu item for the published version of this content" which belongs to Menu UI module.

The string is defined in /core/modules/menu_ui/src/Plugin/Validation/Constraint/MenuSettingsConstraint.php like below:

<?php

namespace Drupal\menu_ui\Plugin\Validation\Constraint;

use Symfony\Component\Validator\Constraint;

/**
 * Validation constraint for changing the menu settings in pending revisions.
 *
 * @Constraint(
 *   id = "MenuSettings",
 *   label = @Translation("Menu settings.", context = "Validation"),
 * )
 */
class MenuSettingsConstraint extends Constraint {

  // This string is untranslatable.
  public $message = 'You can only change the menu settings for the <em>published</em> version of this content.';
  public $messageWeight = 'You can only change the menu item weight for the <em>published</em> version of this content.';
  public $messageParent = 'You can only change the parent menu item for the <em>published</em> version of this content.';
  public $messageRemove = 'You can only remove the menu item in the <em>published</em> version of this content.';

}

This extends a class from Symfony and doesn't use t() function, but other strings defined in the same way are translatable(which means you can find the string in the localize.drupal.org). Below is an example of a translatable string.

<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 * @Target({"CLASS", "PROPERTY", "METHOD", "ANNOTATION"})
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class Expression extends Constraint
{
    const EXPRESSION_FAILED_ERROR = '6b3befbc-2f01-4ddf-be21-b57898905284';

    protected static $errorNames = [
        self::EXPRESSION_FAILED_ERROR => 'EXPRESSION_FAILED_ERROR',
    ];

    // This string is translatable.
    public $message = 'This value is not valid.';
    public $expression;

    /**
     * {@inheritdoc}
     */
    public function getDefaultOption()
    {
        return 'expression';
    }

    /**
     * {@inheritdoc}
     */
    public function getRequiredOptions()
    {
        return ['expression'];
    }

    /**
     * {@inheritdoc}
     */
    public function getTargets()
    {
        return [self::CLASS_CONSTRAINT, self::PROPERTY_CONSTRAINT];
    }

    /**
     * {@inheritdoc}
     */
    public function validatedBy()
    {
        return 'validator.expression';
    }
}

I guess there're Drupal wrappers to make the strings originated in Symfony class implementations translatable. But why does the string in Menu UI remain untranslatable? It's not urgent, but I'm curious.

EDIT: Entity Validation API overview says "Symfony validator is configured to use a Drupal translator class, such that violation messages correctly run through t(). ". So if my understanding is right, the untranslatable string also gets wrapped in t() eventually...?

2

There are two different aspects. The first one is how Drupal compiles the core translation list. This is based on the (not running) PHP code using the Translation template extractor (POTX).

You find only the first of the four messages on localize.drupal.org because of a naming issue in this particular constraint. Drupal searches for translation strings in certain locations and $messageParent doesn't match:

/**
 * Detect validation constraint messages. Drupal 8+.
 *
 * This sequences is searched for:
 *   T_POTX_CONSTRAINT = T_CONSTANT_ENCAPSED_STRING.
 *
 * note: T_POTX_CONSTRAINT is marked for T_VARIABLE tokens inside .php files
 *   with the "Constraint" suffix, where the token is "$message", or ends
 *   with "Message"
 *
 * @param string $file_name
 *   Name of file parsed.
 * @param string $save_callback
 *   Callback function used to save strings.
 */
function _potx_find_constraint_messages($file_name, $save_callback) {

See https://www.drupal.org/project/potx/issues/2884361#comment-13052396

The second aspect is about the run-time behavior. Symfony contraints are integrated into the Drupal translation system, so that messages are wrapped in a Drupal translatable markup object.

So a quick fix would be to visit the site in a non english language and trigger the error, then the string will be added to the translation list of your local site.

1
  • The first string appeared in /admin/config/regional/translate after I triggered the error following @4k4's advice. Thanks a lot!
    – 863
    Feb 19 '20 at 11:52

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.