Index: i18nsync.module =================================================================== --- i18nsync.module (revision 3242) +++ i18nsync.module (working copy) @@ -150,6 +150,7 @@ */ function i18nsync_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) { global $i18nsync; // This variable will be true when a sync operation is in progress. + static $i18nsync_old_node = NULL; // Only for nodes that have language and belong to a translation set. if (translation_supported_type($node->type) && !empty($node->language) && !$i18nsync) { @@ -198,28 +199,74 @@ } // Intentional no break. case 'update': - // Let's go with field synchronization. - if (!empty($node->tnid) && ($fields = i18nsync_node_fields($node->type)) && ($translations = _i18nsync_node_translations($node, TRUE))) { - $i18nsync = TRUE; - $count = 0; - // If we have fields we need to reload them so we have the full data (fid, etc...) - if (!empty($node->files) && in_array('files', $fields)) { - $node->files = upload_load($node); - } - // Disable language selection temporarily, enable it again later - i18n_selection_mode('off'); - foreach ($translations as $trnode) { - if ($node->nid != $trnode->nid) { - i18nsync_node_translation($node, $trnode, $fields, $op); - $count++; + // Process field synchronization, but check first if it's necessary. + // We have the previous state of the node object stored in $i18nsync_old_node. + if ($i18nsync_old_node && !empty($node->tnid) && ($fields = i18nsync_node_fields($node->type)) && ($translations = _i18nsync_node_translations($node, TRUE))) { + $i18nsync = FALSE; // no synchronization yet + // load a fresh node object as it might contain a lot of form validation junk, e. g. "_error_element", + // making a field compare impossible. + $node = node_load($node->nid, $node->vid); + foreach ($fields as $field) { + switch ($field) { + case 'files': + // Check whether to sync existing attached files. + if (count((array)$node->files) == count((array)$old_node->files)) { + foreach ((array)$node->files as $fid => $file) { + if (!isset($i18nsync_old_node->files[$fid]) || !empty($file->remove)) { + $i18nsync = TRUE; + break; + } + } + } + else { + $i18nsync = TRUE; + } + break; + + default: + // For fields that don't need special handling. + if (isset($node->$field)) { + if ($node->$field != $i18nsync_old_node->$field) { + $i18nsync = TRUE; + } + } } + } + + if ($i18nsync) { + $count = 0; + // If we have fields we need to reload them so we have the full data (fid, etc...) + if (!empty($node->files) && in_array('files', $fields)) { + $node->files = upload_load($node); + } + // Disable language selection temporarily, enable it again later + i18n_selection_mode('off'); + foreach ($translations as $trnode) { + if ($node->nid != $trnode->nid) { + i18nsync_node_translation($node, $trnode, $fields, $op); + $count++; + } + } + i18n_selection_mode('reset'); + $i18nsync = FALSE; + $i18nsync_old_node = NULL; // remove old node object + drupal_set_message(format_plural($count, 'One node translation has been synchronized.', 'All @count node translations have been synchronized.')); } - i18n_selection_mode('reset'); - $i18nsync = FALSE; - drupal_set_message(format_plural($count, 'One node translation has been synchronized.', 'All @count node translations have been synchronized.')); } break; - } + + case 'presave': + // Takes a snapshot of the node's state. We need this information for comparing the node's fields + // before and after saving it. Then we can recognize a difference and decide whether a synchronziation is necessary. + if (!empty($node->tnid) && ($fields = i18nsync_node_fields($node->type)) && ($translations = translation_node_get_translations($node->tnid)) && count($translations) > 1) { + if (isset($node->nid) && isset($node->vid)) { // take a node object snapshot + $i18nsync_old_node = node_load($node->nid, $node->vid); + } + } + break; + } + + } }