Код под катом, буду очень благодарен :
Код: Выделить всё
<?xml version="1.0" encoding="UTF-8"?>
<modification>
<name>Akarius — ALT для дополнительных изображений товара</name>
<code>zz_akarius_product_image_alt</code>
<version>6.0.0</version>
<author>Akarius</author>
<link>https://akarius.ru/</link>
<!-- ============================================================
ADMIN MODEL: сохраняем ALT при создании и редактировании
(index="0,1" — меняются оба INSERT: addProduct и editProduct)
============================================================= -->
<file path="admin/model/catalog/product.php">
<operation>
<search index="0,1"><![CDATA[$this->db->query("INSERT INTO " . DB_PREFIX . "product_image SET product_id = '" . (int)$product_id . "', image = '" . $this->db->escape($product_image['image']) . "', sort_order = '" . (int)$product_image['sort_order'] . "'");]]></search>
<add position="replace"><![CDATA[$this->db->query("INSERT INTO " . DB_PREFIX . "product_image SET product_id = '" . (int)$product_id . "', image = '" . $this->db->escape($product_image['image']) . "', sort_order = '" . (int)$product_image['sort_order'] . "', image_alt = '" . $this->db->escape(isset($product_image['image_alt']) ? $product_image['image_alt'] : '') . "'");]]></add>
</operation>
</file>
<!-- ============================================================
ADMIN CONTROLLER: передаём image_alt из БД в форму товара
============================================================= -->
<file path="admin/controller/catalog/product.php">
<operation>
<search><![CDATA['sort_order' => $product_image['sort_order']]]></search>
<add position="replace"><![CDATA['sort_order' => $product_image['sort_order'],
'image_alt' => isset($product_image['image_alt']) ? $product_image['image_alt'] : '']]></add>
</operation>
</file>
<!-- ============================================================
ADMIN LANGUAGE: переменные (RU)
============================================================= -->
<file path="admin/language/ru-ru/catalog/product.php">
<operation>
<search><![CDATA[$_['entry_additional_image'] = 'Дополнительные изображения';]]></search>
<add position="after"><![CDATA[$_['entry_image_alt'] = 'Alt текст (альтернативный текст)';]]></add>
</operation>
</file>
<!-- ============================================================
ADMIN LANGUAGE: переменные (EN)
============================================================= -->
<file path="admin/language/en-gb/catalog/product.php">
<operation>
<search><![CDATA[$_['entry_additional_image'] = 'Additional Images';]]></search>
<add position="after"><![CDATA[$_['entry_image_alt'] = 'Alt text';]]></add>
</operation>
</file>
<!-- ============================================================
ADMIN FORM: колонка ALT + поле ввода + JS + подвал таблицы
============================================================= -->
<file path="admin/view/template/catalog/product_form.twig">
<!-- 1. Заголовок новой колонки -->
<operation>
<search><![CDATA[<td class="text-left">{{ entry_additional_image }}</td>]]></search>
<add position="replace"><![CDATA[<td class="text-left">{{ entry_additional_image }}</td>
<td class="text-left">{{ entry_image_alt }}</td>]]></add>
</operation>
<!-- 2. Поле ввода для существующих изображений -->
<operation>
<search><![CDATA[<td class="text-left"><a href="" id="thumb-image{{ image_row }}" data-toggle="image" class="img-thumbnail"><img src="{{ product_image.thumb }}" alt="" title="" data-placeholder="{{ placeholder }}"/></a> <input type="hidden" name="product_image[{{ image_row }}][image]" value="{{ product_image.image }}" id="input-image{{ image_row }}"/></td>]]></search>
<add position="replace"><![CDATA[<td class="text-left"><a href="" id="thumb-image{{ image_row }}" data-toggle="image" class="img-thumbnail"><img src="{{ product_image.thumb }}" alt="" title="" data-placeholder="{{ placeholder }}"/></a> <input type="hidden" name="product_image[{{ image_row }}][image]" value="{{ product_image.image }}" id="input-image{{ image_row }}"/></td>
<td class="text-left"><input type="text" name="product_image[{{ image_row }}][image_alt]" value="{{ product_image.image_alt|default('') }}" placeholder="{{ entry_image_alt }}" class="form-control"/></td>]]></add>
</operation>
<!-- 3. Поле ALT в JS-шаблоне для динамически добавляемых изображений -->
<operation>
<search><![CDATA[html += ' <td class="text-right"><input type="text" name="product_image[' + image_row + '][sort_order]" value="" placeholder="{{ entry_sort_order }}" class="form-control" />';]]></search>
<add position="replace"><![CDATA[html += ' <td class="text-left"><input type="text" name="product_image[' + image_row + '][image_alt]" value="" placeholder="{{ entry_image_alt }}" class="form-control" /></td>';
html += ' <td class="text-right"><input type="text" name="product_image[' + image_row + '][sort_order]" value="" placeholder="{{ entry_sort_order }}" class="form-control" />';]]></add>
</operation>
<!-- 4. Подвал таблицы: отдельные ячейки вместо colspan -->
<operation>
<search><![CDATA[<tfoot>
<tr>
<td colspan="2"></td>
<td class="text-left"><button type="button" onclick="addImage();" data-toggle="tooltip" title="{{ button_image_add }}" class="btn btn-primary"><i class="fa fa-plus-circle"></i></button></td>
</tr>
</tfoot>]]></search>
<add position="replace"><![CDATA[<tfoot>
<tr>
<td></td>
<td></td>
<td></td>
<td class="text-left"><button type="button" onclick="addImage();" data-toggle="tooltip" title="{{ button_image_add }}" class="btn btn-primary"><i class="fa fa-plus-circle"></i></button></td>
</tr>
</tfoot>]]></add>
</operation>
</file>
<!-- ============================================================
CATALOG CONTROLLER: добавляем alt в массив images
(search по уникальной строке ProStore)
============================================================= -->
<file path="catalog/controller/product/product.php">
<operation>
<search><![CDATA['additional' => $this->model_tool_image->resize($result['image'], $this->config->get('theme_' . $this->config->get('config_theme') . '_image_additional_width'), $this->config->get('theme_' . $this->config->get('config_theme') . '_image_additional_height'))]]></search>
<add position="replace"><![CDATA['additional' => $this->model_tool_image->resize($result['image'], $this->config->get('theme_' . $this->config->get('config_theme') . '_image_additional_width'), $this->config->get('theme_' . $this->config->get('config_theme') . '_image_additional_height')),
'alt' => !empty($result['image_alt']) ? $result['image_alt'] : $product_info['name']]]></add>
</operation>
</file>
<!-- ============================================================
PROSTORE TEMPLATE: используем image.alt для доп. изображений
Главное фото ({{ thumb }}) не трогаем.
============================================================= -->
<file path="catalog/view/theme/prostore/template/product/product.twig">
<!-- 1. Миниатюры дополнительных изображений (image.thumb) -->
<operation>
<search><![CDATA[<img src="{{ image.thumb }}" alt="{{ heading_title }}" width="{{ image_thumb_width }}" height="{{ image_thumb_height }}" {% if lazyload %}loading="lazy"{% endif %} {% if zoom_ezplus %} data-zoom-{{ zoom_ezplus }} data-zoom-image="{{ image.popup }}"{% endif %}>]]></search>
<add position="replace"><![CDATA[<img src="{{ image.thumb }}" alt="{{ image.alt|default(heading_title)|e }}" width="{{ image_thumb_width }}" height="{{ image_thumb_height }}" {% if lazyload %}loading="lazy"{% endif %} {% if zoom_ezplus %} data-zoom-{{ zoom_ezplus }} data-zoom-image="{{ image.popup }}"{% endif %}>]]></add>
</operation>
<!-- 2. Большие дополнительные изображения (image.additional) -->
<operation>
<search><![CDATA[<img src="{{ image.additional }}" alt="{{ heading_title }}" width="{{ image_additional_width }}" height="{{ image_additional_height }}" {% if lazyload %}loading="lazy"{% endif %}>]]></search>
<add position="replace"><![CDATA[<img src="{{ image.additional }}" alt="{{ image.alt|default(heading_title)|e }}" width="{{ image_additional_width }}" height="{{ image_additional_height }}" {% if lazyload %}loading="lazy"{% endif %}>]]></add>
</operation>
</file>
</modification>

