We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 27460
    • 13 Posts
    Давно начал использовать для создания мультиязычных сайтов плагин EasyLingual, так как для таких решений был самым удобным.
    Но мне вывода TV не хватало, поскольку зачастую использую так же самописные сниппеты, ну и конешно нехватало перевода отдельных фраз в шаблонах и чанках. Для этого приходилось часто делать чанки в виде сниппетом, в которых был массив с переводами и через switch по сессии выбирать какой-же брать массив с фразами и выводить. Со временнем это мне надоело, а как известно "Лень - двигатель прогреса", решил написать модуль и плагин.
    Прошу сильно не пинать, код не претендует на универсальность, хочеться донести саму идею и пищу для мозгов..
    Итак, начнем. В моем варианте - перевод для 3-х языков (английский, русский и украинский).

    UPD: Код изменнен. За критику и подсказки спасибо AKots

    1. Создаем отдельну таблицу в нашей БД:
    (modx_lang - префикс незабываем менять на свой!)
    CREATE TABLE IF NOT EXISTS `modx_lang` (
      `en` varchar(255) NOT NULL,
      `ru` varchar(255) NOT NULL,
      `uk` varchar(255) NOT NULL,
      UNIQUE KEY `en` (`en`),
      KEY `en_2` (`en`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;


    2. Создаем модуль Translate:
    (В нем и будем заполнять поля перевода фраз)
    if(isset($_POST['save'])){
    $table = $modx->getFullTableName( 'lang' );
    foreach($_POST as $lns){
    if($lns!='save'){
    $sql = "INSERT INTO ".$modx->getFullTableName( 'lang' )." (en,ru,uk) VALUES ('" . $lns['en'] . "','" . $lns['ru'] . "','" . $lns['uk'] . "')
      ON DUPLICATE KEY UPDATE ru= '" . $lns['ru'] . "',  uk = '" . $lns['uk'] . "' ";
    mysql_query($sql);
    }
    }
    }
    $content ='<html><head><link href="media/style/MODxCarbon/style.css" type="text/css" rel="stylesheet">
    <style>
    table tr th{font-size:14px; width:200px}
    table tr td{font-size:12px; width:200px}
    table tr td input{font-size:12px;width:200px}
    </style>
    </head><body>';
    $langs=array();
    $res = $modx->db->select("content", $modx->getFullTableName('site_templates'),  "content LIKE '%\[\%t \`%'");
    $members = $modx->db->makeArray( $res );
    
    $langs = array_merge($langs, $members);
    $rescont = $modx->db->select("content", $modx->getFullTableName('site_content'),  "content LIKE '%\[\%t \`%'");
    $lncont = $modx->db->makeArray( $rescont );
    $langs = array_merge($langs, $lncont );
    
    $restv = $modx->db->select("value", $modx->getFullTableName('site_tmplvar_contentvalues'),  "value LIKE '%\[\%t \`%'");
    $lntv = $modx->db->makeArray( $restv );
    $langs = array_merge($langs, $lntv);
    
    $ressp = $modx->db->select("snippet", $modx->getFullTableName('site_snippets'),  "snippet LIKE '%\[\%t \`%' ");
    $lnsp = $modx->db->makeArray( $ressp);
    $langs = array_merge($langs, $lnsp);
    $content .='<form method="post"><table><tr><th>English</th><th>Russian</th><th>Ukrainian</th></tr>';
    $mathcln = array();
    
    foreach($langs as $scont )
    {
    preg_match_all("~\[\%t \`(.*)\`\%\]~U", $scont['content'], $matches); 
    $mathcln = array_merge($mathcln, $matches[1]);
    preg_match_all("~\[\%t \`(.*)\`\%\]~U", $scont['snippet'], $matches); 
    $mathcln = array_merge($mathcln, $matches[1]);
    }
    
    
    $lnuniq = array_unique($mathcln);
    $i=0;
    foreach($lnuniq as $lnen){
    $content .='<tr>';
    $content .= '<td>'.$lnen.' <input type="hidden" name="'.$i.'[en]" value="'.$lnen.'"></td>';
     $ress = $modx->db->select("ru, uk", $modx->getFullTableName('lang'),  "en = '".$lnen."' ");
    if(mysql_num_rows($ress)>0){
    $content .= '<td><input type="text" name="'.$i.'[ru]" value="'.mysql_result($ress, 0, 0).'"></td>';
    $content .= '<td><input type="text" name="'.$i.'[uk]" value="'.mysql_result($ress, 0, 1).'"></td>';
    }else{
    $content .= '<td><input type="text" name="'.$i.'[ru]" value=""></td>';
    $content .= '<td><input type="text" name="'.$i.'[uk]" value=""></td>';
    }
    $content .='</tr>';
    $i++;
    
    }
    $content .= '</table><input type="submit" value="Зберігти" name="save"></form></body></html>';
    
    return $content;


    3. Модифицируем плагин EasyLingual:
    Дописываем после
    // Remove lowercased tags when current lang is default lang
    if($default_lang == $_SESSION['lang'])
    	$lang_att = $language = "";

    следующее
    $res = $modx->db->select("*", $modx->getFullTableName('lang'));
    
    $lnarray = $modx->db->makeArray($res);
    
    preg_match_all("~\[\%t \`(.*)\`\%\]~U", $modx->documentOutput, $matchesz); 
    foreach($matchesz[1] as $ln){
    foreach($lnarray as $lnf){
    if($lnf['en'] == $ln){
    $modx->documentOutput = str_replace("[%t `".$ln."`%]", $lnf[$LANG_ATT], $modx->documentOutput);
    }
    }
    }


    Теперь всюду, где необходимо, встаем плейсхолдер вида
    [%t `фраза на английском`%]

    Вот вроде бы и все. Спасибо за внимание.
      • 785
      • 2,113 Posts
      Менять document.parser.class.inc.php под конкретную задачу, тем более, что в принципе в изменениях совершенно нет необходимости – чрезвычайно неудачная идея.
      Также неудачна реализация, при которой для каждого слова выполняется отдельный запрос к базе. Да и вообще, для описанной задачи не следует использовать сниппеты – можно написать плагин, назначив его событию OnWebPagePrerender (или другому, в соответствии с особенностями задачи), и менять за один раз все плейсхолдеры с определенным префиксом. То есть на страницах (и в других сниппетах) будут не вызовы сниппета, а плейсхолдеры, а в плагине выполняется одно обращение к базе для всех их.
        Создание сайтов на MODx, поддержка сайтов, поисковая оптимизация, программирование, копирайтинг
        Статьи о MODx, регулярно новые публикации
        • 27460
        • 13 Posts
        единственное, в чем не согласен, что плохого в изменении document.parser.class.inc.php? а именно - дополнение одной функцией?(ну про обновление ЦМС - да, плохо)

        Ваша идея кажеться лучше, хотелось бы реализовать таким способом, только подскажите, в каком виде должны быть плейсхолдеры с фразами?
          • 785
          • 2,113 Posts
          Quote from: Skakruk at Jun 12, 2010, 05:15 AM

          ну про обновление ЦМС - да, плохо
          Именно об этом и речь. Тем более, что в конкретном случае исправления совсем не требуются.

          Quote from: Skakruk at Jun 12, 2010, 05:15 AM

          в каком виде должны быть плейсхолдеры с фразами?
          Не совсем то же самое, но похоже (реализация работы с плейсхолдерами) – плагин для мультиязычного сайта. В принципе в EasyLingual тоже похожие средства есть.
            Создание сайтов на MODx, поддержка сайтов, поисковая оптимизация, программирование, копирайтинг
            Статьи о MODx, регулярно новые публикации
            • 27460
            • 13 Posts
            все было бы отлично, если бы плагин срабатывал после инициализации сниппетов и чанков..

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

            так что, пока остаюсь при своем, развечто можна огранизовать хранение фраз в файле, что б лишний раз не трогать БД.
              • 785
              • 2,113 Posts
              Quote from: Skakruk at Jun 12, 2010, 07:18 AM

              все было бы отлично, если бы плагин срабатывал после инициализации сниппетов и чанков
              Я не просто так написал о событии OnWebPagePrerender, хотя в этот момент стандартных плейсхолдеров уже не будет, и надо думать о своих собственных. В любом случае надо думать, но все в принципе решаемо.
                Создание сайтов на MODx, поддержка сайтов, поисковая оптимизация, программирование, копирайтинг
                Статьи о MODx, регулярно новые публикации
                • 27460
                • 13 Posts
                так этот плагин и вызываеться по OnWebPagePrerender, OnLoadWebDocument, OnLoadWebPageCache, так же пробовал и с другими.. но результат неутешителен..
                а использую плейсхолдеры типа [%t `text`%] и ищу их в $modx->documentContent

                  • 785
                  • 2,113 Posts
                  Для OnWebPagePrerender следует использовать $modx->documentOutput. Но если не хочется изучать особенности MODx, можно и сниппетами все реализовать.
                    Создание сайтов на MODx, поддержка сайтов, поисковая оптимизация, программирование, копирайтинг
                    Статьи о MODx, регулярно новые публикации
                    • 27460
                    • 13 Posts
                    Quote from: AKots at Jun 12, 2010, 11:01 AM

                    Для OnWebPagePrerender следует использовать $modx->documentOutput.

                    век живи - век учись) теперь все работает)Спасибо)