Chris@0: getDefinition($field->getType()); Chris@0: $column_groups = $definition['column_groups']; Chris@0: if (!empty($column_groups) && count($column_groups) > 1) { Chris@0: $options = []; Chris@0: $default = []; Chris@0: $require_all_groups_for_translation = []; Chris@0: Chris@0: foreach ($column_groups as $group => $info) { Chris@0: $options[$group] = $info['label']; Chris@0: $default[$group] = !empty($info['translatable']) ? $group : FALSE; Chris@0: if (!empty($info['require_all_groups_for_translation'])) { Chris@0: $require_all_groups_for_translation[] = $group; Chris@0: } Chris@0: } Chris@0: Chris@0: $default = $field->getThirdPartySetting('content_translation', 'translation_sync', $default); Chris@0: Chris@0: $element = [ Chris@0: '#type' => 'checkboxes', Chris@0: '#title' => t('Translatable elements'), Chris@0: '#options' => $options, Chris@0: '#default_value' => $default, Chris@0: ]; Chris@0: Chris@0: if ($require_all_groups_for_translation) { Chris@0: // The actual checkboxes are sometimes rendered separately and the parent Chris@0: // element is ignored. Attach to the first option to ensure that this Chris@0: // does not get lost. Chris@0: $element[key($options)]['#attached']['drupalSettings']['contentTranslationDependentOptions'] = [ Chris@0: 'dependent_selectors' => [ Chris@4: $element_name => $require_all_groups_for_translation, Chris@0: ], Chris@0: ]; Chris@0: $element[key($options)]['#attached']['library'][] = 'content_translation/drupal.content_translation.admin'; Chris@0: } Chris@0: } Chris@0: Chris@0: return $element; Chris@0: } Chris@0: Chris@0: /** Chris@0: * (proxied) Implements hook_form_FORM_ID_alter(). Chris@0: */ Chris@0: function _content_translation_form_language_content_settings_form_alter(array &$form, FormStateInterface $form_state) { Chris@0: // Inject into the content language settings the translation settings if the Chris@0: // user has the required permission. Chris@0: if (!\Drupal::currentUser()->hasPermission('administer content translation')) { Chris@0: return; Chris@0: } Chris@0: Chris@0: /** @var \Drupal\content_translation\ContentTranslationManagerInterface $content_translation_manager */ Chris@0: $content_translation_manager = \Drupal::service('content_translation.manager'); Chris@0: $default = $form['entity_types']['#default_value']; Chris@0: foreach ($default as $entity_type_id => $enabled) { Chris@0: $default[$entity_type_id] = $enabled || $content_translation_manager->isEnabled($entity_type_id) ? $entity_type_id : FALSE; Chris@0: } Chris@0: $form['entity_types']['#default_value'] = $default; Chris@0: Chris@0: $form['#attached']['library'][] = 'content_translation/drupal.content_translation.admin'; Chris@0: Chris@0: $entity_manager = Drupal::entityManager(); Chris@0: $bundle_info_service = \Drupal::service('entity_type.bundle.info'); Chris@0: foreach ($form['#labels'] as $entity_type_id => $label) { Chris@0: $entity_type = $entity_manager->getDefinition($entity_type_id); Chris@0: $storage_definitions = $entity_type instanceof ContentEntityTypeInterface ? $entity_manager->getFieldStorageDefinitions($entity_type_id) : []; Chris@0: Chris@0: $entity_type_translatable = $content_translation_manager->isSupported($entity_type_id); Chris@0: foreach ($bundle_info_service->getBundleInfo($entity_type_id) as $bundle => $bundle_info) { Chris@0: // Here we do not want the widget to be altered and hold also the "Enable Chris@0: // translation" checkbox, which would be redundant. Hence we add this key Chris@0: // to be able to skip alterations. Alter the title and display the message Chris@0: // about UI integration. Chris@0: $form['settings'][$entity_type_id][$bundle]['settings']['language']['#content_translation_skip_alter'] = TRUE; Chris@0: if (!$entity_type_translatable) { Chris@0: $form['settings'][$entity_type_id]['#title'] = t('@label (Translation is not supported).', ['@label' => $entity_type->getLabel()]); Chris@0: continue; Chris@0: } Chris@0: Chris@0: // Displayed the "shared fields widgets" toggle. Chris@0: if ($content_translation_manager instanceof BundleTranslationSettingsInterface) { Chris@0: $settings = $content_translation_manager->getBundleTranslationSettings($entity_type_id, $bundle); Chris@0: $force_hidden = ContentTranslationManager::isPendingRevisionSupportEnabled($entity_type_id, $bundle); Chris@0: $form['settings'][$entity_type_id][$bundle]['settings']['content_translation']['untranslatable_fields_hide'] = [ Chris@0: '#type' => 'checkbox', Chris@0: '#title' => t('Hide non translatable fields on translation forms'), Chris@0: '#default_value' => $force_hidden || !empty($settings['untranslatable_fields_hide']), Chris@0: '#disabled' => $force_hidden, Chris@0: '#description' => $force_hidden ? t('Moderated content requires non-translatable fields to be edited in the original language form.') : '', Chris@0: '#states' => [ Chris@0: 'visible' => [ Chris@0: ':input[name="settings[' . $entity_type_id . '][' . $bundle . '][translatable]"]' => [ Chris@0: 'checked' => TRUE, Chris@0: ], Chris@0: ], Chris@0: ], Chris@0: ]; Chris@0: } Chris@0: Chris@0: $fields = $entity_manager->getFieldDefinitions($entity_type_id, $bundle); Chris@0: if ($fields) { Chris@0: foreach ($fields as $field_name => $definition) { Chris@0: if ($definition->isComputed() || (!empty($storage_definitions[$field_name]) && _content_translation_is_field_translatability_configurable($entity_type, $storage_definitions[$field_name]))) { Chris@0: $form['settings'][$entity_type_id][$bundle]['fields'][$field_name] = [ Chris@0: '#label' => $definition->getLabel(), Chris@0: '#type' => 'checkbox', Chris@0: '#default_value' => $definition->isTranslatable(), Chris@0: ]; Chris@0: // Display the column translatability configuration widget. Chris@0: $column_element = content_translation_field_sync_widget($definition, "settings[{$entity_type_id}][{$bundle}][columns][{$field_name}]"); Chris@0: if ($column_element) { Chris@0: $form['settings'][$entity_type_id][$bundle]['columns'][$field_name] = $column_element; Chris@0: } Chris@0: } Chris@0: } Chris@0: if (!empty($form['settings'][$entity_type_id][$bundle]['fields'])) { Chris@0: // Only show the checkbox to enable translation if the bundles in the Chris@0: // entity might have fields and if there are fields to translate. Chris@0: $form['settings'][$entity_type_id][$bundle]['translatable'] = [ Chris@0: '#type' => 'checkbox', Chris@0: '#default_value' => $content_translation_manager->isEnabled($entity_type_id, $bundle), Chris@0: ]; Chris@0: } Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: $form['#validate'][] = 'content_translation_form_language_content_settings_validate'; Chris@0: $form['#submit'][] = 'content_translation_form_language_content_settings_submit'; Chris@0: } Chris@4: Chris@0: /** Chris@0: * Checks whether translatability should be configurable for a field. Chris@0: * Chris@0: * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type Chris@0: * The entity type definition. Chris@0: * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $definition Chris@0: * The field storage definition. Chris@0: * Chris@0: * @return bool Chris@0: * TRUE if field translatability can be configured, FALSE otherwise. Chris@0: * Chris@0: * @internal Chris@0: */ Chris@0: function _content_translation_is_field_translatability_configurable(EntityTypeInterface $entity_type, FieldStorageDefinitionInterface $definition) { Chris@0: // Allow to configure only fields supporting multilingual storage. We skip our Chris@0: // own fields as they are always translatable. Additionally we skip a set of Chris@0: // well-known fields implementing entity system business logic. Chris@5: return $definition->isTranslatable() && Chris@0: $definition->getProvider() != 'content_translation' && Chris@0: !in_array($definition->getName(), [$entity_type->getKey('langcode'), $entity_type->getKey('default_langcode'), 'revision_translation_affected']); Chris@0: } Chris@0: Chris@0: /** Chris@0: * (proxied) Implements hook_preprocess_HOOK(); Chris@0: */ Chris@0: function _content_translation_preprocess_language_content_settings_table(&$variables) { Chris@0: // Alter the 'build' variable injecting the translation settings if the user Chris@0: // has the required permission. Chris@0: if (!\Drupal::currentUser()->hasPermission('administer content translation')) { Chris@0: return; Chris@0: } Chris@0: Chris@0: $element = $variables['element']; Chris@0: $build = &$variables['build']; Chris@0: Chris@0: array_unshift($build['#header'], ['data' => t('Translatable'), 'class' => ['translatable']]); Chris@0: $rows = []; Chris@0: Chris@0: foreach (Element::children($element) as $bundle) { Chris@0: $field_names = !empty($element[$bundle]['fields']) ? Element::children($element[$bundle]['fields']) : []; Chris@0: if (!empty($element[$bundle]['translatable'])) { Chris@0: $checkbox_id = $element[$bundle]['translatable']['#id']; Chris@0: } Chris@0: $rows[$bundle] = $build['#rows'][$bundle]; Chris@0: Chris@0: if (!empty($element[$bundle]['translatable'])) { Chris@0: $translatable = [ Chris@0: 'data' => $element[$bundle]['translatable'], Chris@0: 'class' => ['translatable'], Chris@0: ]; Chris@0: array_unshift($rows[$bundle]['data'], $translatable); Chris@0: Chris@0: $rows[$bundle]['data'][1]['data']['#prefix'] = '