Попробуем подружить ZOO 2.4 и JoomFish 2.1.7 или создать мультиязычность на ZOO 2.4.
Писать эту статью начинал несколько раз, но только недавно добился полного рабочего перевода ZOO.
В этой статье я опишу основные этапы для реализации мультиязычности, которые подходят для любого приложения ZOO 2.4. Я думаю что владея описанными ниже знаниями
опытный програмист-дизайнер сможет запросто сделать свой Joomla - ZOO сайт мультиязычным. Я не зря выделил слово
опытный, так как перевод ZOO 2.4 требует некоторых хаков и модификаций, и начинающий пользователь просто может запутаться и испортить свой сайт. Для новичков я всё таки посоветовал бы приобрести ZOOlingual - так как он удобней и не требует хаков. Хотя программисты ZOOOlanders пишут что их плагин не переводит ZOO на 100%.
Сразу хочу предупредить что необходимо сделать бэкап сайта перед началом операций.ZOOlingual стоит 39 евро, на мой взгляд это очень дорого за этот плагин (я не покупал платную версию), поэтому будем пробовать перевезти ZOO своими руками, опираясь на ZOOlingual первой (бесплатной) версии.
Обозначения: В этой статье я буду отличать две сущности:
Элемент и
элемент.
Элемент с Большой буквы - это ZOO Item, а
элемент с маленькой буквы - это ZOO element из папки
media/zoo/elements.Будем реализовывать двух-язычный сайт с русским и английским языками. И так приступим:
Открываем файл
media/zoo/applications/<приложение>/application.xml и находим
params строки:
application-config,
category-config,
item-config:
Строку:
<params group="application-config">
Заменяем на:
<params group="application-config">
<param name="page_title_ru-RU" type="text" size="20" default="" label="Russian Title" description="Set a Russian title." />
<param name="page_title_en-GB" type="text" size="20" default="" label="English Title" description="Set a English title." />
Далее:<params group="category-config">
Заменяем на:
<params group="category-config">
<param name="page_title_ru-RU" type="text" size="20" default="" label="Russian Title" description="Set a Russian title." />
<param name="page_title_en-GB" type="text" size="20" default="" label="English Title" description="Set a English title." />
И удаляем строку:
<param name="page_title" type="text" size="20" default="" label="Page Title" description="Page Title" />
Далее:<params group="item-config">
Заменяем на:
<params group="item-config">
<param name="page_title_ru-RU" type="text" size="20" default="" label="Russian Title" description="Set a Russian title." />
<param name="page_title_en-GB" type="text" size="20" default="" label="English Title" description="Set a English title." />
И удаляем строку:
<param name="page_title" type="text" size="20" default="" label="Page Title" description="Page Title" />
Эти строки добавят нам следующие поля в раздел
Config (спойлер справа) для
Главной страницы,
Категории и
Элемента для ввода
title.
Теперь займемся переводом Элемента.Идем в конфигуратор приложений, выбираем приложение, которое переводим, и нажимаем
Edit Elements для соответствующего типа
Элемена.
Здесь нам необходимо создать для каждого поля, которое нуждается в мультиязычности по одному на каждый язык. Например 2 поля
Text (Textarea) и пометить их соответственно
Text-RU (Textarea) и
Text-EN (Textarea), ввести названия в поле
Name, для того чтобы в будущем было удобнее ориентироваться куда вводить нужный переведенный текст.
Основные элементы, которые обычно нуждаются в мультиязычности это
Text,
Textarea.
Related Items - дублировать не нужно, они будут автоматически переводиться после полного перевода сайта.
Теперь нам нужно создать новый
ZOO элемент для вывода переведенного заголовка. Мы создадим новый элемент на основе системного
itemname элемента. Для этого сразу скопируем папку
media/zoo/elements/itemname в папку
media/zoo/applications/<приложение>/elements тем самым защитим его от пропадания после обновления ZOO, воспользовавшись технологией override.
Переименовываем папку
itemname на
itemtitle, файлы
itemname.php и
itemname.xml на
itemtitle.php и
itemtitle.xml соответственно.
В файле
itemtitle.xml вставляем следующий код:
<?xml version="1.0" encoding="utf-8"?>
<element type="itemtitle" group="Core" hidden="true">
<name>Item Title</name>
<author>YOOtheme</author>
<creationDate>December 2009</creationDate>
<copyright>Copyright (C) YOOtheme GmbH</copyright>
<authorEmail>info@yootheme.com</authorEmail>
<authorUrl>http://www.yootheme.com</authorUrl>
<version>1.0.0</version>
<description>Item Name Core System</description>
<params group="render">
<param name="showlabel" type="radio" default="0" label="Show Label" description="Show/Hide element label">
<option value="0">JNO</option>
<option value="1">JYES</option>
</param>
<param name="altlabel" type="text" default="" label="Alternative Label" description="CUSTOM_LABEL" />
<param name="link_to_item" type="radio" default="1" label="Link to item" description="Wrap name in link to item">
<option value="0">JNO</option>
<option value="1">JYES</option>
</param>
</params>
</element>
Внимание в файле
itemtitle.php мы вставим php код, который поможет нам в будущем реализовывать мультиязычность. Этот код мы еще несколько раз будем вставлять в файлы ZOO.
// ZOOmultilingual begin
$lang =& JFactory::getLanguage()->_lang;
// ZOOmultilingual end
Файл
itemtitle.php должен выглядить следующим образом:
<?php
/**
* @package ZOO
* @author YOOtheme http://www.yootheme.com
* @copyright Copyright (C) YOOtheme GmbH
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 only
*/
/*
Class: ElementItemTitle
The item title element class
*/
class ElementItemTitle extends Element {
/*
Function: hasValue
Checks if the element's value is set.
Parameters:
$params - render parameter
Returns:
Boolean - true, on success
*/
public function hasValue($params = array()) {
return true;
}
/*
Function: edit
Renders the edit form field.
Returns:
String - html
*/
public function edit() {
return null;
}
/*
Function: render
Renders the element.
Parameters:
$params - render parameter
Returns:
String - html
*/
public function render($params = array()) {
// ZOOmultilingual begin
$lang =& JFactory::getLanguage()->_lang;
// ZOOmultilingual end
if (!empty($this->_item)) {
$params = $this->app->data->create($params);
if ($params->get('link_to_item', false) && $this->_item->getState()) {
$url = $this->app->route->item($this->_item);
return '<a title="'.$this->_item->getParams()->get('config.page_title_'.$lang).'" href="' . JRoute::_($url). '">' . $this->_item->getParams()->get('config.page_title_'.$lang). '</a>';
} else {
return $this->_item->getParams()->get('config.page_title_'.$lang);
}
}
}
}
Для того чтобы этот элемент появился в списке системных нам необходимо будет добавить строку:
<param type="itemtitle" identifier="_itemtitle" name="Item Title" description="" default="" />
в файл
media/zoo/elements/core.xmlВнимание этот файл перезаписывается после обновлений, так что лучше держать его копию в папке
media/zoo/applications/<приложение>/elements. Для него к сожалению override не работает.
Этот элемент появиться в разделе назначения элементов соответствующим полям.
Очень удобно с ним работать: например назначив его для
Teaser мы выбираем режим
Link to Item - Yes и тогда будет выводиться название элемента с сылкой на него. А для
Full мы выберем режим
Link to Item - No и тогда название
Элемента не будет ссылаться на самого себя (
очень полезно для SEO).
Теперь переходим к правке файла
positions.xml из папки
media/zoo/applications/<приложение>/templates/<шаблон>/renderer/itemВ нем нам нужно будет создать по одно полю на язык там где мы хотим чтобы было переключение языков. В нашем случае мы хотим чтобы наши элементы
Textarea Text-RU и
Text-EN переключались с одного на другого при смене языка сайта. Поэтому мы добавляем следующие строки:
<position name="content_ru-RU">Content_ru-RU</position>
<position name="content_en-GB">Content_en-GB</position>
Эти строки добавим для отображения
Full. После этого у нас появятся следующие поля:
Еще раз хочу повториться, что я показываю маленький пример для реализации мультиязычности, в Вашем случае могут быть одно и более полей чем поле
Content. Главная идея здесь
name="content_ru-RU" вместо
content Вы должны вставить название соответствующего поля, а добавочный суффикс
_ru-RU должен соответствовать тому языку, который Вы хотит видеть на сайте, в соотвтетствубщем разделе. Проделайте необходимые изменения для отображения
Teaser и
Related если необходимо.
Теперь добавим элемент
Text-RU (Textarea) в поле
Сontent_ru-RU, а
Text-EN (Textarea) в поле
Content_en-GB.
В поле
Title добавим наш системный элемент
Item Title и выберем режим
Link to Item - No.
К стати здесь отличительная выгода от использования созданного нами элемента
Item title - нет необходимости создавать дополнительные поля для заголовка в файле
positions.xml.
Сохраняем и переходим к редактированию render файлов
Элемента Категории и
Главной страницы:
Открываем файл
full.php из папки
media/zoo/applications/<приложение>/templates/<шаблон>/renderer/itemи вставляем следующий код после
defined('_JEXEC') or die('Restricted access'); и получаем:
// no direct access
defined('_JEXEC') or die('Restricted access');
// ZOOmultilingual begin
$lang =& JFactory::getLanguage()->_lang;
// ZOOmultilingual end
Далее находим или создаем вывод нашего
Content поля:
<?php if ($this->checkPosition('content_'.$lang)) : ?>
<div class="pos-content"><?php echo $this->renderPosition('content_'.$lang); ?></div>
<?php endif; ?>
Здесь
content_'.$lang выведет текст соответствующий языку страницы. Проделайте эту операцию для вывода мультиязычных полей, которые Вы создадите для Вашего сайта.
Теперь перейдем к выводу заголовка
Категории. Открываем файл
category.php из папки
media/zoo/applications/<приложение>/templates/<шаблон>/ вставляем наш код вначале файла
// no direct access
defined('_JEXEC') or die('Restricted access');
// ZOOmultilingual begin
$lang =& JFactory::getLanguage()->_lang;
// ZOOmultilingual end
и находим строку вывода названия
Категории:
<h1 class="title"><?php echo $this->category->name; ?></h1>
и меняем его на:
<h1 class="title"><?php echo $this->category->getParams()->get('config.page_title_'.$lang); ?></h1>
Если у Вас на сайте есть вывод Subtitle Description для Категории, тогда таким образом можно будет сделать мультиязычность для этих полей, но перед этим необходимо создать соответствующие поля в файле application.xml.Идем дальше: перевод
Главной страницы. Открываем файл
frontpage.php в папке
media/zoo/applications/<приложение>/templates/<шаблон>/ вставляем наш код вначале файла
// no direct access
defined('_JEXEC') or die('Restricted access');
// ZOOmultilingual begin
$lang =& JFactory::getLanguage()->_lang;
// ZOOmultilingual end
и находим строку вывода названия
Главной страницы:
<h1 class="title"><?php echo $this->application->getParams()->get('content.title'); ?></h1>
и меняем его на:
<h1 class="title"><?php echo $this->application->getParams()->get('config.page_title_'.$lang); ?></h1>
Следующий этап - перевод
Title и
Breadcrumbs. Для этого нам необходимо будет хак/правка файла
default.php из папки
components/com_zoo/controllersВначале вставляем в строки 104 и 202 после строк
public function item() { и
public function category() { код:
// ZOOmultilingual begin
$lang =& JFactory::getLanguage()->_lang;
// ZOOmultilingual end
Далее находим код примерно в строке 137 (до изменений)
// create item pathway
$itemid = $this->params->get('item_id');
if ($this->item->id != $itemid) {
$categories = $this->application->getCategoryTree(true);
if (isset($categories[$category_id])) {
$category = $categories[$category_id];
$addpath = false;
$catid = $this->params->get('category');
foreach ($category->getPathway() as $cat) {
if (!$catid || $addpath) {
$link = JRoute::_($this->app->route->category($cat));
$this->pathway->addItem($cat->name, $link);
}
if ($catid && $catid == $cat->id) {
$addpath = true;
}
}
}
$this->pathway->addItem($this->item->name, JRoute::_($this->app->route->item($this->item)));
}
// update hit count
$this->item->hit();
// get page title, if exists
$title = $this->item->getParams()->get('config.page_title');
$title = empty($title)? $this->item->name : $title;
if ($menu = JSite::getMenu()->getActive()) {
if ($page_title = $this->app->parameter->create($menu->params)->get('page_title')) {
$title = $page_title;
}
}
Этот код отвечает за создание пути в
Breadcrumbs и создания тега
Title у
Элемента, и меняем его на:
// create item pathway
$itemid = $this->params->get('item_id');
if ($this->item->id != $itemid) {
$categories = $this->application->getCategoryTree(true);
if (isset($categories[$category_id])) {
$category = $categories[$category_id];
$title = $category->getParams()->get('config.page_title_'.$lang);
$addpath = false;
$catid = $this->params->get('category');
foreach ($category->getPathway() as $cat) {
if (!$catid || $addpath) {
$link = JRoute::_($this->app->route->category($cat));
$this->pathway->addItem($title, $link);
}
if ($catid && $catid == $cat->id) {
$addpath = true;
}
}
}
$this->pathway->addItem($this->item->getParams()->get('config.page_title_'.$lang), JRoute::_($this->app->route->item($this->item)));
}
// update hit count
$this->item->hit();
// get page title, if exists
$title = $this->item->getParams()->get('config.page_title_'.$lang);
$title = empty($title)? $this->item->name : $title;
if ($menu = JSite::getMenu()->getActive()) {
if ($page_title = $this->app->parameter->create($menu->params)->get('page_title_'.$lang)) {
$title = $page_title;
}
}
Далее находим код примерно в строке 240 (до изменений):
// create pathway
$addpath = false;
$catid = $this->params->get('category');
foreach ($this->category->getPathway() as $cat) {
if (!$catid || $addpath) {
$link = $this->app->route->category($cat);
$this->pathway->addItem($cat->name, $link);
}
if ($catid && $catid == $cat->id) {
$addpath = true;
}
}
// set page title
if ($title = $this->category->getParams()->get('config.page_title')) {
$this->app->document->setTitle($title);
}
Этот код отвечает за создание пути в
Breadcrumbs и создания тега
Title у
Категории, и меняем его на:
// create pathway
$title = $this->category->getParams()->get('config.page_title_'.$lang);
$addpath = false;
$catid = $this->params->get('category');
foreach ($this->category->getPathway() as $cat) {
if (!$catid || $addpath) {
$link = $this->app->route->category($cat);
$this->pathway->addItem($title, $link);
}
if ($catid && $catid == $cat->id) {
$addpath = true;
}
}
// set page title
if ($title = $this->category->getParams()->get('config.page_title_'.$lang)) {
$this->app->document->setTitle($title);
}
Сохраняем файл в той же папке.
Теперь переходим к наполнению сайта двумя языками и тестированию переключения языков.
И главное не забываем про папки
ru-RU и
en-GB в
media/zoo/applications/<приложение>/language так как не будут переведены системные тексты. Да и кстати очень удобно использовать внутри шаблона системные тексты, например
<?php echo JText::_('LanguageTitle'); ?>
А в соответствующем файле, например
ru-RU.com_zoo.ini из папки
media/zoo/applications/<приложение>/language/ru-RUделаем запись-перевод для нашего системного текста:
LANGUAGETITLE="Системный Заголовок на русском "Я показал очень коротко как реализовать мультиязысность, прошу расматривать как руководство, или как маленький пример. ZOO позволяет очень бурно разыграться фантазии в построении сайта, поэтому с вышеуказанными знаниями опытный програмист сможет реализовать мультиязычность сайта полностью.Не забудем установить
JoomFish и перевести пункты меню, для того чтобы они отображались в
Breadcrumbs.
У меня ушло много времени пока я не понял почему у меня не переводятся эти строки. В конце поговорим немного о недостатках:1) Тексты из полей с
config.page_title_ не были протестированы на сохранение в ZOO бэкап на момент написания статьи. Для переноса информации я использую запросы SQL, так не нарушаются Item ID. Это отдельная статья почему это необходимо делать.
2) Все вышесказанное реализованно в
Joomla 1.5.23 - JoomFish 2.1.7 - ZOO 2.4.14, я не тестировал на
Joomla 1.6 и
Joomla 1.7, так как
JoomFish не работает на
Joomla 1.6-1.7.
ZOO 2.5 будет переработан и нет гарантии что все вышеописанное будет работать в новой версии.
3) Метаданные - они не переведены, так как я не пользуюсь метаданными Joomla и ZOO, я использую AceSEF и там назначаю метаданные для каждой страницы в соответствующем языке.
4) ZOO Tags тоже не переведены, пока я не использую их в мультиязычных сайтах, как только доберусь, опишу процесс перевода.
Я мог что-то упустить в этой статье, так как писал очень быстро, имея очень мало времени. Я обязательно дополню упущеное, отвечу на вопросы, и исправлю ошибки если таковые найдутся.