Языковые файлы Битрикс отвечают за то, чтобы текст кнопки, сообщение об ошибке или подсказка в админке подтягивались из php-массива, а не были зашиты прямо в разметку компонента. Когда беру в работу проект на 1С-Битрикс с мультиязычным фронтом или просто с кастомными компонентами, первым делом смотрю, как разложены эти файлы - по ним видно, писал компонент разработчик, который понимает архитектуру ядра, или просто скопировал .default и захардкодил текст в шаблоне.
Структура каталогов lang в компонентах и модулях
Любой компонент, шаблон или модуль в Битрикс хранит переводы в подпапке lang, а внутри неё - в папках с кодом языка: ru, en, при необходимости de, uk и так далее. Главное правило, из-за которого чаще всего путаются новички: имя языкового файла должно точно повторять имя php-файла, для которого он пишет переводы, и лежать по тому же относительному пути.
| Файл компонента | Языковой файл |
|---|---|
| component.php | lang/ru/component.php |
| class.php (для комплексных компонентов) | lang/ru/class.php |
| templates/.default/template.php | templates/.default/lang/ru/template.php |
| .description.php (описание компонента в списке) | lang/ru/.description.php |
| .parameters.php (параметры в настройках) | lang/ru/.parameters.php |
Заметьте: у шаблона своя папка lang внутри templates/имя_шаблона/, отдельная от языковых файлов самого компонента. Это разделение постоянно забывают, и потом удивляются, почему текст в шаблоне не переводится, хотя в component.php всё подключено верно.
Подключение языковых файлов: IncludeModuleLangFile и Loc::loadMessages
В старом ядре (D7 ещё не был обязателен) языковые файлы подключались через IncludeModuleLangFile(__FILE__). Функция рабочая и до сих пор встречается в legacy-компонентах, но с переходом на пространства имён Битрикс продвигает класс BitrixMainLocalizationLoc.
use BitrixMainLocalizationLoc;
Loc::loadMessages(__FILE__);
$arResult['TITLE'] = Loc::getMessage('MY_COMPONENT_TITLE');
Важный нюанс: Loc::loadMessages подгружает языковой файл, соответствующий переданному пути к файлу - не ко всей папке компонента. Если вызвать её в component.php, сообщения из lang-файла шаблона всё равно не станут доступны - там нужен свой вызов, обычно в начале template.php.
Ещё один момент, который экономит время при отладке: если языковой файл для текущего языка сайта отсутствует, ядро автоматически ищет фолбэк в lang/ru (или в языке по умолчанию, заданном в настройках). Но фолбэк работает только если сама папка ru физически существует - пустая директория без файла message-код не найдёт нигде, и вместо текста вы получите пустую строку или код сообщения на странице.
Формат сообщений и плейсхолдеры
Внутри языкового файла лежит обычный php-массив $MESS:
$MESS['CATALOG_ADD_TO_BASKET'] = 'Добавить в корзину';
$MESS['CATALOG_ITEMS_COUNT'] = 'В наличии: #COUNT# шт.';
Плейсхолдеры вида #COUNT# подставляются вторым аргументом при вызове:
echo Loc::getMessage('CATALOG_ITEMS_COUNT', ['#COUNT#' => $arItem['QUANTITY']]);
На практике держусь одного правила по именованию кодов: префикс модуля или компонента плюс смысловое имя - CATALOG_ADD_TO_BASKET, а не MESS1 или TEXT_OK. На проекте, где переводов набирается пара сотен, обезличенные коды превращаются в отдельный квест - приходится открывать файл и искать по контексту, что и где используется. С внятным неймингом это отпадает: код сообщения сам объясняет, откуда он и для чего.
Отдельно слежу за кодировкой: все языковые файлы должны быть в UTF‑8 без BOM, если сайт работает на UTF-8-ядре (актуально для всех новых проектов на D7). На старых сайтах, доставшихся в наследство, иногда встречается windows-1251 - тогда либо весь сайт живёт в этой кодировке, либо файл перекодируется перед подключением, иначе вместо кириллицы вылезут кракозябры именно в тех местах, где текст берётся из lang, а не выводится напрямую из базы.
Бесплатный материал
🎁 Полезный скрипт в подарок
Подпишитесь на Telegram - пришлю готовый скрипт по этой теме.
Без спама. Отписка в 1 клик.
Локализация шаблонов компонентов и .default
Шаблон компонента - отдельная сущность со своим набором языковых файлов, и это осознанное архитектурное решение: один и тот же компонент может использовать несколько шаблонов оформления под разные разделы сайта, и тексты в них могут отличаться (например, в шаблоне для каталога - «Все товары», а в шаблоне для акций - «Все предложения»).
При разработке кастомного шаблона на основе .default я всегда копирую не только template.php и файлы стилей, но и папку lang целиком, а потом уже правлю тексты под задачу. Пропуск этого шага - частая причина, когда кастомный шаблон выводит пустые строки там, где в .default всё работало: система ищет сообщение в lang-папке нового шаблона, а её просто нет.
Локализация внутри style.php и component_epilog.php
Эти файлы часто выпадают из внимания при аудите локализации. style.php обычно не содержит текста, а вот component_epilog.php нередко используется для вывода хлебных крошек, заголовков или meta-тегов - и туда тоже нужен отдельный Loc::loadMessages(__FILE__), если текст берётся из языкового файла, а не формируется динамически из данных инфоблока.
Мультиязычность в кастомных модулях
Если делаете собственный модуль (а не просто компонент), к языковым файлам добавляется ещё один уровень - папка install/index.php и общий lang/ru/.description.php модуля, отвечающий за то, как модуль называется в списке «Модули» в админке. Забытый файл там не вызывает ошибку - модуль просто отображается латиницей по системному имени вместо человекочитаемого названия, что выглядит небрежно при сдаче проекта заказчику.
На практике мультиязычные модули и компоненты с нуля разумно закладывать сразу на этапе проектирования, а не докручивать задним числом - переписывать хардкод текста на Loc::getMessage в уже работающем коде на боевом проекте всегда дольше, чем сделать правильно сразу. Если нужна разработка или доработка сайта на 1С-Битрикс с нормальной структурой языковых файлов и мультиязычностью из коробки, обычно проще один раз обсудить архитектуру с разработчиком, чем потом распутывать смесь захардкоженных строк и Loc::getMessage по всему проекту.
Частые ошибки при работе с языковыми файлами
- Забыли Loc::loadMessages в template.php. Компонент грузит свои сообщения, а шаблон - нет, потому что это разные вызовы для разных файлов.
- Кэш компонента хранит уже переведённый текст. Если включено кэширование компонента и вы поменяли текст в lang-файле, старый вариант может отдаваться из кэша до его очистки - на многоязычных сайтах это особенно заметно, когда кэш общий для всех языковых версий без разбивки по LANGUAGE_ID.
- Смешение $MESS и Loc::getMessage на одном проекте. Оба механизма технически совместимы, но вперемешку это усложняет поддержку - на аудите я обычно советую унифицировать на Loc::getMessage как более актуальный API.
- Отсутствующий фолбэк-язык. Если сайт мультиязычный, а перевод для нового языка не готов, лучше явно продублировать файл из lang/ru в новую папку языка, а не оставлять пустоту - иначе часть интерфейса просто исчезнет для пользователей этой языковой версии.
- BOM в начале php-файла с $MESS. Невидимый символ перед
<?phpломает вывод заголовков и может привести к ошибке headers already sent - типичная проблема при редактировании lang-файлов в неправильно настроенном редакторе.
Чтобы сайт работал без сбоев
Техподдержка
от 15 000 ₽/мес
Подробнее →Частые вопросы
Чем IncludeModuleLangFile отличается от Loc::loadMessages?
IncludeModuleLangFile - функция из старого ядра, она подключает языковой файл по прямому пути и до сих пор работает в legacy-компонентах. Loc::loadMessages - актуальный метод из пространства имён BitrixMainLocalization, он же используется во всех современных компонентах ядра. Функционально разница небольшая, но в новых проектах и кастомных компонентах стоит использовать именно Loc, потому что старая функция считается устаревшей и может быть убрана из будущих версий ядра.
Как добавить в Битрикс язык, которого нет среди стандартных ru/en?
Нужно создать языковую версию сайта в настройках (Настройки → Веб-мастеру → Языковые версии), указать её код, а затем для каждого используемого компонента и модуля создать соответствующую папку lang с этим кодом и скопировать туда файлы из lang/ru как основу для перевода. Автоматически новый язык не подтянет тексты - Битрикс просто не найдёт файлы и покажет пустые значения или фолбэк на язык по умолчанию.
Почему после правки текста в языковом файле на сайте ничего не поменялось?
Чаще всего дело в кэше компонента - очистите его через админку (Настройки → Автокэширование → сброс кэша) или удалите папку /bitrix/cache вручную. Реже причина в опечатке в коде сообщения: если код в Loc::getMessage не совпадает с ключом массива $MESS буква в букву, метод вернёт пустую строку без ошибки, и найти проблему на глаз сложно - помогает временный var_dump массива $MESS сразу после подключения файла.
Можно ли подключать языковые файлы не из стандартной папки lang?
Технически да - можно включить любой php-файл с массивом $MESS напрямую через include, минуя Loc и IncludeModuleLangFile. Но тогда теряется автоматический фолбэк на язык по умолчанию и совместимость со стандартными механизмами кэширования локализации, поэтому на практике так делают только для разовых задач вне компонентной модели, а не для полноценных модулей и шаблонов.