Problem/Motivation

\Drupal\language\Plugin\LanguageNegotiation::getLanguageSwitchLinks() and \LanguageNegotiationContentEntity::getLanguageSwitchLinks() do not set a language key in the links.

This can lead to incorrect switch links in the following situation (among others):
1. Add a language, so that you have at least two, let's say language A (let's say that's the default one) and language B (let's say with language code bb).
2. Change language negotiation to be session-based (and disable URL negotiation).
3. Enable the language switcher block.
4. Create an alias for a path in language A, say /pathA.
5. Create an alias for the same path in language B, say /pathB.
6. Visit /pathA.

At this point the language switcher should link to /pathB?language=bb, but it instead links to /pathA?language=bb

Proposed resolution

Add the language to the switch links.

Instead of copy-pasting even more code into the already ~80% copy-pasted methods this patch provides a trait for code re-use. As you can see from this and other previous bugs in this area it is very hard to get this stuff right, so this is not for some theoretical purpose but it is to prevent future bugs in core and contrib.

Remaining tasks

Contributor tasks needed
Task Novice task? Contributor instructions Complete?
Create a patch Instructions Yes
Add automated tests Instructions Yes
Review patch to ensure that it fixes the issue, stays within scope, is properly documented, and follows coding standards Instructions

User interface changes

None.

API changes

Due to the minor refactoring to improve future maintenance and stability this breaks contrib and custom language negotiation plugins if they extend LanguageNegotiationContentEntity, LanguageNegotiationSession or LanguageNegotiationUrl and one of the following is true:
1. They provide a private method called getLanguageManager() or processLanguageSwitchLink()
2. They provide a public or protected method called getLanguageManager() that does not return an object implementing \Drupal\Core\Language\LanguageManagerInterface
3. They provide a public or protected method called processLanguageSwitchLink() that takes different arguments from the ones introduced here.
3. They use a trait that has a method called getLanguageSwitchLinks() or processLanguageSwitchLink().
If this is considered a BC break, then this could be avoided as well, by simplifying the patch at the cost of future maintenance and stability. We could also considering doing the improved version for 8.1 and the extra-safe version for 8.0.

Data model changes

None.

CommentFileSizeAuthor
#41 interdiff_39-41.txt2.52 KBravi.shankar
#41 2666634-41.patch14.75 KBravi.shankar
#39 interdiff_38-39.txt2.64 KBTanuj.
#39 2666634-39.patch15.02 KBTanuj.
#38 core-lang-switcher-2666634-38.patch13.85 KBrossb89
#37 2666634-nr-bot.txt2.39 KBneeds-review-queue-bot
#34 core-lang-switcher-2666634-34.patch14.01 KBjames.williams
#32 core-lang-switcher-2666634-32.patch14.05 KBjames.williams
#32 interdiff-2666634-25-32.txt1.06 KBjames.williams
#27 interdiff_25-27.txt1.17 KBvsujeetkumar
#27 2666634-27.patch14.93 KBvsujeetkumar
#25 core-lang-switcher-2666634-25.patch14.07 KBjames.williams
#25 interdiff-2666634-23-25.txt1.11 KBjames.williams
#23 core-lang-switcher-2666634-23.patch14.04 KBjames.williams
#23 interdiff-2666634-21-23.txt1.11 KBjames.williams
#21 core-lang-switcher-2666634-21.patch13.99 KBjames.williams
#21 interdiff-2666634-20-21.txt2.54 KBjames.williams
#20 core-lang-switcher-2666634-19.patch14.08 KBjames.williams
#19 core-lang-switcher-2666634-19.patch0 bytesjames.williams
#8 2666634-8.patch14.31 KBtstoeckler
#8 2666634-6-8--interdiff.txt1.76 KBtstoeckler
#6 2666634-6.patch14.37 KBtstoeckler
#6 2666634-3-6--interdiff.txt2.66 KBtstoeckler
#3 2666634-3.patch13.72 KBtstoeckler
#3 2666634-3--tests-only.patch3.44 KBtstoeckler
language-switch-links.patch10.28 KBtstoeckler
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

tstoeckler created an issue. See original summary.

tstoeckler’s picture

Status: Active » Needs review
tstoeckler’s picture

In writing a test for #2666628: Language-aware aliases are broken with anything but path language negotiation I realized that the manual config edit is in fact not necessary. Updating the issue summary accordingly.

Also adding a test to the patch which is basically test as in the referenced issue, except for the assertions that validate that the alias is accessible, because that will be fixed there and is not related to the switch links itself. The tests-only patch is also the interdiff.

Note that the test failures in the test-only patch are cheating a little bit, because the xpatch relies on the hreflang attribute which is not there (which is why there are 2 fails, even though only one link is incorrect), but if you run the tests locally you will see that the link is actually incorrect in the test.

The last submitted patch, 3: 2666634-3--tests-only.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 3: 2666634-3.patch, failed testing.

tstoeckler’s picture

Status: Needs work » Needs review
FileSize
2.66 KB
14.37 KB

I didn't account for Drupal being installed in a subfir. Yay, tests!

Status: Needs review » Needs work

The last submitted patch, 6: 2666634-6.patch, failed testing.

tstoeckler’s picture

Status: Needs work » Needs review
FileSize
1.76 KB
14.31 KB

Well it helps to actually run the tests from within a subdir. This should be green; I tested this both with a subdir and without.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

manuel.adan’s picture

Still present in 9.x. Build multilingual websites without the URL language detection is almost unuseful in Drupal at the moment.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

james.williams’s picture

FileSize
0 bytes

Here's a re-rolled version of the patch.

james.williams’s picture

Argh, sorry! Here's the re-rolled version...

james.williams’s picture

Updated patch to resolve issues flagged by code checks.

Status: Needs review » Needs work

The last submitted patch, 21: core-lang-switcher-2666634-21.patch, failed testing. View results

james.williams’s picture

Status: Needs work » Needs review
FileSize
1.11 KB
14.04 KB

Updated test to match newer alias form fields.

Status: Needs review » Needs work

The last submitted patch, 23: core-lang-switcher-2666634-23.patch, failed testing. View results

james.williams’s picture

Status: Needs work » Needs review
FileSize
1.11 KB
14.07 KB

Ugh, sorry. I guess this is what I get for taking on what I thought could be a simple re-roll. Try again, updating the test in yet another way...

Status: Needs review » Needs work

The last submitted patch, 25: core-lang-switcher-2666634-25.patch, failed testing. View results

vsujeetkumar’s picture

Status: Needs work » Needs review
FileSize
14.93 KB
1.17 KB

Fixed the fail tests, Please have a look.

james.williams’s picture

I'm not sure fixing the test like that is correct? The test is supposed to check that only the current language list item is marked as active on the language switcher block. The test is showing that no item is marked as active, which seems like a valid fail to me, indicating an actual bug fix is still needed?

james.williams’s picture

I've just spent most of the day investigating this. It turns out we are indeed running into this bug: #2845319: The highlighting of the active menu-link does not respect query strings and fragment identifiers ! So I'm sorry @vsujeetkumar, but that change to the test was incorrect - the patch should be failing, but because of that other bug, rather than anything introduced here.

I suspect we might be able to work around this by changing the test to check on a different page. However, since the test was quite deliberately originally written to test the special case of the switcher block on the homepage (#220559: Language switcher block highlights ALL languages as active - over a decade ago, for Drupal 6!), I think that check should remain in place, otherwise we're reducing existing test coverage!

I've run the tests locally with my patch from #25, as well as MR !866 from #2845319: The highlighting of the active menu-link does not respect query strings and fragment identifiers, which passed. So I think we need to get #2845319 resolved first, then we can push this one along.

In the meantime - reviews & testing are otherwise very welcome here!

james.williams’s picture

Issue summary: View changes
james.williams’s picture

Issue summary: View changes
james.williams’s picture

Although #29 was true, we can also handle that ourselves quite nicely here. It turns out that since the patch from #8 was written, #2689607: Language from URL negotiator does not add request query to language switcher links had added query string support, specifically to the LanguageNegotiationUrl class. So that needed extracting into the new trait too.

...and with that, regardless of #2845319: The highlighting of the active menu-link does not respect query strings and fragment identifiers tests pass locally, so I think we can progress here without that.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

james.williams’s picture

Re-rolled, this should apply to latest 9.3.x as well as 9.4.x.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
FileSize
2.39 KB

The Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.

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

rossb89’s picture

Status: Needs work » Needs review
FileSize
13.85 KB

Re-rolled for latest 9.5.x

Tanuj.’s picture

smustgrave’s picture

getLanguageManager() {
1. new function should be typehinted

LanguageSwitchLinksTrait
2. New trait will need a change record

getLanguageSwitchLinks(Request $request, $type, Url $url) {
3. Should be typehinted

In LanguageNegotiationContentEntity
4. NIT the space removal seems unneccessary

Rest seems good to me.

ravi.shankar’s picture

Addressed point 1, 3 and 4 of comment #40, keeping the status needs work for change record as per point 2.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.