Problem/Motivation

D7 follow-up for #2859297: Migrate taxonomy term references for D6 Node translations. This issue is about translations of vocabularies and references from the migrated node translations to the terms.

Proposed resolution

Write the migration in the same fashion as we did for D6 in #2859297: Migrate taxonomy term references for D6 Node translations.

The scope of this issue is the reference from the node translation to the taxonomy term.

Test case 1 when using 'Localized' vocabulary together with 'Node translation' concept.

  • Have two node entities in Drupal 7, one in English (nid A) and one for example in Finnish (nid B). Associate these as translations of each other.
  • Have one taxonomy term in Drupal 7 which is translated in Drupal 7 using the 'Localized' concept.
  • Make sure that both English and Finnish versions of the Drupal 7 node have a reference to the term.

Expected result:

  • The Finnish language version of the node is migrated as a translation to the English node. In other words, there were 2 nodes in Drupal 7 but there will only be 1 node in Drupal 8.
  • Both language versions of the Drupal 8 node must have a reference to the term.

Implementation in D7 fixture:
Vocabulary name: vocablocalized,
French translation: name, 'fr - VocabLocalized', description, 'fr - Vocabulary localize option'
Icelandic translation: name, 'is - VocabLocalized', description, 'is - Vocabulary localize option'

Test case 2 when using 'Translated' vocabulary.

  • Have two node entities in Drupal 7, one in English and one for example in Finnish. Associate these as translations of each other.
  • Have two taxonomy terms in Drupal 7. The vocabulary must have the 'Translate' multilingual setting. Both taxonomy terms will have their language defined.
  • Make sure that the English node has a reference to the English term in Drupal 7.
  • Make sure that the Finnish node has a reference to the Finnish term in Drupal 7.

Expected result:

  • The Finnish language version of the node is migrated as a translation to the English node. In other words, there were 2 nodes in Drupal 7 but there will only be 1 node in Drupal 8.
  • When viewing the English version of the Drupal 8 node (original language of the node), it must have a reference to the English term.
  • When viewing the Finnish translation of the Drupal 8 node, it must have a reference to the Finnish term.

Implementation in D7 fixture:
Vocabulary name: vocabtranslate.
French translation: None added
Icelandic translation: name, 'is - VocabTranslate', description, 'is - Vocabulary translate option'

Remaining tasks

Review, commit.

User interface changes

N/A

API changes

N/A

Data model changes

N/A

CommentFileSizeAuthor
#50 3035392-50.patch33.15 KBquietone
#50 interdiff-48-50.txt2.34 KBquietone
#48 3035392-48.patch32.73 KBquietone
#48 interdiff-43-48.txt2.73 KBquietone
#43 interdiff-36-43.txt788 bytesquietone
#43 3035392-43.patch33.06 KBquietone
#41 interdiff-31-41.txt849 bytesquietone
#41 3035392-41.patch33.12 KBquietone
#36 3035392-31.patch33.04 KBGábor Hojtsy
#32 3035392-32-test-only.patch35.96 KBquietone
#31 interdiff-29-31.txt546 bytesquietone
#31 3035392-31.patch33.04 KBquietone
#29 interdiff-23.29.txt1.29 KBquietone
#29 3035392-29.patch33.11 KBquietone
#23 3035392-23.patch33.25 KBquietone
#23 interdiff-19-23.txt1.79 KBquietone
#20 interdiff-12-19.txt1004 bytesquietone
#20 3035392-19.patch31.46 KBquietone
#12 with-node-translation.patch37.08 KBquietone
#12 no-node-translation.patch37.11 KBquietone
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

masipila created an issue. See original summary.

masipila’s picture

Status: Reviewed & tested by the community » Active

This was accidentally created as RTBC when I cloned this from the D6 issue... Now back to active status.

masipila’s picture

Status: Active » Postponed

Argh, to postponed and not active...

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

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

quietone’s picture

Issue summary: View changes
quietone’s picture

Issue summary: View changes
Issue tags: -migrate-d6-d8 +migrate-d7-d8

This is just the D7 version, #2859297: Migrate taxonomy term references for D6 Node translations ss the D6 versin.

quietone’s picture

Issue summary: View changes
quietone’s picture

Issue summary: View changes
masipila’s picture

Issue summary: View changes
Status: Postponed » Active

#2979966: Migrate D7 i18n taxonomy term language just landed, this should no longer be postponed.

quietone’s picture

Assigned: Unassigned » quietone
Issue summary: View changes

I've got a patch for this but need to do more testing.

quietone’s picture

Started from the d6 issue and made migration for Vocabulary and Taxonomy Term. I also added tests to MigrateNode to confirm that the correct translation was attached to the nodes. I discovered that the drupal7 fixture, despite my efforts, had wonky lids in the locales_target table. I found that out when clicking around the translations via the UI. So there are changes here to fix that.

There are two patches here, both of which fail but for different reasons. The no-node-translation removed d7_node_translation from the MigrateNode test. In this case the test fails when testing if there is an Icelandic translation for node 2, which is correct. The point is that before that assertion there is an assertion for the taxonomy term reference 'field_vocab_fixed' on node 2 that passes, which is what the taxonomy_term migration does. However, when the d7_node_translation is run, the assertion for the 'field_vocab_fixed' fails because it is NULL. And what is curious about that is that field_vocab_fixed is correct after the run of d7_node. But after d7_node_translation the value of that field is removed. There is NOT a translation of field_vocab_fixed for node 2, icelandic, and when that row is saved there isn't a property for that field in the row and somehow that removes the field contents on the node. I hope that makes sense to you.

Status: Needs review » Needs work

The last submitted patch, 12: with-node-translation.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

quietone’s picture

This is odd. Working with the D7 fixture, I have seen that the fixed language terms do not work as I would expect based on this from
/admin/structure/taxonomy/vocabfixed/edit
Fixed Language. Terms will have a global language and they will only show up for pages in that language.

The term, which is in French, can appear on the English and Icelandic version of the article. That doesn't make sense to me.

What is meant by 'Per language' vocabulary? The options are

  • Localize. Terms are common for all languages, but their name and description may be localized.
  • Translate. Different terms will be allowed for each language and they can be translated.
  • Fixed Language. Terms will have a global language and they will only show up for pages in that language.
masipila’s picture

Issue summary: View changes

Hi @quietone!

1. Regarding 'what is meant by per language' vocabulary.

This term is used in D6, see the screenshot ofcthe admin form at https://www.drupal.org/docs/8/upgrade/upgrading-multilingual-drupal-6-to...

This is conceptually the same thing as 'translate' mode in D7 where the a term can be assigned a language code.

I updated the IS to use the D7 names instead the copy-pasted D6 names.

2. Regarding the fixed language concept.
If memory serves me well, this concept is as follows:

  • The language is defined on the vocabulary level.
  • Once the term has been created, the language of the term cannot be changed in the UI.
  • If I remember correctly, the D6/D7 worked so on the database level the term did not even have a language code assigned on the term level (as it was defined for the whole vocabulary). I might be wrong with this as I can't check this right now (read: it is also possible that the D6/D7 terms did have a language code in the db but the user could not change that after the term had been created)

3. Regarding the possible combinations
Quietone wrote:

The term, which is in French, can appear on the English and Icelandic version of the article. That doesn't make sense to me.

Just to confirm: you're still talking about terms that belong to a Fixed Language vocabulary (and not to a Translated vocabulary), right?

Cheers,
Markus

quietone’s picture

Kia ora masipila!

Thanks for the explanations. For #1, I expected that 'per language' was the same as 'translate'. Good to have that confirmed. For #2/3, Yes, he vocabulary (vocabfixed) is fixed, with a language of 'fr' in the 'taxonomy_vocabulary' table. It has one term, 'FR - Crewman' which also has a 'fr' language in the 'taxonomy_term_data' table. And yet when I add an 'en' language node, that French language term is a valid choice. A bit strange, but that is how D8 behaves.

So, moving on. This patch correctly migrates localized and translated vocabulary are per the proposed resolution in the IS. However, d7_node_translation breaks the migration of the FixedVocabulary. Details of that are in #12.

Not sure how to fix this one. Any ideas?

Gábor Hojtsy’s picture

And yet when I add an 'en' language node, that French language term is a valid choice. A bit strange, but that is how D8 behaves.

Drupal 8 does not filter selectable terms based on language in core. You could install a contrib to do that. The thinking is you may want to actually translate the terms (or some terms) and still be able to select them. Same goes for menu item parents, etc. Such UI filtering is not available in core.

quietone’s picture

Wait a minute, rechecked with both D7 and D8 with a vocabulary fixed taxonomy and find that D7 behaves differently than D8. In D8, the term is always the same on all the translations of the node whereas in D7 the term can be NULL on one of the translated nodes. I can't get that to happen in D8. Plus, the D7 fixed has that case, where the term is 'FR - Crewman' on one of the translated nodes and NULL on another, that is the problem. If that is all true then term reference for fixed vocabularies can't be migrated to match the source site. The term reference migrated will be the one in the last migrated translated node.

Gábor Hojtsy’s picture

@quietone: are you comparing D7 node or entity translations to D8? If the term was fixed language and cannot be assigned to translations it makes sense that the D7 translation would not have it assigned. D8 does not have a setting to prohibit assigning it, but it does have a setting to fix it to a specific language. So whether you assign it or not depends on whether the field value was set optional (not required) and whether it was set to be translatable (can be different per language). In the case where the D8 field is optional and can be different per language, it can be unset for a certain language. There is no UI or other mechanism to enforce that you cannot pick a different language term though if you want to. So the migration cannot migrate into the same UI behavior but it can migrate to the same data state IMHO.

quietone’s picture

Status: Needs work » Needs review
FileSize
31.46 KB
1004 bytes

With that in mind, cleanup the patch from #12 to remove test garbage I left in and modify MigrateNodeTest so that the taxonomy term ref for vocab fixed is tested with a NULL value.

So, to be clear the English version of the node has the term ref for the fixed vocab as 'FR - Crewman' and the Icelandic term ref is empty/NULL. The migration will use NULL for the term for for both the English and Icelandic versions of the node. That is not a match for the D7 source but the D7 and D8 behave differently so I don't see what else can be done. This will need some documentation.

quietone’s picture

Assigned: quietone » Unassigned

Status: Needs review » Needs work

The last submitted patch, 20: 3035392-19.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

quietone’s picture

Status: Needs work » Needs review
FileSize
1.79 KB
33.25 KB

And correct the migration states.

quietone’s picture

Here is snippet of D7 code for translation vocabulary fixed, from i18n_taxonomy.module, https://git.drupalcode.org/project/i18n/blob/7.x-1.x/i18n_taxonomy/i18n_...

        // We translate just some vocabularies: translatable, fixed language
        // Fixed language ones may have terms translated, though the UI doesn't support it
        if ($mode & I18N_MODE_LANGUAGE || $mode & I18N_MODE_TRANSLATE) {
          $translation[$index] = i18n_taxonomy_translate_terms($tdata, $langcode, $fullterms);
        }
        elseif ($fullterms) {
          $translation[$index] = array_map('_i18n_taxonomy_filter_terms', $tdata);
        }
        else {
          $translation[$index] = array_map('_i18n_taxonomy_filter_tids', $tdata);
        }

Here is states that for the fixed mode (i18N_MODE_LANGUAGE) that that, in fact, the terms can be translated though it can't be done via the UI. So, the source can have translations for a vocabulary fixed field but D8 can't. The way the migration runs the last translated value will be migrated. In a way that is what is seen in the test where the first value migrated is 'FR - Crewman' and that is overwritten by the last translated value, which is NULL. AFAICT there will be data loss here.

Maybe the migration of fixed vocabulary needs to be smarter and get the value of the translation from the node of the same language. I don't know.

Gábor Hojtsy’s picture

Does the fixture having translation mean that the i18n module itself would allow those translations or is it just that the fixture has them added? If the later (which I assume) then we need the fixture fixed not the migration.

quietone’s picture

I created the fixed vocabulary from the UI and from the UI I can set the English version of the node to use the fixed vocab term 'FR - Crewman' and the Icelandic term ref to empty/NULL. Yes, just from the UI and I have triple checked that.

quietone’s picture

We seem stuck here because of the behavior of vocab fixed. I have checked that behavior with the fixture and with a vanilla D7 site and they behave the same, which his different that D8. Can anyone confirm that?

If my results are correct, we need to make a decision about how to migrate terms with a fixed vocabulary.

quietone’s picture

Assigned: Unassigned » quietone
Status: Needs review » Needs work

OK, Thanks to Gábor Hojtsy and simplytestme I finally see what is going on. Pretty sure this is about the 'Users may translate this field setting' in regard to the vocabulary fixed.

quietone’s picture

Status: Needs work » Needs review
FileSize
33.11 KB
1.29 KB

Found an error in the test where it was testing the node and not the translation. Fixed that and changed the term references for the fixed vocabulary to properly reflect what is in the D7 source db. It will fail tests until #3080492: Migrate fixed vocabulary term reference fields as translatable to conform to data expectations when nodes get merged is in.

Status: Needs review » Needs work

The last submitted patch, 29: 3035392-29.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

quietone’s picture

Status: Needs work » Needs review
FileSize
33.04 KB
546 bytes

Coding standard fix

quietone’s picture

The last submitted patch, 31: 3035392-31.patch, failed testing. View results

quietone’s picture

Issue summary: View changes
Status: Needs review » Postponed

The test only patch passed tests so just need to postpone this on #3080492: Migrate fixed vocabulary term reference fields as translatable to conform to data expectations when nodes get merged and when that happens use the patch in #31.

Gábor Hojtsy’s picture

Gábor Hojtsy’s picture

Reuploading #31 just for posterity to have before-after results kept/shown properly.

Status: Needs review » Needs work

The last submitted patch, 36: 3035392-31.patch, failed testing. View results

Gábor Hojtsy’s picture

Status: Needs work » Needs review
masipila’s picture

Queued for postgres and sqlite

masipila’s picture

Status: Needs review » Needs work

We seem to have test failures with PostgreSQL... :(

quietone’s picture

Status: Needs work » Needs review
FileSize
33.12 KB
849 bytes

@masiplia, thx for running tests against sqlite and postgres.

I can't get lando to bring up a postgres so I am taking my best guess at fixing this without the ability to test locally.

Status: Needs review » Needs work

The last submitted patch, 41: 3035392-41.patch, failed testing. View results

quietone’s picture

Arg, ignore that patch. On the bright side I've got postgres setup in one of my LXC containers.

Starting over from the patch in #36.

quietone’s picture

The test failure with postgresql is not related it is in Drupal\Tests\media_library\FunctionalJavascript\MediaLibraryTest

quietone’s picture

Assigned: quietone » Unassigned
alexpott’s picture

Gábor Hojtsy’s picture

Title: Migrate taxonomy term references for D7 Node translations » Migrate vocabulary translations and taxonomy term references for Drupal 7 node translations
Issue summary: View changes

Updated title and summary based on what is included.

Two things I don't understand:

+    $query = parent::query();
+    $query->leftjoin('i18n_string', 'i18n', 'CAST (v.vid AS CHAR(222))= i18n.objectid');
+    $query->innerJoin('locales_target', 'lt', 'lt.lid = i18n.lid');
+    $query
+      ->condition('type', 'vocabulary')
+      ->fields('lt')
+      ->fields('i18n');
+    $query->addField('lt', 'language', 'lt.language');
+    $query->addField('lt', 'lid', 'lt_lid');

lt.language would already be added by adding all fields of lt, no?

+      'format' => $this->t('The {filter_format}.format of the string'),
+      'ltlanguage' => $this->t('Language code from locales_source table'),
+      'plid' => $this->t('Parent lid'),

That would be from the locales_target table, not source :)

+    if ($this->getDatabase()
+      ->schema()
+      ->fieldExists('taxonomy_vocabulary', 'language')) {
+      $query->addField('v', 'language');
+    }
[...]
+  public function prepareRow(Row $row) {
+    parent::prepareRow($row);
+    // For ease of reading the migration use 'language' as the property name for
+    // the language.
+    $language = $row->getSourceProperty('ltlanguage');
+    $row->setSourceProperty('language', $language);
+  }

Would this unconditionally overwrite the language from the query with ltlanguage at all times? Why have the language in the query then?

quietone’s picture

@Gábor Hojtsy, well spotted and that exposed a problem with getIds() too.

The fields() entries are changed for the two language fields, the 'property' value is added to getIds() and the query adjusted. And now, the prepareRow() is not longer needed.

Status: Needs review » Needs work

The last submitted patch, 48: 3035392-48.patch, failed testing. View results

quietone’s picture

Oh dear, changing the source plugin requires changing the source plugin test. That is now done.

quietone’s picture

Ah, more failures with PostgreSQL and they are unrelated to the patch. None are the media problem mentioned in #46

One is failing on HEAD, https://www.drupal.org/pift-ci-job/1410286

Gábor Hojtsy’s picture

Status: Needs review » Reviewed & tested by the community

Thanks for fixing those, looks good now :)

masipila’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs issue summary update

The issue summary has still todo items. Can we please clean it up?

quietone’s picture

Issue summary: View changes
Status: Needs work » Needs review
Issue tags: -Needs issue summary update

Updated the IS with the added vocabularies and their translations.

@masipila, Did I get everything?

Gábor Hojtsy’s picture

Status: Needs review » Reviewed & tested by the community

Thanks, let's get this in!

  • larowlan committed 932a453 on 8.8.x
    Issue #3035392 by quietone, Gábor Hojtsy, masipila: Migrate vocabulary...
larowlan’s picture

Status: Reviewed & tested by the community » Fixed

Committed 932a453 and pushed to 8.8.x. Thanks!

🎉

Status: Fixed » Closed (fixed)

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