Экстраполя в Cotonti: полное руководство по созданию и локализации значений
Введение
Cotonti — мощная и гибкая CMS с открытым кодом, которая позволяет расширять функциональность практически безгранично благодаря системе «экстраполей» (extra fields). Экстраполя — это пользовательские поля, которые можно добавлять к любым таблицам базы данных: пользователям, страницам, продуктам, комментариям и т.д. Это позволяет хранить дополнительную информацию без необходимости править структуру таблиц или писать сложные запросы.
Однако одного лишь добавления поля недостаточно. Для создания удобного интерфейса и поддержки многоязычности необходимо правильно организовать локализацию как названий полей, так и их значений (например, для выпадающих списков или радиокнопок). В этой статье мы подробно разберём, как устроены экстраполя в Cotonti, как их создавать и, самое главное, как правильно переводить значения, чтобы ваш сайт был понятен пользователям на любом языке.
Теоретическая часть: архитектура и API экстраполей
1. Таблица cot_extra_fields
Все настройки экстраполей хранятся в централизованной таблице cot_extra_fields. Основные поля этой таблицы:
field_location — имя целевой таблицы (например, cot_users, cot_pages, cot_market).field_name — уникальное имя поля (только латиница, без пробелов).field_type — тип поля (input, textarea, select, radio, checkbox, datetime, country, file, checklistbox, range, currency, double и др.).field_html — HTML-шаблон для отображения поля (можно оставить пустым, используется шаблон по умолчанию).field_variants — варианты значений для select, radio, checklistbox (через запятую).field_params — дополнительные параметры (диапазон для range, допустимые расширения для file, формат даты и т.п.).field_default — значение по умолчанию.field_required — обязательно ли поле (0/1).field_enabled — активно ли поле (0/1).field_parse — тип парсинга содержимого (HTML, Text, и т.д.).field_description — краткое описание (для администратора).
Экстраполя кешируются, поэтому после изменений в таблице необходимо сбрасывать кеш (обычно это происходит автоматически при редактировании через админку).
2. API-функции для работы с экстраполями
Cotonti предоставляет набор функций для удобного создания, импорта, отображения и обработки экстраполей.
2.1. Добавление поля
function cot_extrafield_add($location, $name, $type, $html = '', $variants = '', $default = '', $required = false,
$parse='HTML', $description='', $params = '', $enabled = 1, $noalter = false, $customtype = '')
Эта функция добавляет запись в cot_extra_fields и, если $noalter = false, создаёт соответствующую колонку в целевой таблице.
Пример применения “под капотом” (в код залазить не нужно):
cot_extrafield_add('cot_market', 'product_status', 'select',
'', 'unknown,instock,outofstock,ending,onorder', 'unknown', 0,
'HTML', 'Статус наличия', '', 1);
2.2. Построение HTML-элемента
cot_build_extrafields($name, $extrafield, $data) — возвращает готовый HTML-код поля (input, select и т.д.) для использования в формах.
2.3. Импорт данных из формы
cot_import_extrafields($inputname, $extrafield, $source = 'P', $oldvalue = '', $titlePrefix = '') — обрабатывает входящие данные, применяет валидацию, проверяет обязательность, а для файлов выполняет загрузку.
2.4. Формирование значения для вывода
cot_build_extrafields_data($name, $extrafield, $value, $parser = '') — подготавливает значение поля к отображению на сайте. Для типов select, radio, checklistbox эта функция автоматически пытается найти перевод значения в языковом массиве.
2.5. Получение заголовка поля
cot_extrafield_title($extrafield, $titlePrefix = '') — возвращает локализованное название поля, проверяя ключи $L['location_name_title'], $L['name_title'] и field_description.
3. Типы полей и их особенности
Рассмотрим основные типы экстраполей:
- input — обычное текстовое поле.
- inputint — целое число.
- currency, double — числа с плавающей точкой.
- textarea — многострочное поле.
- select — выпадающий список.
- radio — группа радиокнопок.
- checkbox — один флажок.
- datetime — выбор даты и времени.
- country — список стран.
- file — загрузка файла.
- checklistbox — группа флажков (множественный выбор).
- range — выбор числа из диапазона.
Для каждого типа в API предусмотрены соответствующие методы построения и валидации.
Локализация значений экстраполей
1. Принцип локализации в Cotonti
В Cotonti языковые строки хранятся в глобальном массиве $L. Они могут быть определены в файлах модулей, темы или в общих языковых файлах. Для экстраполей используется следующее соглашение:
- Заголовок поля:
$L['location_name_title'] или $L['name_title']. Если ни один из ключей не найден, используется field_description. - Значения select/radio/checklistbox:
$L['name_value'], где name — имя поля, value — конкретное значение из field_variants.
Например, для поля product_status со значениями instock, outofstock нужно определить строки:
php
$L['product_status_instock'] = 'В наличии';
$L['product_status_outofstock'] = 'Нет в наличии';
Именно такой формат ожидает функция cot_build_extrafields_data при выводе значения.
2. Где размещать языковые строки
Языковые файлы могут находиться в разных местах, и приоритет загрузки влияет на то, какие строки будут использоваться. Обычно рекомендуется размещать переводы для экстраполей в языковом файле модуля, к которому поле относится. Например, для модуля «market» — в modules/market/lang/ru/ru.market.lang.php.
Если вы используете экстраполя в кастомной разработке и не хотите править ядро или модули, можно добавить строки в языковой файл темы: themes/ваша_тема/ваша_тема.ru.lang.php. Этот файл загружается позже и может переопределить строки модуля.
Важно помнить: если язык темы не определён, Cotonti загружает язык по умолчанию (обычно английский).
3. Практический пример: поле «Статус товара»
Предположим, мы создали экстраполе product_status типа select для таблицы cot_market. В таблице cot_extra_fields это поле настроено так:
field_name = product_statusfield_type = selectfield_variants = unknown,instock,outofstock,ending,onorderfield_default = unknownfield_description = Статус наличия товара
Для корректного отображения на русском языке в языковом файле нужно определить строки:
php
$L['product_status_unknown'] = 'Не указано';
$L['product_status_instock'] = 'В наличии';
$L['product_status_outofstock'] = 'Нет в наличии';
$L['product_status_ending'] = 'Заканчивается';
$L['product_status_onorder'] = 'Под заказ';
В шаблоне страницы товара используется тег {MARKET_PRODUCT_STATUS}. При его генерации Cotonti вызывает cot_build_extrafields_data, которая видит тип select, проверяет наличие $L['product_status_'. $value] и подставляет перевод. Если перевода нет, выводится исходное значение (например, «instock»).
Также доступен тег {MARKET_PRODUCT_STATUS_TITLE}, который выводит локализованный заголовок поля. Он формируется функцией cot_extrafield_title и может быть переопределён через $L['market_product_status_title'] или $L['product_status_title'].
4. Локализация для других типов полей
- radio — аналогично select.
- checklistbox — значения хранятся в виде строки, разделённой запятыми. При выводе каждое значение переводится отдельно, затем склеивается (по умолчанию через запятую, но можно изменить через
field_params). - country — встроенный перевод названий стран из
$cot_countries. - checkbox — для отображения обычно используется 0/1, но можно задать переводы через
$L['fieldname_checked'] и $L['fieldname_unchecked'] вручную в шаблоне.
5. Префиксы в ключах
Иногда бывает удобно добавить префикс к ключам локализации, чтобы избежать конфликтов. Например, в модуле «market» можно использовать $L['market_product_status_instock']. Для этого при импорте данных используется параметр $titlePrefix функции cot_import_extrafields. При выводе заголовка cot_extrafield_title проверит ключи с префиксом, а при выводе значения — нет. Значения всегда ищутся по шаблону $L['fieldname_value'] без префикса.
Поэтому если вы хотите локализовать значения с префиксом, вам всё равно придётся определить ключи без префикса, либо модифицировать функцию вывода (не рекомендуется).
Практическая часть: создание и локализация шаг за шагом
Рассмотрим полный цикл создания экстраполя для модуля «market» и его локализацию.
Шаг 1. Создание экстраполя
Через административную панель (Модули → Экстраполя) добавим новое поле:
- Таблица:
cot_market - Имя поля:
product_status - Тип:
select - Варианты:
unknown,instock,outofstock,ending,onorder - По умолчанию:
unknown - Обязательное: нет
- Описание:
Статус наличия товара - Включено: да
После сохранения Cotonti автоматически создаст колонку fieldmrkt_product_status в таблице cot_market.
Шаг 2. Добавление языковых строк
Открываем языковой файл модуля market: modules/market/lang/ru/ru.market.lang.php. Добавляем строки:
php
$L['product_status_unknown'] = 'Не указано';
$L['product_status_instock'] = 'В наличии';
$L['product_status_outofstock'] = 'Нет в наличии';
$L['product_status_ending'] = 'Заканчивается';
$L['product_status_onorder'] = 'Под заказ';
// Если хотим локализовать заголовок поля (иначе будет использовано описание):
$L['market_product_status_title'] = 'Статус наличия';
Если модуль market не имеет своего языкового файла, можно добавить эти строки в глобальный языковой файл (lang/ru/ru.lang.php) или в языковой файл темы.
Шаг 3. Использование в шаблоне
В шаблоне страницы товара (например, market.tpl) выводим статус:
html
<!-- IF {MARKET_PRODUCT_STATUS} -->
<div class="product-status">
<span class="label">{MARKET_PRODUCT_STATUS_TITLE}:</span>
<span class="value">{MARKET_PRODUCT_STATUS}</span>
</div>
<!-- ENDIF -->
Если в базе данных для товара указано outofstock, на странице отобразится:
Статус наличия: Нет в наличии
Локализация названия или заголовка экстрполей
Для перевода заголовка поля (тег {MARKET_PRODUCT_STATUS_TITLE}) используются языковые переменные с двумя возможными форматами:
- С префиксом расположения (таблицы):
$L['market_product_status_title'] — где market — это суффикс таблицы (обычно часть имени таблицы после cot_). - Без префикса:
$L['product_status_title'].
Если определён первый вариант, используется он, иначе проверяется второй. Если ни один не найден, подставляется значение из поля field_description в таблице cot_extra_fields.
Примеры для разных языков
Русский (ru):
php
$L['market_product_status_title'] = 'Статус наличия';
// или
$L['product_status_title'] = 'Статус наличия';
Английский (en):
php
$L['market_product_status_title'] = 'Availability status';
// или
$L['product_status_title'] = 'Availability status';
Польский (pl):
php
$L['market_product_status_title'] = 'Stan dostępności';
// или
$L['product_status_title'] = 'Stan dostępności';
Украинский (uk):
php
$L['market_product_status_title'] = 'Статус наявності';
// или
$L['product_status_title'] = 'Статус наявності';
Где размещать
Эти строки следует добавить в языковой файл модуля (например, modules/market/lang/ru/ru.market.lang.php) или в языковой файл вашей темы (themes/ваша_тема/ваша_тема.ru.lang.php). После добавления не забудьте сбросить кеш
Шаг 4. Проверка и сброс кеша
После добавления языковых строк необходимо сбросить кеш языка и кеш экстраполей. В админке Cotonti есть соответствующие кнопки в разделе «Кеш». Либо можно удалить временные файлы вручную.
Шаг 5. Пример для английской версии
Аналогично создаём файл en.market.lang.php:
php
$L['product_status_unknown'] = 'Unknown';
$L['product_status_instock'] = 'In stock';
$L['product_status_outofstock'] = 'Out of stock';
$L['product_status_ending'] = 'Ending soon';
$L['product_status_onorder'] = 'On order';
$L['market_product_status_title'] = 'Availability status';
При переключении языка сайта значения будут автоматически заменяться на английские.
Шаг 6. Обработка множественного выбора (checklistbox)
Если тип поля — checklistbox, значения в базе хранятся как строка "instock,ending". При выводе cot_build_extrafields_data разобьёт строку на массив, переведёт каждый элемент по ключу product_status_instock и т.д., затем объединит обратно с разделителем, указанным в field_params (по умолчанию запятая).
Расширенные возможности и подводные камни
1. Использование field_params для тонкой настройки
Параметр field_params может содержать дополнительные инструкции для конкретного типа поля. Например:
- Для
datetime можно указать min,max,format (например, 2000,2030,d.m.Y H:i). - Для
file — путь к папке загрузки (по умолчанию datas/files/extra). - Для
range — минимальное и максимальное значение через запятую. - Для
checklistbox — разделитель при выводе (например, |).
2. Приоритет загрузки языковых файлов
Языковые файлы загружаются в следующем порядке (на примере русского языка):
lang/ru/main.ru.lang.phpmodules/*/lang/ru/ru.*.lang.phpplugins/*/lang/ru/ru.*.lang.phpthemes/тема/тема.ru.lang.php
Каждый следующий файл может переопределить строки из предыдущих. Поэтому если вы хотите изменить перевод какого-то экстраполя, проще всего сделать это в языковом файле темы.
3. Регистр ключей
Ключи локализации чувствительны к регистру. Общее правило — использовать только нижний регистр для имени поля и значений. Например, если в field_variants указано InStock, ключ должен быть product_status_instock (все буквы строчные). В большинстве случаев Cotonti автоматически приводит значение к нижнему регистру при поиске перевода, но для надёжности лучше придерживаться единого стиля.
4. Кэширование экстраполей
Данные из таблицы cot_extra_fields кэшируются. Если вы вносите изменения напрямую в БД (минуя админку), не забудьте сбросить кеш через Cot::$cache->db->remove('cot_extrafields', 'system'). Иначе новые поля могут не появиться, а старые — не исчезнуть.
5. Совместимость с разными версиями
В Cotonti Siena (0.9.x) и более новых ветках API экстраполей практически идентичен. Различия могут быть в именах некоторых глобальных переменных (например, $cot_extrafields вместо $cot_extrafields), но в целом код из статьи должен работать в любой современной версии.
6. Частые ошибки
Если использовать ключи вида $L['market_product_status_instock'], ожидая, что они сработают для поля product_status - то стоит понимать, что функция cot_build_extrafields_data не учитывает префикс модуля при переводе значений. Она ищет именно $L['product_status_instock']. Поэтому правильные ключи — без префикса market_.
Также стоит проверить, что языковой файл загружается (то есть имеет правильное имя и расположение) и что кеш сброшен. Если после исправления всё равно не работает, можно временно вывести $L для отладки или посмотреть в коде, что возвращает cot_build_extrafields_data.
Заключение
Экстраполя в Cotonti — мощный инструмент для создания гибких и многофункциональных сайтов. Правильная локализация значений полей делает интерфейс дружественным для пользователей из разных стран. Ключевой момент — соблюдение соглашения об именовании языковых переменных: $L['fieldname_value'].
В этой статье мы рассмотрели:
- архитектуру экстраполей и их API;
- способы локализации заголовков и значений;
- практические примеры создания поля «Статус товара»;
- типичные ошибки и пути их решения.
Применяя эти знания, вы сможете легко добавлять новые поля к любому модулю и обеспечивать их корректный перевод на все языки вашего проекта. Помните о кэшировании, приоритетах языковых файлов и всегда тестируйте изменения.