Problem/Motivation

This came up in #3221375: Wrong language field labels after `drush cr` because of Drush language negotiation. Currently LanguageRequestSubscriber sets the current user on LanguageNegotiator. As far as I can tell there is no need for this indirection. And in fact this means that if you are not within the context of a request, but you do have a current user set that user language negotiation does not work.

This is one of those ones which can be a bug, a task or a feature request depending on how you look at it. Marking as bug as it helps #3221375: Wrong language field labels after `drush cr` because of Drush language negotiation, but also fine with re-classifying it differently.

Proposed resolution

Set the current user directly on the language negotiator.

This also removes the need for the path language negotiator to set the current user, so that is removed, as well.

Remaining tasks

User interface changes

-

Introduced terminology

-

API changes

  1. LanguageNegotiator takes a new $currentUser constructor argument while LanguageRequestSubscriber and PathProcessorLanguage no longer take a $current_user constructor argument.
  2. Language negotiation is now performed during CLI requests by default

Data model changes

-

Release notes snippet

-

Issue fork drupal-3544395

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

tstoeckler created an issue. See original summary.

tstoeckler’s picture

Issue summary: View changes

Adding note about PathProcessorLanguage to the issue summary.

tstoeckler’s picture

Status: Active » Needs review

Wrote a draft change record and a test. Let's see if anything breaks.

smustgrave’s picture

Status: Needs review » Needs work

Appears to have a phpstan failure

Line core/tests/Drupal/Tests/Core/PathProcessor/PathProcessorTest.php
------ --------------------------------------------------------------------
140 Class Drupal\language\HttpKernel\PathProcessorLanguage constructor
invoked with 5 parameters, 4 required.
🪪 arguments.count

Not sure a good rule of thumb but do we think these interfaces could be pretty widely uses in translation contrib modules? Only mention if maybe we should wait till 13 to remove.

tstoeckler’s picture

Status: Needs work » Needs review

I don't really have any strong feelings regarding the deprecation but per the Drupal Code Search:

tstoeckler’s picture

So those last failures were fun, we actually had tests that were relying on language negotiation not running in order to work. And due to the default configuration that's actually not too far fetched. Wrote a change notice to that end in case anyone encounters that same issue.

Let's see if this is now finally green.

tstoeckler’s picture

Issue summary: View changes
needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new91 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

tstoeckler’s picture

Issue summary: View changes
tstoeckler’s picture

Status: Needs work » Needs review

Rebased and squashed

dcam’s picture

Status: Needs review » Needs work

I left feedback in MR comments. Mostly, your change record URLs resulted in 404 pages. So I'm setting the issue to Needs Work for that. There's also a note about future-proofing the new test.

tstoeckler’s picture

Status: Needs work » Needs review

Thanks for the review @dcam! Applied your suggestions and also updated the unit test to use createStub() instead. Thanks for pointing that out, wasn't aware of that subtlety with mocks and stubs. 👍️

dcam’s picture

Status: Needs review » Reviewed & tested by the community

I rebased the MR because there were some weird test failures. Rebasing fixed them and everything is passing now.

I re-read all of the changes and change records. I don't have any additional feedback. So I'm going to set this to RTBC.

tstoeckler’s picture

Perfect thanks, yeah, was wondering about those failures, totally missed that the branch wasn't up-to-date 🙈. Thanks!

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

needs-review-queue-bot’s picture

Status: Reviewed & tested by the community » Needs work
StatusFileSize
new2.36 KB

The Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

dcam’s picture

Status: Needs work » Reviewed & tested by the community

Post-bot-rebellion rebase

longwave’s picture

Status: Reviewed & tested by the community » Needs review

I dug through git history to find the source of this. #1862202: Objectify the language system added this code, where initially both the current request and the the current user were injected by LanguageRequestSubscriber. This was picked up in review, but the answer was "If we want to support lazy language negotiation, I cannot see an alternative to storing those into the negotiator" - but still not sure why it wasn't injected directly. Request was later removed with no issues when the request object was removed from the container - the request stack was available but it wasn't required.

However, while we are here, shouldn't we also remove LanguageNegotiatorInterface::setCurrentUser() and deprecate any implementations?

longwave’s picture

Probably for a followup but I also wonder why we do this:

  public function getNegotiationMethodInstance($method_id) {
    if (!isset($this->methods[$method_id])) {
      $instance = $this->negotiatorManager->createInstance($method_id, []);
      $instance->setLanguageManager($this->languageManager);
      $instance->setConfig($this->configFactory);
      $instance->setCurrentUser($this->currentUser);
      $this->methods[$method_id] = $instance;
    }
    return $this->methods[$method_id];
  }

Feels like these services should be injectable into the plugins in the normal way too, via create() or autowiring? Most of the plugins don't use all three services.