«А давайте выйдем на рынок СНГ»: как масштабировать сайт, если он к этому не готов

Ноябрь 2022
~7 мин
Все публикации
Роман Сыроешкин
Источник: Хабр

Вас могут заинтересовать услуги:

Вы­со­ко­наг­ру­жен­ные пор­та­лы и сервисы
Подробнее
Разработка информационного портала
Подробнее
Разработка портала
Подробнее

Рано или поздно у крупных проектов наступает такой этап, когда достигнут потолок по аудитории или финансовым показателям и нужно как-то расти дальше. И вот в один прекрасный день сияющие коллеги приходят к тебе со словами «Мы тут решили выйти на рынок США/Китая/СНГ…».

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

Я тимлид финансового маркетплейса «Выберу.ру», сейчас допиливаю казахстанскую версию сайта на .NET. Хочу рассказать о нюансах, которые всплывают при масштабировании на другую страну, и о способах их поправить.

Полагаю, в ближайшее время все больше компаний будут рассматривать для себя зарубежные рынки. Если вам тоже предстоит адаптировать огромные объемы кода, который до этого годами создавался только для России — буду рад, если мой опыт окажется полезен.

Подход к работе с геоданными

Первая проблема возникает на самом старте, если ваш сайт использует городские домены типа moskva.(домен).ru или tula.(домен).ru, а возможности приобрести домен первого уровня, например .kz, по каким-либо причинам нет. Как определять страну в этом случае?

Есть сущность регионов (Region), которая упрощенно выглядит так:

Под Region у нас были представлены все географические сущности (страны, республики, области, города и т. д.). Мы добавили свойство CountryId и записали туда идентификатор региона-страны. Россия была добавлена первой (у неё Id = 1), Казахстан добавили позже. Теперь в базе несколько записей с ParentId = null — запись уровня страны.

Теперь надо научить сайт определять страну, для которой отображается страница. Тут есть несколько моментов:

  • Если пользователь первый раз зашел на сайт и попал на страницу России (основной домен), то определяем его местоположение и предлагаем подтвердить наше решение.

  • Если пользователь сразу зашел на домен города, например, moskva.(домен).ru или tula.(домен).ru, то вопрос о местоположении пользователя не задаем, а принимаем в качестве него город домена.

  • Как только мы определили город пользователя, сразу можем определить и страну. Данные о городе и стране записываем в cookie. Эту запись пользователь может сменить, выбрав другой город или другую страну.

За счет этого мы можем реализовать механизм определения региона при каждом запросе по двум параметрам: из URL и из cookie, — обеспечивающим гибкость настроек. В случае с URL для определения страны и региона будем учитывать домены первого и третьего уровней соответственно. Для moskva.(домен).ru мы выберем город с Alias = «moskva». Для страны Alias = «ru» мы не найдем и используем значение по умолчанию — Россия (нюанс в том, что Alias России в нашей базе есть «www»).

Вывод локализованных параметров

Когда мы научились определять страну, то можем выводить локализованные данные.

Что это может быть? Есть универсальные параметры: денежные единицы, формат даты. В зависимости от тематики сайта могут добавиться и другие. Например, для автомобильных агрегаторов — единицы скорости и расхода топлива, для объектов недвижимости — площади и расстояния и т. д. На финансовом ресурсе, чтобы показать, скажем, вклады в России, по умолчанию нужны доллары, евро и рубли, а в Казахстане потребовалось скрыть значки рублей и показать тенге (₸). 

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

Чтобы корректно выводить такие параметры, выносим данные о странах в отдельный файл (в нашем случае localization.json) и включаем в него следующее:

  • название страны;

  • домен для страны;

  • имя культуры (для классов CultureInfo и RegionInfo во фреймворке .NET, помогающих форматировать даты, числа и другие параметры локализации в зависимости от страны, подробнее здесь CultureInfo Конструктор (System.Globalization) | Microsoft Learn);

  • список доступных валют (или других нужных вам элементов);

  • список разделов/функциональных возможностей сайта.

Загружаем файл при старте сайта. Данные из него доступны при выполнении запросов на сайт. Создаем для этого класс CultureOptions и получаем нужные данные для страны.

Выглядит так: LocalizationOptions localizationOptions = LocalizationOptions.Get(countryAlias).

Платформа .NET располагает расширенными методами для локализации/глобализации приложений. Приведенные классы платформы используем как:

Настройка блоков контента под страну

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

Для этого можно создать систему управления конфигурацией. С ее помощью все разделы, настройки региональности, локализация вынесены в отдельный блок кода — отдельную систему, где легко указать, что показывать или скрывать (это тот самый список фич из файла localization.json). 

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

Вот пример:

LocalizationOptions localizationOptions = LocalizationFeatures.GetOptions(country.Alias); 
bool requestFormEnabled = localizationOptions 
    .IsEnabled(LocalizationOptionsNames.ProductListing.EnableRequestForm);

Если requestFormEnabled равен true, то выводим блок. 

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

Геонезависимые страницы

Итак, мы определили страну, вывели на нужных страницах локализованные данные и настроили индивидуальный набор разделов/функциональных элементов. Остались страницы продуктов, не привязанные к конкретному региону — мы называем их региононезависимые или геонезависимые. По умолчанию они отображаются по адресу www.(домен).ru.

Раньше у нас было так:

  • зашли на moskva.(домен).ru — видим московские продукты;

  • tula.(домен).ru — тульские продукты;

  • (домен).ru — российские продукты.

Для Москвы родительский элемент геоструктуры — это www.(домен).ru — Россия. Если мы возьмем населенный пункт Снегири, он относится к Москве, у него родительский moskva, у того родительский www.(домен).ru — Россия. Все просто, тем более при отсутствии продуктов в Снегирях, можно показать продукты для всей России (для www). Однако теперь у нас несколько стран и просто выводить продукты для России (для www) не получится.

Если не менять логику и не научить продуктовый поиск учитывать разные страны, человек, находясь в разделе Казахстан, увидит содержимое, предназначенное для России. Для Казахстана нужно выводить не www.(домен).ru, а kz.(домен).ru как корневой узел страны пользователя. Выходит, если раньше поиск мог учитывать только один геопараметр (город), то теперь нужно закладывать два: город и страну.

Когда будем добавлять города, допустим, Астану, узловой элемент самого верхнего уровня будет kz, а не www. Соответственно, когда человек из Казахстана зайдет на страницу, которую мы считали раньше геонезависимой, он должен видеть не www.(домен).ru, а kz.(домен).ru как корневую страницу страны Казахстан.

Оптимизация скорости загрузки

Когда мы оперируем странами, а не городами, возникает еще одна проблема — замедление работы сайта.

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

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

Работа с текстами

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

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

  2. Подготовить SEO-тексты и описания продуктов. Тут доработка уже намного масштабнее. Сначала SEO-тексты нужно красиво написать на иностранном, оптимизировать. Потом описания продуктов в админке — проверить, адаптировать.

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

 

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

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

Найдем решение вашей задачи

Заполнить бриф
Форматы: jpg, png, xsl, PDF, doc. Размер до 2 МБ
Нажимая кнопку «Отправить», Вы принимаете условия обеспечения конфиденциальности персональных данных.
Отправить