Je migre du contenu multilingue vers Drupal 8 à partir d'un groupe de fichiers CSV, et j'en suis à environ 95% du chemin. J'ai un champ d'image attaché à un type de contenu d'article qui partage l'image parmi toutes les traductions, mais l'attribut alt est traduisible. Le problème restant de 5% réside dans la configuration de la migration pour utiliser un seul fichier d'image commun fid
pour toutes les langues, mais un texte alt
différent pour autres langues.
articles.csv
id,title_en,title_fr,body_en,body_fr,image,alt_en,alt_fr
1,Title 1,Titre 1,<p>English Body paragraph text 1</p>,<p>French Body paragraph text 1</p>,image1.jpg,Alt text English 1,Alt text French 1
2,Title 2,Titre 2,<p>English Body paragraph text 2</p>,<p>French Body paragraph text 1</p>,image2.jpg,Alt text English 2,Alt text French 2
3,Title 3,Titre 3,<p>English Body paragraph text 3</p>,<p>French Body paragraph text 1</p>,image3.jpg,Alt text English 3,Alt text French 3
images.csv
image
image1.jpg
image2.jpg
image3.jpg
Ma migration de contenu en anglais par défaut fonctionne très bien avec les images importées et attachées aux nœuds.
migrate_plus.migration.articles_images.yml
id: articles_images
status: true
dependencies:
module:
- file
migration_tags:
- CSV
migration_group: default
label: Article Images
source:
constants:
source_base_path: ../import/images
uri_file: 'public://images/imported'
plugin: csv
track_changes: true
path: ../import/images.csv
header_row_count: 1
keys:
- image
column_names:
-
image: Image
process:
source_full_path:
-
plugin: concat
delimiter: /
source:
- constants/source_base_path
- image
-
plugin: urlencode
uri_file:
-
plugin: concat
delimiter: /
source:
- constants/uri_file
- image
-
plugin: urlencode
filename:
-
plugin: skip_on_empty
method: row
source: image
-
plugin: get
source: image
uri:
plugin: file_copy
source:
- '@source_full_path'
- '@uri_file'
destination:
plugin: 'entity:file'
migration_dependencies:
required: { }
optional: { }
migrate_plus.migration.articles_en.yml
id: articles_en
status: true
migration_tags:
- CSV
migration_group: default
label: Articles
source:
plugin: csv
path: ../import/articles.csv
header_row_count: 1
keys:
- id
column_names:
-
id: Id
-
title_en: 'Title EN'
-
title_fr: 'Titre FR'
-
body_en: 'Text EN'
-
body_fr: 'Texte FR'
-
image: Image
-
alt_en: 'Alt Text EN'
-
alt_fr: 'Alt Text FR'
process:
type:
plugin: default_value
default_value: article
title: title_en
body/value: body_en
body/format:
plugin: default_value
default_value: basic_html
field_image/target_id:
-
plugin: skip_on_empty
method: process
source: image
-
plugin: migration
migration: articles_images
source: image
no_stub: true
field_image/alt:
-
plugin: skip_on_empty
method: process
source: image
-
plugin: skip_on_empty
method: process
source: alt_en
-
plugin: get
source: alt_en
destination:
plugin: 'entity:node'
migration_dependencies:
optional:
- articles_images
Cependant, chaque configuration que j'essaie de faire utiliser les traductions en langue étrangère utilise le même FID mais un texte différent alt échoue.
migrate_plus.migration.articles_fr.yml
id: articles_fr
status: true
migration_tags:
- CSV
migration_group: default
label: Articles French
source:
plugin: csv
path: ../import/articles.csv
header_row_count: 1
keys:
- id
column_names:
-
id: Id
-
title_en: 'Title EN'
-
title_fr: 'Titre FR'
-
body_en: 'Text EN'
-
body_fr: 'Texte FR'
-
image: Image
-
alt_en: 'Alt Text EN'
-
alt_fr: 'Alt Text FR'
process:
type:
plugin: default_value
default_value: article
nid:
plugin: migration
source: id
migration: articles_en
langcode:
plugin: default_value
default_value: fr
title:
-
plugin: skip_on_empty
method: row
source: title_fr
-
plugin: get
source: title_fr
language: fr
body/value:
-
plugin: skip_on_empty
method: row
source: body_fr
-
plugin: get
source: body_fr
language: fr
body/format:
plugin: default_value
default_value: basic_html
field_image/target_id:
plugin: migration
migration: articles_images
source: image
language: fr
field_image/alt:
-
plugin: skip_on_empty
method: process
source: image
-
plugin: skip_on_empty
method: process
source: alt_fr
-
plugin: get
source: alt_fr
language: fr
destination:
plugin: 'entity:node'
translations: true
migration_dependencies:
required:
- articles_en
optional: { }
En exécutant la migration des données en français, je reçois un message d'erreur.
InvalidArgumentException: Invalid translation language (und) specified.
in Drupal\Core\Entity\ContentEntityBase->getTranslation() (line 745 of
web/core/lib/Drupal/Core/Entity/ContentEntityBase.php).
Invalid translation language (und) specified.
(web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php:770)
Traduction de contenu français avec partage d'images de base
J'ai également essayé de traiter uniquement l'image field_image pour la copier dans les traductions étrangères, mais cela donne la même erreur:
field_image:
plugin: migration
migration: articles_images
source: image
no_stub: true
Ajout ou suppression de language: fr
le paramètre de l'un des processeurs de terrain ne fait aucune différence - l'erreur est la même dans les deux cas.
Inspection d'un field_image
attaché à un nœud qui a été créé et traduit manuellement via Drupal UI at node/X/devel
montre la structure suivante:
[field_image] => array(
[x-default] => array(
[0] => array(
[target_id] => 123
[alt] => English Alt text
[title] =>
[width] => 480
[height] => 360
)
)
[fr] => array(
[0] => array(
[target_id] => 123
[alt] => French alt text.
[title] =>
[width] => 480
[height] => 360
)
)
)
Ces articles de blog et exemples de référentiels ont été utiles à l'approche de l'endroit où je suis actuellement bloqué:
Je pense que j'ai compris cela. Vous devez définir la propriété 'content_translation_source' sur le nœud traduit, afin que Drupal sache de quelle langue il provient.
Par exemple:
migrate_plus.migration.articles_fr.yml
process:
#...
content_translation_source:
plugin: default_value
default_value: en
#...
(Assurez-vous de substituer la valeur en
à la langue que vous avez importée pour la première fois - l'exemple de l'OP utilise l'anglais, mais cela peut être n'importe quoi).
On m'a demandé comment j'ai compris cela:
Je suis le gars qui a obtenu des migrations multilingues dans le noyau D8, donc je connais un peu la question :)
Dans ce cas, j'ai utilisé xdebug et mis un point d'arrêt où l'exception a été levée (ContentEntityBase.php ligne 745). Il semblait étrange d'utiliser "und" comme langcode, plutôt que "en" - j'ai donc recherché la pile d'appels pour voir d'où cela venait. Il s'agit de content_translation_entity_presave (), qui s'exécute:
$ source_langcode =! $ entity-> original-> hasTranslation ($ langcode)? $ manager-> getTranslationMetadata ($ entity) -> getSource (): NULL;
Dans ce cas, $manager->getTranslationMetadata($entity)->getSource()
est fondamentalement équivalent à $entity->content_translation_source->value
.
Je me demandais, pourquoi cela donnerait-il "und"? J'ai vérifié ce qui se passe lorsque je traduis une entité dans le navigateur, et dans ce cas, cela me donne "en". Quelque chose doit définir la langue source! En effet, ContentTranslationHandler :: entityFormEntityBuild () appelle setSource () lorsque nous traduisons dans le navigateur.
Donc, j'ai pensé que je reproduirais simplement ce comportement dans la migration, en définissant content_translation_source dans le processus. Cela explique également pourquoi la migration D6 -> D8 des traductions fonctionne, car d6_node_translation.yml a content_translation_source dans le processus.
Merci @vasi, ceux qui sont toujours confrontés au problème peuvent mettre à jour le script de traduction comme:
process:
content_translation_source: source_langcode
où code_source correspond aux nœuds par défaut code_langue