使图像字段在自定义块中可翻译

时间:2018-09-19 09:28:04

标签: drupal drupal-modules drupal-8

我有一个自定义模块,该模块定义了一个具有单个图像字段的块。

public function blockForm($form, FormStateInterface $form_state){

    $form['block_logo_image'] = [
        '#type' => 'managed_file',
        '#title' => $this->t('Logo'),
        '#description' => $this->t('Provide a logo'),
        '#default_value' => $this->configuration['block_logo_image'],
        '#upload_location' => 'public://site_logos/',
        '#upload_validators' => array('file_validate_extensions' => array('png jpg gif')),
    ];

    return $form;
}

public function blockSubmit($form, FormStateInterface $form_state) {
    $this->configuration['block_logo_image'] = $form_state->getValue('block_logo_image');
}

public function build() {
    $image = File::load($this->configuration['block_logo_image'][0]);

    return [
        '#markup' => "<img class=\"site_logo\" src=\"/sites/subs/files/site_logos/{$image->getFilename()}\" />"
    ];
}

我想使此块可翻译,所以我创建了一个模式:

block.settings.logo_block:
  type: block_settings
  label: 'Configuration'
  mapping:
    block_logo_image:
      label: 'Logo'
      type: image

但这似乎不起作用,当我去翻译块时,图像字段未显示?

1 个答案:

答案 0 :(得分:1)

不幸的是,managed_file元素在Drupal核心中是不可即时翻译的。 https://www.drupal.org/docs/8/multilingual/translating-configuration不在此处。

对于自定义模块配置,我必须实现自定义表单更改和自定义表单提交处理程序以添加翻译后的表单元素及其值。

use Drupal\Core\Form\FormStateInterface;
use Drupal\file\Entity\File;
use Drupal\file\FileUsage\FileUsageInterface;


 /**
 * Implements hook_form_alter().
 *
 * Add managed_file form elements to config_translation add and edit forms to
 * allow users to translate the mymodule_image
 * configuration value.
 *
 * The managed_file form elements as file entity references are not translatable
 * by Drupal core config_translation module.
 *
 * @Todo: Save translated configuration only when the mymodule_image
 * is translated. When no other config is translated, config is not saved in
 * Drupal\config_translation\Form\ConfigTranslationFormBase::submitForm()
 */
function kraken_settings_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if (in_array($form_id, ['config_translation_add_form', 'config_translation_edit_form'])) {
    $mapper = $form_state->get('config_translation_mapper');

    // For the mymodule settings, add new header image form element to the
    // config translation form.
    $config_name = 'mymodule.settings';
    if (is_array($mapper->getConfigNames()) && in_array($config_name, $mapper->getConfigNames())) {
      $config = \Drupal::config($config_name);
      $element_name = 'mymodule_image';
      $lang = $form_state->get('config_translation_language')->getId();
      // Add these to form_state for use in the submit handler.
      $form_state->setFormState([
        'config_name' => $config_name,
        'language' => $lang,
        'element_name' => $element_name,
      ]);

      // Create new form elements for source and translation elements.
      $element = [
        '#title' => t('My Module Image'),
        '#type' => 'managed_file',
        '#default_value' => '',
        '#description' => t('My Module Configuration Image'),
        '#upload_location' => 'public://mymodule-image/',
      ];

      // Add the source form elements and set defaults. Wrap
      // elements in markup from to resemble other translated form elements.
      // @see config_translation_manage_form_element.html.twig
      $source_value = $config->get($element_name);
      // Check if null to avoid php notices.
      $source_default = isset($source_value) ? $source_value : '';
      $form['mymodule_config_trans_source_div'] = [
        '#type' => 'container',
        '#prefix' => '<div class="translation-set clearfix"><div class="layout-column layout-column--half translation-set__source">',
        '#suffix' => '</div>',
        '#weight' => -10,
      ];
      $form['mymodule_config_trans_source_div']['mymodule_config_trans_source'] = $element;
      $form['mymodule_config_trans_source_div']['mymodule_config_trans_source']['#default_value'] = $source_default;
      // @Todo: Render the a preview of the source image instead of rendering
      // as disabled managed_file form element.
      $form['mymodule_config_trans_source_div']['mymodule_config_trans_source']['#disabled'] = TRUE;
      $form['mymodule_config_trans_source_div']['mymodule_config_trans_source']['#description'] = t('The original source file. Can not remove.');

      // Add translated form element much like the source.
      $trans_value = $config->get('translations.' . $lang . '.' . $element_name);
      // Check if null to avoid throwing php notices. If set, add as an array
      // for Drupal\file\Element\ManagedFile.
      $trans_default = (isset($trans_value)) ? [$trans_value] : '';
      $form['mymodule_config_trans_div'] = [
        '#type' => 'container',
        '#prefix' => '<div class="layout-column layout-column--half translation-set__translated">',
        '#suffix' => '</div>',
        '#weight' => -10,
      ];
      $form['mymodule_config_trans_div']['mymodule_config_trans'] = $element;
      $form['mymodule_config_trans_div']['mymodule_config_trans']['#default_value'] = $trans_default;

      // Add custom submit handler to manage the translated value first.
      array_unshift($form['#submit'], 'mymodule_config_translation_submit');
    }
  }
}

/**
 * Submit handler to save translated mymodule_image image.
 */
function mymodule_config_translation_submit(array $form, FormStateInterface $form_state) {
  $config = \Drupal::configFactory()->getEditable($form_state->get('config_name'));
  $translations = $config->get('translations');
  $element_name = $form_state->get('element_name');
  $language = $form_state->get('language');
  $trans_value = $form_state->getValue('mymodule_config_trans');
  $file_usage = \Drupal::service('file.usage');

  // Check for array keys to avoid Notice: Undefined index warnings.
  if (isset($translations[$language][$element_name])) {
    $trans_config = $translations[$language][$element_name];
  }
  else {
    $trans_config = NULL;
  }

  // If there's a submitted form value and its different from the saved config,
  // then process changed value.
  if (!empty($trans_value[0])) {
    // Delete previous trans config file usage if set and different.
    if (isset($trans_config) && $trans_value[0] !== $trans_config) {
      $old_file = File::load($trans_config);
      $file_usage->delete($old_file, 'mymodule', 'file', $trans_config);

      // Save new file as permanent and record its usage.
      mymodule_config_trans_file_save($file_usage, $trans_value[0]);

      // Save new translation value within existing translation values.
      // Key array by language to manage multiple language translations.
      $translations[$language][$element_name] = $trans_value[0];
      $config->set('translations', $translations)->save();
    }

    // If config is not set, save new value.
    if (!isset($trans_config)) {
      mymodule_config_trans_file_save($file_usage, $trans_value[0]);

      // Save new translation value within existing translation values.
      // Key array by language to manage multiple language translations.
      $translations[$language][$element_name] = $trans_value[0];
      $config->set('translations', $translations)->save();
    }
  }
  else {
    // If submitted value is empty and configuration isset, remove file usage
    // and stored configuration value.
    if (isset($trans_config)) {
      $old_file = File::load($trans_config);
      // Note, removing all file usages will not change file status to temporary
      // per file.settings.make_unused_managed_files_temporary setting.
      // @see https://www.drupal.org/project/drupal/issues/2801777#comment-12221514.
      // @see \Drupal\file\FileUsage\FileUsageBase::delete().
      $file_usage->delete($old_file, 'mymodule', 'file', $trans_config);

      // Clear specific config key, leaving other possible translated language
      // configuration in place.
      $config->clear('translations.' . $language . '.' . $element_name);
      $config->save();
    }
  }
}

/**
 * Save new file usage.
 *
 * @param \Drupal\file\FileUsage\FileUsageInterface $file_usage
 *   The file.usage service.
 * @param int $fid
 *   A file id.
 */
function mymodule_config_trans_file_save(FileUsageInterface $file_usage, $fid) {
  $file = File::load($fid);
  $file->setPermanent();
  $file->save();
  $file_usage->add($file, 'mymodule', 'file', $fid);
}