Несколько мультиязычных сайтов в одной админке
Вот как реализовать переключение контекстов на нескольких доменах, но когда языки находятся в папках.
Вот пример:
Я поднял этот вопрос, в результате которого мы нашли решение. Думаю это решение пригодится многим.
Вместе с Сергеем (спасибо ему большое за идеи) у нас получилось найти работающее решение (возможно есть вариант и изящнее).
Остальные настройки можно взять из статьи Василия bezumkin.ru/sections/tips_and_tricks/2439/
2. Проверки на несуществующие языки типа /de/ решаются просто — достаточно во всех контекстах сайта прописать настройку страницы 404 [error_page] для каждого контекста отдельно, даже для web. Тогда если человек пройдёт по несущесвующей ссылке site2.ru/de/, то он попадёт на 404-ю страницу, которая указана сайту site2.ru
2. Удобство управления, особенно когда есть 5 связанных между собой сайтов с 3-мя языками каждый. Очень скоро именно на таком проекте я испытаю этот плагин!
3. Если грамотно настроить права, то разные группы пользователей (менеджеров) смогут заходить в одну и ту же админку не подозревая, что на ней крутятся ещё много других сайтов. К тому же заходят они в админку на своём домене, например site1.ru/manager и site2.ru/manager
P.S.
Если вы знаете как решить эту задачу красивее — можете предложить в комментариях!
Вот пример:
- site1.ru/ru
- site1.ru/en
- site2.ru/ru
- site2.ru/en
Я поднял этот вопрос, в результате которого мы нашли решение. Думаю это решение пригодится многим.
Вместе с Сергеем (спасибо ему большое за идеи) у нас получилось найти работающее решение (возможно есть вариант и изящнее).
Плагин
Плагин на OnHandleRequest:<?php
// Работаем только на фронтенде
if ($modx->event->name != 'OnHandleRequest' || $modx->context->key == 'mgr') {return;}
$alias = $modx->getOption('request_param_alias', null, 'alias', true);
$request = &$_REQUEST[$alias];
// Определяем язык папки из URL
preg_match('|/(.*)/|', $_SERVER['REQUEST_URI'], $m);
$lang = trim($m[1]);
// Выбираем все существующие на сайте языки
$q = $modx->newQuery('modContextSetting');
$q->select('value');
$q->where(array('key' => 'cultureKey'));
$q->prepare();
$q->stmt->execute();
$langs = $q->stmt->fetchAll(PDO::FETCH_ASSOC);
$lang_arr = array();
foreach ($langs as $l) {
array_push($lang_arr, $l['value']);
}
// Если папка пуста, указываем русский язык
if (!in_array($lang,$lang_arr)) $lang = 'ru';
// Формируем нужный host_language
$host_language = $_SERVER['HTTP_HOST'].'_'.$lang;
// Выбираем контекст с настройкой host_language
$q = $modx->newQuery('modContextSetting', array('key' => 'host_language', 'value' => $host_language));
$q->select('context_key');
$tstart = microtime(true);
if ($q->prepare() && $q->stmt->execute()) {
// Учитываем наш запрос в БД
$modx->queryTime += microtime(true) - $tstart;
$modx->executedQueries++;
// Получаем ключ контекста
if ($context = $q->stmt->fetch(PDO::FETCH_COLUMN)) {
// Web инициализируется в index.php - на него переключаться не нужно
if ($context != 'web') {
$modx->switchContext($context);
$request = preg_replace('/^'.$lang.'\//', '', $request);
}
}
}Контексты
В настройки контекстов добавляем ключ host_language со значением site.ru_en, где «en» = cultureKey.Остальные настройки можно взять из статьи Василия bezumkin.ru/sections/tips_and_tricks/2439/
Проблема
1. Плагин не работает почему-то с ресурсами-контейнерами, поэтому пришлось обойти костылём и убрать«Суффикс контейнера» в настройках системы [container_suffix].2. Проверки на несуществующие языки типа /de/ решаются просто — достаточно во всех контекстах сайта прописать настройку страницы 404 [error_page] для каждого контекста отдельно, даже для web. Тогда если человек пройдёт по несущесвующей ссылке site2.ru/de/, то он попадёт на 404-ю страницу, которая указана сайту site2.ru
Возможные варианты применения решения:
1. Экономия места на хостинге, не нужно переплачивать за лишний хостинг.2. Удобство управления, особенно когда есть 5 связанных между собой сайтов с 3-мя языками каждый. Очень скоро именно на таком проекте я испытаю этот плагин!
3. Если грамотно настроить права, то разные группы пользователей (менеджеров) смогут заходить в одну и ту же админку не подозревая, что на ней крутятся ещё много других сайтов. К тому же заходят они в админку на своём домене, например site1.ru/manager и site2.ru/manager
P.S.
Если вы знаете как решить эту задачу красивее — можете предложить в комментариях!
Комментарии: 38
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
2)не обязательно проверяя «in_array» уникализировать значения
3)нет проверки на язык отсутствующий у домена
например есть набор контекстов:
если мы запросим для test2.com/de что получится?
P.S. я бы предложил выбрать сначала все контексты с текущим доменом, а потом уже среди них выбрать тот что с языком
2) Убрал. Логично.
3) Добавил проверку с редиректом на 404-ю страницу текущего контекста
P.S. Я пробовал так, но что-то у меня не завелось…
Буду пробовать.
План такой:
1)берем контексты по домену, если их нет показываем что-то по умолчанию(web например)
2)если контексты нашли проверяем язык внутри них, если наш язык не найден — берем первый контекст или контекст по-умолчанию и выбираем его
3)если найден контекст с нужным языком — берем его
Если хочешь, можешь попробовать написать!!!
Что бы в версии en выводился чанк $enmenu а в русскоязычной $menu
Слышал, что можно методом else, them а как не знаю…
конструкции вида:
Спасибо
Есть же стандартный метод вывода?
Как модиксу проверить если контекст en, то выводить чанк в wayfinder [[$enmenu]]
Если контекст web то выводить [[$menu]]
Спасибо
Либо проверить контексты:
Либо твой пример:
Присмотрись в сторону Fenom, уверяю тебя, ни грамма не пожалеешь об этом.
prntscr.com/8zlelh
Но не отображается, потому что пакет не поставлен..? fenom
Я просто почему стандартными средствами., потому что сам не люблю добавления ставить. кажется, что каждое дополнение будет тормозить работу скриптов в целом, ошибался.
В работе с Феном много тонкостей. Например, скорей всего на твоём сайте, если ты поставишь pdoTools с включённым Феном, у тебя повываливаются ошибки и страница не отобразится, как надо. Это связано с тем, что Феном любой код (даже JS, даже JSON в параметрах сниппетов стандартным выводом) с фигурной скобой {, если после неё идёт какой-либо текст, а не пробел, таб или перенос строки, будет считать «за своего» и пытаться обработать. Естественно синтаксис его не устроит и он вывалит ошибку. Приведу пример:
Мы на странице вызываем код fancybox вот так:
Феном видит это безобразие и в логе ошибок в бекенде сообщает нам, что он не понимает синтаксис, который мы указали для него на странице. Что нам надо сделать, чтобы удовлетворить потребность Фенома в корректном синтаксисе? Да просто после фигурной скобы поставить пробел, вот так:
Или есть у нас сниппет вызываемый стандартными средствами MODX с параметром, в котором указана JSON строка вот так:
Феном не устроит подобное отношение и он, как и в прошлом примере скажет нам, что синтаксис не уместен. Что мы делаем? Правильно! Просто ставим пробел после скобы:
И так со всем кодом на странице. Когда все подобные моменты на странице будут исправлены — Феном будет радовать нас своими возможностями и скоростью работы.
а сейчас решил наплодить темплейты — в Главной [[$menu]] в копия главной [[$enmenu]] ппц как топор))
Например чанки [[$enmenu]] и [[$rumenu]], а потом просто подставлять системный параметр:
Можно и по другим параметрам, но принцип ясен.
а чанки menu_ru и menu_en
Но проверку для несуществующего языка (/de/) ещё не дописал…
Создаем контексты для все языков с ключами host-language — site1-ru (для site1.ru), site1-en (для site1.ru/en/), site2-ru (для site2.ru), site2-en (для site2.ru/en/). Контекст web не рабочий. В нем одна страница 404.
Вот плагин.
А если все домены в разных доменных зонах? И новые домены будут добавляться непонятно каких зон? Как автоматизировать этот момент?
Не стал развивать этот момент, т.к. тогда пришлось бы переносить весь контекст web в другой контекст, а потом настраивать всё это. К тому же синхронизация ресурсов в Babel-е может слететь. Особенно неудобно это будет, если в контексте web настроенный рабочий магазин с тысячами товаров.
В конце концов можно регулярку сделать более универсальной — убрать зоны.
В моём варианте я тоже вначале срезал у регулярки зоны, правда не знаю как она себя поведёт в ситуации с поддоменами типа sub.site.ru — я не силён в регулярках. Поэтому я не использую её для определения хоста, а запрашиваю контекст из БД через $host_language, который у меня указан вместе с доменной зоной (site.ru_en)
Все мои задачи уже решены!
судя по твоему коду, будет не найден ключ вида host_language и по умолчанию показан контекст web
Если считаешь что правильно все, то ладно)
- bazstudio.com/
- macinatorul.com/
Оба этих сайта в одной админке. У первого языки ru (web) и en, а у второго ru, en, ro. Можешь погонять, пока они ещё в тестовом режиме.bazstudio.com/en/ — en
macinatorul.com/ — macinatorul-ru
macinatorul.com/en/ — macinatorul-en
macinatorul.com/ro/ — macinatorul-ro
bazstudio.com/ — web
bazstudio.com/en/ — en
bazstudio.com/ro/ — ro
macinatorul.com/ — macinatorul-ru
macinatorul.com/en/ — macinatorul-en
при обращении к macinatorul.com/ro/
будет показываться 404 с bazstudio.com, а не с macinatorul.com
bazstudio.com/bg/
bazstudio.com/ro/
macinatorul.com/bg/
Выдает:
host_language: bazstudio.com_ru
а должен macinatorul-ru
особенно если разные дизайны будут и наполнение это сильно будет влиять
хотя чего я доказываю, если устраивает как работает, пожалуйста ;)