diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index 9c300ab..6e7d891 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -970,7 +970,6 @@ function comment_links(Comment $comment, Node $node) { $links['comment-translations'] = array( 'title' => t('translations'), 'href' => 'comment/' . $comment->id() . '/translations', - 'html' => TRUE, ); } diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermTranslationController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermTranslationController.php index 2fa4227..d32df12 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermTranslationController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermTranslationController.php @@ -33,8 +33,8 @@ public function entityFormAlter(array &$form, array &$form_state, EntityInterfac function entityFormSave(array $form, array &$form_state) { if ($this->getSourceLangcode($form_state)) { $entity = translation_entity_form_controller($form_state)->getEntity($form_state); - // We need a redirect here, otherwise we would get an access denied page - // since the curret URL would be preserved and we would try to add a + // We need a redirect here, otherwise we would get an access denied page, + // since the current URL would be preserved and we would try to add a // translation for a language that already has a translation. $form_state['redirect'] = $this->getEditPath($entity); } diff --git a/core/modules/translation_entity/lib/Drupal/translation_entity/EntityTranslationController.php b/core/modules/translation_entity/lib/Drupal/translation_entity/EntityTranslationController.php index b08518a..36202eb 100644 --- a/core/modules/translation_entity/lib/Drupal/translation_entity/EntityTranslationController.php +++ b/core/modules/translation_entity/lib/Drupal/translation_entity/EntityTranslationController.php @@ -243,7 +243,7 @@ public function entityFormAlter(array &$form, array &$form_state, EntityInterfac } if ($language_widget) { - $form_langcode['#multilingual'] = TRUE; + $form['langcode']['#multilingual'] = TRUE; } $form['#process'][] = array($this, 'entityFormSharedElements'); diff --git a/core/modules/translation_entity/translation_entity.install b/core/modules/translation_entity/translation_entity.install index e7cbb65..83b50b9 100644 --- a/core/modules/translation_entity/translation_entity.install +++ b/core/modules/translation_entity/translation_entity.install @@ -56,6 +56,9 @@ function translation_entity_schema() { * Implements hook_install(). */ function translation_entity_install() { + // Assign a fairly low weight to ensure our implementation of + // hook_module_implements_alter() is run among the last ones. + module_set_weight('translation_entity', 10); language_negotiation_include(); language_negotiation_set(LANGUAGE_TYPE_CONTENT, array(LANGUAGE_NEGOTIATION_URL => 0)); } @@ -64,10 +67,14 @@ function translation_entity_install() { * Implements hook_enable(). */ function translation_entity_enable() { - $t_args = array( - '!language_url' => url('admin/config/regional/language'), - '!settings_url' => url('admin/config/regional/content-language'), - ); - $message = t('Content translation has been enabled. To use content translation, enable at least two languages and enable translation for content types, taxonomy vocabularies, accounts, or any other element you wish to translate.', $t_args); + // Translation works when at least two languages are enabled. + if (count(language_list()) < 2) { + $t_args = array('!language_url' => url('admin/config/regional/language')); + $message = t('Be sure to enable at least two languages.', $t_args); + } + + // Workflow for language settings can configure content translation settings. + $t_args = array('!settings_url' => url('admin/config/regional/content-language')); + $message .= t('Enable translation for content types, taxonomy vocabularies, accounts, or any other element you wish to translate.', $t_args); drupal_set_message($message, 'warning'); } diff --git a/core/modules/translation_entity/translation_entity.module b/core/modules/translation_entity/translation_entity.module index b9a2bed..3380b8e 100644 --- a/core/modules/translation_entity/translation_entity.module +++ b/core/modules/translation_entity/translation_entity.module @@ -45,9 +45,26 @@ function translation_entity_help($path, $arg) { } /** + * Implements hook_module_implements_alter(). + */ +function translation_entity_module_implements_alter(&$implementations, $hook) { + switch ($hook) { + case 'menu_alter': + case 'entity_info_alter': + // Move some of our hook implementations to the end of the list. + $group = $implementations['translation_entity']; + unset($implementations['translation_entity']); + $implementations['translation_entity'] = $group; + break; + } +} + +/** * Implements hook_language_type_info_alter(). */ function translation_entity_language_types_info_alter(array &$language_types) { + // Make content language negotiation configurable by removing its predefined + // configuration. unset($language_types[LANGUAGE_TYPE_CONTENT]['fixed']); } @@ -176,30 +193,23 @@ function translation_entity_menu() { * Implements hook_menu_alter(). */ function translation_entity_menu_alter(array &$items) { - // Some menu loaders in the item paths might have been altered: we need to - // replace any menu loader with a plain % to check if base paths are still - // compatible. - $paths = array(); - $regex = '|%[^/]+|'; - foreach ($items as $path => $item) { - $path = preg_replace($regex, '%', $path); - $paths[$path] = $path; - } - // Check that the declared menu base paths are actually valid. foreach (entity_get_info() as $entity_type => $info) { if (translation_entity_enabled($entity_type)) { $path = $info['menu_base_path']; - // If the base path is not defined or is not compatible with any defined - // one we cannot provide the translation UI for this entity type. - if (!isset($paths[preg_replace($regex, '%', $path)])) { - drupal_set_message(t('The entities of type %entity_type do not define a valid base path: it will not be possible to translate them.', array('%entity_type' => $info['label'])), 'warning'); + // If the base path is not defined we cannot provide the translation UI + // for this entity type. In some cases the actual base path might not have + // a menu loader associated, hence we need to check also for the plain "%" + // variant. + if (!isset($items[$path]) && !isset($items[_translation_entity_menu_strip_loaders($path)])) { unset( $items["$path/translations"], - $items["$path/translations/add/%language"], + $items["$path/translations/add/%language/%language"], $items["$path/translations/delete/%language"] ); + $t_args = array('@entity_type' => isset($info['label']) ? $info['label'] : $entity_type); + watchdog('entity translation', 'The entities of type @entity_type do not define a valid base path: it will not be possible to translate them.', $t_args, WATCHDOG_WARNING); } else { $entity_position = count(explode('/', $path)) - 1; @@ -226,6 +236,19 @@ function translation_entity_menu_alter(array &$items) { } /** + * Strips out menu loaders from the given path. + * + * @param string $path + * The path to process. + * + * @return + * The given path where all the menu loaders are replaced with "%". + */ +function _translation_entity_menu_strip_loaders($path) { + return preg_replace('|%[^/]+|', '%', $path); +} + +/** * Access callback for the translation overview page. * * @param \Drupal\Core\Entity\EntityInterface $entity @@ -279,10 +302,10 @@ function translation_entity_library_info() { } /** - * Returns the key name used to store the configuration item. + * Returns the key name used to store the configuration setting. * - * Based on the entity type and bundle, the variables used to store the - * configuration will have a common root name. + * Based on the entity type and bundle, the keys used to store configuration + * will have a common root name. * * @param string $entity_type * The type of the entity the setting refers to. @@ -292,7 +315,7 @@ function translation_entity_library_info() { * The name of the setting. * * @return string - * The key name of the configuration item. + * The key name of the configuration setting. * * @todo Generalize this logic so that it is available to any module needing * per-bundle configuration. @@ -369,6 +392,34 @@ function translation_entity_enabled($entity_type, $bundle = NULL, $skip_handler } /** + * Returns all the translatable entity types. + * + * @return array + * An array of entity types keyed by entity type. + */ +function translation_entity_types_translatable() { + $entity_types = &drupal_static(__FUNCTION__, array()); + + foreach (entity_get_info() as $entity_type => $info) { + if (translation_entity_enabled($entity_type)) { + // Lazy load router items. + if (!isset($items)) { + $items = menu_get_router(); + } + // Check whether the required paths are defined. We need to strip out the + // menu loader and replace it with a plain "%" as router items have no + // menu loader in them. + $path = _translation_entity_menu_strip_loaders($info['menu_base_path']); + if (!empty($items[$path]) && !empty($items[$path . '/translations'])) { + $entity_types[$entity_type] = $entity_type; + } + } + } + + return $entity_types; +} + +/** * Entity translation controller factory. * * @param string $entity_type @@ -507,12 +558,8 @@ function translation_entity_entity_load(array $entities, $entity_type) { * The type of the entities. */ function translation_entity_load_translation_data(array $entities, $entity_type) { - $result = db_select('translation_entity', 'te') - ->fields('te', array()) - ->condition('te.entity_type', $entity_type) - ->condition('te.entity_id', array_keys($entities)) - ->execute(); - + $query = 'SELECT * FROM {translation_entity} te WHERE te.entity_type = :entity_type AND te.entity_id IN (:entity_id)'; + $result = db_query($query, array(':entity_type' => $entity_type, ':entity_id' => array_keys($entities))); foreach ($result as $record) { $entity = $entities[$record->entity_id]; // @todo Declare these as entity (translation?) properties. @@ -604,21 +651,18 @@ function translation_entity_form_field_ui_field_settings_form_alter(array &$form $field = $form['#field']; $field_name = $field['field_name']; $translatable = $field['translatable']; - $title = t('Users may translate this field.'); + $label = t('Field translation'); if (field_has_data($field)) { - $path = "admin/config/regional/translation_entity/translatable/$field_name"; - $status = $translatable ? $title : t('This field has data in existing content.'); - $link_title = !$translatable ? t('Enable translation') : t('Disable translation'); - $form['field']['translatable'] = array( - 'message' => array( - '#markup' => $status . ' ', - ), + '#type' => 'item', + '#title' => $label, + '#attributes' => array('class' => 'translatable'), 'link' => array( '#type' => 'link', - '#title' => $link_title, - '#href' => $path, + '#prefix' => t('This field has data in existing content.') . ' ', + '#title' => !$translatable ? t('Enable translation') : t('Disable translation'), + '#href' => 'admin/config/regional/translation_entity/translatable/' . $field_name, '#options' => array('query' => drupal_get_destination()), '#access' => user_access('administer entity translation'), ), @@ -627,10 +671,12 @@ function translation_entity_form_field_ui_field_settings_form_alter(array &$form else { $form['field']['translatable'] = array( '#type' => 'checkbox', - '#title' => $title, + '#title' => t('Users may translate this field.'), '#default_value' => $translatable, ); } + + $form['field']['translatable']['#weight'] = 20; } /**