function _noderelationships_nodeapi_prepare_translation in Node Relationships 6
Implementation of hook_nodeapi('prepare translation').
Here we can assume the following:
- Translation module is enabled.
- Translation for this content type is enabled.
- The current user is allowed to translate.
- The "Translate and reference" feature is enabled for this type.
What do we have here?
- CCK copies all fields from source translation to new node.
- Nodereference module replaces the references for the corresponding translations, but also removes the values for those references that do not have a translation. Also, deltas for multiple value fields are destroyed, meaning nodereference module shifts deltas when removing references that do not have translations, and this breaks fields located in multigroups causing them to loose sync with other fields.
How do we want it to be?
- We want to translate references as nodereference module does, but... for multiple value fields, we still want to keep the form elements for those that do not have translation because we'll provide a method to "Translate and reference" them, hence we need a form element to store the translated reference to.
- Also, we do not want to break nodereference fields in multigroups.
See also
_noderelationships_parent_node_form_alter()
1 call to _noderelationships_nodeapi_prepare_translation()
- noderelationships_nodeapi in ./
noderelationships.module - Implementation of hook_nodeapi().
File
- ./
noderelationships.translation.inc, line 43 - Translation support for Node Relationships module.
Code
function _noderelationships_nodeapi_prepare_translation(&$node, $noderef_settings) {
// Let's concentrate only on fields where "Translate and reference" is enabled.
foreach (array_keys($noderef_settings['translate_and_reference']) as $field_name) {
// Skip this field if it does not exist in translation source.
if (!isset($node->translation_source->{$field_name}) || !is_array($node->translation_source->{$field_name})) {
continue;
}
// If the i18n module is NOT enabled, then the Allowed Values related
// queries in nodereference module are NOT filtered by language, hence
// all references in source translation are still valid in new node.
// @todo: In fact, this could really be fixed in nodereference module.
if (!module_exists('i18n')) {
$node->{$field_name} = $node->translation_source->{$field_name};
continue;
}
// When the i18n module is enabled, queries against the node table are
// filtered to match the "Content selection mode" option enabled in the
// site. Here, there are several options that allow language neutral
// references, or options that allow only current language, default
// language or both. However, when "Content selection mode" is disabled
// all references in source translation are still valid in new node.
// @todo: In fact, this could really be fixed in nodereference module.
if (i18n_selection_mode() == 'off') {
$node->{$field_name} = $node->translation_source->{$field_name};
continue;
}
// When the i18n module is enabled, and "Content selection mode" is not
// disabled, then the i18n module applies a complex logic to alters node
// related queries to enforce language selection options.
// The easiest way to see if references in source translation are still
// valid for new node is perform a query using n.nid IN (...) with the
// help of the nodereference code used to check for valid allowed values.
// So, let's extract references in the translation source that are still
// valid for this translation.
$ids = array();
foreach ($node->translation_source->{$field_name} as $delta => $item) {
if (is_array($item) && !empty($item['nid']) && is_numeric($item['nid'])) {
$ids[] = $item['nid'];
}
}
$field = content_fields($field_name, $node->type);
$valid_references = _nodereference_potential_references($field, '', NULL, $ids);
// Ok, now we can try to rebuild the items of this nodereference field
// while still keeping original deltas.
$node->{$field_name} = array();
foreach ($node->translation_source->{$field_name} as $delta => $reference) {
// Keep delta even when the reference does not exist.
if (empty($reference['nid']) || !is_numeric($reference['nid'])) {
$node->{$field_name}[$delta] = array(
'nid' => NULL,
);
continue;
}
// If the reference is valid for the translation, just get it as-is.
if (isset($valid_references[$reference['nid']])) {
$node->{$field_name}[$delta] = $reference;
continue;
}
// Here we have a reference that is not valid for the translation due to
// content selection rules enforced by i18n module. Let's try to find
// translations for these references. To do so, we first need to read
// the original referenced node.
$reference_node = node_load($reference['nid']);
// If translation is not supported by reference in source translation,
// we can only warn the user about it. It makes no sense to offer them
// a method to translate something that cannot be translated.
if (!translation_supported_type($reference_node->type)) {
$node->{$field_name}[$delta] = array(
'translate_and_reference' => array(
'translation_supported' => FALSE,
'translation_source' => $reference_node,
),
'nid' => NULL,
);
continue;
}
// Ok, let's see if we already have a translation for this reference
// and use it if it exists. Note that we are creating a translation
// here, so that means the node being translated has its language
// attribute populated, and it is a valid language code.
$translations = translation_node_get_translations($reference_node->tnid);
if (!empty($translations) && isset($translations[$node->language])) {
$node->{$field_name}[$delta] = array(
'nid' => $translations[$node->language]->nid,
);
continue;
}
// Finally, we have a translatable reference that has not already been
// translated. This is where our "Translate and reference" option can
// add real value to the translation workflow. Let's provide a method
// to easily translate this reference from the new node.
$node->{$field_name}[$delta] = array(
'translate_and_reference' => array(
'translation_supported' => TRUE,
'translation_source' => $reference_node,
),
'nid' => NULL,
);
}
}
}