web-dev-qa-db-ja.com

CSVから多言語画像のALTフィールドを移行する方法は?

私は多言語コンテンツをDrupal 8からCSVファイルのグループから8に移行しています。その方法の約95%です。共有する記事コンテンツタイプに画像フィールドがアタッチされていますすべての翻訳間の画像ですが、alt属性は翻訳可能です。残りの5%の問題は、すべての言語に対して単一の共通画像ファイルfidを使用するように移行を構成することですが、alt他の言語。

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

画像と代替テキストを含む英語コンテンツの移行

デフォルトの英語コンテンツの移行は、イメージをインポートしてノードにアタッチするとうまく機能します。

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

異なる代替テキストを使用したフランス語コンテンツ翻訳

ただし、外国語翻訳で同じFIDを使用しようとするすべての構成で、differentaltテキストが失敗します。

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: {  }

フランス語のデータ移行を実行すると、エラーメッセージが表示されます。

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)

基本的な画像共有を伴うフランス語のコンテンツ翻訳

また、field_imageだけを処理して外部の翻訳にコピーしようとしましたが、同じエラーが発生します。

field_image:
  plugin: migration
  migration: articles_images
  source: image
  no_stub: true

フィールドプロセッサのいずれかからlanguage: frパラメータを追加または削除しても、違いはないようです。どちらの方法でもエラーは同じです。

意図した結果のデータ構造

Drupal UI at field_imageを介して手動で作成および変換されたノードに接続されたnode/X/develを検査すると、次の構造が表示されます。

[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
    )
  )
)

追加のリソース

これらのブログの投稿とリポジトリの例は、私が現在行き詰まっているところまで導くのに役立ちました。

6
JamesWilson

私はこれを理解したと思います。 Drupalがそれがどの言語から来ているかを知っているように、翻訳されたノードで 'content_translation_source'プロパティを定義する必要があります。

例えば:

migrate_plus.migration.articles_fr.yml

_process:
  #...
  content_translation_source:
    plugin: default_value
    default_value: en
  #...
_

(最初にコンテンツをインポートした言語は必ず値enに置き換えてください。OPの例では英語を使用していますが、これは何でもかまいません)。


私はこれをどうやって理解したのか尋ねられました:

私はD8コアに多言語で移行した人なので、問題については少し知っています:)

この場合、xdebugを使用して、例外がスローされた場所にブレークポイントを設定しました(ContentEntityBase.php行745)。言語コードとして「en」ではなく「und」を使用しているのは奇妙に見えたので、コールスタックを調べて、それがどこから来ているのかを調べました。これは、以下を実行するcontent_translation_entity_presave()からのものであることがわかります。

$ source_langcode =!$ entity-> original-> hasTranslation($ langcode)? $ manager-> getTranslationMetadata($ entity)-> getSource():NULL;

この場合、$manager->getTranslationMetadata($entity)->getSource()は基本的に_$entity->content_translation_source->value_と同等です。

なぜそれが「うん」をもたらすのだろうか?ブラウザでエンティティを翻訳するとどうなるかを確認したところ、「en」が表示されました。ソース言語を設定している必要があります!実際、ブラウザ内で翻訳しているとき、ContentTranslationHandler :: entityFormEntityBuild()はsetSource()を呼び出します。

そのため、プロセスでcontent_translation_sourceを設定することで、移行でその動作を複製するだけだと考えました。これは、d6_node_translation.ymlのプロセスにcontent_translation_sourceがあるため、翻訳のD6-> D8移行が機能する理由も説明します。

7
vasi

@vasiに感謝します。問題が解決しない場合は、次のように翻訳スクリプトを更新できます。

process:
  content_translation_source: source_langcode

ここで、source_codeはデフォルトのノードのlanguage_codeです。

0
Subhash