Problem/Motivation

On #2886609: Migrate translations for D6 i18n taxonomy 'localized' terms, we found that vocabulary vocabulary settings from the i18n Taxonomy translation module are not being migrated.

On a D6 site with this module enabled, the Vocabulary page has a "Multilingual options" section of the settings that looks like this:
Multilingual vocabulary options screenshot

D6 data source

The multilanguage mode is saved in variable i18ntaxonomy_vocabulary. The structure is an associative array of $vid => $mode and here are the mode options and constant values:

  // this is i18ntaxonomy_vocabulary_options():
  return array(
    I18N_TAXONOMY_NONE => t('None. No multilingual options for this vocabulary.'),
    I18N_TAXONOMY_LOCALIZE => t('Localize terms. Terms are common for all languages, but their name and description may be localized.'),
    I18N_TAXONOMY_TRANSLATE => t('Per language terms. Different terms will be allowed for each language and they can be translated.'),
    I18N_TAXONOMY_LANGUAGE => t('Set language to vocabulary. The vocabulary will have a global language and it will only show up for pages in that language.'),
  );

  // and the constants are defined as:

// No multilingual options
define('I18N_TAXONOMY_NONE', 0);
// Run through the localization system
define('I18N_TAXONOMY_LOCALIZE', 1);
// Predefined language for all terms
define('I18N_TAXONOMY_LANGUAGE', 2);
// Multilingual terms, translatable
define('I18N_TAXONOMY_TRANSLATE', 3);

The D6 can also have a language if (and only if) the multilanguage mode is set as 'Set language to vocabulary'. D6 UI forces an empty value to this drop down list if any other multilanguage mode is selected. The language is saved in D6 database in vocabulary.language column.

'Localized terms' concept

The data model in D6 is illustrated in the picture below.
D6 'localized' concept

  • The node translations are separate nodes but they are both pointing to the same term.
  • There is only one term entity, but the title and description of the term can be translated in D6.

The D8 equivalent to this concept is shown in the picture below.
D8 shared term with translations

D6 'per language' concept

The data model in D6 is illustrated in the picture below.
D6 'per language' concept

  • The node translations are separate nodes.
  • There are two separate term entities which may be linked together as translations of each other but the translation link does not necessarily exist.

The closest D8 equivalent to this concept is shown in the picture below.
D8 separate terms

  • There is a conceptual difference between D6 and D8.
  • In D6, the different taxonomy term entities can be linked as translations of each other but in D8 they can not be linked like in D6.
  • The data model described in the picture above is the closest equivalent in D8.

D8 vocabulary settings

The D8 vocabulary settings are shown in the picture below.
D8 vocabulary settings

The 'Term language / Default language' corresponds to the D6 vocabulary language.
Note that the vocabulary itself has a language in D8. This is not related to the D6 language settings, the 'Language' field of D8 can be used to indicate the language of the vocabulary so that the vocabulary name and description can be translated.

Proposed resolution

Common mapping to all multilingual modes

  • D8 vocabulary term default language: Migrate from D6 vocabulary language if it is set. Otherwise migrate to site default language.
  • Note: this does not impact the language of the terms to be migrated, only new terms that will be created in D8.

D6 'No multilingual options for this vocabulary' setting

Test vocabulary: tags, forums and type

  • D8 vocabulary 'Show language selector on create and edit pages': FALSE
  • D8 vocabulary 'Enable translation': FALSE.
  • D8 content type field settings for the term reference 'Users may translate this field': FALSE

D6 'localize terms'

Test vocabulary: vocabulary 3 (i=2)

  • D8 vocabulary 'Show language selector on create and edit pages': TRUE
  • D8 vocabulary 'Enable translation': TRUE
  • D8 content type field settings for the term reference 'Users may translate this field': FALSE

D6 'per language terms'

Test vocabulary: vocabulary 1 (i=0)

  • D8 vocabulary 'Show language selector on create and edit pages': TRUE
  • D8 vocabulary 'Enable translation': FALSE.
  • D8 content type field settings for the term reference 'Users may translate this field': TRUE

D6 'Set language to vocabulary'

Test vocabulary: vocabulary 2 (i=1)

  • D8 vocabulary 'Show language selector on create and edit pages': FALSE
  • D8 vocabulary 'Enable translation': FALSE.
  • D8 content type field settings for the term reference 'Users may translate this field': FALSE

Remaining tasks

1. Patch
2. Add tests.
3. Review.
4. Commit

User interface changes

N/A

API changes

N/A

Data model changes

N/A

CommentFileSizeAuthor
#64 interdiff-61-64.txt706 bytesquietone
#64 2975509-64.patch16.81 KBquietone
#61 interdiff-59-61.patch776 bytesquietone
#61 2975509-61.patch16.8 KBquietone
#59 interdiff_50-59.txt750 bytesgaydabura
#59 2975509-59.patch16.71 KBgaydabura
#50 interdiff.txt778 bytesquietone
#50 2975509-50.patch16.76 KBquietone
#46 interdiff-40.46.txt4.11 KBquietone
#46 2975509-46.patch16.81 KBquietone
#40 2975509-40.patch17.52 KBquietone
#40 interdiff-37-40.txt1.09 KBquietone
#37 2975509-37.patch17.74 KBquietone
#37 interdiff-33-37.patch10.29 KBquietone
#36 interdiff.txt58.13 KBquietone
#36 2975509-36.patch68.1 KBquietone
#33 interdiff.txt3.03 KBquietone
#33 2975509-33.patch12.06 KBquietone
#30 2975509-30.patch12.02 KBquietone
#30 interdiff.txt3.37 KBquietone
#28 interdiff.txt4.14 KBquietone
#28 2975509-28.patch10.8 KBquietone
#24 2975509-24.patch10.11 KBmasipila
#24 interdiff-2975509-9-24.txt2.67 KBmasipila
#11 2979486-d8-localized-vocabulary-settings.PNG14.32 KBmasipila
#11 2975509-d8-shared-term.PNG11.48 KBmasipila
#11 2975509-d8-per-language.PNG13.78 KBmasipila
#11 2975509-d6-per-language.PNG9.92 KBmasipila
#11 2975509-d6-localized.PNG11.86 KBmasipila
#9 2975509-9.patch9.96 KBquietone
#7 2975509-7.patch7.88 KBquietone
#5 2975509-5.patch17.25 KBquietone
multilingual_taxonomy.png32.71 KBjhodgdon
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

jhodgdon created an issue. See original summary.

jhodgdon’s picture

Issue summary: View changes

HTML typo

quietone’s picture

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

Assigning to myself, I'm about halfway through making a patch.

quietone’s picture

Assigned: quietone » Unassigned
Status: Needs work » Needs review
FileSize
17.25 KB

@jhodgdon, thanks for the research, most helpful. I didn't see it until after I had done another look at the d6 code and I came to the same conclusion as you.

I manually tested this patch and it worked just fine but I haven't reviewed the code yet, I just got something to work.

Status: Needs review » Needs work

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

quietone’s picture

Status: Needs work » Needs review
FileSize
7.88 KB

Let's try that again. That was a bad patch.

Status: Needs review » Needs work

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

quietone’s picture

Status: Needs work » Needs review
FileSize
9.96 KB

This adds a source plugin test

Status: Needs review » Needs work

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

masipila’s picture

D6 has four options in vocabulary language settings. Let's cover all of them in this issue but limit the scope of this issue strictly to D8 Vocabulary settings as it was originally.

I updated the issue summary and proposed the mappings to all four scenarios.

Remaining tasks:
1. Review and agree the configuration settings of the proposed resolution
2. Update the patch accordingly with tests.
3. Test manually.

Cheers,
Markus

masipila’s picture

Issue summary: View changes

Formatting and fix to broken img URL.

Gábor Hojtsy’s picture

Looks all fine, except these ones which are the same in all cases:

D8 vocabulary language: Migrate from D6 vocabulary language. If empty on D6, migrate to 'und' (Not specified).

This may be fine, but I was wondering it we should migrate it to the site default language or just English when empty. I think D6 makes assumptions about this, and while I am not sure it will probably assume the site default language(?)

masipila’s picture

Re: #13.

I was thinking the same myself. I don't think we should use English as a fallback. I can easily imagine a D6 site where the primary language is something else but the vocabulary language is empty in D6. Let's fallback to the site default language.

I'll update the issue summary later today (I'm just about to hop off from the bus).

Markus

masipila’s picture

Issue summary: View changes

Re #13-14: IS updated.

masipila’s picture

D7 i18n_taxonomy module has the same 4 vocabulary options that we have in D6. The data is stored in taxonomy_vocabulary database table, we have columns 'language' and 'i18n_mode'. In D6 the data is stored in variables as described in the issue summary.

Do we want to increase the scope of this issue and cover both D6 and D7 in this same issue? Conceptually they are the same which would justify handling them in this same issue even though the scope of the issue creeps. I'm ok to handle these also as separate issues if that's what others are preferring.

Cheers,
Markus

masipila’s picture

Re #16: Answering myself, let's handle that as a separate issue as the vocabulary itself can be translated as well. For D6-D8 that part has been already covered in #2225781: Migrate D6 i18n taxonomy vocabularies and for D7 we need to cover a) the vocabulary settings as described in this issue + b) handle the translation of the vocabulary itself. I'll create a separate issue for that.

masipila’s picture

masipila’s picture

Title: Migrate i18ntaxonomy vocabulary settings » Migrate D6 i18ntaxonomy vocabulary settings
masipila’s picture

Assigned: Unassigned » masipila

I was evaluating more about this. D8 vocabluary does not have 'site default' language so the proposed resolution I wrote earlier is quite tricky. I'll continue evaluating and will provide a new patch this evening my time and will update the issue summary with an updated proposed resolution.

Hope you don't mind @quietone that I jump in with patching!

Cheers,
Markus

quietone’s picture

@masipila, not at all.

masipila’s picture

Issue summary: View changes

Ok, I figured out the rest of this.

The D6 vocabulary 'language' can be defined if (and only if) the multilanguage mode is set as 'Set language to vocabulary'. D6 UI forces an empty value to this drop down list if any other multilanguage mode is selected. The language is saved in D6 database in vocabulary.language column. This field controls the language of the new terms to be created i.e. it is an equivalent to D8 'Term language / Default language'.

The D8 vocabulary 'language' field is a different thing and is an attribute of the 'Taxonomy vocabulary' configuration entity. The D6 configuration attributes that that we are migrating here are attributes of the D8 'Content language settings' configuration entity.

Issue summary updated accordingly. Patch will come in the next comment.

Cheers,
Markus

masipila’s picture

Issue summary: View changes

Typo / formatting in IS.

masipila’s picture

Here's the patch that should be migrating all three fields according to the issue summary.

I did not make any changes to the tests yet, tagging for tests.

Markus

masipila’s picture

+source:
+  plugin: d6_language_content_settings_taxonomy_vocabulary
+  constants:
+    target_type: 'taxonomy_term'
+    default_langcode: 'site_default'

This works, but I noticed that @maxocub used a language code 'xx-et-current' in another migration, see #2073467: Migrate Drupal 7 Entity Translation settings to Drupal 8.

What is this 'xx-et-default' and should we use that one instead of 'site_default'?

Markus

maxocub’s picture

The xx-et-* langcodes are specific to the entity_translation module ('et' = 'entity_translation'), so I think 'site_default' is good here.

quietone’s picture

Assigned: masipila » quietone

I'll look at the tests this week.

quietone’s picture

Status: Needs work » Needs review
FileSize
10.8 KB
4.14 KB

Thanks masipila! Updated the test to check the default langcode and the third party settings according to the new migration values.

Status: Needs review » Needs work

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

quietone’s picture

Status: Needs work » Needs review
FileSize
3.37 KB
12.02 KB
  • Added language column to the source plugin test.
  • Added comments in the source plugin (taken from i18ntaxonomy.module) explaining the i18nvocabulary setting values.
  • Updated the entity count in MigrateUpgrade6Test
  • Added content_translation_update_definition to the destination plugin configuration.
masipila’s picture

Assigned: quietone » masipila

I'm checking the tests at the moment.

masipila’s picture

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

A couple of copy-paste error nits.

1.

+++ b/core/modules/language/tests/src/Kernel/Migrate/d6/MigrateLanguageContentTaxonomyVocabularySettingsTest.php
@@ -0,0 +1,76 @@
+ * Tests migration of the ability to translate menu content.

Should be something like 'Tests migration of i18ntaxonomy vocabulary settings.'

2.

+++ b/core/modules/language/tests/src/Kernel/Migrate/d6/MigrateLanguageContentTaxonomyVocabularySettingsTest.php
@@ -0,0 +1,76 @@
+   * Asserts an content language settings configuration.

s/an/the.

3.

+++ b/core/modules/language/tests/src/Kernel/Plugin/migrate/source/d6/LanguageContentTaxonomyVocabularySettingsTest.php
@@ -0,0 +1,81 @@
+ * Tests menu source plugin.

Should be something like 'Tests i18ntaxonomy vocabulary setting source plugin.'

quietone’s picture

Status: Needs work » Needs review
Issue tags: -Need tests
FileSize
12.06 KB
3.03 KB

@masipila, thanks for the review!

Yes, I still leave copy/paste errors behind.

All items in #32 fixed.

Removed the needs tests tags because the tests are here.

masipila’s picture

Issue summary: View changes
Status: Needs review » Needs work

I realized that the vocabulary language settings is not the only thing we need to cover.

  • The D8 content type / field settings has the term reference field.
  • This term reference field has a setting 'Users may translate this field'
  • In the 'per language' concept we need to enable this setting so that the English and Finnish language versions of the node can point to different terms. In all other scenarios, we need to leave this as FALSE.

Issue summary updated with expected result for each of the scenarios.

masipila’s picture

Title: Migrate D6 i18ntaxonomy vocabulary settings » Migrate D6 vocabulary language settings
quietone’s picture

Assigned: Unassigned » quietone
Issue summary: View changes
FileSize
68.1 KB
58.13 KB

This is not finished but I think it is working properly. At minimum, tests are needed for the changes in d6_vocabulary_field_instance and the changes to the dump needs checking.

I've added the names of the test fixture vocabularies to the proposed resolution to help with reviews.

quietone’s picture

Issue summary: View changes
Status: Needs work » Needs review
FileSize
10.29 KB
17.74 KB

The patch is #36 was a work in progress and it was made from HEAD. Oops. This patch is and the interdiff is against the patch in #33.

The four modes of translation are now enabled in the test fixture. Only one vocabulary required a change, that was to set vocabulary vocabulary_3_i_0_ to translate 'localized term'. And they are tested according to the excellent descriptions by masipila in the proposed resolution. I've added the taxonomy names there to help reviewers.

Edit: I really must remember to name interdiff correctly.

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

Status: Needs review » Needs work

The last submitted patch, 37: 2975509-37.patch, failed testing. View results

quietone’s picture

Not sure how the hierarchy for the vocabulary was changed from 2 to 0. It is back to 2 now. And fixed the entity count as well/

quietone’s picture

Issue summary: View changes

This is ready for review. It should now implement all of the proposed resolution, that is the vocabulary settings and the language content settings for the 4 modes of taxonomy translation available in Drupal6.

Change the IS to show that the patch is made and it has tests.

quietone’s picture

Assigned: quietone » Unassigned

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

I tested this manually and the patch #40 works exactly as the issue summary describes. I also reviewed the patch and it looks good. There is also sufficient test coverage.

I'd RTBC this otherwise but I contributed to the patch in #24 so I'm not sure I can do that. But as said, the patch #40 is doing exactly what the issue summary defines for the different scenarios.

Thanks @quietone!

Cheers,
Markus

maxocub’s picture

Status: Needs review » Needs work

Just found a few things, otherwise this looks good, great work everyone!

  1. +++ b/core/modules/language/migrations/d6_language_content_taxonomy_vocabulary_settings.yml
    @@ -0,0 +1,56 @@
    +  default_langcode:
    +    -
    +      plugin: get
    +      source: language
    +    -
    +      plugin: default_value
    +      default_value: site_default
    

    I think this could be written as

    default_langcode:
      plugin: default_value
      default_value: site_default
      source: language
    
  2. +++ b/core/modules/language/tests/src/Kernel/Migrate/d6/MigrateLanguageContentTaxonomyVocabularySettingsTest.php
    @@ -0,0 +1,80 @@
    +    // Create some languages.
    +    ConfigurableLanguage::createFromLangcode('en')->save();
    +    ConfigurableLanguage::createFromLangcode('fr')->save();
    

    Instead of manually creating the languages, we can just run the 'language' migration.

  3. +++ b/core/modules/migrate_drupal/tests/fixtures/drupal6.php
    @@ -8618,6 +8618,16 @@
    +  'nid' => '1',
    +  'timestamp' => '1531475240',
    +))
    +->values(array(
    +  'uid' => '1',
    +  'nid' => '2',
    +  'timestamp' => '1531475241',
    +))
    +->values(array(
    +  'uid' => '1',
    
    @@ -44015,6 +44025,12 @@
    +  'nid' => '9',
    +  'totalcount' => '1',
    +  'daycount' => '1',
    +  'timestamp' => '1531475237',
    +))
    +->values(array(
    

    I don't see the relevance of those changes. I think they can be remove without affecting the tests in this patch.

  4. +++ b/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateVocabularyFieldInstanceTest.php
    @@ -39,19 +39,21 @@ protected function setUp() {
    +    // Test that the field exists.Tags has a multilingual option of 'None'.
    ...
    +    // Test the page bundle as well.Tags has a multilingual option of 'None'.
    

    Missing spaces after the periods.

quietone’s picture

Thanks maxocub.

This should fix #45.1-4.

maxocub’s picture

Status: Needs review » Reviewed & tested by the community

Great, after reading a few times through the IS, the comments and the patch, I think this is ready.

Only one thing though, there's still one unused use statement:

+++ b/core/modules/language/tests/src/Kernel/Migrate/d6/MigrateLanguageContentTaxonomyVocabularySettingsTest.php
@@ -0,0 +1,80 @@
+use Drupal\language\Entity\ConfigurableLanguage;

But that can be fixed on commit, right?

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

masipila’s picture

Queued the last patch to PostgreSQL and SQLite tests just to be sure.

quietone’s picture

Removed the unused use statement spotted in #47.

masipila’s picture

Status: Needs review » Reviewed & tested by the community

Thanks @quietone for the last fix!

I haven't touched the patch since it was last RTBC so I should be allowed to do it now.

Markus

alexpott’s picture

+++ b/core/modules/language/migrations/d6_language_content_taxonomy_vocabulary_settings.yml
@@ -0,0 +1,53 @@
+  'third_party_settings/content_translation/enabled':

+++ b/core/modules/language/src/Plugin/migrate/source/d6/LanguageContentSettingsTaxonomyVocabulary.php
@@ -0,0 +1,65 @@
+ * @MigrateSource(
+ *   id = "d6_language_content_settings_taxonomy_vocabulary",
+ *   source_module = "taxonomy"
+ * )

One thing I can't see (and it might be just because I don't know) is how we are sure that content_translation is enabled on the target site?

masipila’s picture

Status: Reviewed & tested by the community » Needs review

Changing the status back to NR to address @alexpott's question in #52. Ping @quietone / @maxocub.

quietone’s picture

That pattern in the migration yml already exists in core in language/d6_language_content_setttings,yml and language/d7_language_content_settings.yml. That doesn't make it the 'correct' solution but it is out there.

This is further proof we need to discuss how to handle migrations that require multiple destination modules. Perhaps a new issue?

Edit: Made a new issue #3004472: Handle migrations that require multiple destination modules

masipila’s picture

Status: Needs review » Needs work
Issue tags: +Needs documentation

Thanks @quietone for your insight!

I propose that we will not block this issue because of this. Instead, I will emphasize in the docs that when performing multilingual upgrades, the sitebuilder is expected to enable Config translation, Content translation, UI translation and Migrate Drupal multilingual. It is IMO quite safe assumption that more or less any multilingual site will anyway need these modules.

I'll add this to these two pages:
https://www.drupal.org/docs/8/upgrade/upgrading-multilingual-drupal-6-to...

https://www.drupal.org/docs/8/upgrade/upgrading-multilingual-drupal-7-to...

I'll change this to NW for the additional documentation and then back to RTBC once the docs have been updated.

Markus

masipila’s picture

Assigned: Unassigned » masipila
masipila’s picture

Status: Needs work » Reviewed & tested by the community
Issue tags: -Needs documentation

The handbook documentation has now been updated so that we are emphasizing that Language, Interface Translation, Content Translation, Configuration Translation and Migrate Drupal Multilingual need to be enabled before running a multilingual upgrade.

This and @quietone's comment in #54 addresses @alexpott's question in #52.

Back to RTBC.

Cheers,
Markus

masipila’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs reroll

Patch #50 does not apply anymore, needs reroll

gaydabura’s picture

Status: Needs review » Needs work

The last submitted patch, 59: 2975509-59.patch, failed testing. View results

quietone’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
FileSize
16.8 KB
776 bytes

Using git bisect (first time) this error starts when #2994398: Not properly clearing EntityFieldManager's fieldMap leads to fatals, often after migration or bundle creation was committed. Skimming that patch I noticed that the installing the entity schema for node was added to the existing Migrate Language Content Settings tests. So, I added that to this test and it passed locally. Let's see if testbot agrees.

Arg!: My fingers have learned to use the wrong extension for interdiff.

Status: Needs review » Needs work

The last submitted patch, 61: interdiff-59-61.patch, failed testing. View results

quietone’s picture

I guess I ended up testing in the wrong branch.

quietone’s picture

Start over and try again.
The problem is it is trying to add a field to the taxonomy_term_field_data table, so let's just make sure it exists for the test!

Status: Needs review » Needs work

The last submitted patch, 64: 2975509-64.patch, failed testing. View results

quietone’s picture

Status: Needs work » Needs review

There was a testbot hiccough so I reran the test and it is green now

masipila’s picture

Thanks @gaydabura for the reroll in #59!

I reviewed the patches from #59 onwards. As @quietone explained in #64, we need to have taxonomy_term schema in the test that failed in #59.

I queued the latest patch for PostgreSQL and SQLite. Once those are green, this can go back to RTBC as it was before.

Markus

quietone’s picture

Status: Needs review » Reviewed & tested by the community

Tests are passing on PostgreSQL and SQLite so setting to RTBC as recommended by masipila in #67.

masipila’s picture

Assigned: masipila » Unassigned

Un-assigning myself

catch’s picture

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

Committed and pushed d654e1038b to 8.7.x and 9e80041316 to 8.6.x. Thanks!

  • catch committed d654e10 on 8.7.x
    Issue #2975509 by quietone, masipila, gaydabura, jhodgdon, maxocub:...

  • catch committed 9e80041 on 8.6.x
    Issue #2975509 by quietone, masipila, gaydabura, jhodgdon, maxocub:...

Status: Fixed » Closed (fixed)

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