Выборка с учётом языка

Два пути в зависимости от того, как вы получаете элементы.

D7: подстановка на уровне запроса

use mrLexndr\Translate\IblockHelper;

$fields = ['NAME', 'CODE', 'PREVIEW_TEXT', 'DETAIL_TEXT', 'DETAIL_PAGE_URL',
           'PREVIEW_PICTURE', 'COLOR', 'TITLE'];

$select = IblockHelper::prepareD7Select($iblockId, $fields);

$entity = IblockHelper::getEntityDataClass($iblockId);
if ($entity === null) {
    // У инфоблока не задан символьный код API — этот путь недоступен.
    return;
}

$rows = $entity::getList([
    'select' => $select,
    'filter' => ['IBLOCK_ID' => $iblockId, 'ACTIVE' => 'Y'],
    'order'  => ['ID' => 'DESC'],
    'limit'  => 20,
])->fetchAll();

$rows = IblockHelper::processD7Result($rows);

В $rows поле NAME уже содержит перевод, если он есть.

Именно сущность инфоблоков 2.0, а не общая таблица элементов: prepareD7Select() обращается к свойствам через связи, а такие поля есть только у сгенерированных классов. Если у инфоблока не задан символьный код API, сущности нет — используйте второй путь.

Как это устроено: поля, имена которых совпадают со стандартными, кладутся в выборку под псевдонимом и очищаются на разборе результата. Файловые поля и даты проходят как есть. Если свойства с суффиксом языка нет, ищется свойство без суффикса, потом стандартное поле.

Старый API: подстановка в готовый массив

$arItem = $obElement->GetNext(true, false);
IblockHelper::substituteStandardFields($arItem);

Для раздела:

IblockHelper::substituteSectionFields($arSection);

Этот путь работает всегда и не зависит от настроек инфоблока. Им же пользуются штатные компоненты — см. Штатные компоненты.

Правило про запросы в цикле

Подстановка в цикле — нормально. Запрос в базу в цикле — нет.

Хелперы рассчитаны на то, что данные у вас уже на руках. Если для подстановки приходится идти в базу за каждым элементом, значит выборка построена неправильно, и лечится это выборкой, а не переводом.

На базовом языке ничего не происходит

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

Служебные методы фасада

Кроме подстановки, на фасаде есть методы, которые обычно не нужны, но встречаются в чужом коде и в примерах. Коротко, что каждый делает.

Метод Что делает
getSuffix() суффикс языка, который дописывается к имени свойства
isDefaultLang() текущий язык базовый? На нём вся подстановка — пустая операция
extractProps() вытаскивает свойства из массива элемента в плоский вид
getActiveIblocksGrouped() список активных инфоблоков по типам, для экранов выбора
getTranslationMap() карта пар «свойство — его языковой близнец» для инфоблока
getSectionTranslationMap() то же для полей разделов
getHlTranslationMap() то же для полей справочника
clearTranslationMapCache() сбросить эти карты после правки структуры
getEnumLookup() карта вариантов свойства-списка
enumXmlKey() ключ варианта списка, по которому ищется пара на другом языке

Карты кешируются: они строятся из структуры инфоблока, а она меняется редко. Поэтому после синхронизации свойств кеш сбрасывается — иначе новые языковые свойства не появились бы в подстановке до истечения кеша.

Два последних метода нужны там, где значения списков переносятся не текстом, а по совпадению внешнего кода варианта. См. Названия и подсказки свойств.