Информационные блоки в режиме мультиязычности
Модуль modulemarket.translator дополняет стандартную модель Информационных блоков в 1С-Битрикс отдельными таблицами переводов.
Для одной и той же сущности (тип инфоблока, раздел или элемент) в базе хранится несколько строк — по одной на сочетание языка и сайта.
Идентификатор сущности в переводе совпадает с ID записи в штатной ORM-таблице ядра.
Принцип работы — перевод не подменяет строку в b_iblock, b_iblock_section или b_iblock_element, а хранится рядом:
при запросе на нужном языке вы читаете из таблицы перевода и при необходимости объединяете данные с основной записью.
Три уровня данных
| ORM-класс модуля | Таблица переводов | Сущность | Связь с ядром |
|---|---|---|---|
| Modulemarket\Translator\Iblock\IblockTable | fan_translator_iblock |
Тип инфоблока (имя, описание, активность) | Карта полей на основе Bitrix\Iblock\IblockTable |
| Modulemarket\Translator\Iblock\SectionTable | fan_translator_iblock_section |
Раздел инфоблока | Связь SECTION → Bitrix\Iblock\SectionTable |
| Modulemarket\Translator\Iblock\ElementTable | fan_translator_iblock_element |
Элемент инфоблока | Связь ELEMENT → Bitrix\Iblock\ElementTable |
Составной ключ и контекст
Во всех трёх таблицах первичный ключ составной:
ID (ссылка на сущность ядра) + LANGUAGE_ID (два символа) + SITE_ID (два символа).
Поля LANGUAGE_ID и SITE_ID в описании полей имеют значения по умолчанию из констант окружения;
в коде выборок и записей надёжнее передавать язык и сайт явно в filter или в массиве полей при add/update.
Примечание — подробные примеры по каждому классу см. в дочерних страницах раздела: IblockTable, SectionTable, ElementTable.
Общий порядок работы в коде
-
Подключить модули:
Loader::includeModule('iblock')иLoader::includeModule('modulemarket.translator'). -
Знать
IDинфоблока, раздела или элемента в основной таблице ядра — он жеIDв строке перевода. -
Читать перевод:
getList()с фильтром'=ID','=LANGUAGE_ID','=SITE_ID'и нужнымselect. -
Создавать или менять перевод:
add()/update()по первичному ключу; проверятьResult::isSuccess(). -
Для ElementTable можно использовать статический метод
translated($id, $languageId), чтобы проверить наличие перевода без разбора выборки.
События и служебная логика
У классов SectionTable и ElementTable обработчики onBeforeAdd и onBeforeUpdate подставляют TIMESTAMP_X,
если это поле не передано в сохраняемых данных.
У класса IblockTable метод UseForcedUpdates($iblockId) позволяет определить режим принудительных обновлений по константе вида FORCE_TRANSLATE_IB_ID_*
(подробности — на странице IblockTable).
Важно! Набор полей в каждой таблице перевода ограничен методом getTranslatableFields() соответствующего класса —
не каждая колонка основной ORM-карты попадает в перевод. Перед массовой синхронизацией сверяйте список полей в документации к классу.
Типовой фрагмент (чтение перевода элемента)
use Bitrix\Main\Loader;
use Modulemarket\Translator\Iblock\ElementTable;
Loader::includeModule('iblock');
Loader::includeModule('modulemarket.translator');
$row = ElementTable::getRow([
'filter' => [
'=ID' => $elementId,
'=LANGUAGE_ID' => $lang,
'=SITE_ID' => $site,
],
]);Ссылки по теме
Документация 1С-Битрикс: Bitrix\Iblock\IblockTable
Документация 1С-Битрикс: Bitrix\Iblock\SectionTable
Документация 1С-Битрикс: Bitrix\Iblock\ElementTable
Кратко: зачем три разных класса
Тип инфоблока, раздел и элемент — разные сущности с разными наборами полей и разными таблицами в ядре. Модуль держит для каждого уровня свою таблицу перевода и свой DataManager, чтобы ORM-мапы и валидаторы соответствовали исходным таблицам Информационных блоков.