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);
}