SEO-шаблоны: как это устроено внутри
Почему понадобилось отдельное хранилище
Ядро хранит шаблоны SEO и кеш вычисленных значений без измерения языка. Колонки под язык там нет, и добавить её — значит расходиться с платформой навсегда.
Поэтому базовый шаблон остаётся в ядре, а переводы живут в своём highload-блоке. Ядро продолжает работать так, как работало, и ничего не знает о переводах.
Хранилище
Highload-блок MrlexndrTranslateSeo. Одна строка — один шаблон одной сущности:
| Поле | Что в нём |
|---|---|
UF_CODE |
уникальный ключ вида E.<id>.<КОД>, S.<id>.<КОД>, B.<инфоблок>.<КОД> |
UF_ENTITY, UF_ENTITY_ID |
уровень и идентификатор, для фильтра |
UF_IBLOCK_ID |
инфоблок сущности |
UF_LANG_<XX> |
перевод на целевой язык |
Коды — те же, что в ядре: ELEMENT_META_TITLE, SECTION_PAGE_TITLE,
ELEMENT_PREVIEW_PICTURE_FILE_ALT и остальные.
Колонки базового языка нет намеренно: базовый шаблон живёт в ядре, и вторая его копия немедленно начала бы расходиться с первой.
Индексы — уникальный по ключу и обычные по сущности и по инфоблоку. Без них каждое удаление элемента при обмене с 1С сканировало бы таблицу целиком.
Блок переживает удаление модуля: переводы — это контент.
Чтение
Правило одно: уровень с собственным базовым шаблоном побеждает.
По каждому коду уровень-источник определяется средствами ядра. Перевод берётся только у этого уровня. Нет перевода — берётся его базовый шаблон, а не перевод родителя.
Кеш и его сброс
Кешируются собственные переводы сущности — все языки одной строкой.
Каждая запись сбрасывает три вещи: кеш сущности, рантайм-кеш репозитория и тег кеша инфоблока. Без последнего закешированные детальные страницы показывали бы старые мета-теги. В порции перевода тег сбрасывается один раз в конце, а не на каждой записи.
Сбой чтения не кешируется и пишется в журнал. Иначе одна неудачная попытка означала бы, что переводы пропали с сайта до истечения кеша — то есть на сутки.
Чистка
При удалении элемента, раздела или инфоблока соответствующие переводы удаляются по событию.
Если событие не сработало — например, элемент удалили в обход ядра, — остаются строки, чьей сущности больше нет. Они видны отдельным блоком на вкладке «Мусорщик» экрана Обслуживание и удаляются вручную, с повторной проверкой, что сущность действительно исчезла.
Проверка идёт выборками D7: у старого API есть неявные условия, из-за которых живой перевод мог бы попасть в удаление.
Почему нет обработчика эпилога
Соблазнительно было бы подменять мета-теги в самом конце сборки страницы, одним местом на всё. Но в эпилоге нечем узнать, какая сущность на странице: компонент уже отработал и данных о себе не оставил.
Поэтому подстановка делается вызовом хелпера в шаблоне компонента — там сущность известна.
Цена на промахе кеша
Несколько запросов на сущность: цепочка шаблонов, переводы, поля для макросов.
Для детальной страницы это ничто. В списках — звать только внутри кешируемого компонента, иначе цена умножается на число элементов.