Paragraphs entity translation support for Drupal 7

Public

paragraphs_translation.info

</> CopyGet raw version
text
  1. name = Paragraphs translation
  2. description = Custom translation handling for Paragraphs module
  3. core = 7.x
  4.  
  5. dependencies[] = entity_translation
  6. dependencies[] = paragraphs
  7.  
  8. files[] = includes/translation.handler.paragraphs_item.inc

paragraphs_translation.module

</> CopyGet raw version
php
  1. <?php
  2.  
  3. /**
  4.  * Implements hook_entity_info_alter().
  5.  */
  6. function paragraphs_translation_entity_info_alter(&$entity_info) {
  7. $entity_info['paragraphs_item']['translation']['entity_translation']['class'] = 'CustomEntityTranslationParagraphsItemHandler';
  8. }

includes/translation.handler.paragraphs_item.inc

</> CopyGet raw version
php
  1. <?php
  2.  
  3. /**
  4.  * @file
  5.  * Custom paragraphs item translation handler for the entity translation module.
  6.  *
  7.  * These customisations are done to fix unwanted translations from appearing in
  8.  * entity_translation database table. Without these changes all the paragraph
  9.  * items on the node would get translations in every language the node is
  10.  * translated to. This would make it impossible to have different paragraph items
  11.  * in different language versions of the node.
  12.  *
  13.  * TODO Wrong source language can appear on entity_translation table.
  14.  * This seems cause no issues but this is not certain.
  15.  * TODO In some circumstances paragraphs_item fields can have und language.
  16.  * These circumstances are unclear. Example table: field_data_field_gallery_text.
  17.  *
  18.  * @See entity_translation/includes/translation.handler.inc
  19.  * @See paragraphs/includes/translation.handler.paragraphs_item.inc.
  20.  */
  21.  
  22.  
  23. /**
  24.  * Paragraphs item translation handler.
  25.  *
  26.  * Overrides default behaviours for Paragraphs item properties.
  27.  */
  28. class CustomEntityTranslationParagraphsItemHandler extends EntityTranslationParagraphsItemHandler {
  29.  
  30. /**
  31.   * @see EntityTranslationHandlerInterface::saveTranslations()
  32.   */
  33. public function saveTranslations() {
  34. // Here we are filtering out paragraphs_items that are not present in the
  35. // current edit form. Without this all paragraph items would have unwanted
  36. // translations inserted in entity_translation table on every update.
  37.  
  38. // It seems that the problem only appears on updates. Let's handle that.
  39. if(!$this->entity->is_new) {
  40. // Update paragraphs_item only if host entity has items in current form
  41. // language...
  42. if(empty($this->hostEntity->field_paragraphs[$this->getFormLanguage()])) {
  43. return;
  44. }
  45. // ...and item is found from hostEntity's paragraph field values in current
  46. // form language.
  47. $paragraph_items_in_current_language = array_map(function($field_value) {
  48. if(!empty($field_value['value'])) {
  49. return $field_value['value'];
  50. }
  51. if(!empty($field_value['entity'])) {
  52. return $field_value['entity']->item_id;
  53. }
  54. drupal_set_message(t('Cannot handle paragraph field value in translation handler. Unknown value type.'), 'error');
  55. },
  56. $this->hostEntity->field_paragraphs[$this->getFormLanguage()]
  57. );
  58. if(!in_array($this->entityId, $paragraph_items_in_current_language)) {
  59. return;
  60. }
  61. }
  62. // If filtering is passed run default saveTranslations() function.
  63. parent::saveTranslations();
  64. }
  65.  
  66. /**
  67.   * Saves entity translation records to the storage.
  68.   */
  69. protected function doSaveTranslations($translations, $table, $revision = FALSE) {
  70. // Delete and insert, rather than update, in case a value was added.
  71. $query = db_delete($table)
  72. ->condition('entity_type', $this->entityType)
  73. ->condition('entity_id', $this->entityId)
  74. // Changed from EntityTranslationDefaultHandler.
  75. // ---------------------------------------------
  76. // Ensure that only translations in current form language are deleted.
  77. // We don't want to change anything outside the current form.
  78. ->condition('language', $this->hostEntityHandler->getFormLanguage());
  79. // If we are storing translations for the current revision or we are
  80. // deleting the entity we should remove all translation data.
  81. $langcode = $translations->original;
  82. $hook = isset($translations->hook) ? $translations->hook : array();
  83. if ($revision && $this->isRevisionable() && (empty($hook[$langcode]['hook']) || $hook[$langcode]['hook'] != 'delete')) {
  84. $query->condition('revision_id', $this->revisionId);
  85. }
  86. $query->execute();
  87.  
  88. if (count($translations->data)) {
  89. $columns = array('entity_type', 'entity_id', 'revision_id', 'language', 'source', 'uid', 'status', 'translate', 'created', 'changed');
  90. $query = db_insert($table)->fields($columns);
  91.  
  92. // These values should override the translation ones as they are not
  93. // supposed to change.
  94. $overrides = array(
  95. 'entity_type' => $this->entityType,
  96. 'entity_id' => $this->entityId,
  97. 'revision_id' => $this->isRevisionable() ? $this->revisionId : $this->entityId,
  98. );
  99.  
  100. // These instead are just defaults.
  101. $defaults = array(
  102. 'source' => '',
  103. 'uid' => $GLOBALS['user']->uid,
  104. 'translate' => 0,
  105. 'status' => 0,
  106. 'created' => REQUEST_TIME,
  107. 'changed' => REQUEST_TIME,
  108. );
  109.  
  110. // Changed from EntityTranslationDefaultHandler.
  111. // ---------------------------------------------
  112. // We only want to update translations in current form language.
  113. $current_translation_data = $translations->data[$this->getFormLanguage()];
  114. $translation = $overrides + $current_translation_data + $defaults;
  115. $query->values($translation);
  116.  
  117. $query->execute();
  118. }
  119. }
  120.  
  121. }