entity_translation.node.inc 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. <?php
  2. /**
  3. * @file
  4. * The node specific translation functions and hook implementations.
  5. */
  6. /**
  7. * Identifies a content type which has translation support enabled.
  8. */
  9. define('ENTITY_TRANSLATION_ENABLED', 4);
  10. /**
  11. * Hides translation metadata.
  12. */
  13. define('ENTITY_TRANSLATION_METADATA_HIDE', 0);
  14. /**
  15. * Adds translation metadata to the original authoring information.
  16. */
  17. define('ENTITY_TRANSLATION_METADATA_SHOW', 1);
  18. /**
  19. * Replaces the original authoring information with translation metadata.
  20. */
  21. define('ENTITY_TRANSLATION_METADATA_REPLACE', 2);
  22. /**
  23. * Checks if the given entity has node translation enabled.
  24. */
  25. function entity_translation_node($entity_type, $node) {
  26. return $entity_type == 'node' && function_exists('translation_supported_type') && translation_supported_type($node->type);
  27. }
  28. /**
  29. * Node-specific menu alterations.
  30. */
  31. function entity_translation_node_menu_alter(&$items, $backup) {
  32. if (isset($backup['node'])) {
  33. $item = $backup['node'];
  34. // Preserve the menu router item defined by other modules.
  35. $callback['page callback'] = $item['page callback'];
  36. $callback['file'] = $item['file'];
  37. $callback['module'] = $item['module'];
  38. $access_arguments = array_merge(array(1, $item['access callback']), $item['access arguments']);
  39. $page_arguments = array_merge(array('node', 1, $callback), $item['page arguments']);
  40. }
  41. else {
  42. $access_arguments = array(1);
  43. $page_arguments = array('node', 1);
  44. }
  45. $items['node/%node/translate']['page callback'] = 'entity_translation_overview';
  46. $items['node/%node/translate']['page arguments'] = $page_arguments;
  47. $items['node/%node/translate']['access arguments'] = $access_arguments;
  48. $items['node/%node/translate']['access callback'] = 'entity_translation_node_tab_access';
  49. $items['node/%node/translate']['file'] = 'entity_translation.admin.inc';
  50. $items['node/%node/translate']['module'] = 'entity_translation';
  51. }
  52. /**
  53. * Node specific access callback.
  54. */
  55. function entity_translation_node_tab_access() {
  56. $args = func_get_args();
  57. $node = array_shift($args);
  58. if (entity_translation_node('node', $node)) {
  59. $function = array_shift($args);
  60. return call_user_func_array($function, $args);
  61. }
  62. else {
  63. return entity_translation_tab_access('node', $node);
  64. }
  65. }
  66. /**
  67. * Returns whether the given node type has support for translations.
  68. *
  69. * @return
  70. * Boolean value.
  71. */
  72. function entity_translation_node_supported_type($type) {
  73. return variable_get('language_content_type_' . $type, 0) == ENTITY_TRANSLATION_ENABLED;
  74. }
  75. /**
  76. * Implements hook_node_view().
  77. *
  78. * Provides content language switcher links to navigate among node translations.
  79. */
  80. function entity_translation_node_view($node, $build_mode, $langcode) {
  81. if (!empty($node->translations) && drupal_multilingual() && entity_translation_node_supported_type($node->type) && !variable_get("entity_translation_hide_translation_links_{$node->type}", FALSE)) {
  82. $path = 'node/' . $node->nid;
  83. $links = EntityTranslationDefaultHandler::languageSwitchLinks($path);
  84. if (is_object($links) && !empty($links->links)) {
  85. $handler = entity_translation_get_handler('node', $node);
  86. $translations = $handler->getTranslations()->data;
  87. // Remove the link for the current language.
  88. unset($links->links[$langcode]);
  89. // Remove links to unavailable translations.
  90. foreach ($links->links as $langcode => $link) {
  91. if (!isset($translations[$langcode]) || !entity_translation_access('node', $translations[$langcode])) {
  92. unset($links->links[$langcode]);
  93. }
  94. }
  95. $node->content['links']['translation'] = array(
  96. '#theme' => 'links',
  97. '#links' => $links->links,
  98. '#attributes' => array('class' => 'links inline'),
  99. );
  100. }
  101. }
  102. }
  103. /**
  104. * Implements hook_form_FORM_ID_alter().
  105. *
  106. * Provides settings into the node content type form to choose for entity
  107. * translation metadata and comment filtering.
  108. */
  109. function entity_translation_form_node_type_form_alter(&$form, &$form_state) {
  110. if (entity_translation_enabled('node')) {
  111. $type = $form['#node_type']->type;
  112. $t_args = array('!url' => url('admin/config/regional/entity_translation'));
  113. $form['workflow']['language_content_type']['#options'][ENTITY_TRANSLATION_ENABLED] = t('Enabled, with field translation');
  114. $form['workflow']['language_content_type']['#description'] .= ' <p>' . t('If field translation is selected you can have per-field translation for each available language. You can find more options in the <a href="!url">entity translation settings</a>.', $t_args) . '</p>';
  115. // Hide settings when entity translation is disabled for this content type.
  116. $states = array(
  117. 'visible' => array(
  118. ':input[name="language_content_type"]' => array('value' => ENTITY_TRANSLATION_ENABLED),
  119. ),
  120. );
  121. $form['workflow']['entity_translation_hide_translation_links'] = array(
  122. '#type' => 'checkbox',
  123. '#default_value' => variable_get("entity_translation_hide_translation_links_$type", FALSE),
  124. '#title' => t('Hide content translation links'),
  125. '#description' => t('Hide the links to translations in content body and teasers. If you choose this option, switching language will only be available from the language switcher block.'),
  126. '#states' => $states,
  127. );
  128. $form['display']['entity_translation_node_metadata'] = array(
  129. '#type' => 'radios',
  130. '#title' => t('Translation post information'),
  131. '#description' => t('Whether the translation authoring information should be hidden, shown, or replace the node\'s authoring information.'),
  132. '#default_value' => variable_get("entity_translation_node_metadata_$type", ENTITY_TRANSLATION_METADATA_HIDE),
  133. '#options' => array(t('Hidden'), t('Shown'), t('Replacing post information')),
  134. '#states' => $states,
  135. );
  136. if (isset($form['comment'])) {
  137. $form['comment']['entity_translation_comment_filter'] = array(
  138. '#type' => 'checkbox',
  139. '#title' => t('Filter comments per language'),
  140. '#default_value' => variable_get("entity_translation_comment_filter_$type", FALSE),
  141. '#description' => t('Show only comments whose language matches content language.'),
  142. '#states' => $states,
  143. );
  144. }
  145. }
  146. }
  147. /**
  148. * Implements hook_preprocess_node().
  149. *
  150. * Alters node template variables to show/replace entity translation metadata.
  151. */
  152. function entity_translation_preprocess_node(&$variables) {
  153. $node = $variables['node'];
  154. $submitted = variable_get("node_submitted_{$node->type}", TRUE);
  155. $mode = variable_get("entity_translation_node_metadata_{$node->type}", ENTITY_TRANSLATION_METADATA_HIDE);
  156. if ($submitted && $mode != ENTITY_TRANSLATION_METADATA_HIDE) {
  157. global $language_content, $user;
  158. $handler = entity_translation_get_handler('node', $node);
  159. $translations = $handler->getTranslations();
  160. $langcode = $language_content->language;
  161. if (isset($translations->data[$langcode]) && $langcode != $translations->original) {
  162. $translation = $translations->data[$langcode];
  163. $date = format_date($translation['created']);
  164. $name = FALSE;
  165. if ($node->uid != $translation['uid']) {
  166. $account = $user->uid != $translation['uid'] ? user_load($translation['uid']) : $user;
  167. $name = theme('username', array('account' => $account));
  168. }
  169. switch ($mode) {
  170. case ENTITY_TRANSLATION_METADATA_SHOW:
  171. $variables['date'] .= ' (' . t('translated on <em>!date</em>', array('!date' => $date)) . ')';
  172. if ($name) {
  173. $variables['name'] .= ' (' . t('translated by !name', array('!name' => $name)) . ')';
  174. }
  175. break;
  176. case ENTITY_TRANSLATION_METADATA_REPLACE:
  177. $variables['date'] = $date;
  178. if ($name) {
  179. $variables['name'] = $name;
  180. }
  181. break;
  182. }
  183. }
  184. }
  185. }
  186. /**
  187. * Returns whether the given comment type has support for translations.
  188. *
  189. * @return
  190. * Boolean value.
  191. */
  192. function entity_translation_comment_supported_type($comment_type) {
  193. $type = str_replace('comment_node_', '', $comment_type);
  194. return entity_translation_node_supported_type($type);
  195. }
  196. /**
  197. * Implements hook_query_TAG_alter().
  198. *
  199. * Filters out node comments by content language.
  200. *
  201. * @todo Find a way to track node comment statistics per language.
  202. */
  203. function entity_translation_query_comment_filter_alter(QueryAlterableInterface $query) {
  204. $node = $query->getMetaData('node');
  205. if (!empty($node->type) && variable_get("entity_translation_comment_filter_{$node->type}", FALSE)) {
  206. // Determine alias for "comment" table.
  207. $comment_alias = FALSE;
  208. foreach ($query->getTables() as $table) {
  209. if (is_string($table['table']) && $table['table'] == 'comment') {
  210. $comment_alias = $table['alias'];
  211. break;
  212. }
  213. }
  214. // Only show comments without language or matching the current content language.
  215. if ($comment_alias) {
  216. $query->condition(db_or()
  217. ->condition($comment_alias . '.language', $GLOBALS['language_content']->language)
  218. ->condition($comment_alias . '.language', LANGUAGE_NONE)
  219. );
  220. }
  221. }
  222. }
  223. /**
  224. * Implements hook_node_update_index().
  225. *
  226. * Add translated node content to search index.
  227. */
  228. function entity_translation_node_update_index($node) {
  229. $text = '';
  230. $langcodes = array_keys(language_list());
  231. $translations = entity_translation_get_handler('node', $node)->getTranslations();
  232. foreach ($langcodes as $langcode) {
  233. // Skip the default language (already indexed by search.module).
  234. if ($GLOBALS[LANGUAGE_TYPE_CONTENT]->language != $langcode && isset($translations->data[$langcode])) {
  235. // Render the node in each language.
  236. node_build_content($node, 'search_index', $langcode);
  237. $rendered = drupal_render($node->content);
  238. $text .= '<h1>' . check_plain($node->title) . '</h1>' . $rendered;
  239. }
  240. }
  241. return $text;
  242. }