Problem/Motivation

When viewing a node revision in a non-default language, it still displays in the default language.

To reproduce:

  • Create a translated node, with multiple revisions
  • Go to the revision history page in a non-default language, eg: /fr/node/1/revisions
  • Click one of the revisions displayed. The node displays in the default language, see attached picture.

Proposed resolution

Add getTranslationFromContext() in NodeController::revisionShow().

Remaining tasks

Write patch. Write tests.

User interface changes

Revisions will display in the correct language. Anybody who depends on the old behaviour had odd ideas.

API changes

None.

Data model changes

None.

Comments

vasi created an issue. See original summary.

vasi’s picture

StatusFileSize
new3.55 KB

Here's a test that demonstrates the problem.

vasi’s picture

Status: Active » Needs review
vasi’s picture

StatusFileSize
new4.27 KB
new744 bytes

And here's a fix.

vasi’s picture

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

Present in 8.0 through 8.2, it turns out. Patches still apply to 8.2.

The last submitted patch, 2: 2694555-fail.patch, failed testing.

The last submitted patch, 2: 2694555-fail.patch, failed testing.

heddn’s picture

Status: Needs review » Reviewed & tested by the community

I reviewed the code in question to see what getTranslationFromContext() does. Code looks solid and is doing the right thing. Tests look sufficient.

  1. I enabled content translation & language.
  2. Then added Spanish language.
  3. Then I marked that Page is a translatable content type.
  4. Then I added an English page with a Spanish translation.
  5. Then I added some English and Spanish revisions.

Without the patch, the behaviour is identical as described in #0. With the patch, the issue is fixed.

dawehner’s picture

IMHO we should fix this in \Drupal\Core\ParamConverter\EntityRevisionParamConverter as well, given that this will be used hopefully in the future for nodes as well.

heddn’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new5.04 KB
new781 bytes

re#9: Is this what you mean?

dawehner’s picture

Status: Needs review » Needs work
+++ b/core/lib/Drupal/Core/ParamConverter/EntityRevisionParamConverter.php
@@ -52,7 +52,7 @@ public function __construct(EntityTypeManagerInterface $entity_type_manager) {
-    return $entity_storage->loadRevision($value);
+    return $entity_storage->getTranslationFromContext($value);

Just that doesn't work, we need to load the revision still ...

The last submitted patch, 10: drupal-node_revisions_don_t-2694555-10.patch, failed testing.

therealssj’s picture

StatusFileSize
new5.15 KB
new903 bytes

@dawehner
Like this?

therealssj’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 13: 2694555-13.patch, failed testing.

catch’s picture

Priority: Normal » Critical
Issue tags: +Needs Drupal 8 critical triage

I'm not sure what happens if:

- you have a non-default revision
- you load it
- you change something
- you save it

Do we save the non-changed translated values from the revision we loaded, or the default one?

Bumping to crtical, because if it's the default revision that's a data integrity issue, we can downgrade if it's not.

amateescu’s picture

Status: Needs work » Needs review
StatusFileSize
new2.3 KB

Here's a test for the scenario described in #16.

amateescu’s picture

Priority: Critical » Major
Issue tags: -Needs Drupal 8 critical triage +Workflow Initiative
StatusFileSize
new9.52 KB
new10 KB

Fixed the unit test fail from #13 by properly injecting the entity repository service and also moved the test method to an existing test class (\Drupal\node\Tests\NodeTranslationUITest).

Since the test-only patch #17 passed, this is not a critical issue anymore.

amateescu’s picture

Issue tags: +WI critical

Forgot a tag :/

dawehner’s picture

+++ b/core/lib/Drupal/Core/ParamConverter/EntityRevisionParamConverter.php
@@ -32,13 +33,23 @@ class EntityRevisionParamConverter implements ParamConverterInterface {
+   *
+   * @var \Drupal\Core\Entity\EntityRepositoryInterface
+   */
+  protected $entityRepository;
+
+  /**
    * Creates a new EntityRevisionParamConverter instance.
    *
    * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
    *   The entity type manager.
+   * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
+   *   The entity repository.
    */
-  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
+  public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityRepositoryInterface $entity_repository) {
     $this->entityTypeManager = $entity_type_manager;
+    $this->entityRepository = $entity_repository;
   }
 
   /**
@@ -46,8 +57,8 @@ public function __construct(EntityTypeManagerInterface $entity_type_manager) {

@@ -46,8 +57,8 @@ public function __construct(EntityTypeManagerInterface $entity_type_manager) {
    */
   public function convert($value, $definition, $name, array $defaults) {
     list (, $entity_type_id) = explode(':', $definition['type'], 2);
-    $entity_storage = $this->entityTypeManager->getStorage($entity_type_id);
-    return $entity_storage->loadRevision($value);
+    $entity = $this->entityTypeManager->getStorage($entity_type_id)->loadRevision($value);
+    return $this->entityRepository->getTranslationFromContext($entity);
   }
 
...
diff --git a/core/modules/node/src/Controller/NodeController.php b/core/modules/node/src/Controller/NodeController.php

It seems to be that we don't really have test coverage for this code change. The unit tests seems to not really cut it. Could we expand the test in EntityRevisionTranslationTest to include something for that as well?

timmillwood’s picture

@dawehner - Doesn't the test in NodeTranslationUITest cover this?

amateescu’s picture

StatusFileSize
new3.61 KB
new13.13 KB

@timmillwood, nope, that only covers the changes in \Drupal\node\Controller\NodeController::revisionShow().

Here's a test for the changes in EntityRevisionParamConverter. The test-only patch is also the interdiff.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Thank you @amateescu!

The last submitted patch, 22: 2694555-22-test-only.patch, failed testing.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 22: 2694555-22.patch, failed testing.

amateescu’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new3.66 KB
new13.19 KB
new1 KB

Apparently, entity URLs don't go well with simpletest when running in a subdirectory, let's just use the URL directly like we do everywhere else.

dawehner’s picture

+1 for this job. I could have seen that. Ideally you set the langcode in the URL object and just pass that to drupalGet.

berdir’s picture

+++ b/core/modules/system/src/Tests/Entity/EntityRevisionsTest.php
@@ -144,13 +144,13 @@ public function testEntityRevisionParamConverter() {
 
     // Check that the entity revision is upcasted in the correct language.
-    $revision_url = $forward_revision->toUrl('revision')->toString();
+    $revision_url = 'entity_test_mulrev/' . $entity->id() . '/revision/' . $forward_revision->getRevisionId() . '/view';
 
     $this->drupalGet($revision_url);

you just can't use toString(), you have to use getInternalPath(), then it should work fine. Or you can just pass the Url object to drupalGet(), that should actually work as well (in simpletest, not sure about phpunit ,didn't check what kind of test this is)

The last submitted patch, 26: 2694555-26-test-only.patch, failed testing.

webchick’s picture

Status: Reviewed & tested by the community » Needs work

Sounds like needs work

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new13.2 KB
new1.43 KB

I tried to do that, but I think the test setup is wrong, as it doesn't yet have URL prefixing configured.

Status: Needs review » Needs work

The last submitted patch, 31: 2694555-31.patch, failed testing.

amateescu’s picture

+++ b/core/modules/system/src/Tests/Entity/EntityRevisionsTest.php
@@ -144,13 +145,11 @@ public function testEntityRevisionParamConverter() {
+    $this->drupalGet($forward_revision->getTranslation('de')->toUrl('revision'));

I tried that as well but, unfortunately, it doesn't generate a proper URL for the entity revision in a specific language.

I don't know if that's a bug or just the test setup, so I still think the patch in #26 is good to go.

dawehner’s picture

Status: Needs work » Reviewed & tested by the community

Yeah me too, but we could file a follow up for that.

berdir’s picture

Yes, toUrl() doesn't add that option, you would have to to something like setOption('language', ..) yourself on the url object.

We discussed that before. I think it would be nice if it worked like that.

dawehner’s picture

Yes, toUrl() doesn't add that option, you would have to to something like setOption('language', ..) yourself on the url object.

I did explictly that in #31 but it still didn't worked.

catch’s picture

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

Moving this to 8.1.x since it's a straight bugfix.

alexpott’s picture

StatusFileSize
new13.19 KB

Just uploading the correct patch to be the last patch on the issue.

alexpott’s picture

xjm’s picture

Regarding #37, it's a straight bugfix, but it does involve a constructor change on a paramconverter to add an additional service. In our BC policy we say:

Paramconverters, access checkers, event subscribers and similar services which are never expected to be used directly either as services or value objects, are not considered part of the API. You should not extend from these classes and provide your own implementation instead.

So we are okay doing this in 8.1.x for that not-an-API-change. I wondered though about whether we need to force a cache rebuild.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

The version change will be enough to cause a container rebuild so no cache rebuild is necessary.

Committed and pushed 9b07bc544c49296bd4fb76b08d676665d9e2d0c1 to 8.2.x and 97d2695 to 8.1.x. Thanks!

  • alexpott committed 9b07bc5 on 8.2.x
    Issue #2694555 by amateescu, vasi, dawehner, heddn, therealssj: Node...

  • alexpott committed 9b07bc5 on 8.3.x
    Issue #2694555 by amateescu, vasi, dawehner, heddn, therealssj: Node...

  • alexpott committed 9b07bc5 on 8.3.x
    Issue #2694555 by amateescu, vasi, dawehner, heddn, therealssj: Node...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.