Разработка SEO оптимизированных высокопроизводительных фронтенд приложений на базе 1С-Битрикс.

Мультиязычный контент сайта с общей таблицей переводов

Артем Житник

Артем Житник

Несмотря на появление все большего количества стен между странами и регионами в разных сферах жизни, мы все еще живем в глобальном мире. А раз так было бы неплохо иметь версии сайта на нескольких языках. Даже если интернет фрагментируется на отдельные сегменты, набор языков может поменяться, но необходимость работы в этом направлении останется.

Стандартный подход Битрикса

Битрикс хорошо справляется с многоязычностью статических языковых фраз, типа подписей в шаблонах компонентов, на бекэнде, в javascript на клиентской части. Это идет из коробки и работает. С переводом контента дело обстоит сложнее. Официальная документация предлагает два подхода:

  • Делать отдельные наборы инфоблоков для каждого языка. То есть, например есть новости news_ru, новости news_en. Тема рабочая, я сталкивался с таким приемом, походит для вариантов где русские новости могут сильно отличаться от английских и набором, можно в них публиковать абсолютно разные темы. А можно копировать одинаковые, но тогда появляется сложность с отслеживанием синхронности инфоблоков. Нужны дополнительные обработчики, чтобы например при создании новости на русском - создавалась копия на английском. То же самое при изменении. Тема рабочая, если есть автоперевод, я делал с яндес api.
  • Инфоблок для разных языков остается тот же самый, переводы вводятся в свойства типа "MY_PROPERTY_RU", "MY_PROPERTY_EN". Тоже есть минусы, как переводить поля элемента инфоблбока (NAME, PREVIEW_TEXT и т.д.)? Тоже через свойства? Во многих стандартных компонентах, экспортах подтягивается NAME, а для английской версии что делать? Нужно придумывать какие-то костыли.

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

Реализация общей таблицы переводов

Суть какая, храним все языковые фразы в единой таблице - там и новости, и имена пользователей, и товары. Все что требует перевода. Определяется главный язык, у меня - русский. Каждая запись включает в себя:

  • Уникальный код - хеш. Считается из русской версии, я просто делаю md5, в hex формате беру начальные несколько символов, этого достаточно.
  • Оригинальная фраза, на русском.
  • Перевод на английский.
  • Время последнего обращение к фразе.
  • Галочка "Требуется перевод" (ниже объясню зачем)
Сайт при этом, все инфоблоки, остаются в русской версии, в неизменном виде. Контент редактируется как обычно. Простейший сценарий - нужно перевести страницу, берем русскую фразу, считаем для нее хеш, ищем в таблице переводов по хешу перевод - подменяем фразу. План классный, но есть нюансы.

Плейсхолдеры для языковых фраз

Хотелось бы конечно не делать множество запросов к базе данных для каждой фразы, а получить их все за один раз. Для этого нужно определить хеши всех фраз, выбрать для них переводы и вставить их в места где они используются на странице. Сделал специальную функцию генерации кода плейсхолдера типа #TR_<HASH>#, потом в событии main OnEndBufferContent все плейсхолдеры заменяются на переводы.

Если перевода еще нет, создается запись в таблице переводов с пустой английской версией. В моей логике на странице в этом случае выводится оригинальная русская фраза. А когда перевод появится - выведется он.

Какие фразы нужно запрашивать в таблице переводов для страницы

Там же в OnEndBufferContent через regexp находим все плейсхолдеры, из них вынимаем хеши, по ним ищем переводы для последующей замены плейслолдеров.

Есть еще подход при котором для каждой страницы создается реестр фраз для перевода который заполняется при получении плейсхолдеров и мгновенных запросов перевода. Для компонентов свой собирается свой реестр в result_modifier.php, передается в component_epilog.php (по стандартному механизму, не буду расписывать подробно), где уже этот массив включается в общий реестре языковых фраз страницы.

Прямой запрос перевода

Бывают случаи, когда нет возможности ждать срабатывания OnEndBufferContent, а нужно получить перевод прямо на месте. Например у меня для DETAIL_TEXT в блоге делаются ряд преобразований - добавление ссылок п каталожным кодам в тексте, добавление дополнительных функций картинкам в тексте (ленивая загрузка, превью по клику) и т.д. Сделал отдельный метод - получи мгновенный перевод по языковой фразе, а не отложенный с плейсхолдерами.

Засорение таблицы

При работе с контентом, мы часто меняем оригинальную фразу, соответственно хеш для нее меняется тоже - создается новая запись для перевода. При этом старю запись я не удаляю, потому что прошлая русская версия может где-то использоваться в другом инфоблоке. Но при такой логике таблица может расти бесконечно при частых изменениях. Поэтому каждый раз при запросе переводов происходит обновление времени запроса в соответствующих записях. И затем через специальный агент очистки можно по какой-то логике удалять древние фразы, например дата обращения к которым более 2 месяцев.

Также возник вопрос сброса перевода при изменении русской версии в некоторых местах типа блога. Где бывает необходимо отредактировать детальный текст, хеш меняется и пишется новый пустой перевод. Для таких случаев я сделал копирование старого перевода через событие OnIBlockElementUpdate. То есть новая запись для перевода создается, но с копией старого перевода и с галочкой "Требуется перевод".

Работа переводчика

Переводчик заходит в таблицу переводов в админке - это обычный highloadblock, где может отфильтровать список по галочке "Требуется перевод", отсортировать по дате обращения (чтобы править последние, а не брошенные копии). Далее остается заполнить соответствующие английские версии.

Расширение, модернизация, выводы

Как видно в этом способе тоже есть минусы с засорением таблицы переводов. Также не очень удобно бывает редактировать все в куче, не зная контекста, к какой сущности относится фраза. Например было бы удобно иметь возможность видеть все переводы на странице редактирования поста блога, например в отдельном табе. Видеть и их тут же редактировать. Это решается добавлением кастомного таба, битрикс это умеет.

Есть и несомненные плюсы. Возможность достаточно простого добавления новых языков. Нужно добавить только новую колонку в таблицу переводов. Также плюс в том что практически не трогается структура существующего контента на оригинальном языке. Получается что по сути сайт на русском языке работает как раньше. При запросе плейсхолдера - он поулчает сразу оригинальную фразу без необходимости обращения к языковой таблице. Да, кое-какой код нужно в компонентах внедрить, в основном в result_modifier.php и component_epilog.php, но это меньшее из зол, как мне кажется.

Если нужно быстро развернуть или расширить мультиязычность, это хороший вариант. Можно также добавить автоперевод, который будет например через агент пробегаться по таблице переводов, искать требующие перевод и через api это делать, в том же Яндекс переводчике.

    битрикс
    перевод
    мультиязычность

©2026 ReactiveBx работает на «1С-Битрикс: Управление сайтом» и Next.js