diff --git a/entity_translation.api.php b/entity_translation.api.php index eb73866..cc6e8dd 100644 --- a/entity_translation.api.php +++ b/entity_translation.api.php @@ -35,7 +35,7 @@ * - access callback: The access callback for the translation pages. Defaults to * 'entity_translation_tab_access'. * - access arguments: The access arguments for the translation pages. Defaults - * to "array($entity_type)". + * to "array($entity_type, $entity_position)". * - view path: The menu router path to be used to view the entity. Defaults to * the base path. * - edit path: The menu router path to be used to edit the entity. Defaults to diff --git a/entity_translation.info b/entity_translation.info index 58c8771..8c8884a 100644 --- a/entity_translation.info +++ b/entity_translation.info @@ -3,12 +3,17 @@ description = Allows entities to be translated into different languages. package = Multilingual - Entity Translation core = 7.x configure = admin/config/regional/entity_translation + dependencies[] = locale + files[] = includes/translation.handler.inc files[] = includes/translation.handler.comment.inc files[] = includes/translation.handler.node.inc files[] = includes/translation.handler.taxonomy_term.inc +files[] = includes/translation.handler.user.inc + files[] = tests/entity_translation.test + files[] = views/entity_translation_handler_relationship.inc files[] = views/entity_translation_handler_field_translate_link.inc files[] = views/entity_translation_handler_field_label.inc diff --git a/entity_translation.module b/entity_translation.module index a8fd3cd..18c2b03 100644 --- a/entity_translation.module +++ b/entity_translation.module @@ -89,6 +89,7 @@ function entity_translation_entity_info() { $info['user'] = array( 'translation' => array( 'entity_translation' => array( + 'class' => 'EntityTranslationUserHandler', 'skip original values access' => TRUE, ), ), @@ -351,6 +352,10 @@ function entity_translation_menu_alter(&$items) { $entity_position = array_search($scheme['path wildcard'], $scheme['translate path parts']); + if ($item['access callback'] == 'entity_translation_tab_access') { + $item['access arguments'][] = $entity_position; + } + // Backup existing values for the translate overview page. if (isset($items[$translate_path])) { $backup[$entity_type] = $items[$translate_path]; @@ -642,8 +647,12 @@ function entity_translation_admin_paths() { /** * Access callback. */ -function entity_translation_tab_access($entity_type) { - return drupal_multilingual() && (user_access('translate any entity') || user_access("translate $entity_type entities")); +function entity_translation_tab_access($entity_type, $entity) { + if (drupal_multilingual() && (user_access('translate any entity') || user_access("translate $entity_type entities"))) { + $handler = entity_translation_get_handler($entity_type, $entity); + return $handler->getLanguage() != LANGUAGE_NONE; + } + return FALSE; } /** @@ -1222,8 +1231,16 @@ function _entity_translation_element_title_append(&$element, $suffix) { * Implements hook_form_alter(). */ function entity_translation_form_alter(&$form, &$form_state) { - if (($handler = entity_translation_entity_form_get_handler($form, $form_state)) && !$handler->isNewEntity()) { - $handler->entityForm($form, $form_state); + if ($handler = entity_translation_entity_form_get_handler($form, $form_state)) { + if (!$handler->isNewEntity()) { + $handler->entityForm($form, $form_state); + } + else { + $handler->entityFormLanguageWidget($form, $form_state); + } + // We need to process the posted form as early as possible to update the + // form language value. + array_unshift($form['#validate'], 'entity_translation_entity_form_validate'); } } @@ -1256,6 +1273,14 @@ function entity_translation_entity_form_validate($form, &$form_state) { } /** + * Submit handler for the entity language widget. + */ +function entity_translation_language_widget_submit($form, &$form_state) { + $handler = entity_translation_entity_form_get_handler($form, $form_state); + $handler->entityFormLanguageWidgetSubmit($form, $form_state); +} + +/** * Submit handler for the entity deletion. */ function entity_translation_entity_form_submit($form, &$form_state) { @@ -1452,7 +1477,7 @@ function entity_translation_language($entity_type, $entity) { $langcode = $handler->getLanguage(); $handler->setEntity($entity); $submitted_langcode = $handler->getLanguage(); - // If the entity language has changed we are editing tha original values. In + // If the entity language has changed we are editing the original values. In // this case we need to update the current form language with the submitted // one. if ($submitted_langcode != $langcode) { diff --git a/entity_translation.node.inc b/entity_translation.node.inc index f3fe438..c5d7b13 100644 --- a/entity_translation.node.inc +++ b/entity_translation.node.inc @@ -65,7 +65,7 @@ function entity_translation_node_tab_access() { $node = array_shift($args); if ($node->language != LANGUAGE_NONE) { if (entity_translation_node_supported_type($node->type)) { - return entity_translation_tab_access('node'); + return entity_translation_tab_access('node', $node); } elseif (entity_translation_node('node', $node)) { $function = array_shift($args); diff --git a/includes/translation.handler.comment.inc b/includes/translation.handler.comment.inc index 00342e0..01c48e6 100644 --- a/includes/translation.handler.comment.inc +++ b/includes/translation.handler.comment.inc @@ -16,13 +16,6 @@ class EntityTranslationCommentHandler extends EntityTranslationDefaultHandler { } /** - * @see EntityTranslationDefaultHandler::getLanguage() - */ - public function getLanguage() { - return $this->entity->language; - } - - /** * @see EntityTranslationDefaultHandler::entityForm() */ public function entityForm(&$form, &$form_state) { @@ -32,6 +25,17 @@ class EntityTranslationCommentHandler extends EntityTranslationDefaultHandler { } /** + * @see EntityTranslationDefaultHandler::entityFormLanguageWidget() + */ + public function entityFormLanguageWidget(&$form, &$form_state) { + parent::entityFormLanguageWidget($form, $form_state); + if ($this->isNewEntity()) { + $form['language']['#default_value'] = $GLOBALS[LANGUAGE_TYPE_CONTENT]->language; + $form['language']['#access'] = FALSE; + } + } + + /** * @see EntityTranslationDefaultHandler::entityFormTitle() */ protected function entityFormTitle() { diff --git a/includes/translation.handler.inc b/includes/translation.handler.inc index 778c33f..4ee0deb 100644 --- a/includes/translation.handler.inc +++ b/includes/translation.handler.inc @@ -231,6 +231,16 @@ interface EntityTranslationHandlerInterface { public function entityForm(&$form, &$form_state); /** + * Adds an language selection widget to the entity form. + */ + public function entityFormLanguageWidget(&$form, &$form_state); + + /** + * Performs submission tasks on the submitted entity language. + */ + public function entityFormLanguageWidgetSubmit($form, &$form_state); + + /** * Performs validation tasks on the submitted entity forms. */ public function entityFormValidate($form, &$form_state); @@ -585,7 +595,8 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa return $this->entity->{$language_key}; } } - return language_default()->language; + $translations = $this->getTranslations(); + return !empty($translations->original) ? $translations->original : LANGUAGE_NONE; } /** @@ -837,6 +848,11 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa $no_translations = count($translations->data) < 2; $languages = language_list(); + // Store the information about being editing the original values for later + // reuse: a language change might render impossibile to determine this + // otherwise. + $form_state['entity_translation']['is_translation'] = $is_translation; + // Adjust page title to specify the current language being edited, if we // have at least one translation. if ($form_langcode != LANGUAGE_NONE && (!$no_translations || $new_translation)) { @@ -871,35 +887,17 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa } } - // Disable languages for existing translations, so it is not possible to - // switch this node to some language which is already in the translation - // set. - $language_widget = isset($form['language']) && $form['language']['#type'] == 'select'; - if ($language_widget) { - foreach ($translations->data as $translation) { - if (!empty($translation['source'])) { - unset($form['language']['#options'][$translation['language']]); - } - } - if (count($translations->data) > 1) { - unset($form['language']['#options'][LANGUAGE_NONE]); - } - } - // If there is a language value associated to the form ensure it is correct. - elseif (isset($form['language'])) { - $form['language']['#value'] = $form_langcode; - } + // Add the entity language switcher. + $this->entityFormLanguageWidget($form, $form_state); if ($is_translation) { // If we are editing a translation set the correct value in the language // widget and not current one. // @todo Consider supporting the ability to change translation language. - if ($language_widget) { - $form['language']['#title'] = t('Original language'); - $form['language']['#options'][$langcode] = $languages[$langcode]->name; - $form['language']['#default_value'] = $langcode; - $form['language']['#disabled'] = TRUE; - } + $form['language']['#title'] = t('Original language'); + $form['language']['#options'][$langcode] = $languages[$langcode]->name; + $form['language']['#default_value'] = $langcode; + $form['language']['#disabled'] = TRUE; // Replace the delete button with the delete translation one. if (!$new_translation) { @@ -1003,10 +1001,6 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa $this->menuForm($form, $form_state); } - // We need to process the posted form as early as possible to update the - // form language value. - array_unshift($form['#validate'], 'entity_translation_entity_form_validate'); - // Process entity form submission. $form['#submit'][] = 'entity_translation_entity_form_submit'; @@ -1018,6 +1012,44 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa } /** + * @see EntityTranslationHandlerInterface::entityFormLanguageWidget() + */ + public function entityFormLanguageWidget(&$form, &$form_state) { + $translations = $this->getTranslations(); + $form_langcode = $this->getFormLanguage(); + $languages = entity_translation_languages($this->entityType, $this->entity); + $options = count($translations->data) > 1 ? array() : array(LANGUAGE_NONE => t('Language neutral')); + + foreach ($languages as $langcode => $language) { + // Disable languages for existing translations, so it is not possible to + // switch this entity to some language which is already in the translation + // set. + if (!isset($translations->data[$langcode]) || empty($translations->data[$langcode]['source'])) { + $options[$langcode] = t($language->name); + } + } + + $form[$this->getLanguageKey()] = array( + '#type' => 'select', + '#title' => t('Language'), + '#default_value' => $this->getLanguage(), + '#options' => $options, + ); + + if (!empty($form['actions']['submit']['#submit'])) { + $submit = &$form['actions']['submit']['#submit']; + } + else { + if (!isset($form['#submit'])) { + $form['#submit'] = array(); + } + $submit = &$form['#submit']; + } + + array_unshift($submit, 'entity_translation_language_widget_submit'); + } + + /** * Performs alterations to the menu widget if available. */ protected function menuForm(&$form, &$form_state) { @@ -1031,7 +1063,28 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa // Update the form language as it might have changed. We exploit the // validation phase to be sure to act as early as possible. if (isset($form_state['values']['language']) && !$this->isTranslationForm()) { - $this->setFormLanguage($form_state['values']['language']); + $this->setFormLanguage($form_state['values'][$this->getLanguageKey()]); + } + } + + /** + * @see EntityTranslationHandlerInterface::entityFormLanguageWidgetSubmit() + */ + function entityFormLanguageWidgetSubmit($form, &$form_state) { + $form_langcode = $this->getFormLanguage(); + list(, , $bundle) = entity_extract_ids($this->entityType, $this->entity); + + foreach (field_info_instances($this->entityType, $bundle) as $instance) { + $field_name = $instance['field_name']; + $field = field_info_field($field_name); + $previous_langcode = $form[$field_name]['#language']; + + // Handle a possible language change: new language values are inserted, + // previous ones are deleted. + if ($field['translatable'] && $previous_langcode != $form_langcode) { + $form_state['values'][$field_name][$form_langcode] = $form_state['values'][$field_name][$previous_langcode]; + $form_state['values'][$field_name][$previous_langcode] = array(); + } } } @@ -1039,10 +1092,9 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa * @see EntityTranslationHandlerInterface::entityFormSubmit() */ public function entityFormSubmit($form, &$form_state) { - $langcode = $this->getLanguage(); $form_langcode = $this->getFormLanguage(); $translations = $this->getTranslations(); - $is_translation = $this->isTranslationForm(); + $is_translation = !empty($form_state['entity_translation']['is_translation']); $new_translation = !isset($translations->data[$form_langcode]); $values = isset($form_state['values']['translation']) ? $form_state['values']['translation'] : array(); @@ -1057,7 +1109,7 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa if (!isset($translations->data[$form_langcode])) { // If we have a new translation the language is the original entity // language. - $translation = $is_translation ? array('language' => $form_langcode, 'source' => $this->getSourceLanguage()) : array('language' => $langcode, 'source' => ''); + $translation = $is_translation ? array('language' => $form_langcode, 'source' => $this->getSourceLanguage()) : array('language' => $form_langcode, 'source' => ''); } else { $translation = $translations->data[$form_langcode]; @@ -1072,7 +1124,7 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa // Handle possible language changes for the original values. if (!$is_translation) { - $this->setOriginalLanguage($langcode); + $this->setOriginalLanguage($form_langcode); } $translation['status'] = intval($values['status']); @@ -1176,6 +1228,13 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa } /** + * Returns the translation object key for the wrapped entity type. + */ + protected function getLanguageKey() { + return !empty($this->entityInfo['entity keys']['language']) ? $this->entityInfo['entity keys']['language'] : 'language'; + } + + /** * Returns the entity accessibility. */ protected function getStatus() { diff --git a/includes/translation.handler.node.inc b/includes/translation.handler.node.inc index aab136c..cd7545a 100644 --- a/includes/translation.handler.node.inc +++ b/includes/translation.handler.node.inc @@ -62,6 +62,13 @@ class EntityTranslationNodeHandler extends EntityTranslationDefaultHandler { } /** + * @see EntityTranslationDefaultHandler::entityFormLanguageWidgetSubmit() + */ + function entityFormLanguageWidgetSubmit($form, &$form_state) { + // Do nothing. Locale already takes care of nodes. + } + + /** * @see EntityTranslationDefaultHandler::entityFormSubmit() */ public function entityFormSubmit($form, &$form_state) { diff --git a/includes/translation.handler.taxonomy_term.inc b/includes/translation.handler.taxonomy_term.inc index 2c4d427..bb15b4c 100644 --- a/includes/translation.handler.taxonomy_term.inc +++ b/includes/translation.handler.taxonomy_term.inc @@ -24,9 +24,12 @@ class EntityTranslationTaxonomyTermHandler extends EntityTranslationDefaultHandl // Remove the translation fieldset when the deletion confirm form is being // displayed. if (isset($form_state['confirm_delete'])) { - unset($form['source_language']); - unset($form['translation']); - unset($form['actions']['delete_translation']); + unset( + $form[$this->getLanguageKey()], + $form['source_language'], + $form['translation'], + $form['actions']['delete_translation'] + ); } } } diff --git a/includes/translation.handler.user.inc b/includes/translation.handler.user.inc new file mode 100644 index 0000000..6679c7c --- /dev/null +++ b/includes/translation.handler.user.inc @@ -0,0 +1,24 @@ +