среда, 22 декабря 2010 г.

Взаимосвязанные меню в TYPO3

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




И хотя, на первый взгляд реализация двух взаимосвязанных блоков меню кажется довольно сложной, на самом деле все очень просто. Приведу два кусочка своего typoscript, которые реализовывают данную возможность.

Это кусочек кода который отвечает за верхнюю строку меню. За это отвечает параметр - entryLevel = 0

tempmenu.TOP_MENU = HMENU
tempmenu.TOP_MENU.entryLevel = 0
# исключаем из меню некоторые страницы, например Карта сайта и все-такое...
tempmenu.TOP_MENU.excludeUidList = 44,163
tempmenu.TOP_MENU.1 = TMENU
tempmenu.TOP_MENU.1 {
noBlur = 1
ACT = 1
CUR = 1
}
tempmenu.TOP_MENU.1.NO {
allWrap = <span class="menu_left"> </span><span class="menu">|</span><span class="menu_right"> </span>
}
tempmenu.TOP_MENU.1.ACT {
allWrap = <span class="curmenu_left"> </span><span class="curmenu">|</span><span class="curmenu_right"> </span>
}
tempmenu.TOP_MENU.1.CUR {
allWrap = <span class="curmenu_left"> </span><span class="curmenu">|</span><span class="curmenu_right"> </span>
doNotLinkIt = 1
}

А это кусочек typoscript, который отвечает за генерацию бокового меню или меню подразделов (entryLevel = 1):

# Настройка левого меню
tempmenu.LEFT_MENU = HMENU
tempmenu.LEFT_MENU.entryLevel = 1
tempmenu.LEFT_MENU.wrap = <ul>|</ul>
# Настройка 1-го уровня левого меню
tempmenu.LEFT_MENU.1 = TMENU
tempmenu.LEFT_MENU.1 {
noBlur = 1
ACT = 1
CUR = 1
}
tempmenu.LEFT_MENU.1.NO {
allWrap = <li class="menu_v1_lev2">|</li>
}
tempmenu.LEFT_MENU.1.ACT {
allWrap = <li class="menu_v1_lev2 active">|</li>
}
tempmenu.LEFT_MENU.1.CUR {
allWrap = <li class="menu_v1_lev2 current"><span>|</span></li>
doNotLinkIt = 1
}
# Настройка 2-го уровня левого меню
tempmenu.LEFT_MENU.2 = TMENU
tempmenu.LEFT_MENU.2 {
noBlur = 1
ACT = 1
CUR = 1
}
tempmenu.LEFT_MENU.2.NO {
allWrap = <li class="menu_v1_lev3">|</li>
}
tempmenu.LEFT_MENU.2.ACT {
allWrap = <li class="menu_v1_lev3 active">|</li>
}
tempmenu.LEFT_MENU.2.CUR {
allWrap = <li class="menu_v1_lev3 current"><span>|</span></li>
doNotLinkIt = 1
}


Совет

Несмотря на то, что, по своей неопытности, я использовал в скриптах имя объекта - tempmenu, рекомендую делать красиво и не повторять моих прежних "ошибок".

Используйте в своих TypoScript либо lib объект, либо temp. Возможно Вы спросите - но какая разница между ними? В каких случаях нужно использовать один объект, а когда другой?

Дело в том, что объекты, которые хранятся внутри temp носят временный характер, и как следствие - не кэшируются, в отличии от объекта - lib. Это также означает, что Вы не сможете делать ссылку на объект temp или изменять его по ссылке.

Хочу привести наглядный пример. Допустим у нас есть объекты temp и lib:

temp.myTemp = TEXT
temp.myTemp.value = Это текст внутри temp!
lib.myLib = TEXT
lib.myLib.value = Это текст внутри lib!

Попытаемся вывести данный текст на страницу 3-мя различными способами...
# Вывод значений объектов
page.10 = COA
page.10 {
10 < temp.myTemp
10.wrap = <strong>Temp: </strong>|<br />
20 < lib.myLib
20.wrap = <strong>Lib: </strong>|<br />
wrap = <p>|</p>
}
# Вывод значений объектов по ссылке
page.20 = COA
page.20 {
10 =< temp.myTemp
10.wrap = <strong>Temp: </strong>|<br />
20 =< lib.myLib
20.wrap = <strong>Lib: </strong>|<br />
wrap = <p>|</p>
}
# Передача объекта lib по ссылке объекту temp
temp.myTemp =< lib.myLib
page.30 = COA
page.30 {
10 < temp.myTemp
10.wrap = <strong>Temp: </strong>|<br />
20 < lib.myLib
20.wrap = <strong>Lib: </strong>|<br />
}

Результатом работы данного скрипта будет следующий вывод:

Это текст внутри temp!
Это текст внутри lib!

Это текст внутри lib!

Это текст внутри temp!
Это текст внутри lib!

Надеюсь, Вам все понятно - почему результаты работы именно такие.

 
воскресенье, 19 декабря 2010 г.

4 способа создания страницы 404 (Page not found) в TYPO3

Как я уже писал в одной своей заметке (SEO и общие рекомендации), для сайта очень важно, чтобы при обращении к заведомо несуществующей странице, например http://www.domain.com/bla-bla-bla, сервер не выдавал страницу с кодом: HTTP/1.1 302 Found. Сайт необходимо настраивать так, чтобы при обращении к несуществующей странице веб-сервер возвращал страницу с кодом - Error 404 (Page not found).
В противном случае, некорректная обработка данного запроса может привести к неправильной индексации сайта поисковыми системами, вплоть до полного исключения сайта из индекса поисковой системы.

Как же настроить сайт на TYPO3 надлежащим образом?

Для решения данной задачи у TYPO3 имеется несколько различных способов:

1. Самый простой способ. В конфигурационном файле localconf.php установить параметр:
$TYPO3_CONF_VARS['FE']['pageNotFound_handling'] = true;
После этого, реакция системы на URL типа http://www.domain.com/kgfhted будет приводить к появлению страшного и непонятного для пользователя сообщению:


2. Более сложный подход. В конфигурационном файле localconf.php установить 2 параметра:
$TYPO3_CONF_VARS["FE"]["pageNotFound_handling_statheader"] = 'HTTP/1.1 404 Not Found';
$TYPO3_CONF_VARS["FE"]["pageNotFound_handling"] = "http://www.domain.com.ua/error404.html";
Где error404.html это такая же страница сайта, которая была создана с помощью админки Typo3. Например:


Второй параметр можно прописать и так, заменив алиас страницы, на её id:
$TYPO3_CONF_VARS['FE']['pageNotFound_handling'] = '/index.php?id=page_id';

Этот подход намного цивильнее, т.к. данная страница уже будет содержать более внятные и полезные комментарии, помогающие пользователю быстрее понять, что произошло и как из данной ситуации можно выйти. Вот, 11 советов о том, какой должна быть данная страница (а это перевод). Как вариант, она может выглядеть вот так:


3. Более продвинутый способ. Страницу 404 можно не создавать в BE, а генерировать с помощью php. Для этого в localconf.php нужно установить следующих 2 параметра:
$TYPO3_CONF_VARS["FE"]["pageNotFound_handling_statheader"] = 'HTTP/1.1 404 Not Found';
$TYPO3_CONF_VARS["FE"]["pageNotFound_handling"] = 'USER_FUNCTION:fileadmin/pageNotFoundHandling.php:user_pageNotFound->pageNotFound';

Как видно из значения 2-го параметра, в директории fileadmin должен находиться файл -
pageNotFoundHandling.php (имя файла может быть произвольным), в нем должен быть определен класс - user_pageNotFound, который имеет метод - pageNotFound.
Примерное содержимое pageNotFoundHandling.php, может быть таковым:
<?php
class user_pageNotFound {

function pageNotFound($param,$ref) {

print "<html>\n<head>\n<title>404 Not found : Sitename</title>\n";


//print '<meta http-equiv="refresh" CONTENT="0;URL=/fileadmin/404-not-found.html">\n';

print "</head>\n<body>\n";

print "Запрашиваемая Вами страница не найдена!";
print "<!--

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

-->";

print "</body>\n</html>\n";

}

}
?>

Т.к. страница 404 должна быть размером более 512 байт, я добавил лишние комментарии - Lorem Ipsum...

4. Опять простой способ. TYPO3 можно настроить так, чтобы при возникновении ошибки 404 на сайте, веб-сервер возвращал пользователю статическую html-страничку. Для этого в localconf.php нужно установить 2 параметра:

$TYPO3_CONF_VARS["FE"]["pageNotFound_handling_statheader"] = 'HTTP/1.1 404 Not Found';
$TYPO3_CONF_VARS['FE']['pageNotFound_handling'] = 'READFILE:fileadmin/404.html';

Как видно из примера, в директории fileadmin должен находиться файл 404.html, который и будет видеть пользователь. Напомню еще раз, его размер должен быть более 512 байт!

Обязательно проверьте настройки RealUrl, а то, иногда, можно сломать себе мозг от того, что ничего не работает, хотя все сделано правильно! Обычно, у меня настройки RealUrl находятся в  файлах typo3conf/realurl_conf.php или typo3conf/realurlconf.php. Убедитесь что параметр postVarSet_failureMode не имеет значение - redirect_goodUpperDir. Он должен быть пустым, т.е. postVarSet_failureMode=''.

Что же касается многоязычных сайтов, то для того, чтобы страница с 404-ошибкой была на соответствующем языке, необходимо параметр $TYPO3_CONF_VARS['FE']['pageNotFound_handling'] в typo3conf/localconf.php менять примерно следующим образом:

if (substr($_SERVER['REQUEST_URI'], 0, 4) == '/en/' || $_GET['L'] == 1) {
   $TYPO3_CONF_VARS['FE']['pageNotFound_handling'] = '/en/error404.html';
} elseif (substr($_SERVER['REQUEST_URI'], 0, 4) == '/fr/' || $_GET['L'] == 2) {
   $TYPO3_CONF_VARS['FE']['pageNotFound_handling'] = '/fr/error404.html';
} else {
   $TYPO3_CONF_VARS['FE']['pageNotFound_handling'] = '/error404.html';
}

Начиная с 6-й версии TYPO3 конфигурационный файл системы стал называться LocalConfiguration.php, а также претерпел значительные изменения в формате данных. Для того, чтобы сделать страницу 404-й ошибки мультиязычной для данной версии, я использовал следующие настройки:

'FE' => array(
  ......
 'pageNotFound_handling_statheader' => 'HTTP/1.1 404 Not Found',
 'pageNotFound_handling' => (substr($_SERVER['REQUEST_URI'], 0, 5) == '/rus/' || $_GET['L'] == 1) ? '/rus/error404/' : '/error404/',
),

Ну вот и всё! Упомяну также, что данную задачу можно решить и настройками Apache. Просто почитайте о параметре ErrorDocument.
суббота, 11 декабря 2010 г.

Indexed Search или эпопея с InnoDB


Казалось бы, какая связь между Indexed Search и InnoDB? Но...

Переносил я тут недавно один свой TYPO3-сайт на новый хостинг... Как говорится, перенес один в один. Но все пошло не так гладко как казалось на первый взгляд - перестал работать поиск на сайте, организованный экстом - indexed_search.

Слёту я решил переустановить (uninstall+install), а затем и обновить версию indexed_search, но это не помогло.

Правильное направление поиска причин возникновения проблемы, задала такая вещь. Каждый раз, при проверке настроек экста - indexed_search в менеджере расширений, он предлагал мне сделать update некоторых своих таблиц. Причем, суть данного апдейта сводилась не к созданию отсутствующих таблиц или полей, а смене движка для некоторых таблиц на InnoDB. Ну тут и начался несколько пролонгированный и довольно "сексуальный" курс повышения квалификации в области MySQL.

У меня сразу возник вопрос, а поднят ли этот движок на моем хостинге. Зайдя на консоль мускула я набрал следующую команду:
mysql> show engines;
и увидел ответ:
InnoDB |DISABLED
набрал еще другую команду, которая подтвердила наличие трабл с InnoDB:
mysql> show engine innodb status;
ERROR 1235 (42000): Cannot call SHOW INNODB STATUS because skip-innodb is defined

Немного погуглив, я сделал следующее:
1. Остановил MySQL, с помощью команды: /etc/init.d/mysql stop
2. Переименовал 2 лог-файла - ib_logfile0 и ib_logfile1:
mv /var/lib/mysql/ib_logfile0 /var/lib/mysql/ib_logfile0.bak
mv /var/lib/mysql/ib_logfile1 /var/lib/mysql/ib_logfile1.bak
3. Запустил MySQL: /etc/init.d/mysql start. При запуске на консоли стали появляться довольно страшные сообщения:
101027 20:59:45 InnoDB: Error: page 513 log sequence number 0 972453278
InnoDB: is in the future! Current system log sequence number 0 544625838.
InnoDB: Your database may be corrupt or you may have copied the InnoDB
InnoDB: tablespace but not the InnoDB log files. See
InnoDB: http://dev.mysql.com/doc/refman/5.0/en/forcing-recovery.html
InnoDB: for more information.

Хотя, когда я опять из консоли MySQL выполнил знакомую нам команду:
mysql> show engines;
то увидел более приятное сообщение:
MyISAM | DEFAULT
InnoDB | YES

Таким образом я оживил InnoDB на своем сервере, но моя база оставалась "паламатая".

Вылечил базу мускула я следующими действиями:
1. В конфигурационный файл MySQL - /etc/mysql/my.cnf добавил параметр, который блокирует все Insert и Update на сервере:
innodb_force_recovery = 4
(это позволяет нам, как бы, заморозить базу в исходном состоянии на какое-то время). Заодно можно запомнить или записать значение параметра datadir из my.cnf, указывающий на местонахождение файлов БД и которое будет нужно в дальнейшем.

Если вы не знаете где находится файл my.cnf, то воспользуйтесь командой: find / -name my.cnf.

2. Рестартовал MySQL:
/etc/init.d/mysql stop
/etc/init.d/mysql start

3. Дополнительной утилитой мускула сделал дамп своей базы данных:
mysqldump --force --compress --triggers --routines --create-options -uroot -pROOTPASSWORD --databases DATABASENAME > /usr/mydb.sql

4. В очередной раз остановил сервер MySQL:
/etc/init.d/mysql stop
есть также и другой способ остановки сервиса:
mysqladmin -uroot -pROOTPASSWORD shutdown

5. Нашел физическое местонахождение директории с файлами БД (можно с помощью find / -name DATABASENAME) и записал на листике её имя, имя ее собственника (owner) и сумму прав на неё (rwx------, или 700). Все это может показать команда ls -l

6. Удалил полностью эту директорию (а точнее переместил в другое место - береженого бог бережет, как говорится :):
rm -fdr /var/lib/mysql/DATABASENAME/
БУДЬТЕ ОЧЕНЬ ВНИМАТЕЛЬНЫ, НЕ ЗАХВАТИТЕ НИЧЕГО ЛИШНЕГО!!!

7. Тут же создал директорию с таким же именем и задал её овнера и права:
mkdir /var/lib/mysql/DATABASENAME/
chown -R mysql:mysql /var/lib/mysql/DATABASENAME/
chmod -R 700 /var/lib/mysql/DATABASENAME/

8. Специальной утилитой mysql_install_db создал новые таблицы привилегий MySQL:
/usr/local/bin/mysql_install_db
и на всякий случай повторил присвоение овнера и установку прав:
chown -R mysql:mysql /var/lib/mysql/DATABASENAME/
chmod -R 700 /var/lib/mysql/DATABASENAME/

9. Убрал параметр innodb_force_recovery из конфигурационного файла - my.cnf

10. Запустил mysql:
/etc/init.d/mysql start

11. Импортировал данные обратно в базу данных:
mysql -uroot --compress < /usr/mydb.sql

12. Напоследок, обновил таблицы привилегий mysql:
/usr/bin/mysqladmin -uroot flush-privileges

Ну, вот и всё парни, а точнее мужики если дочитали эту статью до конца. Вы не поверите, но indexed_search у меня заработал.
Неужели для indexed_search так важно иметь движок InnoDB для некоторых своих таблиц?
Чтобы ответить себе на этот вопрос у меня уже не оставалось ни времени, ни сил, ни большого желания.

P.S. Все пути к директориям, которые есть в данной статье, скорее всего у вас будут другими. Поэтому, если вам нужно выполнить какую-то утилиту или найти файл, то используйте команду find / -name file_or_dir_name, она действительно рулит.

 

среда, 10 ноября 2010 г.

SEO и общие рекомендации



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

1. Рекомендации по основным элементам страниц сайта.

Как уже было сказано в предыдущих статьях, для СЕО очень важны 3 вещи - title страницы, meta-тег description и meta-тег keywords.

Что касается длины этих параметров, то общие рекомендации для заточки под Google такие:

Title - должен содержать не более 12 слов, общая длина которых должна составлять от 70 до 80 символов (наиболее важные слова располагайте первыми).
Description - рекомендуемая длина содержимого этого МЕТА-тега – 150 символов и она не должна превышать 200 символов (это должен быть текст описывающий контент вашей страницы, а не набор ключевых слов и словосочетаний).
Keywords - этот тег должен содержать около 200 символов, во всяком случае, длина не должна превышать 250 символов.

На сайте не должно быть страниц с повторяющимися Title и Description!

2. Рекомендации по контенту сайта.

Для каждой страницы может быть только один тег <H1>, несколько тегов <H2> и <H3> (причем тегов <H2> и <H3> может не быть вообще). Желательно, чтобы внутри тегов <H1>, <H2>, <H3> не содержались другие теги (например, <H1><em>текст</em></H1>), а также дополнительные атрибуты (например, <H2 class="red-italic">).

Оформление заголовков <H1>, <H2>, <H3> необходимо переносить в таблицу или файл-стилей.

Оформление текста, который является ссылкой, должно отличаться от оформления основного текста страницы, например подчеркиванием, цветом и т.п.

Оформление текста, помещенного в теги <STRONG>, должно отличаться от оформления основного текста страницы, например полужирным начертанием, курсивом, цветом и т.п.

Все картинки <IMG> должны иметь атрибут - alt.

Для внешних ссылок, которые не являются партнерскими, желательно добавить атрибут rel=”nofollow”, что позволит сократить отток PR с Ваших страниц.

Ключевые слова, которые встречаются в ваших текстах, желательно выделять либо полужирным начертанием, с помощью тегов <B> и <STRONG>, либо курсивом - тегами <I> и <EM>.

По возможности делайте слоганы не графическими а текстовыми.

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

Очень важно! Запомните, недопустимо полное или частичное использование текстов сайта в качестве рекламных текстов, пресс-релизов и т.п. на внешних ресурсах (в т.ч. контекстная реклама, доски объявлений и т.д.), а также недопустимо дублирование текстов внутри самого ресурса. Старайтесь как можно меньше передирать контент с других ресурсов.

Для правильного и оперативного определения поисковой системой региона сайта, настоятельно рекомендую внести на страницу с контактной информацией сайта полные контактные данные, включая индекс и название города в формате:
49000, г. Днепропетровск, ул. Короленко, д. 123.
А также номера телефонов, включая префикс, в формате:
+38 (067) 123-1234, +38 (0562) 111-222 (факс).
Если на сайте не указаны региональные контактные координаты, то может возникнуть ситуация, при которой поисковые системы (например, Яндекс) будут присваивать сайту не соответствующий регион, что приведет к некорректному положению сайта при выдаче результатов поиска.


3. Технические рекомендации.

Каждый сайт должны иметь 3 обязательных файла: robots.txt, sitemap.xml и favicon.ico (думаю, что все знают их назначение). Первые два файла запрашивают все поисковые боты, а последний - все клиентские браузеры, поэтому не нужно их огорчать ;)).

При запросе любых URLs, содержащих неосновные хосты (например, http://domain.com/ или http://domain.com/page.html без префикса WWW) необходимо сделать полный редирект на URL, с ответом сервера HTTP/1.1 301 Moved Permanently, содержащий основной хост - http://www.domain.com/.
Пример решения:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^domain\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/robots\.txt$
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]

На сайте не должны присутствовать повторяющиеся страницы, например главная страница по двум адресам http://www.domain.com/ и http://www.domain.com/index.html. Необходимо оставить http://www.domain.com/ страницу, а для страниц-дубликатов настроить переадресацию с ответом сервера HTTP/1.1 301 Moved Permanently на соответствующие страницы, либо HTTP/1.1 404 Not Found. Необходимо, чтобы каждая страница была доступна только по одному адресу.
Пример решения:
Redirect 301 /index.html http://www.domain.com/

При обращении к заведомо несуществующей странице, например http://www.domain.com/bla-bla-bla сервер не должен выдавать: HTTP/1.1 302 Found. Необходимо настроить сервер так, чтобы при обращении к несуществующей странице он выдавал: HTTP/1.1 404 Not Found.
Некорректная обработка данного запроса может привести к неправильной индексации сайта поисковыми системами и к проблемам с индексацией вообще, вплоть до полного исключения сайта из индекса поисковой системы.


P.S. На SEO влияет также и скорость работы сайта, но это уже тема для отдельного будущего разговора.

 

понедельник, 27 сентября 2010 г.

TYPO3 и SEO (часть вторая - tt_news)

В предыдущей статье, а точнее в первой части темы TYPO3 и SEO, я рассказывал о том, как в Typo3 с помощью дополнительных плагинов и TypoScript можно формировать Title и Description обычных страниц системы - page. Но сайт на Typo3 может иметь и другие страницы...

Tt_news - одно из наиболее популярных расширений, применяемых с Typo3. Данный плагин для просмотра всего списка новостей использует одну единственную страницу - страницу детального просмотра новости. Для единообразия и более успешной раскрутки сайта, данная страница должна иметь тот же формат Title, что и все остальные страницы.

Я покажу как это можно сделать.

Предположим, что мы имеем следующие страницы на сайте:




Причем, уникальные идентификаторы страниц (uid) имеем следующие:
Новости - 12
Новости сайта - 37 (страница единичного просмотра)
Новости и статьи - 4 (Sysfolder со списком новостей)

Typo3 шаблон для страницы Новости и Новости сайта:
plugin.tt_news.code >
# Не индексируем страницу со списком новостей
config.index_enable = 0

plugin.tt_news {
code = LIST
}
[globalVar = TSFE:id = 70]
# На данной странице показываем только архивные новости
plugin.tt_news.archive = 1
[else]
plugin.tt_news.archive = -1
[global]

[globalVar = GP:tx_ttnews|tt_news > 0]
# Страница единичной новости
plugin.tt_news.code = SINGLE
# Страницу единичной новости - индексируем!
config.index_enable = 1
# Для единичной новости или статьи создаем мета-теги по нашим правилам
config.noPageTitle = 2

# Для description страницы используем subheader - подзаголовок новости
page.meta.description >
page.meta.description.data = register:newsSubheader

# Запросом находим title - заголовок новости
lib.meta_news=CONTENT
lib.meta_news.table = tt_news
lib.meta_news.select {
pidInList = 4
andWhere.data = GP:tx_ttnews|tt_news
andWhere.intval = 1
andWhere.wrap = uid=|
}

# Это будет перенос на новую строку (см. далее)
lib.meta_news.renderObj = COA
lib.meta_news.renderObj.5 = TEXT
lib.meta_news.renderObj.5.value (

)

lib.meta_news.renderObj.10 = TEXT
lib.meta_news.renderObj.10 {
field = title
wrap = <title>| : Имя сайта</title>
}
lib.meta_news.renderObj.10.append < lib.meta_news.renderObj.5

# Ручная генерация мета-тега - description
# (если кому-то интересно - можно разкомментировать, но убрать page.meta.description выше)
#lib.meta_news.renderObj.20 = TEXT
#lib.meta_news.renderObj.20 {
# field = short
# wrap = <meta name="description" content="|" />
#}
#lib.meta_news.renderObj.20.append < lib.meta_news.renderObj.5

# Записываем в заголовок мета данные
page.headerData.776 >
page.headerData.776 < lib.meta_news

[global]

# Остальные настройки новостей
plugin.tt_news.stdWrap.wrap =
|

plugin.tt_news.templateFile = fileadmin/templates/tt_news_v3_template.html
# Указываем id папки с новостями
plugin.tt_news.pid_list = 4
# Указываем страницу для детального просмотра
plugin.tt_news.singlePid = 37
# Количество новостей в списке
plugin.tt_news.limit = 6
# Задаем формат даты
plugin.tt_news.displayList.date_stdWrap.strftime = %d.%m.%Y
# Если у новости нет подзаголовка, то в режиме списка новостей отображаем первые 250 символов её "тела"
plugin.tt_news.displayList.subheader_stdWrap {
crop = 250 | ... | 1
ifEmpty.field = bodytext
}
lib.newsContent < plugin.tt_news
воскресенье, 18 июля 2010 г.

TYPO3 и SEO (часть первая)

Думаю, ни для кого не секрет, что базовыми элементами SEO являются: заголовок страницы (TITLE), описание страницы (META DESCRIPTION) и набор ключевых слов (META KEYWORDS).

Благодаря своему скрипту, Typo3 позволяет динамично и довольно гибко управлять данными параметрами, что делает тайповские сайты дружественными для поисковых систем.

Ну что ж, начнем, пожалуй? Но для начала установим небольшое, очень простое и очень полезное расширение - seo_basics.

Данное расширение позволяет очень эффективно просматривать и редактировать все вышеперечисленные параметры для всех страниц сайта:









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


После редактирования полей их необходимо активировать с помощью следующего TypoScript:

page.meta.keywords.field = keywords
page.meta.description.field = description

А где же активация Title спросите Вы. Тут не все так просто! Дело в том, что заголовок страницы, как правило, является составным. В моей практике, это чаще всего - заголовок текущей страницы + разделитель + название сайта. На самом деле, правила формирования Title могут быть какими-угодно. Здесь главное помнить следующее:
1. Поисковики учитывают только 70-80 символов заголовка (Google - 70, Yandex - 80);
2. Чем ближе к началу фразы слово, тем его вес для поисковиков выше;
3. Чем короче заголовок страницы тем весомее каждое его слово;
4. Крайне желательно, чтобы на сайте не было страниц с повторяющимися Title, т.е. заголовки страниц должны быть уникальными.

Я покажу как сформировать заголовок в формате:
Заголовок страницы : Имя сайта (компании)

Имя сайта прописывается здесь:





Теперь с помощью TypoScript собираем все вместе:


# Говорим TYPO3 что title мы формируем сами
config.noPageTitle = 2

plugin.tx_seobasics_sitetitle >
plugin.tx_seobasics_sitetitle = TEXT
plugin.tx_seobasics_sitetitle {
cObject =< plugin.tx_seobasics_sitetitle.multilang
ifEmpty.data = TSFE:tmpl|sitetitle
}

plugin.tx_seobasics >
plugin.tx_seobasics = COA
plugin.tx_seobasics {
# Формируем title страницы
10 = TEXT
10.data = page:tx_seo_titletag // page:title
10.trim = 1
10.stdWrap.stdWrap.append = TEXT
10.stdWrap.stdWrap.append.cObject < plugin.tx_seobasics_sitetitle
10.stdWrap.stdWrap.append.trim = 1
10.stdWrap.stdWrap.append.required = 1
10.stdWrap.stdWrap.append.if.isTrue = {$plugin.tx_seo.titleWrapAppendSiteTitle}
10.stdWrap.stdWrap.append.noTrimWrap = | : ||
10.stdWrap.noTrimWrap = {$plugin.tx_seo.titleWrap}
10.stdWrap.insertData = 1
10.htmlSpecialChars = 1
10.wrap = <title>|</title>

# Если Вам нужен и мета-тег title раскомментируйте нижние две строки
#20 < .10
#20.wrap = <meta name="title" content="|" />

# Ниже приведен скрипт позволяющий формировать остальные SEO-теги вручную

# Building the Keywords tag
#30 = TEXT
#30 < .10
#30.data = page:keywords
#30.stdWrap.noTrimWrap = {$plugin.tx_seo.keywordsWrap}
#30.stdWrap.stdWrap >
#30.required = 1
#30.wrap = <meta name="keywords" content="|" />

# Building the Description tag
#40 = TEXT
#40 < .30
#40.data = page:description
#40.stdWrap.noTrimWrap = {$plugin.tx_seo.descriptionWrap}
#40.wrap = <meta name="description" content="|" />

# Building the date tag (last changed)
#50 = TEXT
#50 < .10
#50.data = page:SYS_LASTCHANGED // page:crdate
#50.date = Y-m-d
#50.stdWrap >
#50.wrap = <meta name="date" content="|" />
}

# Записываем наши теги с раздел head страницы сайта
page.headerData.776 = < plugin.tx_seobasics

P.S. В репозитории расширений Typo3 имеется масса СЕО-прибомбасов, в том числе и такие, которые сами генерируют набор ключевых слов для каждой страницы сайта.

 

понедельник, 28 июня 2010 г.

Продвинутое меню breadcrumb или осваиваем optionSplit

 


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




Итак, поставленная задача примерно такова:
1. Домашнюю страницу нужно отобразить изображением - домиком (это 0-й уровень меню)
2. Меню 1-го уровня (About ICH) необходимо отобразить ссылкой серого цвета
3. Меню остальных уровней - обычные ссылки
4. Текущий пункт меню должен быть крупным и жирным
5. Пункты меню должны отображаться задом наперед, как на картинке.


Эту задачу я не решил, если бы не замечательное свойство optionSplit.

Так, что же такое optionSplit и что оно нам дает?

Само название свойства говорит о том, что оно что-то разбивает на части. Так и есть, optionSplit позволяет разбить любую субстанцию на 3 части с помощью специального разделителя - |*|. Эти три части устроены так: первая, последняя и все остальное, что осталось между ними:

...first part... |*| ...middle part... |*| ...last part...

Сразу для наглядности небольшой пример,
ACT.doNotShowLink = 1 |*| 0 |*| 1
Эта конструкция сделает первый и последний элемент меню простым текстом, а все остальные ссылками.

Если пока еще ничего не понятно, то сейчас при решении нашей конкретной задачи станет яснее:
1. Организуем наше меню с помощью списков UL и LI. Создаем скрипт-заготовку:
lib.breadcrumb = HMENU
lib.breadcrumb.special = rootline
lib.breadcrumb.special.range = 0|-1
lib.breadcrumb.wrap = <ul> | </ul>
lib.breadcrumb.1 = TMENU
lib.breadcrumb.1{
noBlur = 1
NO.allWrap = <li> | </li>

ACT = 1
ACT.allWrap = <li> | </li>

CUR = 1
CUR.allWrap = <li> | </li>
CUR.doNotLinkIt = 1
}

2. Делаем первый пункт навигационного меню изображением домика (следите за изменениями ACT.allWrap).

Сначала наш список пунктов меню делим на 3 части:

ACT.allWrap = <li class="firstcrumb">|</li>|*|<li>|</li>|*|<li class="lastcrumb">|</li>

Добавляем для первого меню картинку:
ACT.allWrap = <li class="firstcrumb">|<img src="fileadmin/templates/img/home.png" alt="Home" /></li>|*|<li>|</li>|*|<li class="lastcrumb">|</li>

Делаем изображение ссылкой:
ACT.allWrap = <li class="firstcrumb">|<a href="http://www.domain.com/"><img src="fileadmin/templates/img/home.png" alt="Home" /></a></li>|*|<li>|</li>|*|<li class="lastcrumb">|</li>

Удаляем текстовую ссылку возле домика:
ACT.allWrap = <li class="firstcrumb"><a href="http://www.domain.com/"><img src="fileadmin/templates/img/home.png" alt="Home" /></a></li>|*|<li>|</li>|*|<li class="lastcrumb">|</li>
# здесь делим список всего на 2 части - первый пункт меню и все остальные
# первый пункт меню - не ссылка!
ACT.doNotShowLink = 1 |*| 0

3. Меню 1-го уровня (About ICH) необходимо отобразить ссылкой серого цвета:
Данный пункт меню является вторым по счету и находится в промежутке между первым и последним пунктом меню. Но как ему задать персональный CSS-стиль? Оказывается optionSplit имеет дополнительные возможности по разбиванию на части. Дополнительная разбивка происходит с помощью специального разделителя - ||(две палки!). Таким образом, по левую сторону от первого разделителя |*|, мы создаем индивидуальные настройки для 1-го и 2-го уровня меню:
ACT.allWrap = <li class="firstcrumb"><a href="http://www.domain.com/"><img src="fileadmin/templates/img/home.png" alt="Home" /></a></li>||<li class="secondcrumb">|</li>|*|<li>|</li>|*|<li class="lastcrumb">|</li>
# здесь делим список всего на 2 части - первый пункт меню и все остальные
# первый пункт меню не отображаем
ACT.doNotShowLink = 1 |*| 0

4. Делаем текущий пункт меню крупным и жирным текстом.
CUR = 1
CUR.doNotLinkIt = 1
CUR.allWrap = <li><strong> | </strong></li>


5. Пункты меню должны отображаться задом наперед:
Тут я схитрил и воспользовался услугами CSS, хотя не исключаю, что все можно было сделать и с помощью TS.
ul, ul li{
display:inline;
list-style:none;
}
#navmenu ul{
float:left;
}
#navmenu li{
float:right;
}

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

Сначала создаем файл tools.php в директории fileadmin/userfuncs/ следующего содержания:
<?php
class user_tools {

function reverseMenuItemProcFunc($I,$conf) {
return array_reverse($I);
}
}
?>

Подключаем и вызываем нашу пользовательскую функцию к скрипту:

includeLibs.myFunc = fileadmin/userfuncs/tools.php
lib.breadcrumb.1.itemArrayProcFunc = user_tools->reverseMenuItemProcFunc

Теперь можно изменить css:
#navmenu li{
float:left;
}


6. Поставим разделитель в виде наклонного слэша между нашими пунктами меню:
ACT.allWrap = <li class="firstcrumb"><span class="delim">/</span><a href="http://www.domain.com/" title="Home"><img src="fileadmin/templates/img/home.png" alt="Home" /></a></li>||<li class="secondcrumb"><span class="delim">/</span>|</li>|*|<li><span class="delim">/</span>|</li>|*|<li class="lastcrumb"><span class="delim">/</span>|</li>


Готовый скрипт выглядит так:
#includeLibs.myFunc = fileadmin/userfuncs/tools.php
lib.breadcrumb = HMENU
lib.breadcrumb.special = rootline
lib.breadcrumb.special.range = 0|-1
lib.breadcrumb.wrap = <div id="navmenu"><ul> | </ul></div>
lib.breadcrumb.1 = TMENU
lib.breadcrumb.1{
noBlur = 1
NO.allWrap = <li> | </li>

ACT = 1
ACT.ATagParams.dataWrap = title="{field:subtitle}"
ACT.allWrap = <li class="firstcrumb"><span class="delim">/</span><a href="http://www.domain.com/" title="Home"><img src="fileadmin/templates/img/home.png" alt="Home" /></a></li>||<li class="secondcrumb"><span class="delim">/</span>|</li>|*|<li><span class="delim">/</span>|</li>|*|<li class="lastcrumb"><span class="delim">/</span>|</li>
ACT.doNotShowLink = 1 |*| 0

CUR = 1
CUR.doNotLinkIt = 1
CUR.allWrap = <li><strong> | </strong></li>
}
# Реверс пунктов меню пользовательской функцией
#lib.breadcrumb.1.itemArrayProcFunc = user_tools->reverseMenuItemProcFunc

Вот мои CSS-стили:

#navmenu ul, #navmenu ul li{
display:inline;
list-style:none;
height:30px;
line-height:30px;
}
#navmenu ul{
float:left;
}
#navmenu li{
float:right;
}

#navmenu strong{
font-size:22px;
color:#333333;
line-height:21px;
}
#navmenu .delim{
color:#333333;
padding:0 7px;
text-align:center;
}
#navmenu .secondcrumb a{
color:#333333;
}
/* end breadcrumb menu */
среда, 23 июня 2010 г.

Меню для футера (подвала) из столбцов

 




Если есть желание или необходимость сделать в подвале сайта меню состоящее из нескольких столбцов (как изображено на скриншоте), которые содержат пункты меню 1-го и 2-го уровня (черные и синие, соответственно), то могу поделиться следующим TS-кодом:

lib.footermenu = HMENU
lib.footermenu {
#wrap = <div class="footer_menu"> | </div>
# исключаем из нашего меню страницы со следующими id (если нужно что-то скрыть)
excludeUidList = 63,4
entryLevel = 0


1 = TMENU
1 {
noBlur = 1
expAll=1
#wrap = <ul class="footer_menu_bar"> | </ul>

NO {
linkWrap = <li class="footer_menu_item"><h3> | </h3></li>
wrapItemAndSub = <ul class="footer_menu_bar"> | </ul>
stdWrap.htmlSpecialChars = 1
doNotLinkIt = 1
}
CUR = 1
CUR {
linkWrap = <li class="footer_menu_item"><h3> | </h3></li>
wrapItemAndSub = <ul class="footer_menu_bar current"> | </ul>
stdWrap.htmlSpecialChars = 1
doNotLinkIt = 1
}
}

2 = TMENU
2 {
noBlur = 1
expAll=1
#wrap = <ul> | </ul>

NO {
linkWrap = |
wrapItemAndSub = <li class="footer_menu_item"> | </li>
stdWrap.htmlSpecialChars = 1
}
ACT = 1
ACT {
linkWrap = |
wrapItemAndSub = <li class="footer_menu_item current"><span> | </span></li>
stdWrap.htmlSpecialChars = 1
doNotLinkIt = 1
}
}

}

Результатом работы данного скрипта будет генерация HTML-кода такого рода:
<ul class="footer_menu_bar current">
<li class="footer_menu_item">
<h3> ABOUT US </h3>
</li>
<li class="footer_menu_item"><a href="about/vision/">Vision</a></li>
<li class="footer_menu_item"><a href="about/history/">History</a></li>
<li class="footer_menu_item"><a href="about/organisation/">Organisation</a></li>
<li class="footer_menu_item"><a href="about/process-of-harmonisation/">Process of harmonisation</a></li>
<li class="footer_menu_item"><a href="about/faq/">FAQ</a></li>
</ul>
<ul class="footer_menu_bar">
<li class="footer_menu_item">
<h3> ICH PRODUCTS </h3>
</li>
<li class="footer_menu_item"><a href="products/guidelines/">Guidelines</a></li>
<li class="footer_menu_item"><a href="products/meddra/">MedDRA</a></li>
<li class="footer_menu_item"><a href="products/ctd/">CTD</a></li>
<li class="footer_menu_item"><a href="products/electronic-standard/">Electronic standard</a></li>
<li class="footer_menu_item"><a href="products/consideration-documents/">Consideration Documents</a></li>
<li class="footer_menu_item"><a href="products/open-consultation/">Open Consultation</a></li>
</ul>
.
.
.
пятница, 21 мая 2010 г.

Как я настраивал indexed_search на TYPO3 (под Suse Linux)

Как обычно, для решения любой задачи, TYPO3 использует комплексный и глобальный подход... Поэтому настройка indexed_search на сайте у меня заняла целый рабочий день. Но из-за этого я не перестаю любить эту систему и желать крепкого здоровья парням пишущим горы запутанной документации. А всё на самом деле оказывается очень просто.

Для настройки индексированного поиска по сайту нужны следующие вещи:

1. Само-собой - indexed_search, который нужно просто активировать в менеджере расширений. Это движок и мозги системы поиска, которые занимаются индексацией контента и внешних файлов (pdf, doc, xls, rtf ...). Нужно знать, что для индексации внешних файлов, indexed_search использует дополнительные внешние утилиты - pdftotext и pdfinfo, catdoc и др., которые отдельно устанавливаются на операционную систему. В настройках плагина нужно обязательно указать пути к этим программам:



2. Для того, чтобы "натравливать" indexed_search на тот контент, который требует индексации, нужен спецальный сканер. Этим сканером является ext - Site Crawler (ключ, для поиска в репозитории расширений - crawler). Настраивается crawler как с помощью TypoScript (что я и сделал), так и с помощью визуальной формы. Вот настройки сканера для одного из моих сайтов:

tx_crawler.crawlerCfg.paramSets.test = &L=[0-3]&contentId=[_TABLE:tt_content]
tx_crawler.crawlerCfg.paramSets.test {
procInstrFilter = tx_indexedsearch_reindex
baseUrl = http://www.DOMAIN.com.ua/
# настройка индексации списка новостей
# _PID:4 указывает на системную папку где хранятся все Новости сайта
tt_news = &tx_ttnews[tt_news]=[_TABLE:tt_news; _PID:4]
tt_news.procInstrFilter = tx_indexedsearch_reindex
tt_news.cHash = 1
# страница единичного просмотра Новости
tt_news.pidsOnly = 37

}

Данные настройки помещаются в свойства корневой страницы сайта:



Нужно также не забыть, что Crawler настраивается и в менеджере расширений. Важным параметром здесь является - PHP Path [phpPath], который указывает сканеру где находится PHP.

3. Так как контент сайта постоянно меняется, то сайт требует периодической переиндексации. Как это сделать? Просто нужно запускать сканер по расписанию! Здесь на помощь приходит утилита crontab. Чтобы отредактировать настройки crontab, нужно запустить его с параметром "-e": crontab -e. Почитать о настройках крона можно, например, здесь.

У меня же настройки такие:




4. Для того, чтобы плагину indexed_search разрешить индексацию страниц, в TS-шаблоне необходимо установить параметр index_enable:

page.config.index_enable = 1
# разрешить индексирование внешних файлов
# page.config.index_externals = 1
# индексируются только закешированные страницы
# page.no_cache = 0

Indexed_search будет индексировать всё, что находится между специальными комментариями и .
Вот пример HTML-шаблона:

<div id="header">
###searchbox###
<div id="logo"><img src="img/logo.png" /></div>
</div>
<div id="content1">
<div id="cornercontent1"></div>
<div id="tabcontent1"></div>
<div class="sitetext">
<!--TYPO3SEARCH_begin-->
<!-- ###CONTENT### -->
<!-- ###CONTENT### -->
<!--TYPO3SEARCH_end-->
<!-- ###SITENEWS### -->
<!-- ###SITENEWS### -->
</div>


Как видно из примера, область со списком новостей сайта (SITENEWS) индексироваться не будет. Согласно нашим настройкам, Новости будут индексироваться другим способом (см. выше).

5. Чтобы отображать результаты поиска создайте отдельную страницу и вставьте в нее плагин - Indexed Search.



Запишите или запомните id этой страницы.


6. Последнее, что нам осталось - прикрутить строку поиска на сайте. Для этих целей я обычно использую плагин macinasearchbox.

Если для строки поиска в HTML-шаблоне отвести специальное место и "пометить" его маркером - ###searchbox### (см.выше.), то оживить его можно с помощью следующего TS-скрипта:

# Прикручиваем плагин macinasearchbox
marks.searchbox >
marks.searchbox < plugin.tx_macinasearchbox_pi1
# pidSearchpage = 47 - указывает на страницу отвечающую за показ результатов поиска
marks.searchbox.pidSearchpage = 47
# указываем путь к HTML-шаблону строки поиска
marks.searchbox.templateFile = fileadmin/templates/searchbox_template.html

# Это дополнительные настройки для indexed search (скрываем ссылку advancedSearch)
plugin.tx_indexedsearch.show.advancedSearchLink = 0
plugin.tx_indexedsearch.show.rules = 0



Как всё это работает на практике можно посмотреть на сайте http://www.arcasalus.com.ua/


P.S. Забыл предупредить! Для сайтов с большой загрузкой indexed_search вреден, т.к. нагружает систему и работает не быстро.

четверг, 13 мая 2010 г.

Настройка стилей встроенного RTE редактора TYPO3

Если Вам захочется добавить свои (пользовательские) стили для дальнейшей работы с ними в RTE-редакторе, то сделать это довольно просто, т.к. TYPO3 замечательная и очень гибкая CMS-система.

Что это даёт? Это позволит нам форматировать целые блоки или фрагменты текста прямо в редакторе, а также задавать им специфические CSS-стили.

Без дополнительных настроек списки предустановленных стилей очень скудны:



Займемся расширением списков стилей.

1. Создадим CSS файл, который содержит наши дополнительные стили. Причем каждый стиль должен занимать только одну строку. Например:

/* Стили блоков */
.float_left { float: left; display:block; margin: 0; padding: 0;}
.float_right { float: right; display:block; margin: 0; padding: 0;}
.center { text-align:center; }
/* Стили текста */
.red_txt { color: red; font-size: 12px;}
.blue_bold_txt { color: blue; font-weight: bold;}


Назовем наш файл стилей - rte.css и скопируем его в директорию fileadmin/rtecss.

2. Теперь нужно как-то сказать TYPO3 где лежат пользовательские стили и указать какие стили можно применять к блокам, а какие к тексту.
Для этого переходим в свойства страницы (например, корневой)



и помещаем в блок Page TSConfig следующий скрипт:

RTE {
default {
showTagFreeClasses = 1
# указываем где находится файл стилей
contentCSS = fileadmin/rtecss/rte.css

# очищаем старые стили
classesAnchor >
classesLinks =
# устанавливаем классы для
# текста
classesCharacter := addToList(coding, note, important, warning, red_txt, blue_bold_txt)
# блоков
classesParagraph := addToList(coding, note, important, warning, float_left, center, float_right)
# ячеек таблиц
classesTD := addToList(sub)
# таблиц
classesTable := addToList(full, fixed)
# список всех доступных классов
proc.allowedClasses := addToList(coding, note, important, warning, float_left, center, float_right)
}
}

Это все. Теперь в редакторе текстов можно увидеть и проделать нечто подобное:

вторник, 20 апреля 2010 г.

Файл ENABLE_INSTALL_TOOL автоматически удаляется

Второй раз столкнулся с ситуацией, когда TYPO3 автоматически удаляет файл ENABLE_INSTALL_TOOL. Как следствие - невозможно попасть в BE в раздел Install. Не было времени разбираться в причинах такого поведения системы, но думаю, что они имеют какой-то определенный смысл и объяснения, поэтому выход из данной ситуации следующий: поместить в тело файла ENABLE_INSTALL_TOOL магическую фразу KEEP_FILE. После этого файл ENABLE_INSTALL_TOOL будет существовать до тех пор, пока Вы его сами не удалите.

Для тех, кто не знает, объясняю, что файл ENABLE_INSTALL_TOOL должен находится в папке typo3conf и служит флажком для входа в раздел Install административной части системы (админки). Создать или удалить файл можно прямо в BE:

вторник, 6 апреля 2010 г.

Мультиязычный сайт на TYPO3

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

Два метода сделать TYPO3-сайт многоязычным


Существует два варианта решения данного вопроса:
1. Сделать два разных дерева страниц внутри одного проекта. При таком подходе каждое иерархическое дерево, по сути является отдельным сайтом, каждая страница которого отвечает только за один язык.
2. Организация единого дерева страниц для поддержки нескольких языков. При таком подходе достаточно один раз создать страницу сайта, а для поддержки мультиязычности для каждого языка необходимо создать отдельный блок контента.

Я расскажу про 2-й вариант решения задачи для трех языков (русский, украинский, английский). И еще, последовательность действий, которая тут описана, пригодна на 100% при использовании шаблонов automaketemplate. Чтобы мультиязычность заработала на сайте с TemplaVoila необходимо вставить еще 5 коп, о которых здесь пока нет ни слова...(хотя здесь все описано)

Что нам для этого понадобится?


1. Расширение static_info_tables - для настройки мультиязычности сайта в бекенде (BE)
2. Расширение sr_language_menu - для выбора языка (на стороне пользователя - FE)
3. Расширение Realurl - чтобы наши URL-ы были "дружественными" для людей и поисковиков

Создаем список дополнительных языков для сайта


Для начала нужно указать какие дополнительные языки мы собираемся использовать на нашем сайте. Для этого:

1. Переходим в режим "Список/List" как показано на скриншоте и выбираем в центральной области самую верхнюю строчку списка, которая имеет пиктограмму глобуса:

Обратите внимание, на заполненную таблицу справа - Языки сайта. Здесь отображаются все дополнительные языки сайта. Изначально этот список будет пустым.

2. Итак, добавляем дополнительный язык для сайта. В самом верху правой части экрана нажимаем кнопку добавить (зеленый плюс) и выбираем тип записи - "Язык сайта".


3. Заполняем следующую формочку:


Таким образом, можно задать сколько угодно языков. Я задал 3 языка: Украинский (id=1), Русский (id=2) и Английский (id=3).
Пока, что условно считаем, что русский язык на нашем сайте является основным.

Настройка Typo3 шаблона


Настраиваем главный (корневой) TS-шаблон для работы с несколькими языками. Добавляем туда следующие строки:

# Настройки для основного языка - РУССКОГО
config.linkVars = L
config.sys_language_uid = 0
config.uniqueLinkVars = 1
config.language = ru
config.locale_all = ru_RU
config.sys_language_overlay = 1
#config.sys_language_mode = content_fallback;0
config.sys_language_mode = ignore
config.htmlTag_langKey = ru-RU
#plugin.tx_indexedsearch._DEFAULT_PI_VARS.lang = 0
#plugin.tx_indexedsearch.templateFile = indexed_search.tmpl

# Настройки для УКРАИНСКОГО языка
[globalVar = GP:L = 1]
config.language = ua
config.locale_all = ua_UA
config.htmlTag_langKey = ua-UA
config.sys_language_uid = 1
#plugin.tx_indexedsearch._DEFAULT_PI_VARS.lang = 1
#plugin.tx_indexedsearch.templateFile = indexed_search.tmpl
# сюда можно добавлять другие строки для более полной локализации (подключение CSS, HTML-шаблонов и т.д.)
[global]

# Настройки для АНГЛИЙСКОГО языка
[globalVar = GP:L = 3]
config.language = en
config.locale_all = en_EN
config.htmlTag_langKey = en-EN
config.sys_language_uid = 3
#plugin.tx_indexedsearch._DEFAULT_PI_VARS.lang = 3
#plugin.tx_indexedsearch.templateFile = indexed_search.tmpl
# сюда можно добавлять другие строки для более полной локализации (подключение CSS, HTML-шаблонов и т.д.)
[global]

Для новичка это может показаться магическим набором невменяемых строк, но на самом деле не всё так сложно.
Вся соль в 2-х ключевых параметрах:
config.linkVars = L (имя GET-переменной отвечающей за идентификацию языка).
Поясню. Обычно страницы нашего сайта доступны по URL типа (без применения RealUrl)
http://mydomain.com/index.php?id=34, что соответствует http://mydomain.com/index.php?id=34&L=0 (язык по умолчанию - русский).
Если же вызвать страницу http://mydomain.com/index.php?id=34&L=1, то увидим страницу с украинским контентом.
Вот, что означает параметр - L.

[globalVar = GP:L = x]
config.sys_language_uid = x
(где, x - id дополнительного языка в списке, в моем случае 1 - укр, 2 - рус, 3 - англ., см. выше). Таким образом, мы сопоставляем значение параметра L с номером (id) дополнительного языка в системе.

Т.к. русский язык является основным для нашего сайта, то отдельную ветвь типа:
[globalVar = GP:L = х]
...
[global]
для него создавать не нужно.

Настройка бекенда (BE)


Для того, чтобы в BE русский язык считался основным и это было видно визуально (см. рисунок ниже),



в свойствах корневой страницы сайта необходимо вставить следующие строки:
mod.web_layout.defLangBinding = 2
mod.SHARED.defaultLanguageLabel = Russia
mod.SHARED.defaultLanguageFlag = ru.gif



Создаем мультиязычный контент в TYPO3


1. Теперь можно создавать дополнительный контент на дополнительных языках. Дополнительный контент это две вещи - заголовок веб-страницы и ее содержимое. Именно по заголовку страницы, с меткой языка, TYPO3 узнает, что страница имеет еще одну языковую версию. Чтобы создать новый заголовок нужно сделать следующее:



Обязательно отмечаем, галочкой для какой страницы нужно создать новый заголовок (Альтернативный язык страницы)







В дальнейшем заголовок можно отредактировать и в режиме Список/List



2. Контент создаем в обычном режиме, но с указанием другого языка:



Т.к. содержимое страницы может состоять из нескольких блоков, то перевести на другой язык нужно каждый такой блок. Но этого мало! Ведь еще нужно эти блоки как-то связать! Чтобы поставить их в соответствие я использую режим Список/List для страницы, открываю на редактирование иноязычный блок контента и указываю оригинал перевода (выбираю из списка):



После этого в режиме Список/List страница будет выглядеть примерно так:



Переключатель языков на стороне пользователя (FE)


Теперь можно подумать и о том как переключаться между разными языками на нашем сайте. Для этого используется довольно популярное расширение - sr_language_menu.
Лично я настроил данный плагин с помощью TS-скрипта следующим образом:
lib {
languageMenu < plugin.tx_srlanguagemenu_pi1 # Список отображаемых языков languageMenu.languagesUidsList = 1,2,3 # Способ представления списка языков - текстовый # (можно также изобразить флажками) languageMenu.defaultLayout = 2 languageMenu.defaultLanguageISOCode = RU #languageMenu.defaultCountryISOCode = languageMenu.link.NO.stdWrap.wrap = <li> | </li> languageMenu.link.CUR.stdWrap.wrap = <li class="curlng"> | </li> languageMenu.link.INACT.stdWrap.wrap = <li> | </li> languageMenu.links.stdWrap.split.wrap = | #languageMenu.hideIfNoAltLanguages = 1 }


Настройка расширения RealURL


В конфигурационном файле RealUrl (например, realurlconf.php) необходимо наличие следующих строк:
'preVars' => array(
array(
'GETvar' => 'no_cache',
'valueMap' => array(
'no_cache' => 1,
),
'noMatch' => 'bypass',
),
array(
'GETvar' => 'L',
'valueMap' => array(
'ru' => '0',
'ua' => '1',
'en' => '3',
),
'noMatch' => 'bypass',
),
),
'pagePath' => array(
'type' => 'user',
'userFunc' => 'EXT:realurl/class.tx_realurl_advanced.php:&tx_realurl_advanced->main',
'spaceCharacter' => '-',
'languageGetVar' => 'L',
'expireDays' => 7,
'rootpage_id' => 1,
),
вторник, 9 марта 2010 г.

TYPO3 и инструменты Google

Если Вы в своей работе используете гугловский "Центр веб-мастеров" и сервис сбора статистики - Google Analytics, то для сайта на TYPO3, потребуется 2 простеньких скрипта на TypoScript:

1. Скрипт, который позволит Вам подтвердить свои права собственности на сайт, через meta-тег:

page.headerData.1 = TEXT
page.headerData.1.insertData=1
page.headerData.1.wrap = <meta name ="google-site-verification" content ="|">
page.headerData.1.value = ваш_алфавитно-цифровой_код_сайта_от_google


абсолютно тоже самое делает такая конструкция:

page.meta.google-site-verification = ваш_алфавитно-цифровой_код_сайта_от_google

Напомню, что данный мета-тег гугл хочет видеть на главной странице сайта. Поэтому этот скрипт нужно добавить в typo3-шаблон корневой страницы.

Алфавитно-цифровой код сайта можно быстро узнать с помощью url:
https://www.google.com/webmasters/verification/verification?hl=ru&siteUrl=http://www.yourdomain.com/

2. Для работы Google Analytics

page.wrap(
| <script type="text/javascript"> var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));</script> <script type="text/javascript"> var pageTracker = _gat._getTracker("UA-КОД_САЙТА");pageTracker._trackPageview();</script>
)


Т.к. статистику желательно собирать со всех страниц сайта, то гугловский скрипт необходимо вставить на все его страницы, причем в самый конец. Чтобы добиться этого для сайта на Typo3, нужно вставить данный код в конец всех typo3-шаблонов.
пятница, 5 марта 2010 г.

Конфликт библиотек perfectlightbox и rgtabs

Вчера потратил половину своего рабочего дня на выяснение причин - почему же у меня не работает расширения rgtabs и jfmulticontent. Т.к. на странице у меня была куча всяких плагинов использующих всевозможные java скрипты и библиотеки, то интуиция почти сразу подсказала, что кто-то с кем-то конфликтует.
Так оно и оказалось! Оказывается, что библиотека protaculous, которую по-умолчанию использует ext perfectlightbox, не дружит с jQuery. Настройка параметра jQueryNoConflict ни к чему не приводила.

Вылечилось все настройкой perfectlightbox: plugin.perfectlightbox.libraryToUse = mootools.

P.S. [1] Тут же попытался заменить mootools от perfectlightbox на t3mootools, но почему-то с ним perfectlightbox работать не захотел :(, а зря...

P.S. [2] Я тут порылся, поекспериментировал немного, оказалось, что t3mootools у меня - 1.2, а perfectlightbox v.2.2.4 использует mootools - 1.1, поэтому и не заработало!
понедельник, 8 февраля 2010 г.

Установка CMS системы TYPO3 на SuSE Linux

Вступление


Данная статья не претендует на оригинальность, т.к. собраный в ней материал уже есть в сети, но он собран воедино, так чтобы админу приходилось минимально гуглить и переводить. Заниматься установкой TYPO3 приходится не каждый день и с течением времени кое-какие вещи забываются, поэтому материал задумывался как "склерозник" для личного пользования, но вполне может быть полезен и другим людям занимающимися CMS-системой TYPO3, особенно новичкам.

Для установки TYPO3 нам понадобится SSH доступ к веб серверу и соответственно SSH клиент. Я рекомендую использовать WinSCP.

Раньше, как только я получал заказ на разработку нового сайта на базе TYPO3, я делал следующее - создавал на веб-сервере папку типа site1.com и устанавливал внутри ее ядро системы и файловый шаблон нового сайта (source и dummy site). Причем, каждый раз, устанавливаемая версия ядра была более свежей, чем предудущая. И выходило так, что весенние сайты работают на версии ядра 4.2.6, а осенние на версии 4.2.10 и т.д. Одним словом - зоопарк, со всеми вытекающими последствиями.

Со временем я поумнел и задался вопросом: "А почему я всегда так делаю? Ведь можно же сделать более изящно и оптимально?". И действительно можно! При этом ядро системы устанавливается всего один раз и на его базе работает сколько угодно сайтов. Таким образом и с версиями ядра порядок, и экономится дисковое пространство, и обновляться затем значительно проще.

При таких раскладах дерево директорий должно выглядеть примерно так:

typo3_src - директория с ядром системы
site1.com - файлы и настройки 1-го сайта
site2.com.ua - файлы и настройки 2-го сайта
site3.biz.ua - файлы и настройки 3-го сайта

А теперь распишу все подробно по шагам...

1. Установка ядра системы TYPO3 4.3.1


а) Логинимся пользователем root и cоздаем директорию для установки ядра (исходников) TYPO3. В моем случае это директория - /usr/www/

б) Скачиваем архив с ядром с сайта http://typo3.org/download/packages/



или с помощью команды:

wget http://prdownloads.sourceforge.net/typo3/typo3_src-4.3.1.tar.gz?download



в) Распаковываем только что полученный архив внутри нашей директории /usr/www/

tar -xzvf typo3_src-4.3.1.tar.gz



После распаковки архива получим следующую файловую структуру:



г) Веб-сервер Apache в SUSE Linux работает под именем пользователя - wwwrun, который является членом группы пользователей - www. Этому пользователю и группе необходимо дать полные права на папку с ядром TYPO3, т.е. - typo3_src-4.3.1. Если мы по-прежнему находимся в папке /usr/www/, то выполняем команду:

chown -R wwwrun:www ./typo3_src-4.3.1

которая делает пользователя wwwrun и группу www собственником (владельцем)
директории typo3_src-4.3.1



д) На папку в которую мы будем устанавливать все наши расширения TYPO3 (плагины, extensions), предоставим веб серверу полный доступ:

chmod -R 775 ./typo3_src-4.3.1/typo3/ext




е) Для нормальной работы системы TYPO3 на сервере должен быть установлен пакет ImageMagick, который отвечает за все манипуляции с картинками. Чтобы проверить стоит ли у вас на сервере ImageMagick, попробуйте выполнить команду identify, если получите, то же, что и у меня на картинке, значить все в порядке. В противном случае займитесь его установкой (для этого зайдите на сайт http://www.imagemagick.org).



Чтобы найти этот файл по имени используйте команду:

find / -name "identify*"



2. Установка нового сайта TYPO3



a) Создаем папку в которой будет находится наш сайт, например - mydomain.com:

mkdir mydomain.com

переходим в нее с помощью команды

cd mydomain.com

б) Скачиваем шаблон сайта с помощью знакомой уже команды:

wget http://prdownloads.sourceforge.net/typo3/dummy-4.3.1.tar.gz?download



и распаковываем этот архив командой:

tar -xzvf dummy-4.3.1.tar.gz



следующей командой:

mv ./dummy-4.3.1/* ./

данные из папки dummy-4.3.1 переносим в папку /usr/www/mydomain.com (на уровень выше)



получаем следующую структуру папок



Теперь можно удалить файл dummy-4.3.1.tar.gz и папку dummy-4.3.1

в) Делаем символическую ссылку typo_src, которая будет "говорить" нашему сайту где находится текущая рабочая версия ядра TYPO3. В дальнейшем, это поможет нам обновлять ядро системы.

Итак, возвращаемся в нашу папку /usr/www/, для этого можно использовать команду:

cd /usr/www/

Для перестраховки удаляем предыдущую символическую ссылку typo_src:

rm -rf ./typo3_src

Создаем новую символическую ссылку:

ln -s /usr/www/typo3_src-4.3.1 typo3_src



Внимание! Не нужно менять имя символической ссылки, оно должно быть именно typo3_src!

В результате получим еще одну папку в нашем дереве каталогов



Все, с ядром мы закончили. Все настройки ядра выполняются только один раз - при создании самого первого сайта!

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

fileadmin
typo3conf
typo3temp
uploads

Это делается следующими 2-мя командами:

chown -R wwwrun:www fileadmin typo3conf typo3temp uploads
chmod -R 775 fileadmin typo3conf typo3temp uploads





д) Т.к. наш веб каталог (/usr/www/mydomain.com) содержит символьный линк, то для его обслуживания необходимо в настройках Apache прописать:

<Directory "/usr/www/mydomain.com">
Options +FollowSymlinks +Indexes +Includes
AllowOverride All
Order allow,deny
Allow from all
</Directory>

e) TYPO3 как и любая CMS система хранит все свои данные и настройки в базе данных MySQL. Желательно создать новую базу данных еще до начала дальнейшего конфигурирования сайта. И хотя установка TYPO3 может это сделать самостоятельно, я это делаю вручную - чтобы перестраховать себя от сюрпризов связанных с кодовыми страницами. Поэтому, заходим в командную строку MySQL:

mysql -u root -p и вводим пароль пользователя root для mysql

и выполняем следующие SQL команды:

CREATE DATABASE db_name DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
GRANT ALL PRIVILEGES ON db_name.* TO username@localhost IDENTIFIED BY 'password';

Здесь мы создали БД в нужной нам кодировке, создали пользователя и дали ему все права на неё.

ж) Теперь можно перейти к заключительной стадии подготовки нового сайта к работе. Это делается с помощью так называемого режима установки - 1-2-3. Но чтобы этот автоматический режим стал доступен необходимо в директории typo3conf создать специальный файл с именем - ENABLE_INSTALL_TOOL, который является своеобразным флагом (семафором). Создадим этот файл с помощью команд Linux:

cd typo3conf
touch ENABLE_INSTALL_TOOL

Условный флаг взведен, можно пробовать. В строке браузера набираем:

http://www.mydomain.com/typo3

Увидим следующую страницу:



Вводим имя и пароль нашего нового пользователя MySql (username) и жмем кнопку Continue.
Внимание! На данном этапе возможны побочные явления такого рода:
1. Если вводить имя и пароль нового пользователя нашей БД - невозможно сделать конект к базе данных.
2. Если вводить имя и пароль root (mysql)- невозможно выбрать БД (Error: No database selected).
Я не понял, что это такое, возможно какие-то накладки или глюки... Но лечится это довольно просто. В директории typo3conf находится главный конфигурационный файл TYPO3 - localconf.php. В нем нужно прописать следующие строки:
$typo_db_username = 'root'; // Modified or inserted by TYPO3 Install Tool.
$typo_db_password = 'парольрута'; // Modified or inserted by TYPO3 Install Tool.
$typo_db_host = 'localhost'; // Modified or inserted by TYPO3 Install Tool.
$typo_db = 'имя базы'; // Modified or inserted by TYPO3 Install Tool.
После этого в URL браузера можно сменить номер инсталляционного шага на цифру 2, например, http://mydomain.com/typo3/install/index.php?TYPO3_INSTALL[type]=config&mode=123&step=2

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

На втором шаге выбираем в выпадающем списке нашу предварительно созданную БД и опять жмем кнопку Continue:



На последнем 3-м этапе нажимаем кнопку Import database:



И хотя фраза "Import database" подразумевает под собой импорт каких-то данных в БД, на самом деле TYPO3 создаст свой репозиторий - набор служебных таблиц со служебными данными.



3. Конфигурация системы TYPO3 4.3.1


Теперь можно смело заходить в админку TYPO3 и делать базовые настройки самой CMS системы.

В строке браузера набираем: http://www.mydomain.com/typo3 и вводим имя пользователя - admin, а в качестве пароля слово - password.



Переходим в раздел Admin Tools\Install и кликаем по пункту 5: All Configuration. В дальнейшем, вход в данный раздел потребует ввода отдельного пароля (не пользователя admin). По умолчанию пароль для All Configuration - joh316.



Здесь можно произвести множество настроек, но самое главное это "заставить" систему нормально работать с кодировкой UTF-8. За что отвечают следующие параметры и их значения:
[setDBinit]
String (textarea): Commands to send to database right after connecting, separated by newline. Ignored by the DBAL extension except for the 'native' type!
[SYS][setDBinit] = SET NAMES utf8 SET SESSION character_set_server=utf8
[forceCharset]
String. Normally the charset of the backend users language selection is used. If you set this value to a charset found in t3lib/csconvtbl/ (or "utf-8") the backend (and database) will ALWAYS use this charset. Always use a lowercase value.
[BE][forceCharset] = utf-8

После этого, по совету Дмитрия Дулепова (для новичков поясню, это известный разработчик сообщества TYPO3) необходимо установить такие параметры системы:

[enable_typo3temp_db_tracking]
Boolean. If set, then all files in typo3temp will be logged in a database table. In addition to being a log of the files with original filenames, it also serves to secure that the same image is not rendered simultaneously by two different processes.
[GFX][enable_typo3temp_db_tracking] = 1

[devIPmask]
Defines a list of IP addresses which will allow development-output to display. The debug() function will use this as a filter. See the function t3lib_div::cmpIP() for details on syntax. Setting this to blank value will deny all. Setting to "*" will allow all.
[SYS][devIPmask] = ВАШ IP АДРЕС,127.0.0.1,::1

[sqlDebug]
Boolean. If set, then database queries that fails are outputted in browser. For development.
[SYS][sqlDebug] = 1

[curlUse]
Boolean: If set, try to use Curl to fetch external URLs
[SYS][curlUse] = 1

[t3lib_cs_convMethod]
String (values: "iconv", "recode", "mbstring", default is homemade PHP-code). Defines which of these PHP-features to use for various charset conversion functions in t3lib_cs. Will speed up charset conversion radically.
[SYS][t3lib_cs_convMethod] = mbstring

[t3lib_cs_utils]
String (values: "iconv", "mbstring", default is homemade PHP-code). Defines which of these PHP-features to use for various charset processing functions in t3lib_cs. Will speed up charset functions radically.
[SYS][t3lib_cs_utils] = mbstring


[no_pconnect]
Boolean: If true, "connect" is used instead of "pconnect" when connecting to the database!
[SYS][no_pconnect] = 1

[multiplyDBfieldSize]
Double: 1-5: Amount used to multiply the DB field size when the install tool is evaluating the database size (eg. "2.5"). This is only useful e.g. if your database is iso-8859-1 encoded but you want to use utf-8 for your site. For Western European sites using utf-8 the need should not be for more than twice the normal single-byte size (2) and for Chinese / Asian languages 3 should suffice. NOTICE: It is recommended to change the native database charset instead! (see http://wiki.typo3.org/index.php/UTF-8_support for more information)
[SYS][multiplyDBfieldSize] = 1

[displayErrors]
Integer: -1,0,1,2. Configures whether PHP errors should be displayed. 0 = Do not display any PHP error messages. Overrides the value of "exceptionalErrors" and sets it to 0 (= no errors are turned into exceptions), the configured "productionExceptionHandler" is used as exception handler, 1 = Display error messages with the registered errorhandler. The configured "debugExceptionHandler" is used as exception handler. 2 = Display errors only if client matches TYPO3_CONF_VARS[SYS][devIPmask]. If devIPmask matches the users IP address the configured "debugExceptionHandler" is used for exceptions, if not "productionExceptionHandler" will be used. -1 = Default setting. With this option, you can override the PHP setting "display_errors". If devIPmask matches the users IP address the configured "debugExceptionHandler" is used for exceptions, if not "productionExceptionHandler" will be used.
[SYS][displayErrors] = 2

[compressionLevel]
Determines output compression of BE output. Makes output smaller but slows down the page generation depending on the compression level. Requires zlib in your PHP installation. Range 1-9, where 1 is least compression and 9 is greatest compression. 'true' as value will set the compression based on the PHP default settings (usually 5). Suggested and most optimal value is 5.
[BE][compressionLevel] = 5

А теперь пройдитесь по следующим разделам админки как показано на скриншотах ниже:






Ну и напоследок необходимо позаботиться о безопасности системы:

1. Сменить пароль пользователя admin, это делается в разделе User settings как показано ниже.



2. Вывести систему из режима настройки, путем удаления семафорного флажка - ENABLE_INSTALL_TOOL

О себе

Моя фотография
Вадим Гиркало
Фрилансер, веб-разработчик сайтов на базе бесплатной, мощнейшей и очень гибкой CMS системы - TYPO3.
Просмотреть профиль

Позвонить мне в Skype

Архив блога

TOP - 3