evoBabel - мультиязычные сайты на MODx EVO - теперь это легко и просто

Как обычно бывает — встала задача, неразрешимая средствами YAMS и очень неудобно рарзешимая другими средствами — создать мультиязычный сайт, чтобы
  • заказчик мог сам добавлять языки
  • переводы не были разбросаны по шаблонам, а содержались в одном месте
  • чтобы переключалка языков отправляла на нужный ресурс на другом языке
  • чтобы нормально без бубна работали сниппеты вроде DocLister, Wayfinder, Breadcrumbs и т.п.
  • и главное — чтобы не было жесткой привязки как в YAMS, т.е. структура сайтов на разных языках могла отличаться, а не было необходимости заполнять каждую новость, каждый товар и т.п.

Из всего этого на основе некоторых идей, почерпнутых из REVO Babel и с вооружившись библиотекой MODx API от Agel_Nash был разработан прототип решения evoBabel. Пример можно посмотреть на тестовом сайте.


Ссылка на установочные файлы, там же в файле readme — очень подробное описание как и что устанавливать.

В качестве поля для связи использовал стандартное поле description, т.к. некогда было заморачиваться с дополнительными TV, для вызова самого сниппета использован TV- параметр с типом ввода Custom Input.

Основные полезности:
  1. создание неграниченного количества языковых версий сайта при этом каждая версия хранится в своем дереве, что не ограничивает нас никак т.е. структура сайта на разных языках может отличаться (в отличие от YAMS), нет проблем с плейсхолдерами, другими сниппетами и т.п.
  2. ресурсы разных языковых версий связаны между собой — что позволяет при навигации переключаться на нужную языковую версию ресурса (за это отвечает сниппет switchLang)
  3. Возможна синхронизация значений нужных ТВ параметров для разных версий ресурса (id нужных ТВ задается в настройках плагина evoBabel)
  4. Переводы и id нужных ресурсов (каталогов новостей и т.п.) указываются в соответствующих языковых чанках без всяких разделителей || — разделителем служит перенос строки \n

Если у кого-то есть интерес и желание потестировать и предложить пути доработки — пожалуйста.

upd




upd2 — обновился архивчик на github

upd3 — удален сниппет switchLang, его функционал перенесен в плагин evoBabel на событие onWebPageInit (он соответственно, тоже обновился). В результате полностью решена проблема с мультиязычными формами на кэшированных страницах :)

Добавлен модуль для переводов. Теперь никаких чанков. Модуль на основе jquery easy ui, с ajax-редактированием инлайн, фильтром/поиском, сортировкой по алфавиту по-умолчанию (чтоб было проще искать), возможностью добавления и удаления новых лексиконов. Плюс, соовтетственно, переписан сниппет switchLang для выборки перевода из базы.



upd 30.12.2013
Обновил до версии 0.2 — github.com/webber12/evobabel-0.2 — скачать архив можно тут

Из основного:
— убрал библиотеку MODxAPI — т.к. отслеживать ее актуальность тяжеловато, да и тягать за собой ради пары функций особого смысла нет.
— ООП
— и главное — хранение языковых связей теперь осуществляется в TV (причем в том же TV, который используется для показа этих связей в админке)
это решает сразу несколько задач:
1. поле description не используется и соответственно пользователь не может повредить связи
2. поле TV для хранения связей имеет вид custom input и также напрямую не выводит нужные связи, что мешает их повредить
3. и все таки, если нужно что-то подправить, админ может переключить тип поля с custom input на обычный text и подправить если нужно. Т.е. в отличие от хранения связей в отдельных таблицах к ней все-таки есть доступ при наличии определенных навыков админа. Ну а без навыков — пусть лучше и не лезет, да и не получится у него :)

— подправил плагин для языковых плейсхолдеров [%перевод%] — теперь ищет лучше.

результат работы обновленной версии можно посмотреть тут

321 комментарий

avatar
Велосипед не велосипед, а пока нормального ничего так и не было. Спасибо, попробую.
avatar
Один вопрос: как в вашем случае решается передача разных языков в чанки для сниппетов? Например, в eForm нужен шаблон формы на текущем языке, как его получить?
avatar
Тут вопрос немного в доработке, т.к. для разных сниппетов по-разному языки называются. Но в целом для того же eForm

<code>[!eForm? &formid=`feedbackForm` &subject=`Обратная связь` &tpl=`eFeedbackForm` &report=`eFeedbackReport` &thankyou=`eFeedbackThank` &to=`{{mail_for_feedback}}` &vericode=`1` &language=`[[lang? &a=`Язык формы`]]`!]</code>

и соответственно в чанке lang_ru строка Язык формы==russian-UTF8, в чанке lang_en — Язык формы==en — отлично передают язык в вызов формы.

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

Аналогично для главной страницы например вызов новостей организован так

[[DocLister? &tpl=`mainnewsDL` &parents=`[[lang? &a=`Папка новости`]]` &display=`2` &tvList=`image` &dateFormat=`[[lang? &a=`Формат даты`]]` &id=`mn` &summary=`notags,len:80`]]

где для разных языков задаются разные папки новостей и разные форматы даты.

Если же речь просто про вывод каталога или новостей — то тут просто parents=`[*id*]` выводит нужные новости/продукты для нужного языка.
Комментарий отредактирован 2013-12-01 16:26:47 пользователем webber
avatar
Очень хорошее дело! Нужно доводить и будет супер.
Что заметил уже.
1. Убрать дубль evobabel.sitex.by/ru/index/evobabel.sitex.by/
2. Есть ли возможность делать язык по-умолчанию без /ru/
  • Shin
  • 0
avatar
1. дубль был т.к. был выключен seo strict встроенный. Сейчас включил — дубля нет
2. Алиас ru убирается путем убирания птички на папке ru «Использовать в URL» — убрал — работает. Текущий язык определяется сниппетом UltimateParent на основе id ресурса для самого верхнего уровня — поэтому url по идее роли не играет для работоспособности.

Можете сейчас посмотреть.
avatar
Надо бы придумать, чтобы эта страница evobabel.sitex.by/en/index/ открывалась по evobabel.sitex.by/en/
avatar
1) Хорошее решение, а можно в топик добавить скрин дерева документов, чтобы не додумывать?

2) На гитхабе некоторые файлы со сниппетами в кодирове windows-1251, что делает их не читаемыми

3) Если потребуется в чанках DocLister использовать языковые фразы, то можно попробовать еще использовать параметр customLang и плейсхолдеры [%xxxx%]

4) Какой тип кэширования используется на сайте (с учетом GET или нет)?

5) Как насчет разработки модуля для управления лексиконами, чтобы не плодить чанки и более комфортно работать добавлять/искать/редактированить фразы? Готов подсобить…
avatar
Кодировку подправил, пару скринов положил. Вся прелесть в том, что просто ведутся параллельно деревья-языки. В каждом ресурсе появляются ссылки на языковые версии (либо «создать» — если данной версии нет, либо «перейти» — если эта версия уже есть).

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

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

Основная же прелесть — можно вести эти деревья независимо друг от друга и не спотыкаться о вечный вопрос «зачем мне в английской версии вакансии» :))

По кэшированию — тут вопросов нет, т.к. языковые переводы читаю в сессию. Т.е. какое угодно может использоваться, т.к. ресурсы имют разные url в разных языках, причем необязательно они должны быть идентичными «за исключением алиаса языка», т.е. это может быть ru/product и en/catalog — т.к. связь идет не через реплейс url, а через отдельную запись вида «ru:10||en:20||fr:30» — которую я просто из лени зашил в description, а не в отдельный TV/

avatar
Спасибо за объяснение. Позже еще гляну исходники.
avatar
По 3 пункту — проверил, в принципе конструкция

[[lang? &a=`Напряжение питания`]]: [+tv.voltage+]V


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

Для каждого языка также предусмотрена своя страница 404 — если она задана в соответствующем чанке переводов и создана в ветке.
avatar
Изумительное и верное решение однозначно +
avatar
Было бы неплохо документацию сделать, хотя бы самую простою.
В идеале, нужно отдельный сайт, с разделами «FAQ», «примеры решений» и «Плейсхолдеры».
avatar
«ru:10||en:20||fr:30» — которую я просто из лени зашил в description
Для начала, все правильно, чтобы обкатать работоспособность. Но в дальнейшем хорошо бы сделать либо через отдельную таблицу связей или дополнительное поле в таблице site_content.
  • Shin
  • +1
avatar
можно и стандартные поля к примеру линк_аттрибутес на мой памяти используется крайне редко
его заюзать + перенести в вкладку настройки через mm
avatar
Идея с тремя деревьями «навскидку» крайне не понравилась, так и раньше было, в-остальном, хотелось бы попробовать хотя бы RC
avatar
Идея и деревьями очень удобна если есть расхождение в контенте :)
собстенно всего 2 варианта существует:
— 1 разные деревья или контексты в случае с REVO
— 2 это доп поля к 1 дереву

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

опять же никто не мешает комбинировать решения
к паримеру для галереи или каталога делать отдельную ветку где будет заполняться оба языка
avatar
Вот бы такую же штуку для поддоменов :)
avatar
поддомены можно подключить не вижу особых проблем :)
avatar
Если не на шареде :)
avatar
да и на шареде можно тоже

$_SERVER[HTTP_HOST]

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

добавляем к основному домену алиасы нужные и дальше уже используем этот параметр :) в идеале правда немного хакнуть ядро что б кеш строился с учетом этого параметра
avatar
это типа количество ресурсов * 2 или я что-то не понял
avatar
Ага все верно :)
но тут или количество ресурсов * 2
или количесво доп полей в ресурсе * 2
в итоге по количесву записей в базе приходим примерно к равенству:)
avatar
эта печально
avatar
Чего ж печального то? у вас ровно в 2 раза больше информации вот и в 2 раза больше полей это ж логично :)
если будет 3 языка будет в 2 раза больше :)

это так же печально как если у вас на сайте 1 страничка или 2 )
avatar
я о том что 1 страница на сайте в 2 языках это 2 записи в БД, я считаю расточительно это, в моем варианте 1 страница = 1 запись (без тв)
avatar
Я же огласил в самом начале список задач, которые решает данная разработка:

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

Если бы YAMS решал хотя бы одну из этих задач — возможно и темы бы такой не поднималось. А так, кроме этого решается еще ряд постоянных проблем, которые тут обсуждаются
— как в шопкипере добавить товар в корзину на другом языке
— почему у меня в eForm все равно русский язык
— куда пропала пагинация на английской версии
— как мне выводить только определенные разделы в другой версии (варианты — «нафиг мне в китайской версии вакансии», «почему я не ввел название новости, а в списке эта новость есть с пустым заголовком»)
— работает ли DocLister с YAMS
— как мне наконец подружить phx с YAMS
— я уже запутался что кэшировать, что некэшировать, когда Ditto надо кэшировать и размешать прямо в контенте его вызов, а когла в шаблоне и с другими параметрами

:)

Короче везде есть свои плюсы/минусы, но т.к. постоянно идут разговоры что в Revo многоязычность есть, а в Evo ее нет — то и был сделан некий аналог, чтоб наконец показать, что и в Evo в таком понимании многоязычность сделать можно (т.к. разные деревья в разных контекстах — то же, что и в нашем случае просто разные деревья, цепляющие разные переводы).
avatar
yams вообще мало чего решает, но пока хватало терпения ним пользовались. когда опубликую свое решение я вам кину ссылку на него. в ево многоязычность была до того как появился рево, она и выглядела примерно так как реализовывается ваш модуль. я встречался с таким решением проблемы, мне оно не нравиться, так как в пустую плодятся ресурсы, и подход в реализации которого есть синхронизация ресурсов мне так же не нравится. ожидайте ;)
avatar
Это вы отсылаете к своему посту от 21 марта сего года modx.im/blog/news/607.html#comment5245? Ну так ничего, мы терпеливые, 9 месяцев прождали, пока выкатите свое решение — подождем и еще немного :)
avatar
я его уже успешно использую на порядка 10 сайтах, однако готового инсталлятора для блондинок нет, тут такое не ценится, все должно ставиться просто и работать понятно, когда найду время для этого муторного процесса выложу. и куда мне торопиться то? надо будет и год не выложу :) главное чтобы когда выложу вопросов не было ведь
avatar
Вы верите в это? что вопросов не будет.
avatar
Обновил архив, добавил модуль для управления переводами на основе jquery easy ui и обновил под него сниппет «читалку переводов» switchLang. Теперь все переводы в одной таблице построчно, никаких чанков — никакого хардкора :)


Инлайновое редактирование переводов без перезагрузки страницы прямо в строках таблицы, фильтр/поиск, создание и удаление языков там же, сортировка по умолчанию по имени перевода по алфавиту и т.п.
Комментарий отредактирован 2013-12-02 11:29:52 пользователем webber
avatar
Песня осталось сделать пакетом и в репозиторий :) надеюсь на недельке найду время потестить
avatar
Да для того и выложил, чтоб хотя бы несколько человек потестило :) А то когда это сам делаешь и сам на своем сайте проверяешь — оно обычно все работает нормально. А когда выходит в массы — начинаются «проблемы» ))))
avatar
12. Создаем новый плагин evoBabel, копируем код из файла plugin.evoBabel.inc.txt

Тут github.com/webber12/evoBabel/blob/master/plugin.evoBabel.inc.txt неправильно. Это надо вынести в файл и подключить, иначе
include_once("functions.evoBabel.php");

работать не будет.
avatar
Ок, спасибо. Обновлю — последний вариант (который работает на сайте) — наверно недозалил :)
include_once(MODX_BASE_PATH."assets/snippets/evoBabel/functions.evoBabel.php");
avatar
Если $synch_TV пусто, то синхронизацию выполнять не нужно.
Сейчас выдает ошибку запроса.
avatar
Спасибо. Поправил до актуальной версии
avatar
Однозначно здорово! На выходных будем тестировать:)
avatar
В снипете switchLang неправильная логика:
$out.=$currLang.$otherLangs;

Получается, что с переходом в другую версию, флажки меняются местами.
  • Shin
  • 0
avatar
Тут под конкретный сайт делалось, где текущий язык отдельно, а остальные в модальном окне всплывают. Хотя над более общим случаем, конечно, не мешает подумать.
avatar
Я тут сделал github.com/Shin777/evoBabel/blob/master/snippet.switchLang.inc.txt.
Можете взять что понравится.
avatar
Что ж вы данные не экранируете перед вставкой в базу. Ошибки ведь будут постоянные.
Вместо
$fields[$k]=$v;
надо
$fields[$k]=$modx->db->escape($v);
  • Shin
  • 0
avatar
Да, понадеялся в одном месте в модуле переводов, что админ не будет в переводах фразы в кавычках писать :) Хотя вы правы, на админов сайта надейся а сам не плошай. Поэтому поправил :)
avatar
готовлю PR для того что б добавить в репозиторий
есть баг и есть предложение

1. Если только 1 тв а все остальные по вкладкам то не показывается видать что то упустил из оформления ТВ параметр и mm не видит

2. Можно сделать плагин для того что б лексикон вынести к примеру в тег [%плейсхолдер%] думаю было бы совсем удобно :)
avatar
По первому пункту — я это тоже видел, но это похоже какой-то общий баг modx или managermanager. Т.е. если только 1 ТВ параметр на General tab и он с custom input, то почему то его не показывает на главной вкладке. Если добавить любой второй туда же, то начинает показывать сразу два.

Как вариант для себя делал — добавлял какой-нибудь левый ТВ и скрывал его через managermanager — тогда показывался нужный :) Отчего так — надо покопаться в районе вывода ТВ в админке и managermanager.
avatar
ага может бага как раз в managermanager
хотя как понимаю он ищет вхождение типа нужный блок если их нет то не показывает

поидее можно поправить добавив такой же html вообщем надо будет поковырять
avatar
Готов пакет для установки через репозиторий
github.com/extras-evolution/evoBabel

Заходим на сайт:
extras.evolution-cms.com/my-repo/my-packages.html
Авторизируемся или регистрируемся
добавляем новый пакет:

github.com/extras-evolution/evoBabel/archive/master.zip

Нажимаем сохранить и далее в модуле он будет доступен

p.s. после тестирования что все ок перенесу в общий репозиторий
avatar
Немного его подправил по мелочи (в частности, уже не нужна установка языкового чанка, т.к. управление языками/переводами идет через модуль). Итоговая версия по старому адресу github.com/webber12/evoBabel

Добавил evoBabel+easyForm в репозиторий — посмотрим, что из этого выйдет :)
Комментарий отредактирован 2013-12-14 14:55:30 пользователем webber
avatar
еще баг словил если в eform в шаблоне ставить ленги то потом запоминает какую то одну версию почему то :( как понимаю надо сам снипет ленга ставить не кешированным тогда может поможет но не совсем кошерно так
потому реши пока делать разные шаблоны для разных языков
avatar
Да, eForm он такой, он жесткий ))) Причем там даже некэшированный сниппет не спасает, надо некэшированный сниппет на некэшированной странице вызывать. Иначе сам язык меняется (т.к. сообщения об ошибках), а вот на вызовы [[lang]] внутри чанков он как-то вяло реагирует — такое чувство, что он их где-то дополнительно кэширует и не дает им повторно к сессии обратиться.

Не помню как там обстоят дела у YAMS с eForm, но пока думаю, что сделать страничку с формой некэшированной это не такая уж большая потеря на фоне всех тех преимуществ, которые в итоге получаются :)

Убедиться что это все-таки можно сделать — можно тут.

Причем такое только с eForm, тот же DocLister вполне нормально меняет языки в чанках даже при кэшированном вызове DocLister на кэшированной странице и с кэшированным [[lang]] внутри чанка.
Комментарий отредактирован 2013-12-12 12:34:16 пользователем webber
avatar
сделать страничку с формой некэшированной это не такая уж большая потеря на фоне всех тех преимуществ, которые в итоге получаются :)

Если форма в на всех страницах, весь сайт не кешировать?
avatar
Как вариант — пойти тем же путем, которым ходит YAMS — создать разные чанки для формы для разных языков и вызвать вот так

[!eForm? &formid=`faqForm` &subject=`Вопрос с сайта (FAQ)` &tpl=`eFaqForm_[[lang? &a=`Алиас`]]` &report=`eFaqReport` &thankyou=`eFaqThank_[[lang? &a=`Алиас`]]` &to=`{{mail_for_feedback}}` &vericode=`1` &language=`[[lang? &a=`Язык формы`]]`!]


При этом страницу можно кэшировать, а в модуле переводов задаем строчку вроде Алиас — ru — en, и сами чанки eFaqForm_ru и eFaqForm_en
avatar
удален сниппет switchLang, его функционал перенесен в плагин evoBabel на событие onWebPageInit (он соответственно, тоже обновился). В результате полностью решена проблема с мультиязычными формами на кэшированных страницах :)
Архив находится по старому адресу и доступ для добавления в репозиторий.
avatar
Было бы хорошо не полностью убирать чанки а оставить их для системных переменных например для id категориий и прочее, а то если клиент захочет поменять и не то изменит и какой блок сломается. можно для чанков сделать отдельную переменю например [[lang? &b=`Главная страница`]]
avatar
Не, я думаю это будет слишком сложно. Но предложение дельное — я уже думал над тем, чтобы саму таблицу разбить на две части (вкладки) — системные и общие. И соответственно снабдить системную часть предупреждением вида «не знаешь — не лезь» )))

А поломать точно также он может и в чанках, даже еще проще — т.к. в таблице есть строчка хотя бы с названием (я так представляю, что русский язык разработчик полностью заполняет, остальные — по аналогии уже владельцем сайта просто заполняются для нужных языков). Т.е. на этапе обслуживания сайта новых строк создавать не нужно (только если меняется шаблон — но это уже на страх и риск, как говорится). А в чанках же придется переписывать руками и все названия переменных — а это вечные проблемы с русскими/нерусскими буквами, лишними пробелами, кавычками, знаками препинания и т.п.
Комментарий отредактирован 2013-12-12 17:53:09 пользователем webber
avatar
Добавлен плагин evoBabelPlaceholders — для удобного задания языковых версий. Теперь в шаблонах и чанках можно использовать конструкцию вида [%параметр%] вместо прежнего [[lang? &a=`параметр`]] для вывода языковых версий.
avatar
Залил в репозиторий последнюю версию
avatar
Надо будет попробовать этот путь с самого начала :))) Со своего ставил — вроде работало нормально, надо попробовать с публичного теперь )
avatar
Всем доброго времени суток! Несколько раз пробегался по инструкции, но так и не получилось достичь конечного результата. TV параметр так и не появился у редактируемых страниц. В чем может быть проблема?







avatar
один из возможных вариантов — проблема в некотором странном отношении то ли modx то ли managermanager к одиночному параметру с типом custom input. Для решения как вариант — добавьте к странице еще один параметр (любой с любым типом, например текстовая строка) и если все сделано правильно — их появится сразу 2 — и языки и новый. Этот новй можно скрыть для всех шаблонов через managermanager.

Вот такая вот пока неясная фишка с custom-input типом ТВ :)

И второй момент — не видно по скринам, заданы для настройки по умолчанию для сниппета, т.к. там тоже нужно задать id шаблона языка &lang_template_id=id шаблона языка;text;11
Комментарий отредактирован 2013-12-23 14:22:55 пользователем webber
avatar
Большое спасибо! Действительно, проблема была с типом ТВ custom-input (:
avatar
Обновил до версии 0.2 — github.com/webber12/evobabel-0.2 — скачать архив можно тут

Из основного:
— убрал библиотеку MODxAPI — т.к. отслеживать ее актуальность тяжеловато, да и тягать за собой ради пары функций особого смысла нет.
— ООП
— и главное — хранение языковых связей теперь осуществляется в TV (причем в том же TV, который используется для показа этих связей в админке)
это решает сразу несколько задач:
1. поле description не используется и соответственно пользователь не может повредить связи
2. поле TV для хранения связей имеет вид custom input и также напрямую не выводит нужные связи, что мешает их повредить
3. и все таки, если нужно что-то подправить, админ может переключить тип поля с custom input на обычный text и подправить если нужно. Т.е. в отличие от хранения связей в отдельных таблицах к ней все-таки есть доступ при наличии определенных навыков админа. Ну а без навыков — пусть лучше и не лезет, да и не получится у него :)

— подправил плагин для языковых плейсхолдеров [%перевод%] — теперь ищет лучше.
Комментарий отредактирован 2013-12-30 10:39:23 пользователем webber
avatar
А на что заменили MODxAPI?
или просто взяли нужные функции оттуда и всЕ?
avatar
Еще момент а зачем сделали отдельным репозиторием на gitHub?
можно ж было старую версию сохранить в версии и все?
avatar
там слишком много изменений и непонятно по какой идти — может кому нравится сохранять в дескрипшн, а не в ТВ — вот и сделал сразу новую )
avatar
Ну как по мне то правильно развивать именно 1м customTV
делать куча зависимостей смысла нет

тоесть слишком много изменений направленны на упрощение и на легкость потому это + и плодить версии как по мне не есть правильно
avatar
Главный минус этой версии — все-таки появляется дополнительная запись ТВ в базе ) И там и там для вывода списка языков в админку используется custom TV, но в первом варианте сама связь была в description, т.е. ТВ вроде как и было, но в базу ничего не писало. А теперь именно в данное TV и пишется связь.
Но с другой стороны — и плюсы есть
1. поломать сложнее, т.к. тип custom tv в админке показывает другую информацию и чтобы увидеть связь надо тип поменять на текст
2. вытекает из п.1 — увидеть и подправить если что-то пошло не так при определенных навыках все-таки можно (в отличие от хранения в сторонних таблицах) — просто поменяв на время тип этого тв на обычный текст :)

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

Ну а насчет версий — первая была обкатана на сайте, т.е. вполне работоспособна с учетом поправленных багов. ВТорая версия делалась под другой сайт, были глобальные переделки и не было понятия доделается ли она до конца — отсюда и новая версия (чтоб не убивать рабочий вариант). Но в процессе ее доработки доработаны и другие элементы, которые внесены и в первую и вторую версию — в частности нормально подружилось это все с кэшированными формами и нормально парсятся языковые плейсхолдеры в чанках и шаблонах обычными [%имя записи%]
Комментарий отредактирован 2013-12-30 12:27:48 пользователем webber
avatar
Не вижу ничего плохого наоборот только плюсы данного апдейта
avatar
да ни на что не менял — мне там нужно было это все дело только для копирования документа в другого родителя со всеми ТВ. Дописал пару функций
1 2 и 3 которыми и копирую и ТВ в плагине синхронизирую и все
avatar
ага понял тогда действительно логичней и правильней
avatar
Ничего не логичней. Возьмите тот же tagSaver. И что? Он работать не будет с текущей реализацией. Придется по новой пересохранять созданный документ, чтобы тэги создались. Придется внедрять invokeEvent. На некоторых проектах лишнее — добавляем новую проверку. В итоге код со временем опять начнет разбухать и получим MODxAPI 2 вид с боку внутри evoBabel. Имхо, дело конечно авторское, но по моему тут кастрация не уместна.
avatar
Что же касается поддержки библиотеки в актуальном состоянии, то тут как бэ хз даже что сказать. Всплыл баг — обновили либу. Нет баги — значит все хорошо. Через месяц появилось время — проверил версию либы и обновил свой репозиторий в случае чего. Ну опять таки. Дело хозяйское. Наше дело предложить — ваше дело отказаться.
avatar
Ну и наконец еще один аргумент после 5 минутного изучения исходника. Куча потенциальных ошибок SQL запросов. Для примера:
1) Создаем документ с кавычкой.
2) Копируем документ.
3) ПОлучаем ошибку.
4) Profit.

Итог — опять внедряем фикс. И идем по тому же пути, который уже прошел MODxAPI, т.к. там именно такой же баг уже фиксился. У меня все.
avatar
Хотя нет, не все. Повторяться не буду, но аналогичная минутка юмора уже была в релизе MDOX Evolution 1.0.12 (в последствии все же от этого кода избавились).

Нет, ну если я еще могу понять функцию для генерации полного имени таблицы с кешированием, чтобы не выполнять сотни конкатенаций. Еще могу понять отказ от каких-то библиотек типа MODxAPI в пользу своей упрощенной версии. Но отказ от штатных средств MODX…

Без обид. Но лично я не понимаю кодинга, где вместо расширения мы занимаемся кастрацией и копипастом. С удовольствием бы помог в развитии, но пока времени не хватает, да и непонятно как помогать. Даже тот же easyForm я начал переписывать, но так из-за нехватки времени приостановился. Сейчас вижу уже версию 0.2 на гитхабе…
avatar
вроде от штатных средств modx нигде не отказывался, а тянуть все modx api ради того, чтобы скопировать ресурс тоже смысла нет.

Будут баги — поправим, если это кому-то будет нужно :) Да и другим поправить пару строк никто не запрещает — все в открытом доступе :)
avatar
Для примера:
1) Создаем документ с кавычкой.
2) Копируем документ.
3) ПОлучаем ошибку.
4) Profit.

Итог — опять внедряем фикс.
так ирония как раз в том, что используются штатные средства. Если уж мне говорят, чтоб я использовал не mysql_insert, а modx->db->insert, мол это безопасно и т.п. и т.д., а он потом валится от того, что в значении одного из полей одиночная кавычка (причем прилетевшая не откуда-нибудь, а из базы, куда средствами modx она и была помещена в таком виде) — то это не беда evoBabel, а беда скорее modx->db->insert ) Может проще сразу в ядре это дело фиксить, а не в каждом приложении? :)

Ну а насчет штатных средств еще раз — они везде и были применены, но если мне лень было писать по коду 20 раз что-то вида
$this->modx->db->getValue($this->modx->db->query($sql))


то я вполне логично заменил это на $this->getValue($sql) и определив метод как:

public function getValue($sql){        
        return $this->modx->db->getValue($this->modx->db->query($sql));
}


то не вижу никаких дополнительных трудностей, которые созданы таким путем :)
Комментарий отредактирован 2013-12-30 15:30:22 пользователем webber
avatar
Может проще сразу в ядре это дело фиксить, а не в каждом приложении? :)
Фикс в ядре приведет к двойному экранированию. Итог — на всех ранее созданных сайтах с предварительным экранированием получим «Hello world\'s» вместо «Hello world's».

тянуть все modx api ради того, чтобы скопировать ресурс тоже смысла нет
Там по сути всего 2 файла. MODX.php и modResource.php. Это не так уж и много. Более того, код который приходится писать на выходе намного короче получается и нет необходимости использовать функции немного сокращающие запись. Допустим
public function checkPage($id){
$result=$this->getValue("SELECT id FROM ".$this->content_table." WHERE id={$id} LIMIT 0,1");
        return $result;   
}

Легко сокращается до
$DOC->edit($id)->getID();

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

Да и другим поправить пару строк никто не запрещает — все в открытом доступе :)
Аналогично можно сказать и про библиотеку от которой было решено отказаться.Еще раз — дело добровольное. Но лишь вижу деградацию модуля в плане архитектуры кода. Да, были функции, а стал класс. Но в целом от этого не легче. Более того — завтра будете писать evoXXXXXXXX модуль и там опять будете копипастить эти же методы. Тут — берете и пользуетесь.
avatar
Ну тут с одной стороны как говорят «нет предела совершенству», а с другой — решение задач зависит от многих факторов: обеспеченность ресурсов, важность и т.п. Мне на данном этапе (да судя по интересу к теме и не только мне) — не нужен совершенный универсальный комбайн с расширяемостью во все стороны но в отдаленной смутной перспективе. Это делалось как рабочее решение для конкретной задачи — варианта многоязычного сайта на Evo «аля REVO-бабель» — о чем говорит и название темы и название самого инструмента.

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

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

п.с. придется походу 3-ю версию делать для следующего сайта путем скрещивания 1-й с modxApi и второй :)
avatar
п.с. придется походу 3-ю версию делать для следующего сайта путем скрещивания 1-й с modxApi и второй :)
Буду рад помочь. Этапы разработки готов обсудить в скайпе/icq/jabber на новогодних каникулах.

P.S. Еще заметил в файле action.php версии 0.2 куча sql-injection
avatar
Ну с учетом того, что этот файл используется только из админки, только для сторонней таблицы lexicon и только через ajax — не думаю, что там все так критично :)

Плюс наткнулся на такую проблему — хотел подключить его через index-ajax.php, но оказалось что сделать это практически невозможно с используемым плагином edatagrid для easyUI, т.к. он передает тип действия action через GET и одновременно сами данные через POST — а index-ajax одновременно, насколько я понял, два типа запроса не поддерживает.
avatar
этот файл используется только из админки
А если обратиться на прямую к этому файлу?
только для сторонней таблицы lexicon
А на что нам SQL injection?
и только через ajax
Подделывать заголовки никто не запрещал
avatar
все там будет хорошо
avatar
И все таки там есть SQL-injection. Пусть не такой явный как казалось мне на первый взгляд.

<?php
$data = array(
        "id"=>1,
        "name=(/**/SELECT/**/password/**/FROM/**/modx_manager_users/**/LIMIT/**/1)#"=>"Hacked by Agel_Nash;-)"
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://example.com/assets/snippets/evoBabel/lexicon/actions.php?action=update");
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, array("X-Requested-With: XMLHttpRequest"));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_REFERER, "http://example.com/");
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_USERAGENT, 'User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Widows NT)');
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_exec($ch);
curl_close($ch);
Комментарий отредактирован 2013-12-31 23:49:12 пользователем Agel_Nash
avatar
А теперь? )

А вообще с такой настойчивостью модх можно поломать через 70% других более распространенных сниппетов не доходя до лексиконов :)
Комментарий отредактирован 2014-01-02 11:31:59 пользователем webber
avatar
Теперь нормально. Но все-таки есть способ обойти такую проверку. Не буду углубляться, т.к. да, с такой настойчивостью можно поломать почти все…
avatar
По поводу использовать или нет API MODX в админке:
1. оно все равно там подключается, потому ресурсов не экономиться.
2. При дальнейшем обновлении с кажем на MySqli не придется переписывать ваше решение.

P.S. почитав диалог понял что Agel_Nash таки прав и использование готовых библиотек облегчает работу и добавляет функционал.
P.S. кста думаю нужно включить MODxAPI по умолчанию в MODX. там пару библиотек уже есть и думаю еще 1 не помешает и это даст возможность использовать библиотеки в своих решениях без необходимсти следить за библиотекой
avatar
Похоже тут какая-то путаница в терминах. Когда я говорю про то, что убрал MODxApi я имею в виду библиотеку modResourse. Т.е. как раз наоборот сейчас используется штатное API и DBAPI MODx вида modx->db->update или modx->db->insert.
Если эти запросы перестанут работать, то они перестанут работать везде, а не только в evoBabel. Поэтому непонятно, что именно повалится, т.к. сейчас везде используются именно штатные методы от MODx и DBAPI — там нет ни одного прямого запроса к базе или чего-то еще в обход модх.

Также не очень понял фразу
1. оно все равно там подключается, потому ресурсов не экономиться.
— если бы оно там стандартно подключалось и входило так сказать в комплект поставки, может быть и всего этого разговора бы не было :) А так, выйдет например новая версия, человек себе ее поставит, а потом приду я со своим evoBabel и поставлю ему наверх его новой версии modResource свою старую, включенную в комплект evoBabel — и у него чего-нибудь отвалится. Оно мне надо, чтоб потом писали вечные темы «после установки evoBabel повалился сайт» ?: ))

А если не включать в комплект поставки — объясняй потом каждому, что надо еще поставить modResource отдельно — тоже дело неблагодарное.

Именно поэтому я его и убрал из evoBabel, а не по каким-то там другим «идейным» причинам :)
Комментарий отредактирован 2014-01-03 15:08:10 пользователем webber
avatar
Добавил в репозиторий обе версии
extras.evolution-cms.com/packages/adminka/evobabel.html

Просьба кто потестирует отпишитесь все ли ок а то пока не успел
avatar
Вторую версию я ставил из репозитория собственного, так что с установкой проблем не было точно. Сайт работает в сети.
Возможно будут проблемы с пониманием что делать и в каком порядке — будем решать по мере поступления :)
avatar
тоже только что поставил на 1-м проекте все ок

единсвенно добавить создание автоматом TV- параметра
+ выбрать картинку в репозиторий что б симпатичная была )
avatar
логотипа точно от меня не дождетесь — страдаю «дизайнерским идиотизмом» (это когда понимаешь как бы было красиво, но вот как только начнешь это в фотошопе делать — плакать хочется от результата) )))) Так что тут если только кто-нибудь подкинет или готовая на глаза попадется ))))
avatar
Подойдет?
avatar
Че-то свастику напоминает ))) Лучше уж что-то такое
avatar
Всем доброго времени суток.
Спасибо автору за такую допку, но у меня вопрос.
В modx да и вообще новичек поэтому сильно не пинайте. Скажите плиз как сделать так что бы корневые папки такие как EN и RU не отображались на сайте. Вывожу меню через WayFinder, пытался принудительно дать Wayfindery id Корневой папки но тогда не меняется название пунктов меню. Что делать?? Делал все по инструкции из файла README.
avatar
Как и в любом другом месте — снять с них птичку «показывать в меню» )
avatar
Да я пытался но тогда вообще ни чего не показывает, ни одного пункта
avatar
А меню чего вы хотите вывести? Обоих сайтов сразу начиная с корня?
avatar
У меня была структура сайта до того как начал ставить мультязычность
Пункт 1
Пункт 2
Пункт 2,1
Пункт 2,2
Пункт 3
Пункт 4
Полсе того как начал заливать мультиязычность структура поменялась

RU
Пункт 1
Пункт 2
Пункт 2,1
Пункт 2,2
Пункт 3
Пункт 4
и на сайте за место того что отображалось просто меню теперь всего лишь 1 пункт RU а остальные выпадают из него. Как то так
Комментарий отредактирован 2014-01-23 10:34:35 пользователем Nitihyami
avatar
Так вы определитесь — на чистый modx или все-таки там уже что-то есть. Если вы переместили все свои разделы в новую папку (а так и должно быть, т.е. папка языка должна быть в корне), то надо поменять в вызове вывода меню startId на новый (в нашем случае, на id языка)
avatar
хочу попробовать на чистый modx залить и посмотреть что получится
avatar
ну так вызов какой? startId=`0`? Wayfinder не ходит сквозь «выключенные из меню» родителей, да и на многоязычном сайте это ни к чему. Пусть у вас папка русского 1, английского — 2. Обе выключить из меню, выводить меню русского сайта startId=`1`, английского — startId=`2`

Если автоматом — заводите в лексиконе (модуле) параметр к примеру Корневая папка со значениями 1 и 2 для русского и английского и в нужном месте шаблона вызываете [[Wayfinder? &startId=`[%Корневая папка%]`...]] — получите меню нужного языка в нужном месте
Комментарий отредактирован 2014-01-23 10:33:35 пользователем webber
avatar
Ок я понял про что Вы
avatar
поправьте меня если я не так понял. то есть у меня будет на странице шаблона несколько вызовов WayFindera и по клику на ссылку переключателя языков я просто буду 1 скрывать а второй показывать так?
avatar
аа то есть так можно. Ну ладно буду пробовать спасибо за быстрый ответ.
avatar
Так и нужно ))) Аналогично и для вывода всяких новостей, каталогов и т.п. нужно указывать вызов родителя соответствующего языка через [%Папка каталог%] (к примеру) или [[lang? &a=`Папка новости`]] (к примеру), где для Папка каталог и Папка новости в модуле указаны id для всех языков сайта. Двойных/тройных и прочих вызовов делать не нужно, скрывать ничего не нужно тоже )
avatar
Скажи а есть где нить полная документация по модулю?
avatar
Надо бы пункт 3 в предупреждениях (про поле description) подписать «Устарело, актуально для версии 0.1»
avatar
Можно править:)
github.com/evolution-cms/docs/blob/master/03_Extras/07_Packages/evoBabel/index.md
поле PR попадает на сайт:)
avatar
Пока кроме readme нет ни полной, ни неполной. Изучаем спрос так сказать ))))
avatar
Доброго времени суток. Вопрос такой. Попытался поставить на чистый modx-1.0.12. Пошел по инструкции github.com/evolution-cms/docs/blob/master/03_Extras/07_Packages/evoBabel/index.md. Теперь при загруке страницы выходит ошибка парса. Вроде проблема в плагине evoBabel и вроде как на строке 111
Строка 111 — foreach($siteLangs as $k=>$v){
Ошибка — Error: Invalid argument supplied for foreach()
комментирую данную строку и сайт нормально начинает работать. Что скажете??

Вот скрин ошибки

Комментарий отредактирован 2014-01-24 09:28:16 пользователем Nitihyami
avatar
Решилось добавление <?php вначале плагина. В исходнике просто есть закрывающий а открывающего нет
avatar
Там ни открывающий ни закрывающий не нужен. Вы скорее всего в настройках плагина не задали или неверно задали id шаблона языка. Либо не создали ни одного ресурса с таким шаблоном (корневой папки RU например).
avatar
Я про то что у Вас в исходном файле есть закрывающий ?> в конце документа
А вот мои настройки плагина

id шаблона языка — 5(шаблон под названием язык)
id TV языковых связей — 4(tv-параметр под названием relation)
язык по умолчанию — Русский (алиас корневого ресурса RU)
avatar
А я про то, что закрывающий тег там тоже не нужен, как и открывающий (это просто остался кусок откуда-то, он ни на что не влияет). А ошибка потому, что у вас в дереве отстутствует ресурс с шаблоном «язык» (под номером 5) — скорее всего :)

И соответственно он не видит массива из хотя бы одного «языкового» ресурса в дереве и не знает что делать.
avatar
мм не знаю в чем прикол, но я пересоздал шаблон язык и назначил снова и все заработало. Может глюк в системе. Но изначально для RU точно шаблон язык был.
avatar
Я может чет не понял, ссылки всегда такого плана site.com/ru/some_text site.com/en/some_text, нет возможности прятать дефолтный язык?
avatar
Ну в принципе на многоязычных сайтах это не особо и принято, но для modx ничего невозможного нет — снимите птичку «показывать в url» для языка ru (корневой папки) и будет вам дефолтный язык без алиаса ru :)
avatar
Точно… блин сразу чет и не вспомнил про такую возможность :) аж стыдно :)
avatar
А как править статичный текст в чанках??
avatar
[%Статичный текст в чанках%] или [[lang? &a=`Статичный текст в чанках`]] с заведением соответствующей строки в модуле. Там же в модуле и править.
avatar
И еще 1 вопросик Где лежит шаблон вывода переключалки языков?? Мне нужны флаги без текста.
avatar
Где лежит шаблон вывода переключалки языков

assets\snippets\evoBabel\config\config.php
avatar
мм файл нашел но все правки которые в него внес не применяются на сайте. Кэш чистил и на сайте и в браузере.
Комментарий отредактирован 2014-01-27 03:45:21 пользователем Nitihyami
avatar
точнее не применяется только для Главной страницы
как то не понятно применяется
Комментарий отредактирован 2014-01-27 04:13:52 пользователем Nitihyami
avatar
Что именно непонятно выводится и что вы в итоге выводите (в файле и на сайте)?
avatar
Ну вот смотри. Я беру файл assets\snippets\evoBabel\config\config.php и редктирую его.
Изачально там так

<?php
//@author webber (web-ber12@yandex.ru)

if(!defined('MODX_BASE_PATH')){die('What are you doing? Get out of here!');}

//активный язык отдельно от списка
$activeLang='<img src="http://assets/images/langs/flag_[+alias+].jpg"><a rel="nofollow">[+name+]</a> <img src="http://site/imgs/lang_pict.jpg">'; 

//активный язык в списке
$activeRow='<img src="http://assets/images/langs/flag_[+alias+].jpg"> <a rel="nofollow">[+name+]</a>';

//неактивный язык списка
$unactiveRow='<img src="http://assets/images/langs/flag_[+alias+].jpg"> <a rel="nofollow">[+name+]</a>';

//обертка списка языков
$langOuter='[+wrapper+]';
?>


я переделал на такое
<?php
//@author webber (web-ber12@yandex.ru)

if(!defined('MODX_BASE_PATH')){die('What are you doing? Get out of here!');}

//активный язык отдельно от списка
$activeLang='<img src="http://assets/images/langs/flag_[+alias+].jpg"><a rel="nofollow">[+name+]</a> <img src="http://site/imgs/lang_pict.jpg">'; 

//активный язык в списке
$activeRow='<div style=«margin-right: 5px; class=»active"><a rel="nofollow"><img src="http://assets/images/langs/flag_[+alias+].jpg"></a>';

//неактивный язык списка
$unactiveRow='<a rel="nofollow"><img src="http://assets/images/langs/flag_[+alias+].jpg"></a>';

//обертка списка языков
$langOuter='[+wrapper+]';

?>


просто перенес img внутрь ссылки и добавил margin так вот в некоторых пунктах меню все отображается нормально то есть флаг становится привязан к ссылке. а в некоторых нет ни каких изменений не знаю с чем это связано. Захожу в админку просто пересохраняю главную страницу и все везде нормально отображается. Впринципе мне уже не надо, но мало ли у кого то же самое будет или я единственный криворукий.
Комментарий отредактирован 2014-01-27 06:33:55 пользователем Nitihyami
avatar
Странное решение да и div для активного языка не закрыт, и с кавычками какая-то свистопляска :)
Не очень понял также про «некоторые пункты меню». Если вам нужны флаги в ссылках, почему бы просто не стилизовать через css нужный вам внешний вид исходный код

//активный язык в списке
$activeRow='<a class="lang [+alias+] active" href="[+url+]">[+name+]</a>';

//неактивный язык списка
$unactiveRow='<a class="lang [+alias+]" href="[+url+]">[+name+]</a>';



a.lang{display:inline-block;width:20px;height:20px;background:url() 0 0 no-repeat;font-size:0;color:transparent;}
a.active{margin-right:5px;}
a.ru{background-image:url(../imgs/ru.jpg);}
a.en{background-image:url(../imgs/en.jpg);}


ну или если таки надо чтоб были картинки именно вставленные, то

//активный язык в списке
$activeRow='<a class="lang [+alias+] active" href="[+url+]"><img src="assets/images/langs/flag_[+alias+].jpg"></a>';

//неактивный язык списка
$unactiveRow='<a class="lang [+alias+]" href="[+url+]"><img src="assets/images/langs/flag_[+alias+].jpg"></a>';


и соответственно в нужном месте шаблона — [+switchLang+]
avatar
а это я просто забыл через code написать;)
avatar
А вообще я сделал так как Ваш второй вариант.
avatar
Не уверен, что все сделано как надо, ибо когда все сделано как надо, оно и работает как надо :) Может тоже где-то div забыли или еще чего, а может случайно галочку на каком-нибудь событии плагина убрали :)
avatar
А какой Вы слайдер юзали на демо http://interconest.by/.Очень надо. У меня на сайте слайдер Orbit Kit и не могу перевести подпись к слайдам.
avatar
Скрипт carouFredSel через multiTV для каждого языка на главной странице свои подписи.
avatar
Обновил вывод языков — стало еще удобнее управлять версиями на разных языках (можно заказчику даже не говорить, что он по дереву ходит)))

avatar
о да так логичнй :)
а дерево в TreeTabs ) и будет мега :)
avatar
Обновился, но список языков по прежнему выводится в ТВ параметре в самом низу


Грешным делом подумал с каким-то плагином конфликт, но нет. Даже отключив все осталось по старому. Я может что-то не так делаю?
avatar
Похоже на то, что в модуле не появился новый параметр show_panel=1 или файл скрипта script.js в папку сниппета не докачался. Честно говоря по поводу технологии обновления особо сказать ничего не могу, т.к. замечал сам, что при обновлении того, что уже есть, часть остается старой, а часть меняется.

Я удаляю все полностью в том числе и папку evoBabel и все плагины/сниппеты/модули по этой теме из админки и ставлю по новой :)

Если все докачалось, то разве что вариант, что папка админки (manager) не на одном уровне с assets (унесена куда-то в целях маскировки)
Комментарий отредактирован 2014-02-04 18:28:01 пользователем webber
avatar
Спасибо. Упустил новый параметр show_panel
avatar
Делал его на случай «если что-то пошло не так». Тогда можно эту панель отключить, поставить тип ТВ для связей text и глянуть чего же там внутри все-таки записано без необходимости лезть в базу
avatar
Что-то я часа 2 ковыряю, не пойму от куда циферка 5 вылазит… В шаблоне нет, в чанках нет…
<div class="boxLang">
				<a class="choosedLang" href="#"><img src="/inc/img/ru.png" alt="">Ru<span class="languageRight"></span></a><u><strong>5</strong></u>
				<div class="openLang">
					<ul><li class="active"><a href="#"><img src="/inc/img/ru.png" alt="">Ru <span class="languageRight"></span></a></li><li><a href="/en/home.html"><img src="/inc/img/en.png" alt="">En <span class="languageRight"></span></a></li></ul>
				</div>
			</div>
avatar
Судя по всему эта часть
<a class="choosedLang" href="#"><img src="/inc/img/ru.png" alt="">Ru<span class="languageRight"></span></a><u><strong>5</strong></u>
— это ваш вывод активного языка отдельно от списка. В ту сторону и копать надо (либо в файле конфига assets\snippets\evoBabel\config\config.php либо в самом плагине evoBabel лишний код в переменной $activeLang
avatar
конфиг — устанавливается в плагине evobabel — так что если не в assets\snippets\evoBabel\config\config.php, то смотреть какой именно файл используется (в настройках плагина) и там проверять.
avatar
Оказалось он выводит значение «id TV для хранения языковых связей», с чего тока так я пока не поля.
Причем я могу ввести 1491307502365235 — любое значение, вывод переключалки работает и показывает то, что ввели :) Прикольно.
Комментарий отредактирован 2014-02-14 14:49:40 пользователем SergeyMiracle
avatar
Ну вот прикол в этом куске… зачем так?
$modx->setPlaceholder("activeLang", $currLang.$eB->params['rel_tv_id']);
avatar
да, похоже враги прокрались и подсунули эту гадость — давно просто не пользовался этой переменной. Это конечно надо удалить.

.$eB->params['rel_tv_id']


Пофиксил. Благодарю за бдительность :)
avatar
Вопросик, в каком месте можно выставить, чтоб созданный перевод был по умолчанию опубликован?
avatar
не очень понял вопрос. Ставьте стартовой для сайта главную страницу из той папки, которую хотите видеть по умолчанию плюс в модуле есть настройка алиас языка по умолчанию — и все.
avatar
Созданный первод по умолчанию — не публикуется… то есть в настройках галочка убрана! Я про это. А надо чтоб галочка стояла!
avatar
А, в смысле ресурс не публикуется. Нет такого функционала по умолчанию, т.к. публиковать непереведенные ресурсы как-то не очень хорошо, если это действительно многоязычный сайт, а не для понту второй язык добавлен :)

Хотя его недолго и добавить.

Вот тут строка, вызывающая функцию копирования ресурса, а сама функция тут — сама функция в которой published=0 по умолчанию.

upd Добавил такую функциональность.
Комментарий отредактирован 2014-02-14 15:42:07 пользователем webber
avatar
Спасиб.
avatar
Установил с репозитория в снипете evoBabel параметры по умолчанию указал &lang_template_id=id шаблона языка;text;5 и вставил id в итоге пишет что не найдет id tv или шаблон в модуле тоже все было указано
заработал когда указал в снипете на прямую
$params['rel_tv_id'] = 5;
$params['lang_template_id'] = 5;
может я где накосячил а может не нет
avatar
косяк скорее всего в районе «общих параметров» — либо у модуля их не открыли и не привязали туда нужные сниппеты/плагины, либо у самих плагинов не импортировали общие параметры из модуля.

Сниппет switchLang удален, его функционал перенесен в плагин evoBabel
avatar
надо в доке указать как важные моменты в частности про настройку модуля
avatar
Есть оно там все в пунктах 16, 18-19 как минимум — github.com/evolution-cms/docs/blob/master/03_Extras/07_Packages/evoBabel/index.md )) только кто ж их читает так далеко )))
Комментарий отредактирован 2014-03-04 09:41:42 пользователем webber
avatar
и нету снипета почему то switchLang или он сейчас не нужен? (ставил с ревозитория)
avatar
Здравствуйте. Хорошая штука, все работает, но у меня вопрос — а как с картинками и ссылками в коде? Например мне надо поставить ссылку на главную страницу и логотип для разных версий разный? Я в общем-то костыль придумал в виде:

<a href="[~[%id%]~]" class="logo"></a>


прописав ID ресурсов в модуле, но гложет меня мысль, что может быть лучше решение?
avatar
Почитал выше, понял что это и есть верное решение, прописать id в модуле. Но как быть с изображениями?
avatar
Правильное решение, только надо писать просто Главная страница в модуле и в соответствующих языках проставлять ее id. Потом на ссылке просто [~[%Главная страница%]~].
Можно конечно и слово id в модуль ставить ничего страшного не случится. Но для корректной обработки страниц 404. Т.к. там идет поиск страницы ошибки для соответствующей версии в таком порядке «Страница ошибки» — «Главная страница» — «Корневая папка». т.е. id этих трех страниц для языков надо задать в модуле. Плюс я завожу еще обязательно строку Язык, в которую пишу алиасы языков. И таким образом конструкция вида logo_[%Язык%].png даст нам для каждого языка свое лого logo_ru, logo_en и т.п.
avatar
Спасибо, про картинки че-то сам не доехал. У меня просто организм восстает против того, чтобы в коде использовать переменные на русском, да еще и с пробелами)))
avatar
Кста предлагаю в модуле по умолчанию создать что б было пару записей
которые всегда нужны в частности как минимум 4 строки уже получается
avatar
Еще вопрос по функционалу хочу задать. Столкнулся с тем, что если у русской страницы нет английского аналога, то при переключении страницы получаю ошибку: « Incorrect number of templates returned from database »

Но если мне не нужен английский аналог данной страницы, как быть? Есть ли вариант, чтобы если страницы-аналога нет, то перебрасывало бы просто на главную выбранного языка?
avatar
Кстати, вот такой вызов тоже валит страницу с ошибкой:


                            [[Ditto?
                            &documents=`[%side-populars%]`
                            &extenders=`nosort`
                            &tpl=`@CODE:<li><a href="[~[+id+]~]">[+pagetitle+]</a></li>`
                            &noResults=` `]]
avatar
1. совершенно не подозреваю что у вас хранится в переменной [%side-popular%]
2. рекомендую не использовать вообще в названиях переменных дефисов — т.к. при определенных условиях они могут интерпретироваться как минусы
3. если эта конструкция находится где-то глубоко в чанках — использовать вместо языковых плейсхолдеров [%плейсхолдер%] сниппет [[lang? &a=`плейсхолдер`]] — т.к. глубина парсинга урезана в связи с тем, что получить второй phx не было желания.
avatar
В [%side-populars%] хранится id ресурса для вывода. При этом тот же multiTV свободно принял и корректно работает с таким указателем. И ditto принимает как parents, но не принимает как documents

За совет с минусом спасибо, как-то даже не задумывался раньше.
avatar
ну так тут проблема скорее в ditto или экстендере nosort — может ему мало одного документа и он хочет чего-нибудь через запятую.
avatar
Да, я в общем-то и имел в виду несовместимость по данному параметру. Обошел ее через multiTV. Кстати, еще есть мелкий баг совместимости, чисто для информации. При использовании плагина TreeTabs для деления язык на табы работает нормально только если в конфигурации выбираешь не показывать родителя. А вот если выбрать показывать, то видны ресурсы только первой вкладки, все остальное пустое.
avatar
Поскольку evoBabel не занимается никакими переключениями — суть проблемы совершенно непонятна. При правильной настройке по инструкции evoBabel формирует лишь ссылки на ресурсы в следующем порядке:
1. если есть связанный ресурс на нужном языке — ссылку на него
2. если такой ресурс отстутствует — на ресурс, связанный с родителем данного ресурса
3. если и связанного родителя нет — на корневую папку искомого языка

Таким образом у вас имеется просто какая-то ссылка, при переходе по которой вы получаете некую ошибку. Это надо разбираться что за ссылка и почему у вас ошибка на странице с этой ссылкой.
Комментарий отредактирован 2014-03-09 08:22:40 пользователем webber
avatar
Да, он отправляет меня на страницу с урлом вида site.net/en.html, которой у меня нет. А родителем является именно контейнер EN. То есть отправка технически правильная, а вот логически нет — корневая папка не является ресурсом во фронтенде
avatar
Ну страница en.html если создана в любом случае есть. Вопрос в другом немного, чем вы изначально озвучили. Попробуйте вот эту правку внести в код плагина.

Я просто в шаблон языка размещаю сниппет, который редиректит на главную страницу этого языка вида
<code>[!redirect? &docid=`[*description*]`!]</code>
и сам код сниппета
<code><?php
$modx->sendRedirect($modx->makeUrl($docid));
?></code>
когда по инструкции в description страницы языка вписывается id главной страницы этого языка, то проблем нет — я и не задумывался, что они у кого-то могут возникнуть :)

Но в принципе, приведенные правки чуть выше решение этой проблемы автоматизировать должно.

upd: вот эта правка будет надежнее.
Комментарий отредактирован 2014-03-09 09:37:17 пользователем webber
avatar
Даже со вписанным id и сниппетом не сработало. А вот приведенный в самом начале фикс помог, спасибо)
avatar
Здравствуйте, в чем может быть проблема с модулем добавления переводов, не сохраняет добавленные переводы, в табличке все редактируется но при сохранении не появляется id и не добавляется запись в базу, так же если запись добавить ручками, она не выводится в модуле ????
avatar
Аналогичная проблема. Решили её? Версия движка 1.1b-d7.0.16.
Комментарий отредактирован 2014-11-19 20:32:00 пользователем Wooof
avatar
Скорее всего вы пытаетесь ввести свои данные в строку поиска, а надо сначала нажать на кнопку «добавить», а уже затем в появившейся новой строке вводить нужные переводы. Для сохранения жмем либо «сохранить» либо просто переводим курсор на другую строку (кликаем по ней) — при ее наличии.
avatar
Ответ: «Подозреваю, что вы пытались внести данные в строку фильтра — обведена красным (она для поиска, а не для ввода новых). Надо жать на кнопку «создать», появится строка, куда и вносим — потом или на кнопку «сохранить» жмем для сохранения или переводим курсор на любую другую строку в таблице (если она есть).»
avatar
Спасибо за данный модуль. Удобные и простые многоязычные сайты на Эволюции теперь реальность! :)

Предложение на доработку, если будет время:
Когда выбираешь документ в дереве и переключаешься к его копии на другом языке, в дереве слева выбранным остаётся первый документ. Удобно было бы что бы дерево перезагружалось и открывалась нужная ветка с активным редактируемым документом.
avatar
И ещё созданные языковые копии документов по умолчанию не публикуются, хотя галочка стоит. Хотелось что бы наследовалось от первоначального документа.
avatar
В настоящий момент в модуле можно выставить публиковать или нет по умолчанию.
Насчет «разворачивания дерева» — было бы неплохо, но это такая специфика модха — при нажатии на дерево пункт становится активным просто по клику (но не перегружается), т.к. работа с деревом идет в другом фрейме (чем основной контент). А чтоб что-то придумать, чтоб перегружалось именно дерево — пока времени на это, к сожалению, нет :)
avatar
А можно посмотреть внутренности тестовго сайта?
avatar
Modx evo 1.0.13-d6.7
evoBabel 0.2
На странице, где вызывается ajax запрос, сыпятся ошибки от плагина evoBabel и нарушается работа скрипта. После отключения плагина все нормально работает и возвращается ответ
avatar
Обидно..))

п.с. в смысле обидно, что не я участник битвы экстресенсов, т.к. не могу догадаться ни что за плагин у вас, ни что за ajax-запрос, ни что за ошибки сыпятся :))
avatar
Передается id, в скрипте работает runSnippet Ditto, результат — pagetitle.
Ошибка странная- пустая (если смотреть через админку)
avatar
Ну теперь то оно конечно стало гораздо понятнее — куда-то как-то зачем-то каким-то способом передается id, где-то зачем-то непонятно каким образом вызывается Дитто через runSnippet (видимо с какими-то доп.параметрами, полученными какими-то php командами), и в результате сыпятся «пустые ошибки» (не знаю что это, но допустим что так и есть) :))))

А можно без «объяснения на пальцах» просто привести код того, как где и что вызывается и скрин того, что получается? А еще лучше — просто доступ к сайту, можно в личку. Ну это так — если вам нужно решить какую-то проблему.
Если же цель просто в констатации факта, что у вас какие-то ошибки при разработке сайта — то можно оставить все как есть :)
Комментарий отредактирован 2014-05-15 18:30:24 пользователем webber
avatar
Аяксом передается параметр id в скрипт, в котором вызывается Дитто через runSnippet, который выдает pagetitle

<code><head>
<script>
function showOption(el)
  {
    $.ajax({
                type:'POST',
                url: '/ajax.php',
                data:{id:el.options[el.selectedIndex].value},
                success:function(data) {        
            			$('.div').html(data);
                        }
        });
        return false;
}
	</script>
<head>

<body>
<select id="d1" onchange="showOption(this)">
<option value="41">41</option>
<option value="42">42</option>

<div class="div"></div>
</body></code>

<code><?php
define('MODX_API_MODE', true);
include_once(dirname(__FILE__)."/index.php");
$modx->db->connect();
if (empty ($modx->config)) {
    $modx->getSettings();
}
$modx->invokeEvent("OnWebPageInit");

if(!isset($_SERVER['HTTP_X_REQUESTED_WITH']) || (strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest')){
        $modx->sendRedirect($modx->config['site_url']);
}
$out = $modx->runSnippet('Ditto', array(
        'documents' => $_REQUEST['id'],
        'tpl' => 'ditto'
));
echo $out;
?></code>

Скрин ошибок из админки

Приходят сообщения на почту, что это именно evoBable
Комментарий отредактирован 2014-05-15 19:25:25 пользователем zloyxrom
avatar
Я так и знал, что ситуация у вас такая, просто хотел, чтобы вы и сами поняли в чем дело.
Вам нужно закомментировать строку
$modx->invokeEvent("OnWebPageInit");
, т.к. она все равно вам не нужна, а вовлекает ненужное событие OnWebPageInit, по которому срабатывает evoBabel.

Про возможные ограничения говорилось и в теме, в которой обсуждался данный метод ajax. Одно из таких ограничений — ваш файл ajax.php не генерирует переменную вроде $modx->documentIdentifier, которая используется в плагине evoBabel для определения того из какого языка ресурс.
avatar
Ну тупооой!
Большое спасибо!
avatar
Доброе время суток. Маленький вопросик. Это у меня одного такая ситуация что если к шаблону нет, кроме языкового, привязанных tv-параметров то не выводится tv-параметр для создания другой версии страницы??
avatar
Нет конечно, не у одного. И тут в ветке обсуждалось, и даже в readme в самом конце с подзаголовком «ВАЖНО» про это написано :))
avatar
Спасибо! Не дочитал просто до конца readme
avatar
Здравствуйте

перечитал все комментарии… наверное один я «завтыкал» где то… при попытке создания более чем одного перевода (у меня их 4) — в ТВ параметр relation не верно записуются связи… вот скрины:



после долгих попыток их удалить (удаляешь значение сохраняешь, удаляешь-сохраняешь документ, а оно снова там)… ну с 10 попытки таки ТВ становиться пустым — тогда пишу туда вручную значения), все начинает работать правильно.

Проверял не раз — вроде бы все верно настроил, никто с таким не стыкался?
avatar
Похоже не очень удачно пофиксил кое-чо прошлый раз. Попробуйте скачать текущую версию и удалить предварительно все эти связи прямо из базы чтобы они не мешали.
avatar
Спасибо большое, вы имеете ввиду отсюда скачать http://extras.evolution-cms.com/packages/adminka/evobabel.html? (Версию: evoBabel 0.2 02-01-2014, ато может я не оттуда качал)

upd

Догадался, и скачал здесь:
https://github.com/webber12/evobabel-0.2

Еще раз большое спасибо! Сейчас отпишусь как оно пошло теперь.
Комментарий отредактирован 2014-06-22 12:42:21 пользователем chosenman
avatar
Это одна и та же версия — github.com/webber12/evobabel-0.2/archive/master.zip :)

Либо обновить через evoStore (это та же версия), предварительно удалив все что было установлено до этого физически — и сниппеты, модули, плагины, и сами папки evoBabel
Комментарий отредактирован 2014-06-22 13:37:00 пользователем webber
avatar
Теперь все работает просто идеально!!! Спасибо тебе большое за такой хороший продукт.

Если можно, хотел бы задать 2 вопроса (немного по наглею на радостях):

1. В плагине evoBabel «ids TV для синхронизации» — это понятно (синхронизировать картинки в товарах, цены, артикула и т.д. на разных языках). А что значит (или как это использовать) «ids шаблонов для синхронизации»?

2. Как пользоваться/как работает модуль «evoBabelLexicon»? Сначала думал что то типа — создаешь параметр с именем «ID каталога» — и в колонках созданных языков (ru,ua,en) заносишь номер соответствующего каталога для каждого из языков. А в чанках или шаблоне пишешь [%ID каталога%] в нужном месте. Но тогда не понятно зачем столбец с названием «id»
? Что туда писать?
avatar
1. id шаблонов используется совместно с id тв для синхронизации, т.е. нужно чтобы совпал и id tv и id шаблона — тогда будет произведена синхронизация. Алгоритм такой — проверяется сначала шаблон ресурса. Если он находится в списке синхронизируемых, то соответственно для него синхронизируются все тв из списка. Если шаблон не в списке — то не синхронизируется. Это например на тот случай, если нужно синхронизировать картинки товара, но не нужно синхронизировать картинки новостей, и при этом используется один и тот же тв для картинки :)

2. колонка id не редактируемая, просто показывает id записи в таблице. А так — создаете параметры для разных языков и на сайте выводите их либо как [[lang? &a=`Имя параметра`]] либо [%Имя парамера%]
Обязательно создать параметры Главная страница, Корневая папка, Страница не найдена с заданием id этих ресурсов для каждого из языка. остальное — по мере необходимости.

И вопрос. В модуле имеется возможность включения показа версий не в нижней части (там где ТВ), а в верхней части ресурса. На скрине почему-то внизу. Это просто так сделано (поставлен 0 в поле «Показывать панель») или оно не работает у вас?
avatar
1. Шикарно — наперед предусмотрели такой важный момент!
2. Спасибо за пояснение. Т.е. обязательные «Главная страница», «Корневая папка», «Страница не найдена» — где то прошиты в компонентах и используются?

— по поводу вашего вопроса: поставлен 0 в поле «показывать панель», так как в результате предидущих «глюков» после создавания более чем 1 языковой версии, при редактировании документа «исчезало» полностью все правое поле в MODx, когда поставил 0 — начало отображаться снова (но появились артефактные панели переключений языков внизу)

и если можно еще один вопрос — давно ломаю голову, но готового ничего не находил:
— Можете ли вы теоретически разработать модуль на основе jquery easy ui с помощью которого можно будет редактировать цены товаров например, и искать их по артикулу или имени (pagetitle документа) (а цены и артикулы хранятся в соответствующих ТВ) ?? (Конечно же не бесплатно.)
avatar
Почти то что вам нужно уже давно разработано. Осталось немного подпилить под конкретные цели.
avatar
Спасибо большое за наводку!!!

Странно, думал я уже весь интернет перелопатил, чего только в гугле и яндексе не писал. Но такого не находил.

У меня зародилось сомнение что "autoFilter" — возможно не самое лучшее/простое решение для фильтрации товара.

Скажите может есть что то проще?

autoFilter — с первой попытки не дался, но я не теряю надежды)…
avatar
Скоро грозятся вот это доделать :) Хотя это все уже не относится к теме топика, поэтому предлагаю свои вопросы задавать в отдельных темах, а не захламлять тему «мультиязычность» :)
avatar
в поле «показывать панель» теперь стоит 1 — и все идеально работает. Какая счастливая случайность — читал документацию YAMS очень долго, вычитывал форумы… так долго читал что пришлось отложить до лучших времен, и бац! Нахожу ваше решение… как я рад что не поставил YAMS ))
avatar
Заметил особенность, при синхронизации ТВ параметров Чек бокс «нет в наличии»:
— когда ставишь галочку, «нет в наличии» — срабатывает на обоих языковых версиях
— когда снимаешь галочку «нет в наличии» — срабатывает только на одной языковой версии, иду в другой язык и там тоже снимаю галочку.

Для меня это абсолютно не критично, и возможно только у меня и наблюдается, но все же решил сообщить.
Комментарий отредактирован 2014-07-11 10:23:00 пользователем chosenman
avatar
Точно, есть такое дело из-за особенностей хранения пустых значений либо значений по умолчанию в MODx (верхнее просто удалять из базы если значение пустое).
Попробуйте вот эту правку.
avatar
Применил «правку» — и оттестировал, действительно синхронизация теперь происходит полностью!!! Спасибо вам.
avatar
Подскажите пожалуйста, почему может не работать вывод плейсхолдера [+switchLang+]


Заранее спасибо за ответ!
Комментарий отредактирован 2014-07-17 10:25:47 пользователем Vorob
avatar
Исходя из представленной исчерпывающей информации можно ответить только одно — понятия не имею почему у вас не выводится этот плейсхолдер и действительно ли он не выводится :))))
Комментарий отредактирован 2014-07-17 11:09:29 пользователем webber
avatar
Извините, я пока новичок, что надо прислать чтобы было понятно в чем дело?
avatar
Есть у меня подозрение, что плейсхолдер то у вас сформирован, просто ссылки с пустым текстом, т.к. вы ничего не указали в полях longtitle и description для ваших корневых языков :)
Проверить так ли это на самом деле можно с помощью какой нибудь opera dragonfly или chrome — просмотр кода элемента. Вполне может случиться, что у вас в нужном месте есть что-то типа такого
<a href="/en/"></a>
с пустым текстом внутри :)
avatar
в полях longtitle и description вписано название языка и id главной страницы

в исходном коде на месте где должен быть плейсхолдер
просто пустое место
Комментарий отредактирован 2014-07-17 16:49:17 пользователем Vorob
avatar
avatar
А общие параметры модуля в плагин и сниппеты вы импортируете?
avatar
Да в evoBabel, lang и evoBabel плагин
avatar
Ну значит дайте доступ к сайту и я найду что не соответствует инструкции :)
avatar
Отправила вам пароли в сообщении. Огромная вам благодарность за помощь.
avatar
Как и обещал — тут же обнаружил ошибки- были сброшены все события для плагина. После их возвращения назад согласно (в том числе согласно инструкции, они там перечислены) — все заработало как надо :)
avatar
Добрый день! Возникла следующас проблема. При присвоении плагину системного события OnWebPageInit выдает
Fatal error: Call to undefined function mb_substr() in Z:\home\saittest\www\manager\includes\document.parser.class.inc.php on line 3026
avatar
А у вас модуль mbstring подключен? Можно посмотреть в phpinfo.
avatar
Не припомню чтоб эта функция где-то в плагинах evoBabel использовалась. Но в любом случае для корректной работы сайта в кодировке utf-8 рекомендую в настройках хостинга разрешить mbstring (или запросить у провайдера, чтобы он в конфиге разрешил).
avatar
Здравствуйте. Стоит последняя сборка Дмитрия, установила из репозитария evoBabel. Настроила по инстукции из readme. Но при переходе на /en/ пустая страница, а главная отображается на /main.html

В чем может быть дело?
Комментарий отредактирован 2014-10-17 17:41:47 пользователем eberezina
avatar
Редиректить надо в шаблоне язык — где-то я об этом уже писал.
Создаете сниппет redirect вида
<?php
$modx->sendRedirect($modx->makeUrl($docid));

а в шаблоне Язык вставляете его вызов
[!redirect? &docid=`[*description*]`!]


при этом по инструкции в этом поле description для каждого языка внесен уже id главной страницы соответствующего языка.
avatar
Спасибо огромное! Заработало!))
avatar
Поначалу все заработало, но теперь почему-то перестали синхронизироваться tv параметры. Сохраняются только pagetitle, content и другие стандартные поля. А tv на обоих языках одинаковые((
avatar
Все работает. Это я тормоз))) синхронизировала их сначала, а потом удивляюсь))
avatar
Здравствуйте!
А можно задать синхронизацию системного параметра «Доступен для поиска»?
avatar
Применил на одном из новых сайтов — работает. Автору — спасибо.

Вопрос — а как синхронизировать уже созданные ресурсы? Так получилось, что в ветке «en» моя помощница наделала вручную копий русскоязычных ресурсов, не пользуясь ссылкой «создать языковую версию» — просто копировала русскоязыные ресурсы и искуственно переносила в ветку «en». Сносить их и создавать заново не хотелось бы, так как она выполнила достаточно масштабную работу и перевела на английский контент, tv-параметры (которых много).

Я так понимаю, что нужно вручную в базе данных заполнить для обеих веток tv-параметр «relation» по аналогии с тем, как он заполнен для тех ресурсов, где языковые версии созданы, вариантов проще и быстрее нет?
avatar
Сильно проще и быстрее нет. Но можно временно установить тип для этого ТВ relation в text и просто задать эти значения вручную не залезая в базу ( по аналогии с теми, что уже заданы — эта «аналогия» при установке типа text также станет очевидна).
avatar
Подскажите, пожалуйста, как для английской версии отобразить свою страницу 404? Перевод ее создан в папке en, а по факту отображается главная страница.
Комментарий отредактирован 2014-10-20 18:55:52 пользователем eberezina
avatar
Задать в модуле переводов для каждого языка свою страницу 404 легко и просто — достаточно там создать строку с названием Страница не найдена и вписать туда id для каждого языка.
avatar
Спасибо.
avatar
Добавить бы еще автоперевод текстов)) Нажал создать в инглише и он уже сразу все пейджтайтлы и содержимое перевел))))))
avatar
Лучше вообще без многоязычности тогда, чем так.
avatar
Уфф, не осилить столько комментов. Скажите, мануал на github.com/webber12/evoBabel/blob/master/readme.md рабочий? А то там говорится про description в п.6, а здесь в upd 30.12.2013 сказано, что поле description не используется. А ещё через Extras сабж не устанавливается: «oops! The page you are looking does not exist! Try to search something different.»
1.0.14-d6.9
avatar
Уже почти год актуальна версия 0.2 github.com/webber12/evobabel-0.2 — о ней собственно и upd от 30.12.2013, она же устанавливается из репозитория, о ней же и почти все комментарии тут. В ней description действительно не используется.
avatar
Подскажите, в чем может быть проблема установки из Extras? По нажатию на «Установить» во всплывающем окне появляется 404-я. Причем, это происходит только на одном моем сайте и только с evoBabel (тот же YAMS и прочие компоненты устанавливаются нормально). После смены хостера и ручной смены версии движка проблема осталась.
avatar
Мне кажется, было бы удобно сделать ячейки таблицы в модуле растягивающимися. Неудобно переводить на языки каждую фразу, содержащуюся в большом чанке, а удобно сразу весь чанк поместить в ячейку таблицы модуля. Но тогда работать неудобно в таком маленьком окошке.
avatar
А для хранения html таблица не приспособлена. Жаль.
avatar
Похоже, у ячеек evoBabelLexicon есть ограничение длины в 255 символов. Подскажите, как увеличить?
avatar
Отвечу одним махом на все сразу. Модуль — это по сути словарь, он предназначен для хранения слов, максимум — небольшой фразы (тип поля задан varchar, у него макс. длина 255 символов в ячейке). Для изменения длины надо менять тип полей в базе данных на text либо даже на longtext. Но тут вопрос в другом — вы пытаетесь решить свои вопросы совершенно не тем инструментом. Если вам нужны разные чанки или разные большие html-блоки, то вам и нужно все это хранить в чанках или в документах в дереве, а в словарях хранятся лишь названия этих чанков или id документов.
Словари не предназначены для того, чтобы туда воткнуть дерево на разных языках, для этого есть дерево, а словари — для перевода статичных небольших фраз и для хранения ссылок на id ресурсов дерева либо на имена чанков (а вот в них уже можно хранить огромные тексты и все что вам надо в html-разметке).
avatar
А почему бы и нет? Это как-то влияет на производительность? В топике вами написано «Теперь никаких чанков», вот и было бы здорово не таскать контент оттуда и отсюда, а поместить всё в evoBabelLexicon. Пардон за ламерский вопрос, если что…
avatar
Спасибо. Если я вас правильно понял, то для вывода чанков, содержащих html с контентом на разных языках, можно сделать так.

В модуле:
Имя параметра=name
(Значение ru)=chunkru
(Значение en)=chunken

В шаблоне:
{{[%name%]}}
Однако так не работает. В выводе пусто.
avatar
Так и не будет работать, потому что оно ищет чанк с неизвестным именем [%name%]. Для чанка я бы сделал простейший сниппет вида langChunk

return $modx->getChunk($name);


и сам сниппет вызывал бы в нужном месте либо
[[langChunk? &name=`[%name%]`]]
или
[[langChunk? &name=`[[lang? &a=`name`]]`]]
. Способ вызова зависит от места, где мы этот сниппет будем вызывать (для большой глубины вложенности друг в друга чанков конструкция [%name%] может не срабатывать (в целях экономии производительности) — тогда более надежно вызывать [[lang? &a=`name`]] — это то же самое.
avatar
Всё отлично работает, спасибо.
avatar
<code>...и для хранения ссылок на id ресурсов дерева </code>
То есть, если в контенте нужно проставить ссылку на другую (НЕ корневую страницу), не связываясь с ручной простановкой URL, то только
<code><a href="[~[%id_страницы%]~]"></code>
с соответствующей простановкой id страниц в модуле? Наверно, можно этого избежать, если уж языковые версии ресурсов связаны?
Комментарий отредактирован 2014-11-22 20:18:26 пользователем Wooof
avatar
Не могу придумать ни одного «случая из жизни», когда и как это могло бы понадобиться :) А если уж понадобилось сделать ссылку на другую страницу (которая, очевидно, существует) то в чем проблема в контенте сделать ссылку на эту страницу из дерева?
В крайнем случае связи страницы хранятся в tv relation, их оттуда можно взять и по какому-нибудь шаблону плагином через preg_replace заменить хоть по всей странице. Вот только зачем это все может пригодиться? :)))
avatar
Вопрос конечно не по evoBabel, он прекрасно работает, но тема к нему напрямую относится.
Значит есть сайт на трех языках. гуглу нужно указать что страницы имеют альтернативу на других языках. Собственно для этого используются атрибуты hreflang
Вот так выглядит конструкция.
<link rel="alternate" hreflang="x-default" href="[~[*id*]~]" />
<link rel="alternate" href="[(site_url)]ua/[~[*id*]~]" hreflang="uk-ua" />
<link rel="alternate" href="[(site_url)]en/[~[*id*]~]" hreflang="en-ua" />

Все вроде бы ок, но когда переходим в другую локализацию то уже такая конструкция криво работает. и получается урл такого вида
site.ru/ua/ua/link.html
В рево для решения этой проблемы есть сниппет BabelLink который выводит ссылки со всех трех контекстов.
Есть ли что-то подобное для ево и как решитьтакую проблему.
Для мультиязычных сайтов это актуальный вопрос.
avatar
Прямого решения нет, но если учесть, что связь хранится в обычном tv, то вот небольшой сниппет набросал

<?php
//внести в модуль лексиконов строку hreflang для каждого языка (uk-ua, en-ua и т.п.)
$out = '';
$curr_lang = $modx->runSnippet("lang", array("a" => "Язык"));
$curr_lang = !empty($curr_lang) ? $curr_lang : 'ru';
$langs = array();
if ($tv && !empty($tv)) {
	$tmp = explode("||", $tv);
	foreach($tmp as $k => $v) {
		$tmp2 = explode(":", $v);
		$langs[$tmp2[0]] = $tmp2[1];
	}
}
$current_link = '';
$alter_link = '';
if (!empty($langs)) {
	foreach ($langs as $lang => $docid) {
		if ($lang == $curr_lang) {
			$current_link .= '<link rel="alternate" hreflang="x-default" href="' . $modx->makeUrl($docid) . '" />';
		} else {
			$alter_link .= '<link rel="alternate" href="' . MODX_SITE_URL . $modx->makeUrl($docid) . '" hreflang="' . $modx->runSnippet("lang", array("a" => "hreflang", "id" => $lang)) . '" />';
		}
	}
}
$out .= $current_link . $alter_link;
return $out;
?>


вызывать в хидере — [[alternate? &tv=`[*relation*]`]] и обязательно обратить на надпись в первой строке сниппета :))))
avatar
Немного доточил и добавил в общий пакет evoBabel — раз уж
Для мультиязычных сайтов это актуальный вопрос
avatar
Как всегда изумительно. Спасибо.
avatar
End Container URL with Slash: no. Use SEO Strict URLs: yes. А на выходе — такое:
<link rel="alternate" hreflang="x-default" href="/en/blog" />
<link rel="alternate" href="http://site.com//blog" hreflang="es" />
<link rel="alternate" href="http://site.com//ru/blog" hreflang="ru" />

Можно как-то решить вопрос с двойным слешем? Спасибо.
avatar
А как сделать, чтобы все языковые версии 404-ой отдавали соответствующий код ответа?
avatar
Ответ 302 дает вот эта строчка —
github.com/webber12/evobabel-0.2/blob/master/install/assets/plugins/plugin.evoBabel.tpl#L34 — причем даже тогда, когда условие не выполняется и соответственно до этой строки дело не доходит. Возможно modx гоняет еще через какие-то страницы при событии pagenotfound.
Почему так происходит — сам понять не могу, если ее закоментить — то будет ответ 404 — но делать так не рекомендую.
avatar
Добрый день.
Использую в проекте ваш плагин.
Почемуто он на событие OnPageNotFound выдает 302 редирект вместо 404 ошибки.
Немогу понять в чем дело.
www.svobodarybinsk.ru/ru/catalog/цуааапвапр
Например выдает в браузере 404, а при проверке ответа сервисами 302 редирект на главную.

Вот еще что. у вас для редиректа используется $modx->sendRedirect при этом даже в браузере сначало идет 302 редирект, потом 404.
Сейчас использую $modx->sendForward($docid,'HTTP/1.1 404 Not Found');
Браузер сразу стал выдавать 404 страницу с соотв. статусом. Но как писал выше сервисы по проверке ответа сервера выдают что у меня 302 редирект на главную.
Комментарий отредактирован 2015-08-04 09:18:37 пользователем akosilov
avatar
А сообщение, находящееся прямо над вашим (до написания вашего оно было последним) прочитать было лениво? :)) С тех пор ничего не изменилось, руки не доходили :)))
avatar
И когда дойдут? Плагин хороший, нужный. Но для SEO он не подходит. Надо бы доделать.
Я использовал $modx->sendForward($docid,'HTTP/1.1 404 Not Found') как и писал, но почемуто если сессий нет он зацикливается и выдает ошибку.
avatar
После установки и создания нескольких ресурсов имею следующую ошибку:
« MODX Parse Error »
Execution of a query to the database failed — Table 'fridextr_frbase.modx_lexicon' doesn't exist
SQL > SELECT * FROM `fridextr_frbase`.`modx_lexicon`
Current Plugin evoBabel(OnWebPageInit)
Подскажите, как решить.
avatar
Создал запись в модуле, всё ок.
avatar
При переносе сайта на другой хостинг возникла ситуация:

в БД в таблице lexicon все переводы в наличии,
в модуле evoBabelLexicon — пусто.

Подскажите пожалуйста куда копать
avatar
Сложно сказать, может файлы не все донесли, а может версия php 5.2 оказалась. Надо смотреть ошибки на сервере или в админке.
avatar
5.4.45
файлы проверю, спасибо.

На всякий случай вопрос: если установить модуль заново без ошибок, он из БД должен подтягивать имеющуюся таблицу lexicon?
avatar
Подскажите, пожалуйста, после установки evoBabel на «Страница не найдена» выдает ошибку:
« MODX Parse Error »
MODX encountered the following error while attempting to parse the requested resource:
« Execution of a query to the database failed — You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AND tmplvarid=46 LIMIT 0, 1' at line 1 »
SQL > SELECT value FROM rehame00_kasua.`modx_site_tmplvar_contentvalues` WHERE contentid= AND tmplvarid=46 LIMIT 0, 1
Basic info
REQUEST_URI: /product
Current Plugin: evoBabel(OnWebPageInit)

tmplvarid=46 – это ТВ — relation (46) — Языковые версии ресурса
В лексиконе: Страница не найдена и id назначены
До установки evoBabel эта страница работала.
С чем это может быть связано, куда копать? Спасибо!
avatar
убираю в плагине evoBabel «Импортировать общие параметры модуля:evoBabelLexicon» и тогда 404 показывается, но не работает переключение языков.
Url на сайте без вложенности, но так как сайт переносили с другого движка, то в псевдониме руками прописано, например: product/mishka3. Но новые Url формируются без уровней, просто, site.ru/mishka4
Может кто-то сталкивался с таким?
avatar
Когда вы отключаете импорт параметров — у вас просто перестает работать плагин. Полностью :)
avatar
После обновления Modx до последней версии, все заработало!!!
Спасибо, webber!
Комментарий отредактирован 2015-11-20 15:30:18 пользователем lebidii
avatar
Не хватает данных — приведите полный код ошибки или киньте доступ к сайту. У вас явно потерялся куда-то id текущего документа, отсюда в выборке mysql ошибка (пустое значение contentid) WHERE contentid= AND.
avatar
На какой из последних версий MODX работает evoBabel, у меня на 1.1b-d7.1.1 не взлетело…
Комментарий отредактирован 2016-03-06 17:50:59 пользователем labasus
avatar
MODX EVO 1.1RC-d7.1.6, последняя, всё работает. На версии с Github тоже всё в порядке.
avatar
Спасибо, победил.
avatar
Прикрепленные через tv картинки должны синхронизироваться? Т.е. при добавлении изображения в испанскую версию та же картинка должна появляться в английской версии? Если да, то что-то не работает… В чём м.б. проблема? Версия 0.2, ставил вручную (через Extras не ставится (проблемы хостинга с SSL?)). Сборка 1.1RC-d7.1.5.
ids TV для синхронизациив плагине прописаны. Всё работает отлично, кроме этого.
Комментарий отредактирован 2016-03-06 20:04:38 пользователем Wooof
avatar
webber?
avatar
Должны. Но кроме тв надо задать еще и id шаблонов для синхронизации, т.е. картинки могут быть синхронизированы для товара, но разные для новостей.

В общем случае, сначала проверяется, входит ли ресурс в список синхронизируемых шаблонов, а уж затем для него «синхронизируются» заданные TV.
avatar
Вот настройка плагина и ресурс с шаблоном id 12 — тут картинка есть, а у английской версии — пусто…
avatar
Не знаю, без доступа сказать невозможно :)
avatar
отправил в личку
avatar
Вы при ручной установке забыли для плагина указать событие OnDocFormSave, на котором синхронизация и производится. Смотреть Samsung Galaxy Note 2 :)
avatar
чОрт… спасибо.
avatar
Ломаю голову, как заставить чудо плагин работать с Еvogallery.
T.e. фото галерия с категориями/папками распрастраняется на все языки, естественно каждая категория переведена на свой язык.
avatar
Ломаю голову, как заставить чудо плагин работать с Еvogallery.
T.e. фото галерия с категориями/папками распрастраняется на все языки, естественно каждая категория переведена на свой язык.
avatar
Галерея прикрепляется к конкретному id ресурса. В многоязычности каждый язык — свой id. Можно заменить на simpleGallery — там вроде можно копировать фото в другие документы (ну или дописать плагин, который будет копировать), опять же подписи к фото на разных языках обычно должны быть, да и «категории». Так что не очень понял вопроса.
avatar
Копировать нельзя, только перемещать. А вот создавать/удалять плагином записи для связанных ресурсов, думаю, что можно. При этом как раз и получится, что файлы одни и те же, а названия/описания разные.
avatar
Кстати, насчет одних и тех же файлов. В EvoGallery была такая беда, что если использовать два раза файл с одним и тем же именем, а потом в одном месте удалить — то сам файл удалялся и вываливалась ошибка (типа нет файла) на сайте. Причем в админке галерея показывалась (т.е. узнать об ошибке можно было только случайно). Есть ли какая-то проверка в SG, когда бы при удалении файла сначала проверялось, чтобы о нем не было ни одной записи в базе? :)
avatar
Мне кажется, что такая ошибка маловероятна: сначала удаляется запись в базе, потом удаляется файл, потом вызывается плагин, который удаляет записи для привязанных ресурсов.
avatar
Ну не скажи — на evogallery приходилось встречаться с такой ошибкой не один раз. Клиент накидает файлов с одинаковым именем в галерею, в итоге «останется только один» (последний). Потом удалит из галереи одну из записей с таким файлом, файл удалился, а еще несколько ссылок на тот же файл осталось. Итог — ошибка, т.к. там даже не было проверки ни на уникальность имени при добавлении ни на наличие файла при его отправке в галерею :) Потому и спрашиваю, как обстоят дела в SG на этот счет :)
avatar
В SG не получится накидать в одну галерею файлов с одинаковым именем.
avatar
А удалить файл, если он используется в другой галерее? :)
avatar
Что-то я не понимаю. Если в другой галерее — то это другой файл (:
avatar
Эхх… не сталкивался ты еще с настоящими админами сайта, у тех может случиться все, что угодно :)

Как вариант — скопировали мы плагином эти же записи из таблицы SimpleGallery в другую языковую версию, не копируя файлы и не меняя адреса.

В итоге работать оно будет, но потом удалив в одном из ресурсов какой-то файл, он перестанет показываться и в другом ресурсе, хотя запись о нем в базе останется :)
avatar
Нет, плагин на удаление картинки удалит все связанные записи. Так что тут скорее файл останется, а записей не будет (:
avatar
А про админов, как раз вот недавно заказчик решил переиначить картинки в галереях, с помощью кнопки переноса и каким-то образом их поудалял. Клялся, что нажимал именно перенос, вводил id документа, то есть правильно все делал. Но по факту файлов нет, записей в таблице тоже нет, в логах пусто.
avatar
А как вывести галерею связанного ресурса с помощью того же sgLister?
Насколько я понял, нужно разобрать параметр [*relation*], который выдаёт запись вида 'en:128||ru:1348'.
avatar
Видимо, да. Написать простенький сниппет, в который передать [*relation*] и разобрать его explode-ами для получения нужного id ресурса нужного языка. После чего там же запустить sgLister через $modx->runSnippet с нужными параметрами
avatar
Накидал сниппет, который при наличии языковой версии выведет изображения из обеих галерей. Возможно, кому-то пригодится:
<?php
if (!isset($relation)) {
	$galleries = $modx->documentIdentifier;
} else {
	$temp = explode('||', $relation);
	$array = array();
	foreach($temp as $item) {
		$arr = explode(':', $item);
    	$array[$arr[0]] = $arr[1];
	}
	$galleries = implode(",", $array);
}
	
$params = array(
	'parents' => $galleries,
	'tpl' => '@CODE:<img src="[+sg_image+]">',
	'display' => 'all'
);
return $modx->runSnippet('sgLister', $params);
?>
И вызов в шаблоне:
[[langGalleries? &relation=`[*relation*]`]]
avatar
Проблемы на новой версии MODX EVO 1.1-d8.0 от 11.04.2016.
Не выводит на странице ресурса кнопочки для создания страниц других языков и перехода на них. Вместо блока выводится просто тв-параметр «Языковые версии ресурса» с типом Custom input
Комментарий отредактирован 2016-06-05 11:09:40 пользователем zloyxrom
avatar
avatar
Спасибо, помогло.
avatar
Скажите, пожалуйста, что именно нужно исправить, чтобы работало на последней версии сборки? По ссылке не очень понятно.
avatar
Сама себе отвечаю: переименовать TV на lang, удалить {} в свойствах сниппетов.
avatar
Еще не работает плагин evoBabelPlaceholder и плейсхолдер [+switchLang+] на новой версии MODX EVO 1.1-d8.0 от 11.04.2016. Т.е. вообще плейсхолдеры [%ключ%] — не работают
Комментарий отредактирован 2016-06-05 11:46:12 пользователем zloyxrom
avatar
Там поломали что то в параметрах плагинов, можно почитать в теме. Лучше остаться пока на предыдущих версиях сборки.
avatar
Ок
avatar
Та же проблема, текущая версия с гитхаба. Нашла вот эти сегоднешние Димины сообщения github.com/dmi3yy/modx.evo.custom/issues/356, означает ли это, что проблема уже пофиксена? Скачала версию по последним изменениям гитхаба (2 часа назад), [+switchLang+] пока не появился.
avatar
Настроил evoBabel на временном поддомене (ru.site.com). Всё отлично.

После переноса на основной сайт (site.com) перестала работать переключалка языков. И все переводы (RU) стали вести на дефолтные версии страниц (EN). Функционал восстанавливается при отключении дружественных URL.

Подскажите, пожалуйста, в чём может быть проблема?
avatar
1. Как убрать index в главных страниц языковых версий? Есть сайт example.com его главный язык украинский, для него открывается example.com (а также редирект на неё с example.com/ua/), два дополнительных языка русский и английский (нигде кроме главных страниц не добавляется index), а на главных получается example.com/ru/index и example.com/en/index (кстати на тестовом сайте evobabel.sitex.by/ та же ошибка), как её устранить (убрать index)?
2. Ещё у меня есть немецкая и французская версии (не опубликованные, красные в списке) так параметр [[alternate? &tv=`[*relation*]`]] их выдает и получается несостыковочка. Также он добавляет в юрл лишний слеш (наведе пример главной страницы):

<link rel="alternate" href="http://example.com//" hreflang="ua" /><link rel="alternate" href="http://example.com//en/index" hreflang="en" /><link rel="alternate" href="http://example.com//de/index" hreflang="de" /><link rel="alternate" href="http://example.com//ru/index" hreflang="ru" /><link rel="alternate" href="http://example.com//fr/index" hreflang="fr" />


Просьба сказать как эти ошибки устранить. Спасибо!
Комментарий отредактирован 2016-10-04 17:03:24 пользователем tunyk
avatar
index — это не ошибка, а реальный адрес вашей страницы. Если вы хотите, чтобы страница была одна, а показывалась при этом другая — то надо писать плагин с $modx->sendForward — методом :)
avatar
По пункту 1. С modx раньше не работал, стоит стандартный evoBabel, подскажете как в него внедрить $modx->sendForward? А то с этим index мучаюсь неделю и только понял что причина в структуре плагина (до этого питался убрать index путем rewriterule в htaccess — ничего не вышло).

По пункту 2 — с чем может быть связан лишний слеш (у настройках сайта стоить пункт не добавлять в конце слеш) и то что добавляются языки, которые не опубликованные?
Комментарий отредактирован 2016-10-05 16:23:59 пользователем tunyk
avatar
Попробывал sendForward — ничего не получилось:
if (!defined('MODX_BASE_PATH')) {
    die ('What are you doing? Get out of here!');
}

$e = & $modx->event;

$content_table = $modx->getFullTableName('site_content');
$tvs_table = $modx->getFullTableName('site_tmplvar_contentvalues');

if (isset($params['rel_tv_id']) && isset($params['lang_template_id'])) {
    include_once MODX_BASE_PATH . 'assets/snippets/evoBabel/evoBabel.class.php';
    $eB=new evoBabel($modx, 0, $params);

    switch ($e->name) {
		case 'OnWebPagePrerender':
        $modx->resource->_output = str_replace('"index/', '"', $modx->resource->_output);
        break;
        case 'OnPageNotFound'://переадресация на нужную страницу 404, указать ее в модуле лексикона
            //$docid = 0;
            $docid = !empty($modx->config['error_page']) ?  $modx->config['error_page'] : $modx->config['site_start'];
            if (!isset($_SESSION['perevod'])) {
                //$docid = $modx->config['site_start'];
                $modx->sendRedirect($modx->makeUrl($docid), 0, 'REDIRECT_HEADER', 'HTTP/1.0 404 Not Found');exit();
            }
            $id = $_SESSION['perevod']['Страница не найдена'];
            $docid = (int)$id;
            if ($docid == 0) {
                $id = $_SESSION['perevod']['Главная страница'];
                $docid = (int)$id;
                if ($docid == 0) {
                    $id = $_SESSION['perevod']['Корневая папка'];
                    $docid = (int)$id;
                }
            }
            if ($docid != 0) {
                $modx->sendRedirect($modx->makeUrl($docid), 0, 'REDIRECT_HEADER', 'HTTP/1.0 404 Not Found');exit();
            }  else {
                $docid = !empty($modx->config['error_page']) ?  $modx->config['error_page'] : $modx->config['site_start'];
            }
		$uri = explode('?', $_SERVER['REQUEST_URI']);
        if ($res = $modx->findResource('index' . $uri[0])) {
            $modx->sendForward($res);
        }
            break ;
        case 'OnDocFormSave'://синхронизация выбранных TV на выбранном шаблоне
            if ($e->params['mode'] == 'upd' && (isset($synch_template) && $synch_template != '') && (isset($synch_TV) && $synch_TV != '')) {
                $eB->synchTVs($synch_TV, $synch_template, $e->params['id']);
            }
            break;
        case 'OnBeforeEmptyTrash': //собираем связи окончательно удаляемых ресурсов, чтобы потом скорректировать их связанные версии
            if (isset($ids) && is_array($ids)) {
                $del_ids = implode(',', $ids);
                $del_array = $eB->makeDelRelsArray($del_ids);
                $_SESSION['del_array'] = $del_array;
            }
            break;
        case 'OnEmptyTrash': //корректируем связи языковых версий с учетом окончательного удаления ресурсов
            $del_array = $_SESSION['del_array'];
            if (!empty($del_array)) {
                $eB->updateDeletedRelations($del_array);
            }
            break;
        case 'OnWebPageInit':
            // в нужном месте прописываем [+activeLang+] (вывод текущего языка) и [+switchLang+] - вывод переключалки (списка) языков
            // параметры вызова
            // &activeLang - шаблон вывода текущего языка (отдельно)
            // &activeRow - шаблон вывода текущего языка в списке языков
            // &unactiveRow - шаблон вывода языков в списке (кроме текущего)
            // &langOuter - шаблон обертки для списка языков

            //шаблоны вывода по умолчанию
            $tmp = isset($config) ? $config : '';
            if(!empty($config) && file_exists(MODX_BASE_PATH . $config)){
                include_once (MODX_BASE_PATH . $tmp);
            }
            //активный язык отдельно
            $activeLang = isset($activeLang) ? $activeLang : '<div id="curr_lang"><img src="assets/snippets/evoBabel/config/images/flag_[+alias+].png"> <a href="javascript:;">[+name+]</a></div>'; 
            //активный язык в списке
            $activeRow = isset($activeRow) ? $activeRow : '<div class="active"><img src="assets/snippets/evoBabel/config/images/flag_[+alias+].png">  <a href="[+url+]">[+name+]</a></div>';
            //неактивный язык списка
            $unactiveRow = isset($unactiveRow) ? $unactiveRow : '<div><img src="assets/snippets/evoBabel/config/images/langs/flag_[+alias+].png">  <a href="[+url+]">[+name+]</a></div>';
            //обертка списка языков
            $langOuter = isset($langOuter) ? $langOuter : '<div class="other_langs">[+wrapper+]</div>';

        //фикс для OnWebPageInit на несуществующей странице с несуществующим documentIdentifier
        if ($modx->documentIdentifier && $modx->documentIdentifier != 0 && $modx->documentIdentifier != '0' && !empty($modx->documentIdentifier) ) {

            $out = '';
            $langs = array();
            $others = array();//массив других языков (кроме текущего)
            $eB->id = $modx->documentIdentifier;
            $siteLangs = $eB->getSiteLangs($eB->lang_template_id);
            $siteAllLangs = $eB->getAllSiteLangs($eB->lang_template_id);
            //если находимся в корневой папке языка, отправляем на главную страницу этого языка (при условии, что она задана и отличается от текущей)
            if (isset($siteLangs[$eB->id]) && $siteLangs[$eB->id]['home'] != '' && (int)$siteLangs[$eB->id]['home'] != 0 && $siteLangs[$eB->id]['home'] != $eB->id) {
                $modx->sendRedirect($modx->makeUrl((int)$siteLangs[$eB->id]['home']));
            }
            $curr_lang_id = $eB->getCurLangId($eB->id);
            $relations = $eB->getRelations($eB->id);
            $relArray = $eB->getRelationsArray($relations);

            //устанавливаем текущий язык
            $currLang = str_replace(array('[+alias+]', '[+name+]', '[+lang+]'), array($siteLangs[$curr_lang_id]['alias'], $siteLangs[$curr_lang_id]['name'], $siteLangs[$curr_lang_id]['lang']), $activeLang);

            //устанавливаем список языков с учетом активного
            $langRows = '';

            foreach ($siteLangs as $k=>$v) {
                $tpl = ($k != $curr_lang_id ? $unactiveRow : $activeRow);
                if (isset($relArray[$v['alias']]) && $eB->checkActivePage($relArray[$v['alias']])) {//если есть связь и эта страница активна
                    $url = $relArray[$v['alias']];
                } else {//нет связи либо страница не активна -> проверяем родителя
                    $parent_id = $modx->db->getValue($modx->db->query("SELECT parent FROM {$eB->content_table} WHERE id={$eB->id} AND published=1 AND deleted=0 AND parent!=0 AND template!=$eB->lang_template_id"));
                    if (!$parent_id) {//если нет родителя, отправляем на главную страницу языка
                        $url = ((int)$v['home'] != 0 ? (int)$v['home'] : $k);
                    } else {//если родитель есть, проверяем его связи
                        $parent_relations = $eB->getRelations($parent_id);
                        $relParentArray = $eB->getRelationsArray($parent_relations);
                        if (isset($relParentArray[$v['alias']]) && $eB->checkActivePage($relParentArray[$v['alias']])) {//у родителя активная связь
                            $url = $relParentArray[$v['alias']];
                        } else {//иначе -> на главную страницу языка
                            $url = ((int)$v['home'] != 0 ? (int)$v['home'] : $k);
                        }
                    }
                }
                $langRows .= str_replace(array('[+alias+]', '[+url+]', '[+name+]', '[+lang+]'), array($v['alias'], $modx->makeUrl($url), $v['name'], $v['lang']), $tpl);
            }
            $langsList .= str_replace(array('[+wrapper+]'), array($langRows), $langOuter);

            // устанавливаем плейсхолдеры [+activeLang+] и [+switchLang+] для вывода активного языка и списка языков соответственно
            $modx->setPlaceholder("activeLang", $currLang);
            $modx->setPlaceholder("switchLang", $langsList);

            //получаем массив перевода для чанков в сессию
            $perevod = array();
            $cur_lexicon = $siteAllLangs[$curr_lang_id]['alias'];
            $q = $modx->db->query("SELECT * FROM " . $modx->getFullTableName('lexicon'));
            while ($row = $modx->db->getRow($q)) {
                $perevod[$row['name']] = $row[$cur_lexicon];
            }
            $_SESSION['evoBabel_curLang'] = $cur_lexicon;
            $_SESSION['perevod'] = $perevod;
        }
            break;
		case 'OnHandleRequest':
        if (strpos($_SERVER['REQUEST_URI'], 'index/') !== false) {
            $url = str_replace('index/', '', $_SERVER['REQUEST_URI']);
            $modx->sendRedirect($url, array('responseCode' => 'HTTP/1.1 301 Moved Permanently'));
        }
        break;
        case 'OnDocDuplicate' :
            if ($e->params['new_id']) {
                $q = $modx->db->query("DELETE FROM " . $eB->tvs_table . " WHERE contentid={$e->params['new_id']} AND tmplvarid={$eB->rel_tv_id}");
            }
            break;
        default:
            return ;
    }
}
avatar
Мне кажется весь ваш код, как бы это помягче сказать — не из той оперы. Ваша опера называется REVO, а текущая тема — про EVO. Потому вам либо не в эту тему (для REVO есть аналогичный компонент Babel), либо сначала разобраться в основах :)

И второй момент — насколько я понимаю ресурс example.ru/en/ — это существующий ресурс, т.е. надо не на событие OnPageNotFound это все делать, а на OnWebPageInit — проверяете, что шаблон равен шаблону языка или что страница соответствует странице «Корневая страница», и делаете внутренний редирект sendForward на страницу под именем «Главная станица»
Комментарий отредактирован 2016-10-07 20:27:19 пользователем webber
avatar
У меня стоит Modx Evo 1 версия, плагин evoBabel. Пример sendForward брал отсюда ilyaut.ru/cribs-for-modx/to-remove-index-from-url-resources-a-subsidiary-of-the-main/
Комментарий отредактирован 2016-10-07 20:35:57 пользователем tunyk
avatar
А код весь вот этот
case 'OnHandleRequest':

$modx->sendRedirect($url, array('responseCode' => 'HTTP/1.1 301 Moved Permanently'));

$modx->resource->_output = str_replace('"index/', '"', $modx->resource->_output);


не из EVO, а из REVO — т.е. вызывает ошибку в плагине, после чего результаты его деятельности в принципе игнорируются (т.е. ломается даже то, что работало).
avatar
К сожалению, примеры sendForward на многоязыковых сайтах, а именно evo отсутствуют. Я раньше работал только с Joomla и только начинаю с modx — вообще ничего не понятно. Если я привык отключать index галочкой в админке, sendForward это как невспаханное поле.
Комментарий отредактирован 2016-10-07 20:46:49 пользователем tunyk
avatar
В вашем примере просто убирается index из тех адресов, которые дочерние по отношению к ресурсу. Т.е. например из адреса index/page.html делается адрес page.html. Этого же эффекта в EVO можно добиться просто птичкой «участвует в URL» в редактировании ресурса. Но это не решает ваше задачу в принципе.
avatar
Как в alternate hreflang выводить только опубликованные ресурсы языков, а то сейчас выводятся даже отключенные?
avatar
Сейчас там сделан простейший перебор языков, которые числятся в параметре tv relation. Т.е. надо сделать доп.проверку на то, включен ли этот язык.

Где-то после строки 38 пишем примерно следующее

$allowed_langs = array();
$q = $modx->db->query("SELECT alias FROM modx_site_content WHERE template=5 AND deleted=0 AND published=1");
while ($row = $modx->db->getRow($q)) {
    $allowed_langs[$row['alias']] = 1;
}


и потом блок подвеграете предварительной проверке

if (isset($allowed_langs[$lang])) {....тут блок ...}


Не забудьте заменить template= на id вашего шаблона «Язык»
Комментарий отредактирован 2016-10-07 21:01:10 пользователем webber
avatar
avatar
Спасибо! Придумал как избавится от index — Использовать вместо отдельных страниц Главных, прямо родителя RU, EN и т.д. (но при этом оставить для главного языка и то и другое, так как index в него не пишется).

Но возникли кое-какие несуразицы — на них не работает модуль лексиконов и все выводится в таком [%lang%], [%title%] и т.д. виде. Не подскажете какие изменения нужно повносить в коды чтобы такие главные страницы нормально работали. Спасибо!
avatar
Ещё вопросы:
1. 404 ошибка работает для языковых версий, но если ошибка example.com/hhjjhjjh (без lang в юрл), то выдается пустая белая страница

2. Если страницы определенной языковой версии не опубликованы и перейти по их юрл выдается ошибка (как её убрать?):
« MODX Parse Error »
`` is not numeric and may not be passed to makeUrl()

Ну и т.д.
Backtrace
DocumentParser->executeParser()
index.php on line 145
DocumentParser->prepareResponse()
manager/includes/document.parser.class.inc.php on line 1726
DocumentParser->parseDocumentSource(string $var1)
manager/includes/document.parser.class.inc.php on line 1813
DocumentParser->evalSnippets(string $var1)
manager/includes/document.parser.class.inc.php on line 1578
DocumentParser->_get_snip_result('top_menus?')
manager/includes/document.parser.class.inc.php on line 1096
DocumentParser->evalSnippet(string $var1, array $var2)
manager/includes/document.parser.class.inc.php on line 1120
eval()
manager/includes/document.parser.class.inc.php on line 1054
DocumentParser->makeUrl('')
manager/includes/document.parser.class.inc.php(1054) : eval()'d code on line 4
avatar
Так это вроде ваш сниппет top_menus? отваливается, причем тут evoBabel? :)
avatar
По 2-му пункту. Причём top_menus если я не писал что ссылка в переключателе появляется, а просто пишу что выдается ошибка если ввести юрл не опубликованного материала (при том что полностью все материалы в данном языке не опубликованные), а должна быть по идее 404 ошибка.

По первому нигде ответа не нашел.
Комментарий отредактирован 2016-10-05 16:22:43 пользователем tunyk
avatar
Если вы немного разуете глаза и просмотрите лог своей ошибки (который вы сюда выложили), то увидите, что она возникает в вашем сниппете, а не в переключалке языков

DocumentParser->_get_snip_result('top_menus?')
avatar
Может кто-нибудь реализовал это решение с каталогом товаров, где используется EvoGallery и SimpleTube.
Пока столкнулся со след. проблемами:
1) т.к. все товары привязаны ( EvoGallery и SimpleTube невозможно синхронизировать к другим документам) к папке основного языка, а в др. языковых папках документы создаю только для СЕО и иногда для уникальности перевода -приходится с Ditto или Doclister'a обращатся к основной папке.
Проблема: [+url+] или [~[*id*]~] в шаблонах выводит естественно только ссылки на основной язык.
2) Проблема не связана с каталогом, но все же нигде не нашел простого решения, как вывести текущий язык для использования в шаблонах, не уже ли нет какого плейсхолдера или нужно использовать только, например Чанк?
[[if? &is=`[[UltimateParent]]:in:1` &then=`ru` &else=`en`]]
avatar
При установке через Extras на версию MODX 1.2.1RC вот такая штука вылезла. Критично?
avatar
А при установке какого-то другого модуля/сниппета/плагина таких ошибок нет? Только в evoBabel?
avatar
Сниппеты ставятся без ошибок. Там, правда, более простая установка сниппетов была, где не появляется во время установки окно с выбором настроек.

Сам evoBabel, кстати, работает, единственное, все равно пришлось вручную часть параметров прописывать, так как автоматический установщик далеко не все сделал из нужного. В частности, TV-параметры не создал и не предлагал, связи модуля, сниппетов и плагинов — тоже вручную прописывал.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.