aliokero

aliokero

С нами с 19 августа 2016; Место в рейтинге пользователей: #1436
aliokero
25 декабря 2019, 04:20
0
В Shopkeeper 3 перевод в корзине тоже не подключался при её обновлении с помощью AJAX, можно использовать такой Wrapper для корзины с помощью плагина:

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

$e =& $modx->Event;
$groupWrapTpl = isset($groupWrapTpl) ? $groupWrapTpl : '';

if ($e->name == 'OnSHKbeforeCartLoad') {
    $modx->lexicon->load($modx->cultureKey . ':localizator:default');
    
    $this_page_url = $this->config['pageId'] && is_numeric($this->config['pageId']) ? $this->modx->makeUrl($this->config['pageId'], '', '', 'full') : '/';
    $url_qs = strpos($this_page_url, "?") !== false ? "&" : "?";
    
    $empty_url = $this_page_url . $url_qs . 'shk_action=empty';
    $order_page_url = $modx->makeUrl($modx->config['personal_catalog_page_id'], '', '', 'full');

    $html = '
<div class="card catalog-cart list-cart rounded-0 my-4 shop-cart" data-shopcart="1">
   <div class="card-header text-uppercase">' . $modx->lexicon('personal_catalog_title') . '</div>
   <div class="card-body p-0">';
    
    if (!empty($_SESSION['shk_order'])) {
        $html .= '
      <div class="d-flex px-2 my-3">
         <p class="cart-clear mr-auto"><a href="' . $empty_url . '" id="shk_butEmptyCart"><i class="fa fa-times-circle pr-1"></i>' . $modx->lexicon('clear_catalog') . '</a></p>
         <p class="cart-print"><a href="' . $order_page_url . '" id="shk_butOrder"><i class="fa fa-print pr-1"></i>' . $modx->lexicon('print_preview') . '</a></p>
      </div>
';
    }

    $e->output($html);
}
aliokero
25 декабря 2019, 04:05
0
Вообще печально, когда возвращаюсь к проектам на ModX, что за такое время не допилили многоязычность по умолчанию из пакета установки. Пришлось потратить много времени, чтобы перенести уже имеющиеся 20 тыс записей из TV в localizator и автоматизировать этот вопрос. Да и добавление в словарь переводов в самом движке требует ~3 кликов мыши — поэтому был написан скрипт генерации mysql запросов. Благодарен автору за реализацию данного модуля, иначе было бы вообще печально редактировать эти переводы в доп. полях, теперь все по полочкам лежит :-)
aliokero
25 декабря 2019, 04:00
0
К примеру, если Вы хотите использовать перевод из словаря для русского слова, которое можно использовать в виде ключа словаря, но для этого нужно перевести к примеру Австрия -> avstrija и уже цеплять по этому ключу перевод из словаря:
{$country | translit | lower | lexicon}
Привожу код, сниппета translit:
<?php
$stringToApplyTransliterationTo = $input;
$options                        = array();
$translitTableName              = 'russian';
$translitClassPath              = $modx->getOption('friendly_alias_translit_class_path', $options, $modx->getOption('core_path', $options, MODX_CORE_PATH) . 'components/') . 'modx/translit/';
if ($modx->getService('translit', 'modTransliterate', $translitClassPath, $options)) {
    $alias = $modx->translit->translate($stringToApplyTransliterationTo, $translitTableName);
}
return $alias;
P.S. Можно добавить trim, или replace пробелов в fenom конструкцию, если контент менеджер случайно пробелы впишет до или после " Австрия"
aliokero
25 декабря 2019, 03:53
0
И последний инструмент, который поможет быстро заполнить переводы в ручном режиме для словаря:
Скрипт, генерации mysql запросов.
Используется при статических переводах, к примеру заголовки и т.д. Вызывается перевод на примере скриншота так
{'product_title' | lexicon}
. Но не забудьте, что сгенерированный запрос нужно выполнить в phpMyAdmin… Сам скрипт, нужно поместить в созданную в корне папку, к примеру lexicongen
aliokero
25 декабря 2019, 03:38
0
Также есть баг, например при использовании tinymcewrapper, поле для ввода перевода контента становится не textarea, а input, и в консоль выпадают критические JS ошибки, не давая всплывающему окну сохранить перевод, лечится таким костылем:
<?php
switch ($modx->event->name) {
    case 'OnManagerPageBeforeRender':
        /* Прерываем ошибку JavaScript при инициализации TinyMCE */
        $tinymwrapper_path = MODX_CORE_PATH . '/components/migx/elements/tv/tinymcewrapper.tpl';
        if (is_file($tinymwrapper_path)) {
            $tpl_content = file_get_contents($tinymwrapper_path);
            
            $tpl_file = preg_replace('/[^\S\r\n](tinymce\.get\(.*?\)\.save\(\);)/', 'try{$1}catch(e){}', $tpl_content);
            file_put_contents($tinymwrapper_path, $tpl_file);
        }

        /* Отключаем редактор для поля CONTENT в localizator, иначе поле будет input */
        $localizator_fields_path = MODX_CORE_PATH . '/components/localizator/processors/mgr/fields.class.php';
        if (is_file($localizator_fields_path)) {
            $tpl_content = file_get_contents($localizator_fields_path);
            
            $tpl_file = preg_replace('/[^\S\r\n]+(\$resourcefields\[\'content\'\])/', '$richtext = false;$1', $tpl_content);
            file_put_contents($localizator_fields_path, $tpl_file);
        }
	break;
}
aliokero
25 декабря 2019, 03:33
0
Разобрался в чем дело, в поле с переводом контента был вставлен сниппет и при использовании
{$_modx->resource.id | locfield : 'content'}
, появлялась ошибка
... core\components\pdotools\model\pdotools\pdotools.class.php : 989) Unexpected token ':' ...
, после добавления processElementTags в конце плагина проблем нет.

Добавляю код допила плагина, с учетом всех косяков.

<?php
/** @var modX $modx */
switch ($modx->event->name) {
    case 'pdoToolsOnFenomInit':
        /** @var Fenom $fenom
        Мы получаем переменную $fenom при его первой инициализации и можем вызывать его методы. 
        Например, добавим модификатор вывода имени домена сайта из произвольной ссылки.
        */
        $pdo = $modx->getService('pdoTools');
        
        // localizator
        $fenom->addModifier('locfield', function($id, $field = null) use ($pdo, $modx)
        {
            $pdo->debugParserModifier($id, 'locfield');
            
            /** @var modResource $resource */
            if (empty($id)) {
                $resource = $modx->resource;
            } elseif (!is_numeric($id)) {
                $field    = $id;
                $resource = $modx->resource;
            } elseif (!$resource = $pdo->getStore($id, 'resource')) {
                $resource = $modx->getObject('modResource', $id);
                $pdo->setStore($id, $resource, 'resource');
            }
            
            $key = $modx->getOption('cultureKey');
            if ($modx->getOption('cultureKey') != 'ru') {
                $q = $modx->newQuery("localizatorContent");
                $q->where(array(
                    "`resource_id` = '" . $id . "'",
                    "`key` = '" . $key . "'"
                ));
                $q->select(array(
                    $field
                ));
                $s = $q->prepare(); // print $q->toSQL(); die;
                $s->execute();
                $array       = $s->fetch(PDO::FETCH_ASSOC);
                $field_value = $array[$field];
                if (empty($field_value)) {
                    if (is_numeric($field)) {
                        $tvId = intval($field);
                    } else {
                        $tvObj = $modx->getObject('modTemplateVar', array(
                            'name' => $field
                        ));
                        if ($tvObj)
                            $tvId = $tvObj->get('id');
                    }
                    if ($tvId == 0) {
                        $resource = $modx->getObject('modResource', $id);
                        if ($resource)
                            return $resource->get($field);
                    }
                    
                    $q = $modx->newQuery("locTemplateVarResource");
                    $q->where(array(
                        "`contentid` = '" . $id . "'",
                        "`key` = '" . $key . "'",
                        "`tmplvarid` = '" . $tvId . "'"
                    ));
                    $q->select('value');
                    $s = $q->prepare();
                    $s->execute();
                    $array = $s->fetch(PDO::FETCH_ASSOC);
                    
                    return $array['value'];
                } else {
                    return $field_value;
                }
                
            }
            
            $output = '';
            if (!empty($resource)) {
                if (!empty($field)) {
                    if (strtolower($field) == 'content') {
                        $output = $resource->getContent();
                    } else {
                        $output = $resource->get($field);
                        if (is_null($output)) {
                            $output = $resource->getTVValue(preg_replace('#^tv\.#i', '', $field));
                        }
                    }
                } else {
                    $output = $resource->toArray();
                }
            }
            $pdo->debugParserModifier($id, 'locfield');
            
            // Get the modParser instance
            $parser = $modx->getParser();
            
            // Define how deep we can go
            $maxIterations = (integer) $modx->getOption('parser_max_iterations', null, 10);
            
            // Parse cached tags, while leaving unprocessed tags in place
            $parser->processElementTags('', $output, false, false, '[[', ']]', array(), $maxIterations);
            // Parse uncached tags and remove anything that could not be processed
            $parser->processElementTags('', $output, true, true, '[[', ']]', array(), $maxIterations);
            
            return $output;
        });
        break;
}
aliokero
25 декабря 2019, 03:17
0
Все это дело тестировалось на MODX Revolution 2.7.2-pl
Не забудьте в чанке, который отвечает за вывод начала документа (
<html><head>...</head>
), прописать
{$_modx->lexicon->load($modx->cultureKey . ':localizator:default')}
<base href="[[++site_url]]"/>
aliokero
25 декабря 2019, 03:06
0
В .htaccess сделал так, список расширений для игнорирования, к примеру /ir/templates/default/css/style.css => /templates/default/css/style.css и т.д.
RewriteCond %{REQUEST_URI} ^/([a-z]{2})/(.*\.(php|css|doc|docx|gif|ico|jpeg|jpg|js|pdf|png|ppt|pptx|svg|xls|xlsx|zip|woff|ttf|txt|xml))$
RewriteRule ^([a-z]{2})/(.*)$ $2 [L,QSA]
Сниппет переключения языка для Bootstrap 4
<?php
$pdo = $modx->getService('pdoTools');

$tplDefault = '@INLINE 
<a href="http://{$link}" class="dropdown-item">
  <img src="{$image}" alt="$language_name" title="{$language_name}">
</a>';

$tplWrapperDefault = '@INLINE
<div class="dropdown show lang-switcher">
    <a class="d-block btn btn-secondary dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{$modx->cultureKey | upper}</a>
    <div class="dropdown-menu" aria-labelledby="dropdownMenuLink">
        {$output}
    </div>
</div>';

$tpl = $modx->getOption('tpl', $scriptProperties, $tplDefault); 
$tplWrapper = $modx->getOption('tplWrapper', $scriptProperties, $tplWrapperDefault); 

$output = array();

// Определяем есть ли языки через "папки"
$uri = $_SERVER['REQUEST_URI'];
if(substr($uri, 0, 1)) {
    $uri = mb_substr($uri, 1);
    $tmp = explode('/', $uri);
    if($path = $tmp[0]) {
        $tmp = $modx->getObject('localizatorLanguage', array('http_host:LIKE' => "%/{$path}/"));
        if($tmp) {
            $uri = str_replace("{$path}/", "", $uri);
        }
    }
}

$languages = $modx->getIterator('localizatorLanguage');
foreach($languages as $language) {
    if(mb_substr($language->http_host, -1) == '/') {
        $link = $language->http_host . $uri;
    } else {
        $link = $language->http_host . '/' . $uri;
    }
    
    $image = "template/default/images/flags/" . $language->key . ".svg";
 
    $params = array(
      'link' => $link,
      'image' => $image,
      'language_name' => $language->name
    );
    $output[] = $pdo->getChunk($tpl, $params);
}

$output = implode("\n", $output);

return $pdo->getChunk($tplWrapper, array('output' => $output));
В чанке, использую так
{if $_modx->config.cultureKey != 'ru'}
	{set $select = '{ "localizator" : "modResource.*, localizator.*, modResource.id" }' }
	{set $where =  '{ "localizator.key" : "' ~ ('localizator_key' | option) ~ '"}' }
{/if}

{set $langSwitcher = $modx->runSnippet('langSwitcher')}

{$_modx->runSnippet('pdoMenu', [
			'level' => 2,
			'parents' => 0,
			'outerClass' => 'menu w-100',
			'tpl' => '@INLINE <li><a href="[[+link]]">[[+menutitle]]</a>[[+wrapper]]</li>',
			'tplOuter' => '@INLINE 
<ul [[+classes]] id="menu">
  [[+wrapper]]
	<li class="float-right pr-3">' ~ $langSwitcher ~ '</li>
</ul>',
			'tplInner' => '@INLINE <ul>[[+wrapper]]</ul>',
			'tplParentRow' => '@INLINE 
	<li>
		<label for="drop-[[+id]]" class="toggle toogle-2" data-item="[[+menutitle]]"><span class="fa fa-angle-down" aria-hidden="true"></span></label>
		<a href="[[+link]]">[[+menutitle]] <span class="fa fa-angle-down" aria-hidden="true"></span></a>
		<input type="checkbox" id="drop-[[+id]]">
		[[+wrapper]]
	</li>',
  'leftJoin' => '{
    "localizator" : {
      "class" : "localizatorContent",
			"alias" : "localizator",
			"on" : "localizator.resource_id = modResource.id"
		}
	}',
	'select' => $select,
  'where' => $where
])}
P.S. locfield представленный выше модуль, работает криво при выводе content:
{$_modx->resource.id | locfield : 'content'}

А вызов из документации вообще ничего не выводит
{$_modx->resource.localizator_content}
Хотелось бы понять почему так происходит…

Также, может кому-то помогу, представлю mysql запрос, который перенесет уже имеющую локализацию сделанную на доп. полях (tv). К примеру, keywords_en, country_en и т.п. с постфиксом _en на конце:
INSERT INTO modx_localizator_tmplvar_contentvalues (`key`, `tmplvarid`, `contentid`, `value`) 
SELECT 'en' AS 'key',
modx_site_tmplvars_copy.id tmplvarid, 
       modx_site_tmplvar_contentvalues.contentid,
       modx_site_tmplvar_contentvalues.value
FROM   modx_site_tmplvar_contentvalues 
JOIN modx_site_tmplvars 
  ON modx_site_tmplvar_contentvalues.tmplvarid = modx_site_tmplvars.id 
JOIN modx_site_tmplvars modx_site_tmplvars_copy
  ON Substring_index(modx_site_tmplvars.name, '_en', 1) = modx_site_tmplvars_copy.name
WHERE  modx_site_tmplvars.name LIKE '%_en';