Мультиязычность динамического контента в MODX

Александр
817
0
Александр и снова здравствуйте:) Не получается сообразить, как переводить динамический контент на сайте. Со статическим всё более понятно, если коротко, создать компонент лексиконов, прописать там метод вывода, создать пространство имён, создать плагин и повесить его на определённое событие, прописать вывод в шаблоне, тут всё понятно, но а как быть к примеру с полями extendresource и вообще с динамическим контентом фильтра, тв, и т.д, если возможно расскажите пожалуйста, как это лучше и правильней делать?

Не много дополню и уточню вопрос к примеру будет два разных домена на одном modx, site.ru и site.com у второго будут разные языковые версии сайта site.com/di/, site.com/by/ и так далее, фильтр mfilter2 фильтрует по своим полям, компонента extendresource, как в данном случае сделать переводы всех значений, дублировать компонент и таблицы в базе с переводами всех значений для разных версий сайта или как то по другому? Александр как правильно в данном случае это можно реализовать?

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

  1. Александр
    16 января 2020, 02:30
    Александр, огромное спасибо за решение, если возможно, хотел бы уточнить некоторые моменты а точнее, всё ли я понял правильно:

    1) Для каждой языковой версии сайта, свой шаблон, со своими тв, то есть в каждый контекст, нужно продублировать все ресурсы и создать для них шаблоны в которых указаны тв в зависимости от языка?

    2) По поводу extendresource, если я правильно понимаю, нужно продублировать все поля в таблице, добавив к ним свои приставки типа by, перевести все значения, добавив их там же, далее указать их в custom.class.php. В нужных шаблонах языковых версий, разместить вызов mFilter2 у которого в select прописаны название полей с переводами?

    3) Если так и прикинуть что полей в таблице к примеру 10 и значений у этих полей 200 а языковых версий сайта 20, получается дополнительно в одной таблице 190 полей и 3800 значений и это наверно очень сильно повлияет на скорость фильтрации если да, то каким обрам этого можно избежать?
    1. Александр Мальцев
      16 января 2020, 14:13
      А у вас как организована мультиязычность? Через контексты?
      Самый простой вариант — это продублировать. Ресурсы и так у вас будут в каждом контексте свои.

      В extendresource можно просто создать дополнительное поле, в котором сохранять контекст. Тут не нужно ничего дублировать. В результате будет столько же записей сколько ресурсов.
      1. Александр
        16 января 2020, 17:35
        Предполагаю что буду использовать компонент Babel, а это как я понимаю контексты, по поводу ресурсов мне более всё понятно, но по поводу extendresource не могу не как сообразить, к примеру есть поле strana в нём значения Россия, Англия и т.д это поле храниться в таблице компонента extendresource все значения там на русском языке, в фильтре они выводятся тоже на русском, мне не понятно следующее, где хранить значения, которые будут на любом другом языке, как будут они переводиться, если не создаёшь копии полей и значений в таблице extendresource на нужном языке?

        Александр, как Вы считайте, если опираться на скорость, что лучше использовать для мультиязычности, Babel где контексты или к примеру MultiLingual, Localizator?
        1. Александр Мальцев
          17 января 2020, 13:48
          Вам решать, я бы выбрал Babel.
          Тут просто добавить дополнительное поле в таблицу (ну и соответсвенно обновить компонент):
          id  resource   strana  context
           1         1   Россия       ru
           2         2   Russian      en
          
          Затем его использовать в запросах, и следовательно, выбирать только те записи, которые относятся к этому контексту.
          1. Александр
            18 января 2020, 22:44
            Огромное Спасибо! Александр, если возможно, приведите пожалуйста пример, как после этого в mFilter2 выбирать эти значения и какие изменения нужно сделать в файле custom.class.php?
            1. Александр Мальцев
              21 января 2020, 15:32
              Нужно просто добавить к запросу where:
              $q->where(array('context' => 'ru'));
              
              1. Александр
                21 января 2020, 18:41
                Оказывается всё на много проще, чем я думал. Спасибо Вам!
    2. Александр Мальцев
      14 января 2020, 06:21
      Привет!
      Самый простой вариант — это создать разные шаблоны для разных языковых версий сайтов. К одним шаблонам привязать одни TV, например, оканчивающиеся на di, а к другим, другие TV, например, оканчивающиеся на by. После этого в шаблонах и чанках соответственно добавить эти окончания.
      Этот вариант основан на дублировании шаблонов, чанков и т.д. Т.е. для каждой языковой версии сайта создавать свой набор MODX элементов.

      В extendresource это можно попробовать реализовать просто добавив к нему дополнительное поле для хранения контекста. Далее в запросе можно дополнительно указывать контекст и следовательно выбирать только те данные, которые к нему принадлежат.
      1. Александр
        03 ноября 2020, 18:37
        Александр, здравствуйте! Пришлось оставить это дело на потом а сейчас оторвался от другого и появилась возможность всё сделать а именно вариант с добавлением дополнительного поля в extendresource для хранения контекста, добавил поле «context» в фильтре выбираю данные в зависимости от контекста, всё работает но не могу точно понять и определится подходит ли мне этот вариант, в моём случае на сайте более десяти контекстов (разных языковых версий сайта) в каждом контексте переведённые каталог и ресурсы, у каталога с фильтром во всех контекстах один шаблон, теперь возникает такая проблема, если прикинуть что в одном поле 200 значений в моём случае это поле стран, при таком варианте добавляются ещё 200 значений на английском, 200 на немецком и т.д, теперь в админке редактируя ресурс не зависимо от контекста в котором находишься, для выбора значений поля стран, будут выводится все значения стран которые есть в таблице на русском, английском и всех остальных, скажите пожалуйста возможно ли как-то исключать вывод значений поля в админке, те значения которые не соответствуют контексту в котором редактируешь ресурс?
        1. Александр Мальцев
          04 ноября 2020, 08:27
          Здравствуйте! Нужно пробовать, а потом уже решать подойдёт вам этот вариант или нет.
          Александр, отображение дополнительных полей в админке у вас реализовано через плагин ExtendedResource, представленный в этой статье? Если так, то в этом случае нужно просто получить контекст ресурса. Это можно сделать так:
          $contextKey = $resource->get('context_key');
          
          Далее полученный контекст вам нужно использовать в условиях для выборки соответствующих данных из базы данных и в других местах кода при необходимости.
          1. Александр
            15 ноября 2020, 09:57
            Здравствуйте! Сейчас всё реализовано через плагин «ExtendedResource», спасибо. Александр, не могли бы Вы подробней, если возможно конечно, рассказать что нужно изменить в плагине «ExtendedResource» чтобы в админке выводились значения полей в зависимости от контекста? Я смог только дойти до того, что разместил этот код:
            $contextKey = $resource->get('context_key');
            в if блок плагина
                        if (is_object($extendResource)) {
                            $contextKey = $resource->get('context_key');
                            $myhobbies = $extendResource->get('myhobbies');
                        }
            теперь как я понимаю, тут нужно добавить варианты значений для разных контекстов или этот код просто нужно дублировать?
            MODx.combo.extendresourceMyhobbies = function(config) {
            config = config || {};
            Ext.applyIf(config,{
                 xtype:'superboxselect'
                ,triggerAction: 'all'
                ,mode: 'local'
                ,store: new Ext.data.ArrayStore({
                    id: 0
                    ,autoLoad: true
                    ,fields: ['hobbies']
                    ,data: [
                        ['бег'],['дайвинг'],['плавание'],['лыжи'],['боулинг']
                    ]
                })
                ,mode: 'local'
                ,displayField: 'hobbies'
                ,valueField: 'hobbies'
                ,forceSelection: true
                ,triggerAction: 'all'
                ,extraItemCls: 'x-tag'
                ,expandBtnCls: 'x-form-trigger'
                ,clearBtnCls: 'x-form-trigger'
            });
            MODx.combo.extendresourceMyhobbies.superclass.constructor.call(this,config);
            };
            Ext.extend(MODx.combo.extendresourceMyhobbies,Ext.ux.form.SuperBoxSelect);
            Ext.reg('extendresource-myhobbies',MODx.combo.extendresourceMyhobbies);
            возможно я вообще не правильно делаю?
            1. Александр Мальцев
              18 ноября 2020, 13:31
              Привет!
              Добавить варианты значений можно так:
              $contextKey = $resource->get('context_key');
              if ($contextKey === 'web') {
                $hobbiesData = "[['бег'],['дайвинг'],['плавание'],['лыжи'],['боулинг']]";
              } else {
                $hobbiesData = "[['running'], ['diving'], ['swimming'], ['skiing'], ['bowling']]";    
              }
              ...
              $modx->controller->addHtml(<<<HTML
              ...
              Ext.applyIf(config,{
                xtype:'superboxselect'
                ,triggerAction: 'all'
                ,mode: 'local'
                ,store: new Ext.data.ArrayStore({
                  id: 0
                  ,autoLoad: true
                  ,fields: ['hobbies']
                  ,data: {$hobbiesData}
                })
                ...
              
              Дополнительно, если нужно, можно добавить в таблицу «site_content_extend» поле «context_key» также как это сделано в таблице «site_content». После этого добавить его в схему «extendresource.mysql.schema.xml» и сгенерировать новую модель.
              Затем добавить в плагин следующую строку:
              $extendResource->set('context_key', $resource->get('context_key'));
              
              1. Александр
                19 ноября 2020, 17:17
                Александр, здравствуйте! Как обычно я накосячил и не туда код вставил, поэтому были проблемы и не отображались поля в других контекстах, спасибо за отличное решение. Сейчас не понятен один момент, чтобы к примеру добавить свои значения к контексту «deg» делаю так:
                $contextKey = $resource->get('context_key');               
                if ($contextKey === 'web') {
                  $hobbiesData = "[['бег'], [''], ['плавание'], ['лыжи'], ['боулинг']]";
                } 
                if ($contextKey === 'deg') {
                  $hobbiesData = "[['laufen'], ['tauchen'], ['schwimmen'], ['ski'], ['bowling']]";
                } 
                else {
                  $hobbiesData = "[['running'], ['diving'], ['swimming'], ['skiing'], ['bowling']]";    
                }
                всё работает, но на сколько это правильно? Можно ли для этого как-то одним if блоком обойтись?
                1. Александр Мальцев
                  21 ноября 2020, 13:15
                  Здравствуйте! Рад что получилось.
                  Сделайте через ассоциативный массив:
                  $contextKey = $resource->get('context_key');
                  $hobbiesDataArr = [
                    "web" => "[['бег'],['дайвинг'],['плавание'],['лыжи'],['боулинг']]",
                    "en" => "[['running'], ['diving'], ['swimming'], ['skiing'], ['bowling']]",
                    "deg" => "[['laufen'], ['tauchen'], ['schwimmen'], ['ski'], ['bowling']]"
                  ];
                  $hobbiesData = $hobbiesDataArr[$contextKey];
                  
                  1. Александр
                    21 ноября 2020, 16:03
                    Александр, доброго вечера Вам! Спасибо, за отличный вариант. Скажите пожалуйста а в массиве можно, как-то определить, если не указано, то используем «en» то-есть сделать то-же самое как в «if» блоке с параметром «else»?
                    1. Александр Мальцев
                      23 ноября 2020, 15:51
                      Привет!
                      Для этого можно проверить наличие ключа в массиве. Если его нет, то используем какой-то по дефолту (например, en):
                      $contextKey = $resource->get('context_key');
                      $hobbiesDataArr = [
                        "web" => "[['бег'],['дайвинг'],['плавание'],['лыжи'],['боулинг']]",
                        "en" => "[['running'], ['diving'], ['swimming'], ['skiing'], ['bowling']]",
                        "deg" => "[['laufen'], ['tauchen'], ['schwimmen'], ['ski'], ['bowling']]"
                      ];
                      if (array_key_exists($contextKey, $hobbiesDataArr)) {
                        $hobbiesData = $hobbiesDataArr[$contextKey];
                      } else {
                        // если ключ $contextKey не найден в массиве 
                        $hobbiesData = $hobbiesDataArr["en"];    
                      }
                      
                      1. Александр
                        23 ноября 2020, 17:32
                        Александр, огромное спасибо!
                2. Александр
                  18 ноября 2020, 19:18
                  Александр, доброго вечера Вам! Огромное спасибо за решение, но как обычно у меня не совсем всё гладко получается реализовать, как только вношу в плагин эти изменения, во всех контекстах кроме контекста «web», поля перестают отображаться, код добавляю в блок if плагина, после этой строки:
                  if (is_object($extendResource)) {
                  
                  вторым заменяю параметры поля:
                  Ext.applyIf(config,{
                      xtype:'superboxselect'
                      ,triggerAction: 'all'
                      ,mode: 'local'
                      ,store: new Ext.data.ArrayStore({
                          id: 0
                          ,autoLoad: true
                          ,fields: ['hobbies']
                          ,data: [
                              [['бег'],['дайвинг'],['плавание'],['лыжи'],['боулинг']]
                          ]
                      })
                  подскажите пожалуйста с чем это может быть связано?

                  И если я правильно понимаю, при таком условие в админке должны выводится значения так, если контекст «web» выводим одно, если другой любой контекст, выводим другое, а как можно добавить свои значения поля не только для контекста «web» а к примеру для контекста «deg» и некоторых других, как правильно нужно прописывать условие, подскажите пожалуйста?
              2. Александр
                05 ноября 2020, 07:46
                Здравствуйте! Нет, плагин у меня дублирует значения обычных tv в свою таблицу компонента extendresource, реализовано вот таким образом: itchief.ru/questions/591, Александр как я понимаю при таком раскладе значения tv в админке не получится разделять по контексту, не трогая исходники Modx? И самый оптимальный и лучший вариант в данном случае это вывести в админку свои поля?

                1. Александр Мальцев
                  05 ноября 2020, 14:38
                  Привет! В этом случае только если организовать через свои поля.
                  1. Александр
                    05 ноября 2020, 17:06
                    Спасибо!
          Войдите, пожайлуста, в аккаунт, чтобы оставить комментарий.