diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php index a3cd9df..69265c2 100644 --- a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php +++ b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php @@ -583,13 +583,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/translation_entity/translation_entity.admin.inc b/core/modules/translation_entity/translation_entity.admin.inc index 01e9368..785e4ad 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 dec0460..275e6a7 100644 --- a/core/modules/translation_entity/translation_entity.module +++ b/core/modules/translation_entity/translation_entity.module @@ -125,6 +125,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() { @@ -1015,6 +1042,11 @@ function translation_entity_save_settings($settings) { // Store whether a bundle has translation enabled or not. translation_entity_set_config($entity_type, $bundle, 'enabled', $bundle_settings['translatable']); + // Store whether fields are translatable or not. + if (!empty($bundle_settings['fields'])) { + translation_entity_set_config($entity_type, $bundle, 'fields', $bundle_settings['fields']); + } + // Store whether fields have translation enabled or not. if (!empty($bundle_settings['columns'])) { foreach ($bundle_settings['columns'] as $field_name => $column_settings) {