+7 499 938 8452 пн.-пт. 10:00 – 17:00

mrLexndr Мультиязычность: перевод сайта через GPT




Модуль переводит сайт на Битриксе: интерфейс, инфоблоки, каталог, SEO-поля и оформление заказа. Перевод хранится в базе рядом с оригиналом — в том же элементе, а не в копии сайта и не в языковых файлах. Дубли инфоблоков заводить не нужно, а править тексты может контент-менеджер.

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

Что переводится

  • Фразы интерфейса — подписи кнопок, меню, подсказки, тексты блоков вёрстки, письма. Каждая фраза заводится один раз и выводится на языке посетителя.
  • Фразы из языковых файлов — всё, что шаблоны и компоненты выводят штатным GetMessage() из lang/*.php.
  • Инфоблоки — названия, анонсы, описания, свойства и их значения, подписи свойств, разделы, торговые предложения, справочники Highload-блоков.
  • SEO — шаблоны title, description, alt и title картинок на каждом языке, с наследованием по разделам.
  • Магазин — названия товаров и свойств на витрине и в корзине, свойства заказа, типы плательщиков, названия платёжных систем и служб доставки, единицы измерения.
  • Поиск, хлебные крошки, даты — посетитель английской версии видит результаты выдачи и названия месяцев на своём языке.

Названия платёжных систем и служб доставки ядро Битрикса хранит одним текстом на все языки, поля под перевод там нет вовсе. Модуль переносит их в словарь и переводит как обычные фразы — поэтому оформление заказа на английском выглядит английским целиком, а не наполовину.

Длина текста не ограничена, форматы — тоже

  • Обычная строка — название товара, подпись кнопки. Переводится как есть.
  • HTML — описание товара, текст новости. Разметка обязана вернуться из перевода целой, а незакрытый тег чинится всегда: один такой тег разъезжает вёрстку всей страницы.
  • Блочный редактор sprint.editor. Его поле — это JSON со структурой блоков, и переводить его как текст нельзя: перевелись бы имена ключей. Модуль отдаёт такое поле отдельным форматом, переводятся только подписи, заголовки и текстовые значения. Если после перевода число узлов не совпало, запись отменяется целиком. Поддержка идёт из коробки.

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

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

Так работают проекты, где перевод делает штатный редактор или бюро: модуль даёт структуру и инструменты, а откуда взялся текст, ему безразлично. Машинный перевод включается тогда, когда руками становится долго.

Готовый сайт — без переписывания шаблонов
Сайт, собранный до модуля, выводит подписи через GetMessage('КОД'), а текст лежит в lang/ru/*.php рядом с шаблоном. Менять эти вызовы по всему дереву не нужно. Модуль один раз ищет фразы в языковых файлах отмеченных каталогов, заносит их в словарь — и дальше тот же GetMessage() на языках перевода отдаёт текст из словаря. Правка фразы в словаре меняет текст на сайте.

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

С инфоблоками то же. Название, анонс и описание элемента переводятся всегда, а свойства — по языковому суффиксу: TITLE_RU получает пару TITLE_EN. На сайте, который делали без перевода, свойства называются просто BRAND или MATERIAL. Отметьте такой инфоблок в настройках — модуль возьмёт в перевод все его текстовые и списочные свойства: BRAND получит пару BRAND_EN. Инфоблоки, где нет ни одного свойства с суффиксом, настройки называют сами.

В новом коде текст пишется прямо в шаблоне
Для нового кода есть свой вызов. Текст на базовом языке пишется вторым аргументом:

<?= LANG_VAR('SUBMIT_BTN', 'Отправить заявку') ?>

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

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

Переменные подставляются по имени, чтобы фраза оставалась целой: LANG_VAR('DAYS_LEFT', ['COUNT' => 5]) для записи «Осталось #COUNT# дней». Склейка из кусков в другом языке не переводится в принципе — там другой порядок слов.

Копий штатных компонентов в поставке нет
Модуль не подменяет компоненты Битрикса своими копиями. Он подставляет перевод в данные, которые компонент уже получил, — одной строкой в result_modifier.php шаблона:

IblockHelper::substituteStandardFields($arResult);

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

Если элементы вы выбираете сами, не нужно и строки: перевод подставляется при выборке.

Счёт за перевод предсказуем

  • Очередь запоминает, что изменилось, но сама ничего не переводит. Деньги списываются, когда вы нажимаете кнопку. Обмен с 1С на тысячи позиций поэтому не превращается в неожиданный счёт.
  • Сравнение идёт по каждому полю отдельно: поправили заголовок — в перевод уйдёт заголовок, за описание вы не платите второй раз.
  • Большой объём переводится в фоне: запустили кнопкой, закрыли вкладку, над таблицей видно, сколько переведено и как идёт текущий шаг. Пауза проверяется перед каждым платным шагом, отменить задание можно в любой момент — переведённое остаётся.
  • Если сервис не успел ответить, шаг откладывается, а не считается ошибкой: следующий шаг заберёт готовый перевод без повторного списания.
  • Галочка «Перевести заново уже переведённое» стоит в красной плашке и при запуске задаёт отдельный вопрос. Случайно оплатить повторный перевод всего каталога не получится.
  • Баланс и история платежей видны в админке, пополнение — оттуда же.

Перевод предсказуем так же, как счёт

  • Описание сайта для переводчика — несколько предложений о проекте — уходит модели перед каждым переводом. Без него слово «заявка» переводится одним из десятка способов в зависимости от соседних слов.
  • Глоссарий задаёт термины, которые модель не подбирает, а берёт у вас: [EN] О компании = About Us, Сбербанк = Sberbank.
  • Отказ модели обрабатывается сам. Иногда вместо перевода приходит «я не могу обсуждать эту тему» — срабатывает на безобидных текстах про очереди на границе или таможенные ограничения. Модуль делает три попытки подряд: обычный перевод, повтор со строгой формулировкой, машинный переводчик Яндекса. Поля, которые перевела машина, попадают в отдельный список — глоссарий к ним не применялся, и их стоит просмотреть.
  • Сверка находит испорченные переводы — потерянную ссылку, незакрытый тег, оборванный текст. Обычная проверка их не замечает никогда: оригинал не менялся, значит с её точки зрения всё переведено. А на странице при этом может не быть половины текста.
  • Правка руками сильнее машины. Перевод, сохранённый человеком, очередь машинным не заменит, пока не изменится оригинал.

Как с этим работает контент-менеджер

  • Переключите язык админки и откройте карточку товара: поля показывают перевод, сохранение записывает перевод, оригинал остаётся нетронутым. Сверху жёлтая плашка, чтобы не перепутать, в каком режиме вы находитесь.
  • Фразы, выведенные через LANG_VAR(), правятся прямо на странице сайта: клик по фразе открывает маленький редактор, результат сразу виден в вёрстке. Длину текста видно только там — фраза, которая в списке выглядит нормальной, на кнопке не помещается.
  • Словарь выгружается в CSV и заливается обратно. Можно отдать переводчику один язык и залить только его: остальные колонки не затрутся.

Переведённые страницы индексируются
Поисковый робот получает готовую HTML-страницу с переведённым текстом. Ничего не подменяется скриптом на лету и не накладывается поверх оригинала.

Шаблоны title и description переводятся на каждом языке отдельно, поэтому языковые версии не конкурируют между собой в выдаче. Макросы {=this.name} и {=this.property.CODE} подставляют переведённые значения; если модель потеряла макрос при переводе, шаблон не записывается вовсе. Разметка hreflang и файл sitemap настраиваются штатными средствами Битрикса.

Безопасность: что уходит с вашего сервера
Единственный внешний адрес во всём модуле — api.mrlexndr.com. Модуль обращается к нему в трёх случаях: когда вы переводите, когда открываете экран с балансом и когда пополняете счёт. С публичных страниц сайта запросов к сервису нет.

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

Ключей Яндекса и Google на сайте заводить не нужно: сайт узнаётся по хешу лицензии Битрикса, ключи живут на стороне сервиса — красть из настроек модуля нечего. Адрес сервиса сверяется со списком разрешённых хостов, так что подменить его настройкой и увести хеш лицензии на чужой сервер нельзя.

Всё, что меняет данные, идёт методом POST с проверкой токена сессии и права на запись. Перевод в фоне проверяет права того, кто его запустил, а не выполняется от имени системы. Служебные консольные скрипты в поставку не входят.

Переводы остаются вашими
Удаление модуля идёт мастером с подтверждением. Переводы не удаляются ни при какой настройке: словарь и таблица состояния остаются на месте. Это контент, а не служебные данные, и восстановить его неоткуда — вернёте модуль, переводить заново и платить второй раз не придётся. Галочка на первом шаге мастера, включённая по умолчанию, отвечает за другое: за настройки модуля — список языков, глоссарий, описание сайта и выбранный движок.

Хранятся переводы в штатных объектах Битрикса, а не в собственном формате: языковые свойства элементов (NAME_EN, PREVIEW_TEXT_EN), пользовательские поля разделов, highload-блок со словарём. Прочитать их обычным API Битрикса можно и без установленного модуля.

Языковые файлы шаблонов модуль не трогает, поэтому GetMessage() после удаления просто вернётся к текстам из них. В коде проекта от модуля остаются только вызовы LANG_VAR() и IblockHelper в шаблонах. Убрать их — значит вернуться к исходным русским значениям; сайт при этом продолжит работать. Если такая привязка смущает заранее, заведите свою функцию-обёртку: тогда имя модуля будет знать один файл проекта, и этому в документации посвящена отдельная страница.

Для разработчика

  • Публичный интерфейс — LANG_VAR(), Lang::get() и IblockHelper. Для случаев, когда код фразы приходит из данных, а не из шаблона, есть Lang::peek() — чтение без автосоздания, чтобы не мусорить в словаре.
  • Около двадцати пяти обработчиков событий. Экран «Проверка стенда» одной кнопкой прогоняет проверки — обработчики на месте, схема базы в порядке, настройки не противоречат друг другу — и показывает паспорт установки: версии модуля, PHP и СУБД, каталог, из которого загружен модуль, доступные модули Битрикса, языки перевода, запуск агентов по расписанию. Отсутствие обработчика снаружи не видно: очередь просто перестаёт наполняться, и ошибки при этом нет.
  • Кастомный компонент от штатного ничем не отличается: перевод подставляется в тот массив с элементами, который компонент уже собрал.
  • Документация — отдельный раздел на сайте разработчика: от первой установки до внутреннего устройства SEO-хранилища и полного списка сообщений модуля.

Требования

  • PHP 8.2 или новее. Требование жёсткое: часть классов модуля объявлена readonly-классами, а такой конструкции до 8.2 не было.
  • Модули Битрикса: главный и Highload-блоки; для перевода инфоблоков — «Информационные блоки», для магазина — «Интернет-магазин».
  • Для перевода фраз из языковых файлов через GetMessage() — главный модуль версии 23.0.0 или новее. На более старом ядре модуль ставится и работает, не включается только этот перехват.
  • Исходящий HTTPS до сервиса перевода. Без сети словарь и подстановка переводов на витрине работают, не работает только машинный перевод.

Чего модуль не делает

  • Языковые версии сайта делаются языками Битрикса. Если на сайте они устроены иначе — папками или доменами без привязки языка, — модуль будет отдавать один и тот же язык везде.
  • Готовые решения Аспро модуль сейчас не поддерживает. Мультиязычность у Аспро штатно строится на многосайтовости, а шаблон решения лежит в /bitrix/templates/ и перезаписывается его обновлением — строка в result_modifier.php там не проживёт до следующего обновления. Если у вас Аспро, напишите до покупки.
  • Из языковых файлов не забирается текст, вписанный в шаблон напрямую, без GetMessage(), и фразы JavaScript (BX.message). Правка прямо на странице сайта работает только для фраз LANG_VAR().
  • Движки перевода: Google Gemini и Яндекс. DeepL нет.
  • Перевод заново уже переведённого заменяет и поправленные руками тексты; прежние не сохраняются, откатить можно только из бэкапа.

Сколько это стоит
Машинный перевод оплачивается отдельно, с баланса, по фактическому расходу: квоты покупать не нужно, минимального пополнения нет. Сайт на тысячу товаров переводится на один язык через Google Gemini от 500 рублей.

Баланс пополняется картой прямо из интерфейса модуля. Нужен счёт — напишите, выставим.

Перед покупкой
Проведём демонстрацию: покажем работу модуля на живом стенде и ответим на вопросы по вашему проекту. Напишите, о чём идёт речь, и договоримся о времени.

Модуль переводит сайт на Битриксе: интерфейс, инфоблоки, каталог, SEO-поля и оформление заказа. Перевод хранится в базе рядом с оригиналом — в том же элементе, а не в копии сайта и не в языковых файлах. Дубли инфоблоков заводить не нужно, а править тексты может контент-менеджер.

Что переводится

  • Фразы интерфейса — подписи кнопок, меню, подсказки, тексты блоков вёрстки, письма. Каждая фраза заводится один раз и выводится на языке посетителя.
  • Инфоблоки — названия, анонсы, описания, свойства и их значения, подписи свойств, разделы, торговые предложения, справочники Highload-блоков.
  • SEO — шаблоны title, description, alt и title картинок на каждом языке, с наследованием по разделам.
  • Магазин — названия товаров и свойств на витрине и в корзине, свойства заказа, типы плательщиков, названия платёжных систем и служб доставки, единицы измерения.
  • Поиск, хлебные крошки, даты — посетитель английской версии видит результаты выдачи и названия месяцев на своём языке.

Названия платёжных систем и служб доставки ядро Битрикса хранит одним текстом на все языки, поля под перевод там нет вовсе. Модуль переносит их в словарь и переводит как обычные фразы — поэтому оформление заказа на английском выглядит английским целиком, а не наполовину.

Длина текста не ограничена, форматы — тоже
Модуль различает три случая и ведёт себя в каждом по-своему.

  • Обычная строка — название товара, подпись кнопки, короткое поле. Переводится как есть.
  • HTML — описание товара, текст новости. Разметка обязана вернуться из перевода целой, а незакрытый тег чинится всегда, независимо от настроек: один такой тег разъезжает вёрстку всей страницы.
  • Конструкторы страниц. Поле sprint.editor — это JSON со структурой блоков, и переводить его как текст нельзя: перевелись бы имена ключей и служебные значения. Модуль отдаёт такое поле отдельным форматом, переводятся только подписи, заголовки и текстовые значения. Если после перевода число узлов не совпало, запись отменяется целиком. Поддержка идёт из коробки, настраивать ничего не нужно.

Предельной длины у переводимого текста нет: статья на сорок тысяч знаков уходит целиком, а не режется на куски. Размер порции влияет только на то, сколько элементов поедет одним запросом.

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

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

Так работают проекты, где перевод делает штатный редактор или бюро: модуль даёт структуру и инструменты, а откуда взялся текст, ему безразлично. Машинный перевод включается тогда, когда руками становится долго.

Разработчик пишет текст прямо в коде
Выносить фразы в языковые файлы заранее не нужно. Текст на базовом языке пишется прямо в шаблоне, вторым аргументом:

<?= LANG_VAR('SUBMIT_BTN', 'Отправить заявку') ?>

При первом показе страницы фраза заводится в словаре сама, с этим самым текстом. Поля остальных языков остаются пустыми — это честное состояние «перевода ещё нет», и ровно такие поля подбирает автоперевод.

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

Переменные подставляются по имени, чтобы фраза оставалась целой: LANG_VAR('DAYS_LEFT', ['COUNT' => 5]) для записи «Осталось #COUNT# дней». Склейка вида LANG_VAR('LEFT') . $n . LANG_VAR('DAYS') не переводится в принципе — в других языках другой порядок слов, — а целую фразу переводчик видит целиком. Один и тот же код, встреченный на странице дважды, даёт одно обращение к базе, а не два.

Проект уже живёт на языковых файлах Битрикса? Модуль забирает их разом: просматривает /local/templates, /local/components и /local/php_interface, собирает все $MESS и заводит в словаре записи для тех кодов, которых там ещё нет. Существующие коды пропускаются, ничего не перетирается. Старые языковые файлы при этом можно не удалять: пока шаблон зовёт $MESS, он читает их, — так что переезд делается постепенно, а не одним рискованным заходом.

Копий штатных компонентов в поставке нет
Модуль не подменяет компоненты Битрикса своими копиями. Он подставляет перевод в данные, которые компонент уже получил, — одной строкой в result_modifier.php шаблона:

IblockHelper::substituteStandardFields($arResult);

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

Если элементы вы выбираете сами, не нужно и строки: перевод подставляется при выборке.

Счёт за перевод предсказуем

  • Очередь запоминает, что изменилось, но сама ничего не переводит. Деньги списываются в момент, когда вы нажимаете кнопку. Обмен с 1С на тысячи позиций поэтому не превращается в неожиданный счёт.
  • Сравнение идёт по каждому полю отдельно: поправили заголовок — в перевод уйдёт заголовок, за описание вы не платите второй раз.
  • Кнопка «Остановить» проверяется перед каждым платным шагом. Останавливается и фоновое задание, и прогон из браузера, даже если вкладку уже закрыли. После этого перевод продолжается с того же места.
  • Баланс и история операций видны в админке, пополнение — оттуда же.

Перевод предсказуем так же, как счёт

  • Контекст проекта — несколько предложений о сайте — уходит модели перед каждым переводом. Без него слово «заявка» переводится одним из десятка способов в зависимости от соседних слов.
  • Глоссарий задаёт термины, которые модель не подбирает, а берёт у вас: [EN] О компании = About Us, Сбербанк = Sberbank.
  • Отказ модели обрабатывается сам. Иногда вместо перевода приходит «я не могу обсуждать эту тему» — срабатывает на безобидных текстах про очереди на границе или таможенные ограничения. Модуль делает три попытки подряд: обычный перевод, повтор со строгой формулировкой, машинный переводчик Яндекса. Поля, которые перевела машина, попадают в отдельный список — глоссарий к ним не применялся, и их стоит просмотреть.
  • Сверка находит испорченные переводы — потерянную ссылку, незакрытый тег, оборванный текст. Обычная проверка их не замечает никогда: оригинал не менялся, значит с её точки зрения всё переведено. А на странице при этом может не быть половины текста.
  • Правка руками сильнее машины. Перевод, сохранённый человеком, очередь машинным не заменит.

Как с этим работает контент-менеджер

  • Переключите язык админки и откройте карточку товара: поля показывают перевод, сохранение записывает перевод, оригинал остаётся нетронутым. Сверху жёлтая плашка, чтобы вы не перепутали, в каком режиме находитесь.
  • Фразы интерфейса правятся прямо на странице сайта: клик по фразе открывает маленький редактор, результат сразу виден в вёрстке. Длину текста видно только там — фраза, которая в списке записей выглядит нормальной, на кнопке не помещается, а в узкой колонке разваливает сетку.
  • Словарь выгружается в CSV и заливается обратно. Можно выгрузить все языки, отдать переводчику один и залить только его: остальные колонки не затрутся.

Переведённые страницы индексируются
Поисковый робот получает готовую HTML-страницу с переведённым текстом. Ничего не подменяется скриптом на лету и не накладывается поверх оригинала.

Шаблоны title и description переводятся на каждом языке отдельно, поэтому языковые версии не конкурируют между собой в выдаче. Макросы {=this.name} и {=this.property.CODE} подставляют переведённые значения; если модель потеряла макрос при переводе, шаблон не записывается вовсе. Разметка hreflang и файл sitemap настраиваются штатными средствами Битрикса.

Безопасность: что уходит с вашего сервера
Единственный внешний адрес во всём модуле — api.mrlexndr.com. В запросе: строки на перевод, языки, формат, выбранный движок, глоссарий, контекст проекта и домен сайта.

Телеметрии в модуле нет. Данные посетителей, статистика посещений, сведения об установке и содержимое сайта помимо переводимых строк наружу не передаются. Пока вы не запустили перевод, модуль не обращается никуда вовсе.

Ключей Яндекса и Google на сайте заводить не нужно: сайт узнаётся по хешу лицензии Битрикса, а ключи живут на стороне сервиса — красть из настроек модуля нечего. Всё, что меняет данные, идёт методом POST с проверкой токена сессии и права на запись: ссылка, которая что-то меняет, однажды окажется в чужом письме. Служебные консольные скрипты в поставку не входят вовсе.

Переводы остаются вашими
Удаление модуля идёт мастером из двух шагов. Переводы не удаляются ни при какой настройке: словарь и таблица состояния остаются на месте. Это контент, а не служебные данные, и восстановить его неоткуда — вернёте модуль, переводить заново и платить второй раз не придётся. Галочка на первом шаге мастера, включённая по умолчанию, отвечает за другое: за настройки модуля — список языков, глоссарий, контекст и выбранный движок.

Хранятся переводы в штатных объектах Битрикса, а не в собственном формате: языковые свойства элементов (NAME_EN, PREVIEW_TEXT_EN), пользовательские поля разделов, highload-блок со словарём. Прочитать их обычным API Битрикса можно и без установленного модуля.

В коде проекта от модуля остаются вызовы LANG_VAR() и IblockHelper в шаблонах. Убрать их — значит вернуться к исходным русским значениям; сайт при этом продолжит работать. Если такая привязка смущает заранее, заведите свою функцию-обёртку: тогда имя модуля будет знать один файл проекта, и этому в документации посвящена отдельная страница.

Для разработчика

  • Публичный интерфейс — LANG_VAR(), Lang::get() и IblockHelper. Спрятать модуль за своей обёрткой, чтобы код проекта не знал его имени, — штатный сценарий, ему посвящена отдельная страница документации.
  • Есть и чтение без автосоздания — Lang::peek(), для случаев, когда код фразы приходит из данных, а не из шаблона, и мусорить в словаре не нужно.
  • Около двадцати пяти обработчиков событий. Экран «Проверка стенда» показывает, все ли они на месте, и отдаёт паспорт установки: версия модуля, версия PHP, из какого каталога он загружен, какие модули доступны, какие языки целевые, включён ли запуск агентов по расписанию. Отсутствие обработчика снаружи не видно — очередь просто перестаёт наполняться, и ошибки при этом нет.
  • Кастомный компонент от штатного ничем не отличается: перевод подставляется в тот массив с элементами, который компонент уже собрал.
  • Документация — отдельный раздел на сайте разработчика, от первой установки до внутреннего устройства SEO-хранилища и списка всех сообщений модуля.

Требования

  • PHP 8.2 или новее. Требование жёсткое и не декларативное: часть классов модуля объявлена readonly-классами, а такой конструкции до 8.2 не было.
  • Модули Битрикса: главный и Highload-блоки; для перевода инфоблоков — «Информационные блоки», для магазина — «Интернет-магазин».
  • Исходящий HTTPS до сервиса перевода. Без сети словарь и подстановка переводов на витрине работают, не работает только машинный перевод.

Чего модуль не делает

  • Языковые версии сайта делаются языками Битрикса. Если на сайте они устроены иначе — папками или доменами без привязки языка, — модуль будет отдавать один и тот же язык везде.
  • Движки перевода: Яндекс и Google Gemini. DeepL нет.
  • В шаблон штатного компонента добавляется строка вызова. Готовых рецептов под коммерческие сборки вроде Аспро в документации нет: принцип от шаблона не зависит, а точное место вставки зависит от того шаблона, который у вас реально подключён.
  • Включённая перезапись существующих переводов необратима — восстанавливать придётся из бэкапа.

Сколько это стоит
Модуль — 99 990 рублей. Машинный перевод оплачивается отдельно, с баланса, по фактическому расходу: квоты покупать не нужно, минимального пополнения нет. Сайт на тысячу товаров переводится на один язык через Google Gemini от 500 рублей.

Баланс пополняется картой прямо из интерфейса модуля. Нужен счёт — напишите, выставим.

Перед покупкой
Проведём демонстрацию: покажем работу модуля на живом стенде и ответим на вопросы по вашему проекту. Напишите, о чём идёт речь, и договоримся о времени.

Модуль переводит сайт на Битриксе: интерфейс, инфоблоки, каталог, SEO-поля и оформление заказа. Перевод хранится в базе рядом с оригиналом — в том же элементе, а не в копии сайта и не в языковых файлах. Дубли инфоблоков заводить не нужно, а править тексты может контент-менеджер.

Что переводится

  • Фразы интерфейса — подписи кнопок, меню, подсказки, тексты блоков вёрстки, письма. Каждая фраза заводится один раз и выводится на языке посетителя.
  • Инфоблоки — названия, анонсы, описания, свойства и их значения, подписи свойств, разделы, торговые предложения, справочники Highload-блоков.
  • SEO — шаблоны title, description, alt и title картинок на каждом языке, с наследованием по разделам.
  • Магазин — названия товаров и свойств на витрине и в корзине, свойства заказа, типы плательщиков, названия платёжных систем и служб доставки, единицы измерения.
  • Поиск, хлебные крошки, даты — посетитель английской версии видит результаты выдачи и названия месяцев на своём языке.

Названия платёжных систем и служб доставки ядро Битрикса хранит одним текстом на все языки, поля под перевод там нет вовсе. Модуль переносит их в словарь и переводит как обычные фразы — поэтому оформление заказа на английском выглядит английским целиком, а не наполовину.

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

Так работают проекты, где перевод делает штатный редактор или бюро: модуль даёт структуру и инструменты, а откуда взялся текст, ему безразлично. Машинный перевод включается тогда, когда руками становится долго.

Разработчик пишет текст прямо в коде
Выносить фразы в языковые файлы заранее не нужно. Текст на базовом языке пишется прямо в шаблоне, вторым аргументом:

<?= LANG_VAR('SUBMIT_BTN', 'Отправить заявку') ?>

При первом показе страницы фраза заводится в словаре сама, с этим самым текстом. Поля остальных языков остаются пустыми — это честное состояние «перевода ещё нет», и ровно такие поля подбирает автоперевод.

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

Переменные подставляются по имени, чтобы фраза оставалась целой: LANG_VAR('DAYS_LEFT', ['COUNT' => 5]) для записи «Осталось #COUNT# дней». Склейка вида LANG_VAR('LEFT') . $n . LANG_VAR('DAYS') не переводится в принципе — в других языках другой порядок слов, — а целую фразу переводчик видит целиком. Один и тот же код, встреченный на странице дважды, даёт одно обращение к базе, а не два.

Копий штатных компонентов в поставке нет
Модуль не подменяет компоненты Битрикса своими копиями. Он подставляет перевод в данные, которые компонент уже получил, — одной строкой в result_modifier.php шаблона:

IblockHelper::substituteStandardFields($arResult);

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

Если элементы вы выбираете сами, не нужно и строки: перевод подставляется при выборке.

Счёт за перевод предсказуем

  • Очередь запоминает, что изменилось, но сама ничего не переводит. Деньги списываются в момент, когда вы нажимаете кнопку. Обмен с 1С на тысячи позиций поэтому не превращается в неожиданный счёт.
  • Сравнение идёт по каждому полю отдельно: поправили заголовок — в перевод уйдёт заголовок, за описание вы не платите второй раз.
  • Кнопка «Остановить» проверяется перед каждым платным шагом. Останавливается и фоновое задание, и прогон из браузера, даже если вкладку уже закрыли. После этого перевод продолжается с того же места.
  • Баланс и история операций видны в админке, пополнение — оттуда же.

Перевод предсказуем так же, как счёт

  • Контекст проекта — несколько предложений о сайте — уходит модели перед каждым переводом. Без него слово «заявка» переводится одним из десятка способов в зависимости от соседних слов.
  • Глоссарий задаёт термины, которые модель не подбирает, а берёт у вас: [EN] О компании = About Us, Сбербанк = Sberbank.
  • Отказ модели обрабатывается сам. Иногда вместо перевода приходит «я не могу обсуждать эту тему» — срабатывает на безобидных текстах про очереди на границе или таможенные ограничения. Модуль делает три попытки подряд: обычный перевод, повтор со строгой формулировкой, машинный переводчик Яндекса. Поля, которые перевела машина, попадают в отдельный список — глоссарий к ним не применялся, и их стоит просмотреть.
  • Сверка находит испорченные переводы — потерянную ссылку, незакрытый тег, оборванный текст. Обычная проверка их не замечает никогда: оригинал не менялся, значит с её точки зрения всё переведено. А на странице при этом может не быть половины текста.
  • Правка руками сильнее машины. Перевод, сохранённый человеком, очередь машинным не заменит.

Как с этим работает контент-менеджер

  • Переключите язык админки и откройте карточку товара: поля показывают перевод, сохранение записывает перевод, оригинал остаётся нетронутым. Сверху жёлтая плашка, чтобы вы не перепутали, в каком режиме находитесь.
  • Фразы интерфейса правятся прямо на странице сайта: клик по фразе открывает маленький редактор, результат сразу виден в вёрстке. Длину текста видно только там — фраза, которая в списке записей выглядит нормальной, на кнопке не помещается, а в узкой колонке разваливает сетку.
  • Словарь выгружается в CSV и заливается обратно. Можно выгрузить все языки, отдать переводчику один и залить только его: остальные колонки не затрутся.

Переведённые страницы индексируются
Поисковый робот получает готовую HTML-страницу с переведённым текстом. Ничего не подменяется скриптом на лету и не накладывается поверх оригинала.

Шаблоны title и description переводятся на каждом языке отдельно, поэтому языковые версии не конкурируют между собой в выдаче. Макросы {=this.name} и {=this.property.CODE} подставляют переведённые значения; если модель потеряла макрос при переводе, шаблон не записывается вовсе. Разметка hreflang и файл sitemap настраиваются штатными средствами Битрикса.

Что уходит с вашего сервера
Единственный внешний адрес во всём модуле — api.mrlexndr.com. В запросе уходят тексты на перевод, языки, формат, выбранный движок, глоссарий, контекст проекта и домен сайта. Данные посетителей, статистика посещений и содержимое сайта помимо переводимых строк наружу не передаются.

Ключей Яндекса и Google на сайте заводить не нужно: сайт узнаётся по хешу лицензии Битрикса. Всё, что меняет данные, идёт методом POST с проверкой токена сессии и права на запись. Служебные консольные скрипты в поставку не входят.

Для разработчика

  • Публичный интерфейс — LANG_VAR(), Lang::get() и IblockHelper. Спрятать модуль за своей обёрткой, чтобы код проекта не знал его имени, — штатный сценарий, ему посвящена отдельная страница документации.
  • Есть и чтение без автосоздания — Lang::peek(), для случаев, когда код фразы приходит из данных, а не из шаблона, и мусорить в словаре не нужно.
  • Около двадцати пяти обработчиков событий. Экран «Проверка стенда» показывает, все ли они на месте, и отдаёт паспорт установки: версия модуля, версия PHP, из какого каталога он загружен, какие модули доступны, какие языки целевые, включён ли запуск агентов по расписанию. Отсутствие обработчика снаружи не видно — очередь просто перестаёт наполняться, и ошибки при этом нет.
  • Кастомный компонент от штатного ничем не отличается: перевод подставляется в тот массив с элементами, который компонент уже собрал.
  • Документация — отдельный раздел на сайте разработчика, от первой установки до внутреннего устройства SEO-хранилища и списка всех сообщений модуля.

Требования

[LIST]
  • PHP 8.2 или новее. Требование жёсткое и не декларативное: часть классов модуля объявлена readonly-классами, а такой конструкции до 8.2 не было.
  • Модули Би


  • Каталог для ИИ