Problem/Motivation

Steps to reproduce on Drupal 6.

1. Install and enable i18n on your Drupal 6 source site so that you have 2 languages. This example has English as primary and Finnish as secondary language.

2. Enable 'Multilingual support, with translation' to a node content type. This example uses the 'Story' content type.

3. Create an English node and add a comment to it. Let these be nid 1 and cid 1 in Drupal 6.

4. Translate the node from step 3 to Finnish and add a comment to the Finnish translation. Let these be nid 2 and cid 2 in Drupal 6.

5. Run the upgrade to Drupal 8.

In Drupal 8, things boil down...

7. Navigate to node/1 (English) and see that the English content (nid 1 in Drupal 6) and English comment (cid 1 in Drupal 6) are shown as expected.

8. Navigate to fi/node/1 and see that the Finnish node content (nid 2 in Drupal 6) is shown as expceted. However, the English comment (cid 1 in Drupal 6) is shown instead of the Finnish comment (cid 2 in Drupal 6).

9. Navigate to the English comment 1 directly at /comment/1 and see that the English comment (cid 1 in Drupal 6) is shown as expected.

10. Navigate to the Finnish comment 2 directly at /comment/2 or at /fi/comment/2 and notice how you will get an internal server error.

11. Navigate to the comment list at /admin/content/comment and notice how you will get an internal server error.

Root cause analysis and investigation on the database level.

12. The Drupal 6 database table 'comments' does not store the language of the comments. Each comment has a relation to the nid. The nodes have a language in the 'node' database table. D8 'comment' table has a language. All comments are having the site default (English) language after migration. The D8 comment language should be taken from the D6 node language during the migration.

13. D8 comment_entity_statistics has an entry for node/2 (Finnish node in Drupal 6) which does not exist in D8 because the Finnish D6 node was migrated as field level translation to node/1 in Drupal 8. This is not causing the internal server errors, though.

14. The internal server error is caused by an invalid reference in the comment_field_data database table. The Finnish node (nid 2) was migrated as field level translation to the English node (nid 1) in Drupal 8. The comment_field_data for the Finnish comment is pointing to nid 2 which does not exist in D8. If you manually fix this relation to point to nid 1 and clear caches, the internal server error is gone.

Proposed resolution

A. When migrating comments, set the language of the D8 comment based on the Drupal 6 node's language.

B. Ensure that comment_entity_statistics does not get a ghost entry for translated node/2 because it was 'merged' to node/1 as field level translation.

C. Ensure that the records in comment_field_data have correct references when there are comments to translated D6 nodes which are 'merged' to the original language node in D8.

D. Default language and language selector for the new comments posted on D8.
Migrations generate one comment type for each Drupal 6 content type (except Forum which uses the hard coded comment_forum). The D8 comment type has a default language for new comments. It also has an option for showing the language selector. These settings are not currently migrated sensibly for multilingual sites. However, this is an issue of it's own and will be handled in #2981393: Migrate D6 comment type language settings.

Steps to reproduce on Drupal 7

As for Drupal 6 but use the D7 core Content Translation. On D6 we used the contributed i18n family.

Remaining tasks

1. Review proposed resolution.
2. Patch
3. Test coverage
4. Review
5. Commit
6. Evaluate if the same thing happens in D7-D8 migration. Most probably yes.

User interface changes

None.

API changes

None.

Data model changes

None.

Comments

masipila created an issue. See original summary.

masipila’s picture

Title: D6-D8 comment languages not migrated correctly » D6-D8 comment migration corrupts data with multilingual sites
Issue summary: View changes
masipila’s picture

Issue summary: View changes
masipila’s picture

masipila’s picture

Title: D6-D8 comment migration corrupts data with multilingual sites » Comment migration corrupts data with multilingual sites
masipila’s picture

Discussed with @maxocub in Slack.

At first glance, we first need to migrate a langcode for the comments, and the d6_comment source plugin already join the node table so we can get it there.

Then for the step 14, if we look at d6_comment.yml migration, instead of entity_id: nid, we will need to get the new nid with a migration_lookup. I haven't tried to reproduce the problem yet, so I'm not 100% sure about this.

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

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now 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.

masipila’s picture

Issue summary: View changes
Status: Active » Needs review
Issue tags: +Needs tests

Here's a start. The patch does not have tests yet, I'm setting this to NR just to trigger the testbot in order to see if this breaks any existing tests.

Changes:

  • Comment langcode is now mapped from the D6 node language.
  • The node of the comment is now mapped using migration_lookup so that we first check if nid is found in d6_node mapping table and if not, we check if it can be found from the d6_node_translation mapping table.

D7-D8 migration most probably has the same bug, I'll check that next.

masipila’s picture

StatusFileSize
new2.06 KB

I've heard rumors that the system works a bit better if I actually attach the patch to the post. Doh.

Status: Needs review » Needs work

The last submitted patch, 9: 2981392-8.patch, failed testing. View results

masipila’s picture

Issue summary: View changes
Status: Needs work » Needs review
Issue tags: +migrate-d7-d8
StatusFileSize
new3.92 KB
new1.87 KB

Seems that there are quite a few failing tests. Let's break some more by adding D7-D8 to the picture. The same bug is there, the only difference is that the D7 comments have language directly in the comments table so we can use that instead of taking the language of the node.

Setting to NR to trigger the testbot for the D7-D8 tests.

Status: Needs review » Needs work

The last submitted patch, 11: 2981392-11.patch, failed testing. View results

masipila’s picture

I analyzed the test failures a bit for the D6 comment migration. Currently we don't map the destination 'langcode' property at all in d6_comment. As a result, the migrated comments get the site default language ('en' if the D8 site was installed in English).

The patch #11 leaves the destination langcode property empty / null if the source node did not have a language specified. This will boil down in D8 and is not OK.

Option A: Should we map the destination 'langcode' property only if the source 'language' property has been set? This would be close to what the migration is currently doing i.e. the missing langcode mapping will the lead to site's default language code to be assumed.

Option B: Or should we set the destingation 'langcode' as 'und' if the source 'language' property has not been set?

Cheers,
Markus

masipila’s picture

Actually I think the most elegant approach is to indicate the source site language as a fallback in the source plugin if the comment / node language is not set. I'll write a patch with this approach hopefully still today.

masipila’s picture

Status: Needs work » Needs review
StatusFileSize
new15 KB
new12.08 KB

Still work in progress but submitting the next patch version.

This now has fixtures for both D6 and D7.

  • On D6 fixture I used the existing Employee content type which had both translations and comments enabled. There were no existing nodes that were suitable for this test so I added two new nodes as translations of each other + comments to both language versions.
  • On D7 fixture there were existing nodes were I added comments. Hopefully this does not break any existing tests; if it does, then I need to add new nodes there as well.

This also has the first attempt on the D6 tests. There is no test-only patch at this point of time as this is still work in progress.

The language determination logic was discussed today in the weekly meeting. This patch has the D6 language fallback logic in the source plugin. However, it was concluded that it might be more elegant to either try to use migration_lookup + default_language or to write a process plugin that reads the default language of the destination Drupal site. I'll continue on this + test failures (I'm sure there will still be) + D7 part tomorrow.

Status: Needs review » Needs work

The last submitted patch, 15: 2981392-14.patch, failed testing. View results

maxocub’s picture

I confirm that the migration_lookup idea won't work. I looked at the mapping table of the default_language migration and the value you would get back would be system.site (the destination config ID) which is not very useful in our case.

masipila’s picture

Status: Needs work » Needs review
StatusFileSize
new21.65 KB
new17.03 KB

Here's a new patch. It needed a re-roll due to the fact that the D7 fixture had changed. This changed quite much so there's no interdiff. There will most likely still be some real test failures but let's see what the testbot says.

There's only a test-only patch that should fail and show the bug that we are fixing here. As mentioned above, there's most probably some other test failures as well but core/modules/comment/tests/src/Kernel/Migrate/d6/MigrateCommentTest.php and core/modules/comment/tests/src/Kernel/Migrate/d7/MigrateCommentTest.php have been updated so they should definitely fail with the new test data in the fixtures.

I'm still trying to figure out a least painful workflow with the fixture changes so please bare with me...

Cheers,
Markus

p.s. Big thanks to @maxocub on coaching me with the fixtures!

edit: p.p.s This patch still has the language fallback logic in the source plugin. I want to see all tests green before I add more complexity by writing a new process plugin.

Status: Needs review » Needs work

The last submitted patch, 18: 2981392-18-test-only.patch, failed testing. View results

masipila’s picture

Status: Needs work » Needs review
StatusFileSize
new21.66 KB

D6 fixture had changed so this needed a re-roll.

Status: Needs review » Needs work

The last submitted patch, 20: 2981392-20.patch, failed testing. View results

masipila’s picture

Status: Needs work » Needs review
StatusFileSize
new21.66 KB

Doh. I somehow managed to have an extra whitespace in the patch #20 causing it not to apply. Here's a working re-roll.

Status: Needs review » Needs work

The last submitted patch, 22: 2981392-22.patch, failed testing. View results

masipila’s picture

Status: Needs work » Needs review
StatusFileSize
new22.05 KB
new2.07 KB

Here's the next version which should hopefully fix most of the remaining test failures. I could use some help with the MigrateUpgrade7NoMultilingualTest test failure, time to go to bed now...

About the changes here:

   entity_id:
-    plugin: migration_lookup
-    migration:
-      - d6_node
-      - d6_node_translation
-    source: nid
+    -
+      plugin: migration_lookup
+      migration:
+        - d6_node
+        - d6_node_translation
+      source: nid
+    -
+      plugin: skip_on_empty
+      method: row

This fixes the d6\MigrateForumTest failure where things are done to all comments regardless if they are forum comments or any other comments. Thanks @maxocub for your help with this one!

Cheers,
Markus

Status: Needs review » Needs work

The last submitted patch, 24: 2981392-24.patch, failed testing. View results

masipila’s picture

Status: Needs work » Needs review
StatusFileSize
new22.4 KB
new1.42 KB

Fixing entity counts for the UI tests.

Status: Needs review » Needs work

The last submitted patch, 26: 2981392-26.patch, failed testing. View results

masipila’s picture

Status: Needs work » Needs review
StatusFileSize
new22.4 KB

Patch #26 did not apply anymore, let's start with a re-roll. Expecting to see the same test failures as previously so no need to do a review yet, I'm just triggering the testbot by setting this to NR.

Status: Needs review » Needs work

The last submitted patch, 28: 2981392-28.patch, failed testing. View results

masipila’s picture

Status: Needs work » Needs review
StatusFileSize
new23.01 KB
new2.01 KB

Another round with testbot. Unfortunately I'm not able to run the full migration tests on my dev environment so need to test them here :( Please bare with me...

Status: Needs review » Needs work

The last submitted patch, 30: 2981392-30.patch, failed testing. View results

maxocub’s picture

Just a quick review for the recent changes.

  1. +++ b/core/modules/comment/migrations/d7_comment.yml
    @@ -17,7 +17,12 @@ process:
    +  entity_id:
    +    plugin: migration_lookup
    +    migration:
    +      - d7_node
    +      - d7_node_translation
    +    source: nid
    

    We should add a skip_on empty here too.

  2. +++ b/core/modules/comment/tests/src/Kernel/Migrate/d6/MigrateCommentTest.php
    @@ -84,6 +93,31 @@ public function testMigration() {
    +    // Tests that the language of the comment is migrated from the node.
    +    $comment = Comment::load(7);
    +    $this->assertSame('Comment to John Smith - EN', $comment->subject->value);
    +    $this->assertSame('This is an English comment.', $comment->comment_body->value);
    +    $this->assertSame('21', $comment->getCommentedEntityId());
    +    $this->assertSame('node', $comment->getCommentedEntityTypeId());
    +    $this->assertSame('en', $comment->language()->getId());
    +
    +    $node = $comment->getCommentedEntity();
    +    $this->assertInstanceOf(NodeInterface::class, $node);
    +    $this->assertSame('21', $node->id());
    +
    +    // Tests that the comment language is correct and that the commented entity
    +    // is correctly migrated when the comment was posted to a node translation.
    +    $comment = Comment::load(8);
    +    $this->assertSame('Comment to John Smith - FR', $comment->subject->value);
    +    $this->assertSame('This is a French comment.', $comment->comment_body->value);
    +    $this->assertSame('21', $comment->getCommentedEntityId());
    +    $this->assertSame('node', $comment->getCommentedEntityTypeId());
    +    $this->assertSame('fr', $comment->language()->getId());
    +
    +    $node = $comment->getCommentedEntity();
    +    $this->assertInstanceOf(NodeInterface::class, $node);
    +    $this->assertSame('21', $node->id());
    

    Maybe we could also test the language of the commented nodes, to make sure the comments are on the right language.

  3. +++ b/core/modules/comment/tests/src/Kernel/Migrate/d7/MigrateCommentTest.php
    @@ -85,6 +92,21 @@ public function testMigration() {
    +    // Tests that the commented entity is correctly migrated when the comment
    +    // was posted to a node translation.
    +    $comment = Comment::load(3);
    +    $this->assertInstanceOf(Comment::class, $comment);
    +    $this->assertSame('Comment to IS translation', $comment->getSubject());
    +    $this->assertSame('This is a comment to an Icelandic translation.', $comment->comment_body->value);
    +    $this->assertSame('2', $comment->getCommentedEntityId());
    +    $this->assertSame('node', $comment->getCommentedEntityTypeId());
    +    $this->assertSame('is', $comment->language()->getId());
    +
    +    $node = $comment->getCommentedEntity();
    +    $this->assertInstanceOf(NodeInterface::class, $node);
    +    $this->assertSame('2', $node->id());
    

    Same here.

  4. +++ b/core/modules/migrate_drupal/tests/fixtures/drupal6.php
    @@ -2169,6 +2201,18 @@
     ->values(array(
    + 'vid' => '2002',
    +  'nid' => '21',
    +  'delta' => '0',
    +  'field_company_nid' => NULL,
    +))
    

    Indentation of 'vid'.

  5. +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7NoMultilingualTest.php
    @@ -26,6 +26,7 @@ class MigrateUpgrade7NoMultilingualTest extends MigrateUpgradeExecuteTestBase {
    +    'migrate_drupal_multilingual',
    

    This test is supposed to check what happen if we try to run multilingual migrations without Migrate Drupal Multilingual enabled. So, we should not enable it. I think the fact that we have failure here is because the migration shown on the UI change depending on the discovery order. This is something we should try to fix in another issue. For now, we should find which migration is displayed in the warning and change it. I'm currently running the test and I'll report back with the correct migration in a few minutes.

    EDIT: Change d7_node_entity_translation:article to d7_node_translation:article.

masipila’s picture

Status: Needs work » Needs review
StatusFileSize
new23.83 KB
new4.2 KB

1. Fixed.

2. I don't think we can.

  • In D6 the two language versions were different nodes.
  • In D8 the translations are just different language versions of the same node (nid 21).

3. Same as above.

4. Fixed.

5. Fixed.

Let's see if I got any luck with the entity counts in the UI tests this time...

Markus

EDIT: typos

Status: Needs review » Needs work

The last submitted patch, 33: 2981392-33.patch, failed testing. View results

maxocub’s picture

Status: Needs work » Needs review

Unrelated failure, back to Needs review.

maxocub’s picture

Status: Needs review » Reviewed & tested by the community

I tested the patch manually with both D6 & D7.
The problems mentioned in the IS no longer occur and the resolutions from the IS have been implemented.
Patch looks good, let's move this into RTBC land.

  • catch committed b42529c on 8.7.x
    Issue #2981392 by masipila, maxocub: Comment migration corrupts data...

  • catch committed 53b2cf8 on 8.6.x
    Issue #2981392 by masipila, maxocub: Comment migration corrupts data...
catch’s picture

Version: 8.7.x-dev » 8.6.x-dev
Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.7.x and cherry-picked to 8.6.x. Thanks!

Status: Fixed » Closed (fixed)

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