Сделать мультиязычные поля в админке Opencart 3
Есть в админке Opencart 3, в настройках Магазина поле "Режим работы". Мне понадобилось сделать это поле мультиязычным. Решил сделать по примеру других страниц.
Файл admin\view\template\setting\setting.twig. Нахожу код этого поля
<div class="form-group">
<label class="col-sm-2 control-label" for="input-open"><span data-toggle="tooltip" data-container="#tab-general" title="{{ help_open }}"> {{ entry_open }}</span></label>
<div class="col-sm-10">
<textarea name="config_open" rows="5" placeholder="{{ entry_open }}" id="input-open" class="form-control">{{ config_open }}</textarea>
</div>
</div>
Добавляю к нему {% for language in languages %}, картинки флажков, и ID языка. Получается так:
{% for language in languages %}
<div class="form-group">
<label class="col-sm-2 control-label" for="input-open{{ language.language_id }}"><img src="language/{{ language.code }}/{{ language.code }}.png" title="{{ language.name }}" /><span data-toggle="tooltip" data-container="#tab-general" title="{{ help_open }}"> {{ entry_open }}</span></label>
<div class="col-sm-10">
<textarea name="config_open{{ language.language_id }}" rows="5" placeholder="{{ entry_open }}" id="input-open{{ language.language_id }}" class="form-control">{{ config_open }}</textarea>
</div>
</div>
{% endfor %}
В админке появилось два поля под каждый язык. Но когда ввожу в него данные и сохраняю, после сохранения информация в этих полях пропадает.

Сравниваю с другими мультиязычными полями и в шаблоне и в контроллере все одинаково. Не вижу разницы, между моим творением и стандартными мультиязычными полями. Но раз не работает, значит что-то упускаю. Подскажите пожалуйста что именно.
ОБНОВЛЕНИЕ
Поменял textarea на input, теперь сохраняется, но не выводится во фронт энд.
<input type="text" name="config_open[{{ language.language_id }}][title]" placeholder="{{ entry_open }}" id="input-open{{ language.language_id }}" value="{{ config_open[language.language_id] ? config_open[language.language_id].title }}" class="form-control" />
В контроллере фронт энда вывожу так. Пока был один язык, все выводилось
$data['open'] = nl2br($this->config->get('config_open'));
В итоге дает такую ошибку: Warning: nl2br() expects parameter 1 to be string, array given in /var/www/fastuser/data/www/localstite.loc/storage/modification/catalog/controller/common/header.php on line 81
Ответы (2 шт):
<textarea name="config_open[{{ language.language_id }}]" rows="5" placeholder="{{ entry_open }}" id="input-open{{ language.language_id }}" class="form-control">
{{ config_open[language.language_id] }} // [title] не нужен, это лишняя вложенность
</textarea>
Значение любого поля группы настроек в opencart с префиксом config_ в имени сохраняется в таблице setting с типом text. Это логично, т.к. все настройки это по сути строки. Иногда туда записываются массивы, для чего в классе модели ModelSettingSetting (admin/model/setting.php) предусмотрена логика сериализации данных.
Когда вы привели textarea config_open к виду поля с локализацией, в модель, при сохранении, в $this->request->post['config_open'] стал прилетать массив, в котором ключи - id языков, значения - контент config_open
Далее, при выборке этих данных в контроллере фронта, вы предсказуемо стали получать не строку, как раньше, а десериализованный массив.
Поле config_open в админке имеет тип textarea, что подразумерает возможность сохранять строку с переносами, которые при сохранении переводятся в сивмолы (\n\r) В данной строчке nl2br($this->config->get('config_open')); в контроллере фронта применяется функция nl2br, преобразующая сивмолы переноса строки в html (<br/>) и на вход она ожидает строку, но получает массив, о чём php прямо и сообщает:
Warning: nl2br() expects parameter 1 to be string, array given in /var/www/fastuser/data/www/localstite.loc/storage/modification/catalog/controller/common/header.php on line 81
Соответственно, необходимо менять логику получения/обработки настройки, получаемой через $this->config->get('config_open')
$data['open'] = nl2br($this->config->get('config_open')[$this->config->get('config_language_id')]);
Вопрос решен. Помогли на другой площадке. Вот, что нужно было сделать. Сначала в файле контролера админки отредактировать код вывода этой переменной и добавить языковую переменную.
Вместо этого
if (isset($this->request->post['config_open'])) {
$data['config_open'] = $this->request->post['config_open'];
} else {
$data['config_open'] = $this->config->get('config_open');
}
Пишем это
$this->load->model('localisation/language');
$languages = $this->model_localisation_language->getLanguages();
foreach ($languages as $language) {
if (isset($this->request->post['config_open' . $language['language_id']])) {
$data['config_open'][$language['language_id']] = $this->request->post['config_open' . $language['language_id']];
} else {
$data['config_open'][$language['language_id']] = $this->config->get('config_open' . $language['language_id']);
}
}
Потом в шаблоне админки вместо этого
<div class="form-group">
<label class="col-sm-2 control-label" for="input-open"><span data-toggle="tooltip" data-container="#tab-general" title="{{ help_open }}"> {{ entry_open }}</span></label>
<div class="col-sm-10">
<textarea name="config_open" rows="5" placeholder="{{ entry_open }}" id="input-open" class="form-control">{{ config_open }}</textarea>
</div>
</div>
Пишем это
{% for language in languages %}
<div class="form-group">
<label class="col-sm-2 control-label" for="input-open{{ language.language_id }}"><img src="language/{{ language.code }}/{{ language.code }}.png" title="{{ language.name }}" /><span data-toggle="tooltip" data-container="#tab-general" title="{{ help_open }}"> {{ entry_open }}</span></label>
<div class="col-sm-10">
<input type="text" name="config_open{{ language.language_id }}" placeholder="{{ entry_open }}" id="input-open{{ language.language_id }}" value="{% if config_open[language.language_id] %}{{ config_open[language.language_id] }}{% endif %}" class="form-control" />
</div>
</div>
{% endfor %}
В контролере фронт энда выводим это так
$data['open'] = nl2br($this->config->get('config_open' . $this->config->get('config_language_id')));