You are here

i18n_node_reference.module in i18n node reference synch 7

Provides i18n field synchronisation for a node_reference field.

File

i18n_node_reference.module
View source
<?php

/**
 * @file
 * Provides i18n field synchronisation for a node_reference field.
 */

/**
 * Implements hook_field_info_alter().
 */
function i18n_node_reference_field_info_alter(&$info) {
  $info['node_reference']['i18n_sync_callback'] = 'i18n_node_reference_field_prepare_translation';
}

/**
 * Prepare and synchronize translation for term reference fields.
 */
function i18n_node_reference_field_prepare_translation($entity_type, $entity, $field, $instance, $langcode, &$items, $source_entity, $source_langcode) {

  // Translate the items one by one.
  $nids = array();
  $new_items = array();
  foreach ($items as $index => $item) {
    $node = node_load($item['nid']);
    if ($node) {
      if ($translation = i18n_node_reference_node_get_translation($node, $langcode)) {
        $new_items[] = array(
          'nid' => $translation->nid,
        );
        $nids[] = $translation->nid;
      }
    }
  }

  // Also add the existing node references for this translation that are
  // untranslated in the source entity. These options should not be removed!
  // The reason for this is that a user editing the node edit form did not see
  // the reference options (the nodes do not exist in that language) and after
  // saving the form it is undesirable that these node references are lost in
  // the node's other translations that have those references set!
  $current_items = field_get_items($entity_type, $entity, $field['field_name']);
  if ($current_items) {
    foreach ($current_items as $current_item) {
      if (!in_array($current_item['nid'], $nids)) {

        // Check if this node is multi-language and available in this language.
        $node = node_load($current_item['nid']);
        if ($node) {
          $translation = i18n_node_reference_node_get_translation($node, $source_langcode);
          if (!$translation) {

            // The reference was not available in the source language.
            // Preserve it.
            $new_items[] = $current_item;
          }
        }
      }
    }
  }
  $items = $new_items;
}

/**
 * Find the specified node translation from the translation set.
 *
 * @param object $node
 *   Node object to find translation.
 * @param string $langcode
 *   Language code to find translation for.
 *
 * @return bool|mixed
 *   Node in the correct language, if it exists. FALSE otherwise.
 */
function i18n_node_reference_node_get_translation($node, $langcode) {
  if ($node->language == LANGUAGE_NONE || $node->language == $langcode || !translation_supported_type($node->type)) {

    // Node is not translatable thus the same for every language.
    return $node;
  }
  else {

    // Find translation.
    $translations = translation_node_get_translations($node->tnid);
    if ($translations && array_key_exists($langcode, $translations)) {

      // Translation exists.
      return node_load($translations[$langcode]->nid);
    }
    else {

      // Translation does not exist.
      return FALSE;
    }
  }
}

/**
 * Implements hook_field_attach_prepare_translation_alter().
 */
function i18n_node_reference_field_attach_prepare_translation_alter(&$entity, $context) {

  // Node reference doesn't filter out untranslated references nodes. This is
  // noticable if the 'autocomplete' widget is used. We would like to complete
  // remove untranslatable referenced nodes, because this module handles that
  // situation perfectly.
  $options = array(
    'language' => $context['langcode'],
  );

  // Call a custom field hook to do the work.
  _field_invoke('prepare_node_reference_translation', $context['entity_type'], $entity, $context['source_entity'], $context['source_langcode'], $options);
}

/**
 * Implements hook_field_prepare_node_reference_translation().
 */
function node_reference_field_prepare_node_reference_translation($entity_type, $entity, $field, $instance, $langcode, &$items, $source_entity, $source_langcode) {

  // This hook is called by
  // i18n_node_reference_field_attach_prepare_translation_alter for every node
  // reference field.
  // Filter out the nodes that could not be translated.
  $new_items = array();
  if (isset($items) && is_array($items)) {
    foreach ($items as $key => $item) {
      $translated_node = node_load($item['nid']);
      if (empty($translated_node->language) || !translation_supported_type($translated_node->type) || entity_language('node', $translated_node) == $entity->language) {
        $new_items[] = $item;
      }
    }
  }
  $items = $new_items;
}

Functions

Namesort descending Description
i18n_node_reference_field_attach_prepare_translation_alter Implements hook_field_attach_prepare_translation_alter().
i18n_node_reference_field_info_alter Implements hook_field_info_alter().
i18n_node_reference_field_prepare_translation Prepare and synchronize translation for term reference fields.
i18n_node_reference_node_get_translation Find the specified node translation from the translation set.
node_reference_field_prepare_node_reference_translation Implements hook_field_prepare_node_reference_translation().