diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php index f3a8790..4581e87 100644 --- a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php +++ b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php @@ -730,13 +730,18 @@ public function getFieldDefinitions(array $constraints) { $hooks = array('entity_field_info', $this->entityType . '_property_info'); drupal_alter($hooks, $this->entityFieldInfo, $this->entityType); - // Enforce fields to be multiple by default. - foreach ($this->entityFieldInfo['definitions'] as &$definition) { - $definition['list'] = TRUE; - } - foreach ($this->entityFieldInfo['optional'] as &$definition) { - $definition['list'] = TRUE; + // Enforce fields to be multiple and untranslatable by default. + $base_fields = array_flip(array_filter(array($this->idKey, $this->revisionKey, $this->bundleKey, $this->uuidKey, 'langcode'))); + foreach (array('definitions', 'optional') as $key) { + foreach ($this->entityFieldInfo[$key] as $name => &$definition) { + $definition['list'] = TRUE; + // Ensure base fields are never made translatable. + if (isset($base_fields[$name]) || !isset($definition['translatable'])) { + $definition['translatable'] = FALSE; + } + } } + cache()->set($cid, $this->entityFieldInfo, CacheBackendInterface::CACHE_PERMANENT, array('entity_info' => TRUE)); } } diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php index 4bc59fe..aae5e30 100644 --- a/core/modules/node/lib/Drupal/node/NodeFormController.php +++ b/core/modules/node/lib/Drupal/node/NodeFormController.php @@ -9,13 +9,13 @@ use Drupal\Component\Utility\NestedArray; use Drupal\Core\Datetime\DrupalDateTime; -use Drupal\Core\Entity\EntityFormController; +use Drupal\Core\Entity\EntityFormControllerNG; use Drupal\Core\Language\Language; /** * Form controller for the node edit forms. */ -class NodeFormController extends EntityFormController { +class NodeFormController extends EntityFormControllerNG { /** * Prepares the node object. diff --git a/core/modules/node/lib/Drupal/node/NodeStorageController.php b/core/modules/node/lib/Drupal/node/NodeStorageController.php index db3ba75..251df5e 100644 --- a/core/modules/node/lib/Drupal/node/NodeStorageController.php +++ b/core/modules/node/lib/Drupal/node/NodeStorageController.php @@ -229,42 +229,50 @@ public function baseFieldDefinitions() { 'label' => t('Title'), 'description' => t('The title of this node, always treated as non-markup plain text.'), 'type' => 'string_field', + 'translatable' => TRUE, ); $properties['uid'] = array( 'label' => t('User ID'), 'description' => t('The user ID of the node author.'), 'type' => 'entity_reference_field', 'settings' => array('target_type' => 'user'), + 'translatable' => TRUE, ); $properties['status'] = array( 'label' => t('Publishing status'), 'description' => t('A boolean indicating whether the node is published.'), 'type' => 'boolean_field', + 'translatable' => TRUE, ); $properties['created'] = array( 'label' => t('Created'), 'description' => t('The time that the node was created.'), 'type' => 'integer_field', + 'translatable' => TRUE, ); $properties['changed'] = array( 'label' => t('Changed'), 'description' => t('The time that the node was last edited.'), 'type' => 'integer_field', + 'translatable' => TRUE, ); $properties['comment'] = array( 'label' => t('Comment'), 'description' => t('Whether comments are allowed on this node: 0 = no, 1 = closed (read only), 2 = open (read/write).'), 'type' => 'integer_field', + 'translatable' => TRUE, ); $properties['promote'] = array( 'label' => t('Promote'), 'description' => t('A boolean indicating whether the node should be displayed on the front page.'), 'type' => 'boolean_field', + 'translatable' => TRUE, ); $properties['sticky'] = array( 'label' => t('Sticky'), 'description' => t('A boolean indicating whether the node should be displayed at the top of lists in which it appears.'), 'type' => 'boolean_field', + 'translatable' => TRUE, ); $properties['tnid'] = array( 'label' => t('Translation set ID'), diff --git a/core/modules/node/lib/Drupal/node/NodeTranslationController.php b/core/modules/node/lib/Drupal/node/NodeTranslationController.php index 4531a8e..6ed7182 100644 --- a/core/modules/node/lib/Drupal/node/NodeTranslationController.php +++ b/core/modules/node/lib/Drupal/node/NodeTranslationController.php @@ -8,12 +8,12 @@ namespace Drupal\node; use Drupal\Core\Entity\EntityInterface; -use Drupal\translation_entity\EntityTranslationController; +use Drupal\translation_entity\EntityTranslationControllerNG; /** * Defines the translation controller class for nodes. */ -class NodeTranslationController extends EntityTranslationController { +class NodeTranslationController extends EntityTranslationControllerNG { /** * Overrides EntityTranslationController::getAccess(). diff --git a/core/modules/translation_entity/translation_entity.admin.inc b/core/modules/translation_entity/translation_entity.admin.inc index dd7874c..01f2c5c 100644 --- a/core/modules/translation_entity/translation_entity.admin.inc +++ b/core/modules/translation_entity/translation_entity.admin.inc @@ -76,6 +76,8 @@ function _translation_entity_form_language_content_settings_form_alter(array &$f $dependent_options_settings = array(); foreach ($form['#labels'] as $entity_type => $label) { $entity_info = entity_get_info($entity_type); + $controller = Drupal::entityManager()->getStorageController($entity_type); + foreach (entity_get_bundles($entity_type) as $bundle => $bundle_info) { // Here we do not want the widget to be altered and hold also the "Enable // translation" checkbox, which would be redundant. Hence we add this key @@ -85,35 +87,55 @@ function _translation_entity_form_language_content_settings_form_alter(array &$f // Only show the checkbox to enable translation if the bundles in the // entity might have fields and if there are fields to translate. if (!empty($entity_info['fieldable'])) { - $fields = field_info_instances($entity_type, $bundle); + $fields = $controller->getFieldDefinitions(array('EntityType' => $entity_type, 'Bundle' => $bundle)); + if ($fields) { $form['settings'][$entity_type][$bundle]['translatable'] = array( '#type' => 'checkbox', '#default_value' => translation_entity_enabled($entity_type, $bundle), ); - // @todo Exploit field definitions once all core entities and field - // types are migrated to the Entity Field API. - foreach ($fields as $field_name => $instance) { - $field = field_info_field($field_name); - $form['settings'][$entity_type][$bundle]['fields'][$field_name] = array( - '#label' => $instance['label'], - '#type' => 'checkbox', - '#default_value' => $field['translatable'], - ); - $column_element = translation_entity_field_sync_widget($field, $instance); - if ($column_element) { - $form['settings'][$entity_type][$bundle]['columns'][$field_name] = $column_element; - - if (isset($column_element['#options']['file'])) { - $dependent_options_settings["settings[{$entity_type}][{$bundle}][columns][{$field_name}]"] = array('file'); + $field_settings = translation_entity_get_config($entity_type, $bundle, 'fields'); + foreach ($fields as $field_name => $definition) { + $translatable = !empty($field_settings[$field_name]); + + // We special case Field API fields as they always natively support + // translation. + if (!empty($definition['configurable']) && ($field = field_info_field($field_name))) { + $instance = field_info_instance($entity_type, $field_name, $bundle); + $form['settings'][$entity_type][$bundle]['fields'][$field_name] = array( + '#label' => $instance['label'], + '#type' => 'checkbox', + '#default_value' => $translatable, + ); + + $column_element = translation_entity_field_sync_widget($field, $instance); + if ($column_element) { + $form['settings'][$entity_type][$bundle]['columns'][$field_name] = $column_element; + + // @todo This should not concern only files. + if (isset($column_element['#options']['file'])) { + $dependent_options_settings["settings[{$entity_type}][{$bundle}][columns][{$field_name}]"] = array('file'); + } } } + // Instead we need to rely on field definitions to determine whether + // they support translation. Whether they are actually enabled is + // determined through our settings. As a consequence only fields + // that support translation can be enabled or disabled. + elseif (isset($field_settings[$field_name]) || !empty($definition['translatable'])) { + $form['settings'][$entity_type][$bundle]['fields'][$field_name] = array( + '#label' => $definition['label'], + '#type' => 'checkbox', + '#default_value' => $translatable, + ); + } } } } } } + $settings = array('dependent_selectors' => $dependent_options_settings); $form['#attached']['js'][] = array('data' => array('translationEntityDependentOptions' => $settings), 'type' => 'setting'); $form['#validate'][] = 'translation_entity_form_language_content_settings_validate'; @@ -326,11 +348,11 @@ function _translation_entity_update_field_translatability($settings) { foreach ($bundle_settings['fields'] as $field_name => $translatable) { // If a field is enabled for translation for at least one instance we // need to mark it as translatable. - $fields[$field_name] = $translatable || !empty($fields[$field_name]); + if (field_info_field($field_name)) { + $fields[$field_name] = $translatable || !empty($fields[$field_name]); + } } } - // @todo Store non-configurable field settings to be able to alter their - // definition afterwards. } } diff --git a/core/modules/translation_entity/translation_entity.module b/core/modules/translation_entity/translation_entity.module index bbe6605..7770390 100644 --- a/core/modules/translation_entity/translation_entity.module +++ b/core/modules/translation_entity/translation_entity.module @@ -124,6 +124,33 @@ function translation_entity_entity_bundle_info_alter(&$bundles) { } /** + * Implements hook_entity_field_info_alter(). + */ +function translation_entity_entity_field_info_alter(&$info, $entity_type) { + $translation_settings = config('translation_entity.settings')->get($entity_type); + + if ($translation_settings) { + // Currently field translatability is defined per-field but we may want to + // make it per-instance instead, so leaving the possibility open for further + // easier refactoring. + $fields = array(); + foreach ($translation_settings as $bundle => $settings) { + $fields += !empty($settings['translation_entity']['fields']) ? $settings['translation_entity']['fields'] : array(); + } + + $keys = array('definitions', 'optional'); + foreach ($fields as $name => $translatable) { + foreach ($keys as $key) { + if (isset($info[$key][$name])) { + $info[$key][$name]['translatable'] = (bool) $translatable; + break; + } + } + } + } +} + +/** * Implements hook_menu(). */ function translation_entity_menu() { @@ -1013,6 +1040,7 @@ function translation_entity_save_settings($settings) { if (isset($bundle_settings['translatable'])) { // Store whether a bundle has translation enabled or not. translation_entity_set_config($entity_type, $bundle, 'enabled', $bundle_settings['translatable']); + translation_entity_set_config($entity_type, $bundle, 'fields', $bundle_settings['fields']); // Store whether fields have translation enabled or not. if (!empty($bundle_settings['columns'])) {