Synopsis
Changing the language of a translatable node with a translatable menu link from a "real" language (e.g. en) to a "pseudo" language (und or zxx) will result in an invalid argument exception: Invalid translation language (und) specified. or Invalid translation language (zxx) specified. respectively.
Note: If you are using the contributed token module, you will get a similar error in token_node_menu_link_submit() instead, since that function uses code very similar to _menu_ui_node_save() (see related issues in the sidebar).
Steps to reproduce
- Install Drupal 10.1.x-dev (Standard profile) in English language
- Enable Content Translation module
- Add a second language (e.g. German) at Configuration > Region and language > Languages
- Enable content translation with default settings for Content/Basic page and Custom menu link/Custom menu link at Configuration > Region and language > Content language and translation
- Add a new basic page in English:
- Fill in the title field (e.g. "123")
- Expand "Menu settings" in the sidebar and check "Provide a menu link"
- Leave everything else at default settings
- Click "Save"
- Edit your new basic page:
- Set the language to either "- Not specified - " (
und) or "- Not applicable -" (zxx) - In "Menu settings" in the sidebar, change "Menu link title" to "234"
- Leave everything else alone
- Click "Save"
- Set the language to either "- Not specified - " (
Expected result
- Language of basic page is either
undorzxx, depending on your choice above - Title of menu link is "234"
- Language of menu link is equal to language of basic page
- Neither basic page nor menu link have any translations
Actual result
White page with error message:
The website encountered an unexpected error. Please try again later.
InvalidArgumentException: Invalid translation language (und) specified. in Drupal\Core\Entity\ContentEntityBase->addTranslation() (line 952 of core/lib/Drupal/Core/Entity/ContentEntityBase.php).
_menu_ui_node_save() (Line: 342)
menu_ui_form_node_form_submit()
call_user_func_array() (Line: 114)
Drupal\Core\Form\FormSubmitter->executeSubmitHandlers() (Line: 52)
Drupal\Core\Form\FormSubmitter->doSubmitForm() (Line: 597)
Drupal\Core\Form\FormBuilder->processForm() (Line: 325)
Drupal\Core\Form\FormBuilder->buildForm() (Line: 73)
Drupal\Core\Controller\FormController->getContentResult()
call_user_func_array() (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 583)
Drupal\Core\Render\Renderer->executeInRenderContext() (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext() (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 163)
Symfony\Component\HttpKernel\HttpKernel->handleRaw() (Line: 74)
Symfony\Component\HttpKernel\HttpKernel->handle() (Line: 58)
Drupal\Core\StackMiddleware\Session->handle() (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle() (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass() (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle() (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle() (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle() (Line: 51)
Drupal\Core\StackMiddleware\StackedHttpKernel->handle() (Line: 698)
Drupal\Core\DrupalKernel->handle() (Line: 19)
Proposed resolution
The Menu UI module doesn't use the API correctly. It tries to add a translation when it shouldn't.
When updating a translatable menu link in _menu_ui_node_save() and the node is not translatable, don't try to add a translation for the untranslatable language, which would trigger the exception, but instead set the language of the menu link to the node language.
Remaining tasks
User interface changes
None.
API changes
None.
Data model changes
None.
Release notes snippet
n/a
MR to commit
| Comment | File | Size | Author |
|---|---|---|---|
| #15 | 2904899-interdiff-6-15.txt | 5.81 KB | feyp |
Issue fork drupal-2904899
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:
- 2904899-invalid-argument-exception
changes, plain diff MR !5399
Comments
Comment #2
feyp commentedAttached is a patch against 8.4.x-dev.
Comment #6
idflood commentedReroll of patch in #2 for 8.8.x
Comment #7
esolitosI feel that there should be a method pn the Language object like: "canTranslate" to avoid this check.
This would also be useful in several other places where an "AddTranslation" is called, for instance I found this bug report coming from a Paragraph issue.
What do you think?
Comment #13
anybodyJust ran into this issue and was wondering I wasn't ever running into this before, seems to be an edge-case, but still existing.
Comment #15
feyp commentedI'm not convinced that the API change proposed in #7 is in scope here. Adding such a method would constitute a b/c break and would delay this bug fix until Drupal 11, which I don't think is reasonable. If we want to add such a method, this could easily be done in a separate issue later.
Attached are updated patches for Drupal 10.1.x-dev and an interdiff with #6. I renamed the test class to MenuUiContentTranslationTest so that other integration tests with content_translation could be added there in the future, if needed. I also replaced the two test methods with a data provider. The rest of the changes in the test file are for code that was deprecated in Drupal 8 or Drupal 9.
Comment #16
feyp commentedcspell again...
Comment #18
smustgrave commentedCan the issue summary be updated. to include proposed solution.
Also the steps were written for D8 are they still the same for D10? Fine if they are just want to double check.
Comment #19
feyp commentedThanks once more for your review @smustgrave!
The steps to reproduce still apply for the latest 10.1.x-dev, which is also confirmed by the new test coverage. I still did a new manual test following the STR in the IS and updated the core version, a few UI strings that changed slightly since 8.4.x and also updated the stack trace in the actual result. I also updated the IS with the missing info from the current issue summary template including a proposed resolution.
Comment #20
smustgrave commentedThanks! That made it much more clear and was able to replicate.
Patch fixes the issue.
Comment #22
smustgrave commentedMeant to cleanup tags.
Also random failure.
Comment #24
feyp commentedRandom test failure, see #3361121: [random test failure] InstallerExistingConfig[SyncDirectory]MultilingualTest::testConfigSync, retest was green. Back to RTBC per #20.
Comment #26
quietone commentedDoing RTBC triage. Thank you all for an up to date Issue Summary, it truly helps.
Reading the proposed resolution I wonder why this just being applied when saving a menu_link in the UI. Surely this can be done outside of the UI? And thus things will break? Am I not understanding something?
I think a followup is needed for #7, but as always, search first. Adding tag.
I do not see any comments here explaining what was done for a code review. And it is still listed as a remaining task.
Setting to NW because of my question above.
Comment #27
feyp commentedThis is not an API issue. The issue is the way the Menu UI module uses the API to update a menu link. It tries to create a translation when it shouldn't. I tried to rephrase the proposed resolution so that this is hopefully more clear. Feel free to improve on that.
Filed #3379839: Add an API method to LanguageInterface to simply checking, if a language is a pseudo language. If this needs to be postponed against a Drupal 11 meta or any tags or something, I'd appreciate your guidance.
Didn't do the review, so can't comment on that. Back to Needs review.
Comment #28
smustgrave commentedFollow up has been filed. Not sure if it should be postponed on this but a user has already started work on it.
#20 did the steps in the IS to verify the issue and the patch solved the issue.
Comment #29
alexpottThis can be simpler. Looking at \Drupal\Core\Entity\ContentEntityBase::isTranslatable() - we can change this to
if (!$node->language()->isLocked()) {See
But I think the following change is even better...
As it is using $node->isTranslatable() so we're a bit more logical. Ie. we say if we can translate this menu link and this node then make the languages match. If not then the menu_link must match the language of the node.
Comment #31
feyp commentedThanks @alexpott for the review.
W/r/t pointing out
LanguageInterface::isLocked(), I closed the follow-up #3379839: Add an API method to LanguageInterface to simply checking, if a language is a pseudo language issue as "Works as designed".I agree that the changes you suggested are shorter, more logical and more readable, so I updated the code.
I took the opportunity to switch to an MR based workflow. Added the MR under review to the IS as requested elsewhere by @xjm.
Comment #32
feyp commentedDoh, forgot to set to Needs review...
Comment #33
feyp commentedI should have updated the proposed resolution in the IS also, done that now.
Comment #34
smustgrave commentedAppears feedback has been addressed
Thanks for updating the issue summary :)
Comment #35
alexpottCommitted and pushed ff1090382f0 to 11.x and 91acedade93 to 10.2.x. Thanks!