Forum categories

Проблема: Некорректная работа переключателя языка в админ-панели Cotonti при использовании плагина i18n и ЧПУ

Сайт на Cotonti, если установлен плагин i18n (многоязычность) и включены Handy URLs (ЧПУ) с префиксами языка, то при попытке сменить язык интерфейса внутри административной панели генерируются неправильные ссылки и получаем ошибку 404.

Привет , ты много пропустил
webitproff
Telegram for messages
@webitproff
webitproff • 2026-04-19 18:32 #1

Суть проблемы 

Если на сайте Cotonti установлен плагин i18n (многоязычность) и включены Handy URLs (ЧПУ) с префиксами языка, то при попытке сменить язык интерфейса внутри административной панели генерируются неправильные ссылки. Вместо корректного URL вида:

https://cotonti.local/admin/page

формируется ошибочный адрес:

https://cotonti.local/en/page?m=page 

вместо нужного

https://cotonti.local/en/admin/page 

В результате браузер переходит на несуществующую страницу, и пользователь видит ошибку 404 – Страница не найдена.

Почему так происходит

Плагин i18n в файле i18n.header.tags.php при построении ссылок для языкового селектора использует универсальную функцию cot_url(), передавая ей в качестве первого аргумента значение $i18n_ext. Для админ-панели эта переменная получает значение 'admin', но вызов cot_url('admin', $params) с сырыми GET-параметрами (например, m=other&p=extentionname) не даёт правильного пути с учётом настроек ЧПУ. Роутер строит URL так, будто это обычная фронтовая страница, что приводит к неверной структуре ссылки.

Решение

Необходимо явно обрабатывать случай админ-панели и принудительно формировать ссылку через cot_url('admin', $params), сохраняя все актуальные GET-параметры текущего запроса. При этом для фронтенда логика остаётся прежней.

Файл, который нужно изменить:
/plugins/i18n/i18n.header.tags.php

Инструкция по исправлению:

  1. Откройте файл /plugins/i18n/i18n.header.tags.php в текстовом редакторе.
  2. Найдите в цикле foreach ($i18n_locales as $lc => $lc_title) блок, где формируется переменная $i18n_ext и удаляется rwr.
  3. Добавьте перед присвоением значения в шаблон проверку на COT_ADMIN и сохраните результат в переменную $url.
  4. Замените строку 'I18N_LANG_ROW_URL' => cot_url($i18n_ext, $i18n_urlparams, '', false, true) на 'I18N_LANG_ROW_URL' => $url.

Готовый исправленный фрагмент файла:

 

<?php
/* ====================
[BEGIN_COT_EXT]
Hooks=header.tags
Tags=header.tpl:{I18N_LANG_ROW_URL},{I18N_LANG_ROW_CODE},{I18N_LANG_ROW_TITLE},{I18N_LANG_ROW_CLASS},{I18N_LANG_ROW_SELECTED}
[END_COT_EXT]
==================== */

/**
 * Renders language selector
 *
 * @package I18n
 * @copyright (c) Cotonti Team
 * @license https://github.com/Cotonti/Cotonti/blob/master/License.txt
 */

defined('COT_CODE') or die('Wrong URL');

if (count($i18n_locales) > 0) {
    foreach ($i18n_locales as $lc => $lc_title) {
        if ($lc === $i18n_locale) {
            $lc_class = 'selected';
            $lc_selected = 'selected="selected"';
        } else {
            $lc_class = '';
            $lc_selected = '';
        }

        $i18n_urlparams = $_GET;

        // Управление параметром языка в URL
        if ($cfg['plugin']['i18n']['omitmain'] 
            && $lc === $i18n_fallback 
            && (!$cfg['plugin']['i18n']['cookie'] || !cot_import('i18n_locale', 'COOKIE', 'ALP'))
        ) {
            unset($i18n_urlparams['l']);
        } else {
            $i18n_urlparams['l'] = $lc;
        }

        // Определение расширения для роутинга
        if (defined('COT_PLUG')) {
            $i18n_ext = 'plug';
        } else {
            $i18n_ext = $env['ext'];
            unset($i18n_urlparams['e']);
        }

        if (isset($i18n_urlparams['rwr'])) {
            unset($i18n_urlparams['rwr']);
        }

        // === ИСПРАВЛЕНИЕ ДЛЯ АДМИН-ПАНЕЛИ ===
        // При смене языка в админ-панели строим URL с префиксом /admin/
        // Пример: https://cotonti.local/en/admin/page вместо ошибочного https://cotonti.local/en/page?m=page
        if (defined('COT_ADMIN') && COT_ADMIN) {
            $url = cot_url('admin', $i18n_urlparams, '', false, true);
        } else {
            // старый I18N_LANG_ROW_URL из $t->assign переносим сюда в else самого условия if (defined('COT_ADMIN') && COT_ADMIN) {
            // 'I18N_LANG_ROW_URL' => cot_url($i18n_ext, $i18n_urlparams, '', false, true),
            $url = cot_url($i18n_ext, $i18n_urlparams, '', false, true);
        }

        $t->assign([
            'I18N_LANG_ROW_URL'      => $url,
            'I18N_LANG_ROW_CODE'     => $lc,
            'I18N_LANG_ROW_FLAG'     => $lc === 'en' ? 'gb' : $lc,
            'I18N_LANG_ROW_TITLE'    => htmlspecialchars($lc_title),
            'I18N_LANG_ROW_CLASS'    => $lc_class,
            'I18N_LANG_ROW_SELECTED' => $lc_selected,
        ]);

        $t->parse('HEADER.I18N_LANG.I18N_LANG_ROW');
    }

    $t->parse('HEADER.I18N_LANG');
}

 

ВАЖНОЕ Примечание!!!!!!!!!

Данное исправление не затрагивает работу языкового селектора на пользовательской части сайта. Ветка else сохраняет оригинальное поведение для фронтенда. Проблема возникает исключительно в административной области из-за особенностей роутинга.

Если у вас используется другая версия плагина i18n или индивидуальная тема с кастомным языковым переключателем, принцип решения аналогичен: нужно обеспечить правильную генерацию URL для административного раздела через проверку COT_ADMIN.

Совместимость: Cotonti Siena 0.9.26 и выше, плагин i18n (стандартный).
Дата: 2026-Apr-19

после обновления всё слетит! я не в команде разработчиков Cotonti, - пишите им, если хотите чтоб записали рефакторинг под капот в ядро!

This post was edited by webitproff (2026-04-20 14:42, 4 months ago)
2/2/0

🗿

🧙‍♂️ Well met, good traveler! Fate has guided your steps to our humble realm. Here, wise sages and masters of the coding craft ⚒️📜 gather to unravel the mysteries of the code ✨⚙️, share their knowledge, and add new chapters to our chronicles.
⬅️ To the left lie ancient scrolls 📚 filled with forgotten wisdom. ⬆️ Straight ahead, friendly folk offer counsel 💬 to those in need. ➡️ To the right, you may become a chronicler ✍️ yourself, sharing your craft and leaving words of wisdom for those yet to come.
📝 Delay no longer—tell us the name by which you are known, complete the rite of registration 🛡️, and join our fellowship!
🏰 Our brotherhood holds no secret initiation, yet many halls remain closed to wandering guests, for some knowledge 💎 is reserved for those who choose to walk this path beside us.

Recommended Products in This Topic

Admin Panel Theme "CotCP" (Cotonti Control Panel)

The minimalistic CMF Cotonti Siena v.0.9.26 control panel theme, based on Bootstrap 5.3.6, supports Themes and Templates for Cotonti

The Newest Ukrainian language pack for Cotonti

This package delivers a fully Ukrainian interface for the standard “out-of-the-box” CMF/CMS Cotonti Cotonti Engine

Cotonti CMF: Plugin Installation, Integration, and Adaptation

professional services for the installation, deep integration and adaptation of plug-ins for Cotonti Support and Services Cotonti