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

Drupal 使图像字段在自定义块中可翻译,drupal,drupal-modules,drupal-8,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

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

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()}\" />"
    ];
}

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

不幸的是,在Drupal core中,托管文件元素是不可即时翻译的;这里没有列出

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

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);
}
使用Drupal\Core\Form\FormStateInterface;
使用Drupal\file\Entity\file;
使用Drupal\file\FileUsage\FileUsageInterface;
/**
*实现hook\u form\u alter()。
*
*将托管文件表单元素添加到配置中添加和编辑表单到
*允许用户翻译mymodule_图像
*配置值。
*
*作为文件实体引用的托管文件表单元素不可翻译
*通过Drupal核心配置转换模块。
*
*@Todo:仅当mymodule_映像
*是翻译的。当没有翻译其他配置时,配置不会保存在中
*Drupal\config\u translation\Form\ConfigTranslationFormBase::submitForm()
*/
函数kraken_设置_表单_更改(&$form,FormStateInterface$form_state,$form_id){
if(在数组中($form\u id,['config\u translation\u add\u form','config\u translation\u edit\u form'])){
$mapper=$form\u state->get('config\u translation\u mapper');
//对于mymodule设置,将新的标题图像表单元素添加到
//配置翻译表单。
$config_name='mymodule.settings';
如果(是_数组($mapper->getConfigNames())&&in_数组($config_name,$mapper->getConfigNames())){
$config=\Drupal::config($config\u name);
$element_name='mymodule_image';
$lang=$form\u state->get('config\u translation\u language')->getId();
//将这些添加到表单_状态,以便在提交处理程序中使用。
$form_state->setFormState([
'config_name'=>$config_name,
“语言”=>$lang,
'element_name'=>$element_name,
]);
//为源元素和翻译元素创建新的表单元素。
$element=[
“#title”=>t(“我的模块图像”),
“#键入”=>“托管文件”,
“#默认值”=>”,
“#description”=>t(“我的模块配置映像”),
“#上传位置”=>”public://mymodule-image/',
];
//添加源表单元素并设置默认值。换行
//标记中的元素与其他已翻译的表单元素相似。
//@请参阅config\u translation\u manage\u form\u element.html.twig
$source\u value=$config->get($element\u name);
//检查是否为null以避免php通知。
$source\u default=isset($source\u值)?$source\u值:“”;
$form['mymodule\u config\u trans\u source\u div']=[
“#type”=>“container”,
“#前缀”=>”,
“#后缀”=>”,
“#重量”=>-10,
];
$form['mymodule\u config\u trans\u source\u div']['mymodule\u config\u trans\u source']=$element;
$form['mymodule_config_trans_source_div']['mymodule_config_trans_source']['#default_value']=$source_default;
//@Todo:渲染源图像预览,而不是渲染
//作为禁用的托管文件表单元素。
$form['mymodule_config_trans_source_div']['mymodule_config_trans_source']['#disabled']=TRUE;
$form['mymodule_config_trans_source_div']['mymodule_config_trans_source']['#description']=t('原始源文件。无法删除');
//添加翻译后的表单元素,就像源代码一样。
$trans_value=$config->get('translations.$lang.'.$element_name);
//检查是否为null以避免抛出php通知。如果设置为null,则添加为数组
//对于Drupal\file\Element\ManagedFile。
$trans_default=(isset($trans_value))?[$trans_value]:'';
$form['mymodule\u config\u trans\u div']=[
“#type”=>“container”,
“#前缀”=>”,
“#后缀”=>”,
“#重量”=>-10,
];
$form['mymodule\u config\u trans\u div']['mymodule\u config\u trans']=$element;
$form['mymodule_config_trans_div']['mymodule_config_trans']['#default_value']=$trans_default;
//添加自定义提交处理程序以首先管理转换后的值。
数组_unshift($form['#submit'],'mymodule_config_translation_submit');
}
}
}
/**
*提交处理程序以保存已翻译的mymodule_图像。
*/
函数mymodule\u config\u translation\u submit(数组$form,FormStateInterface$form\u state){
$config=\Drupal::configFactory()->getEditable($form\u state->get('config\u name');
$translations=$config->get('translations');
$element\u name=$form\u state->get('element\u name');
$language=$form_state->get('language');
$trans_value=$form_state->getValue('mymodule_config_trans');
$file\u usage=\Drupal::service('file.usage');
//检查数组键以避免注意:未定义索引警告。
if(isset($translations[$language][$element\u name])){
$trans_config=$translations[$language][$element_name];
}
否则{
$trans_config=NULL;
}
//如果有一个提交的表单值,并且它与保存的配置不同,
//然后处理更改的值。
如果(!empty($trans_值[0])){
//删除以前的trans-config文件用法(如果已设置且不同)。
如果(isset($trans_配置)&&$trans_值[0]!==$trans_配置){
$old_file=file::load($trans_config);
$file\u usage->delete($old\u file,'mymodule','file',$trans\u config);
//将新文件保存为永久文件并记录其使用情况。
mymodule_config_trans_file_save($file_usage,$trans_value[0]);
//在现有转换值中保存新转换值。
//按语言设置的键数组,用于管理多语言翻译。
$translations[$language][$element_name]=$trans_值[0];
$config->set('translations',$translations)->save();
}
//如果未设置配置,请保存新值。
如果(!isset($trans_config)){
mymodule_config_trans_file_save($file_用法,$trans_值[0]
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);
}