Постановка задачи

Весной 2020-го года мы получили заказ на разработку мультиязычного b2b интернет-магазина для крупного бренда. Целевая аудитория: несколько тысяч дилеров из России, Европы и США. У всех наших проектов есть изюминка, из-за которой пришли именно к нам. Этот проект выделялся хранением данных: товары (картинки, описания, переводы) в postgre, цены и остатки — в нетиповой конфигурации 1С.

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

Архитектура

От postgre и нетиповой 1С избавиться на первом этапе не представляется возможным, в первые годы жизни сайта они точно останутся. Но нужно предусмотреть копирование всех данных из postgre в сайт на Битриксе (который на mysql), чтобы в дальнейшем безболезненно отказаться от старой базы.

Как хранятся товары

В БД postgre хранится вся информация о товарах: название, описание, свойства, фотографии (каждый текст, каждый файл в 10-ти вариантах: на популярных европейских языках). 

БД postgre устроена иначе, чем любимая Битриксом mysql (речь про допустимое количество колонок в таблице). Сделать копию данных 1 к 1 на новом сайте не получилось, пришлось трансформировать (почти транспонировать) данные.

Было

Article

NAME_EN

NAME_FR

NAME_IT

Еще ~100 колонок

150

Binoculars Praktica 10x25 WA

Jumelles Praktica 10x25 WA

Binocolo Praktica 10x25 WA

...

151

Discovery Sky Trip ST80 Telescope

Discovery Sky Trip ST80 Télescope

Discovery Sky Trip ST80 Telescopio

...

Стало

Article

LANG

NAME

Еще ~10 колонок

150

EN

Binoculars Praktica 10x25 WA

...

150

FR

Jumelles Praktica 10x25 WA

...

150

IT

Binocolo Praktica 10x25 WA

...

151

EN

Discovery Sky Trip ST80 Telescope

...

151

FR

Discovery Sky Trip ST80 Télescope

...

151

IT

Discovery Sky Trip ST80 Telescopio

...

Так как структура всех подобных таблиц в postgre была идентичной, удалось сделать единый механизм импорта с простыми настройками: из какой таблицы postgre взять данные, в какой Hl-блок сложить и сопоставить поля. Так мы смогли синхронизировать 24 таблицы.

Как хранятся цены

У заказчика сложная система ценообразования: для основных стран Европы есть до 4-х цен, как с НДС, так и без. Всего насчитывается 57 типов цен и все они используются, каждая для своей группы клиентов. Каждый дилер покупает товар по одной из этих цен. По какой именно — решает менеджер и фиксирует в 1С, в зависимости от страны дилера и его объема закупок.

Как данные попадают на сайт

Для 2-ух источников данных (postgre, 1C) разработали 2 с половиной механизма обмена.

  1. Каждый день по расписанию сайт «ходит» в postgre по SQL-соединению и синхронизирует данные в своих HL-блоках

  2. По расписанию 1С присылает на сайт через REST API данные каталога, дилеров, склады (пореже), цены и остатки (почаще). При этом сразу создаются неактивные товары без фото, без описания и свойств, так как в 1С этого нет.

  3. Постоянно работающий агент на сайте следит за товарами. Он их “обогащает” переводами, фотографиями, свойствами из HL-блоков и “включает”.

Преимущества такого подхода:

  1. База переводов в понятном виде хранится на сайте в стандартном табличном интерфейсе HL-блоков. Когда понадобится — сделаем более удобный интерфейс и отключим postgre.

  2. 1С “знает” что происходит на сайте. Запросы к REST API сайта синхронные, завершаются ответом, что было успешно импортировано, а что нет.

  3. Сразу после выгрузки на сайте создается “скелет” каталога — настоящие разделы и “пустые” товары (без фото, текстов — только служебные названия, цены и остатки).

  4. В течение нескольких минут у каждого “пустого” товара заполняются поля на нужном языке, товар “включается” и его уже можно покупать. Проблем с кешем это не создает, так как такие изменения происходят редко и массово.

Как организована мультиязычность

Мы выбрали “хитрый” способ: копипаст с автоматизацией. У товаров в базе заказчика всегда есть перевод хотя бы на английский, и если нужного языка нет — берем его. Когда проблему замечает контент-менеджер, то исправляет в postgre, и данные постепенно мигрируют в публичный каталог, чтобы новый перевод начал радовать глаз иностранного посетителя.

Много было споров по поводу архитектуры каталога — очень хотелось сделать 1 каталог, и все к этому шло. Проблему с языковыми версиями можно было бы решить, напрямую используя для вывода HL-блоки с переводами. Это бы создало предсказуемые проблемы с поиском и генерацией фидов, которые мы знали, как решать.

Но для разных стран заказчику, по соображениям маркетинга, нужны были разные деревья разделов, разный их состав и даже разная сортировка! Так что на свет появилось такое соответствие: 1 язык -> 1 сайт (в терминах Битрикса) -> 1 каталог товаров с SKU.

А где же результат увидеть?

После 2-ой итерации в конце 2020-го, когда техническая сторона была готова, решили все таки сделать собственный дизайн для сайта. Следующая остановка была летом 2021-го года, тогда мы начали тестирование на реальных дилерах.

Этот проект отлично демонстрирует, какие задачи мы можем и хотим решать: веб-интеграцию любых систем с 1С и сайтом. Продолжение в следующей статье.

Автор: Анатолий Ерофеев.

Комментарии (5)


  1. AnnaVera
    19.11.2021 11:10

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


    1. stepan_ovchinnikov Автор
      19.11.2021 11:12

      вы верно задаете вопрос

      тут масса вопросов помимо БД. есть еще организационные сложности

      да, копирование полей и таблиц это денормализация, но это по факту оказывается наименьшим злом при реальной разработке

      в моей старой статье 14 года все вопросы, в том числе структуры БД, рассмотрены
      почитайте -- давайте обсудим https://www.intervolga.ru/blog/projects/bitrix-multylanguage-site/


  1. SbWereWolf
    22.11.2021 18:22

    Для переводов очевидно использовать json, нет ? Или mysql не умеет json колонки ?

    Или переводы на каждый язык это всё равно отдельная запись HL-блока ?

    Второе забавное. На колонку можно навешать своё правило сортировки (например считать что "е" и "ё" равны, или считать, что "е" меньше "ё"). В postgre, я думаю так и сделано. Но когда вы все переводы переносите в одну колонку, в этот момент вы теряете возможность сортировки строк с учетом языковых особенностей.

    С другой стороны сортировка по названию наверное не принципиальна.

    И последний вопрос, правильная архитектура в контексте Битрикса ?


    1. stepan_ovchinnikov Автор
      23.11.2021 08:38

      1 - json в mysql в 8 версии только. с таблицами/префиксами/id языка проблем особых нет

      2 - либо запись, либо колонка.

      3 - про сортировку интересная мысль, спасибо

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


  1. stepan_ovchinnikov Автор
    23.11.2021 08:37

    --