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

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

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

Комментарии: 21

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

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

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

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

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

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

    В extendresource это можно попробовать реализовать просто добавив к нему дополнительное поле для хранения контекста. Далее в запросе можно дополнительно указывать контекст и следовательно выбирать только те данные, которые к нему принадлежат.
    1. Александр
      Александр
      2020-11-03 18:37:33
      Александр, здравствуйте! Пришлось оставить это дело на потом а сейчас оторвался от другого и появилась возможность всё сделать а именно вариант с добавлением дополнительного поля в extendresource для хранения контекста, добавил поле «context» в фильтре выбираю данные в зависимости от контекста, всё работает но не могу точно понять и определится подходит ли мне этот вариант, в моём случае на сайте более десяти контекстов (разных языковых версий сайта) в каждом контексте переведённые каталог и ресурсы, у каталога с фильтром во всех контекстах один шаблон, теперь возникает такая проблема, если прикинуть что в одном поле 200 значений в моём случае это поле стран, при таком варианте добавляются ещё 200 значений на английском, 200 на немецком и т.д, теперь в админке редактируя ресурс не зависимо от контекста в котором находишься, для выбора значений поля стран, будут выводится все значения стран которые есть в таблице на русском, английском и всех остальных, скажите пожалуйста возможно ли как-то исключать вывод значений поля в админке, те значения которые не соответствуют контексту в котором редактируешь ресурс?
    2. Александр Мальцев
      Александр Мальцев
      2020-11-04 08:27:03
      Здравствуйте! Нужно пробовать, а потом уже решать подойдёт вам этот вариант или нет.
      Александр, отображение дополнительных полей в админке у вас реализовано через плагин ExtendedResource, представленный в этой статье? Если так, то в этом случае нужно просто получить контекст ресурса. Это можно сделать так:
      $contextKey = $resource->get('context_key');
      
      Далее полученный контекст вам нужно использовать в условиях для выборки соответствующих данных из базы данных и в других местах кода при необходимости.
    3. Александр
      Александр
      2020-11-05 07:46:38
      Здравствуйте! Нет, плагин у меня дублирует значения обычных tv в свою таблицу компонента extendresource, реализовано вот таким образом: itchief.ru/questions/591, Александр как я понимаю при таком раскладе значения tv в админке не получится разделять по контексту, не трогая исходники Modx? И самый оптимальный и лучший вариант в данном случае это вывести в админку свои поля?

    4. Александр Мальцев
      Александр Мальцев
      2020-11-05 14:38:52
      Привет! В этом случае только если организовать через свои поля.
    5. Александр
      Александр
      2020-11-05 17:06:44
      Спасибо!
    6. Александр
      Александр
      2020-11-15 09:57:01
      Здравствуйте! Сейчас всё реализовано через плагин «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);
      возможно я вообще не правильно делаю?
    7. Александр Мальцев
      Александр Мальцев
      2020-11-18 13:31:16
      Привет!
      Добавить варианты значений можно так:
      $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'));
      
    8. Александр
      Александр
      2020-11-18 19:18:47
      Александр, доброго вечера Вам! Огромное спасибо за решение, но как обычно у меня не совсем всё гладко получается реализовать, как только вношу в плагин эти изменения, во всех контекстах кроме контекста «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» и некоторых других, как правильно нужно прописывать условие, подскажите пожалуйста?
    9. Александр
      Александр
      2020-11-19 17:17:26
      Александр, здравствуйте! Как обычно я накосячил и не туда код вставил, поэтому были проблемы и не отображались поля в других контекстах, спасибо за отличное решение. Сейчас не понятен один момент, чтобы к примеру добавить свои значения к контексту «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 блоком обойтись?
    10. Александр Мальцев
      Александр Мальцев
      2020-11-21 13:15:00
      Здравствуйте! Рад что получилось.
      Сделайте через ассоциативный массив:
      $contextKey = $resource->get('context_key');
      $hobbiesDataArr = [
        "web" => "[['бег'],['дайвинг'],['плавание'],['лыжи'],['боулинг']]",
        "en" => "[['running'], ['diving'], ['swimming'], ['skiing'], ['bowling']]",
        "deg" => "[['laufen'], ['tauchen'], ['schwimmen'], ['ski'], ['bowling']]"
      ];
      $hobbiesData = $hobbiesDataArr[$contextKey];
      
    11. Александр
      Александр
      2020-11-21 16:03:34
      Александр, доброго вечера Вам! Спасибо, за отличный вариант. Скажите пожалуйста а в массиве можно, как-то определить, если не указано, то используем «en» то-есть сделать то-же самое как в «if» блоке с параметром «else»?
    12. Александр Мальцев
      Александр Мальцев
      2020-11-23 15:51:07
      Привет!
      Для этого можно проверить наличие ключа в массиве. Если его нет, то используем какой-то по дефолту (например, 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"];    
      }
      
    13. Александр
      Александр
      2020-11-23 17:32:01
      Александр, огромное спасибо!