День добрый!
Стала актуальной тема сделать интернет-магазин мультиязычным. Когда планируется полнофункционально реализовать данную функцию в Вашем движке.
Спасибо
День добрый!
Стала актуальной тема сделать интернет-магазин мультиязычным. Когда планируется полнофункционально реализовать данную функцию в Вашем движке.
Спасибо
Как я вижу строение шаблонизатора, поддерживается хелпер на PHP. Значит можно сделать что хочется, если на подхвате есть веб мастер с прямыми руками. Для мультиязычности присутствует все. Не пойму причину, почему это надо переложить на CMS, а не отдельный модуль.
gitt, так поделитесь кодом, как сделать мультиязычность с помощью хелпера. А заявления, на php можно что хочешь, оставьте тролям.
От разработчика: Спасибо gitt за ответ и пример реализации. Я позволил себе чуть исправить и прокомментировать ваш код, чтобы был понятен читателю.
Кодом не делюсь, разрабатывайте сами, а основу пожалуйста покажу.
1 Вам надо код языка сначала получить, добавить параметром в запрос. Тут хватит правила .htaccess.
RewriteCond %{HTTP_HOST} ^(en|de|fr|ru|by|ua)\..+$ [NC] RewriteCond %{QUERY_STRING} !^(.*&)?UserLang= [NC] RewriteRule ^(.*)$ $1?UserLang=%1 [L,QSA]
Альтернатива А вот тут описан способ 2, какой-то задрочный, как сделать без правила htaccess.
От разработчика: Тем кто не знаком с серверным модулем Rewrite - переназначение адреса страницы согласно неким правилам, поясню ход мысли gitt-а. Он предлагает разместить языковые версии сайта на двухбуквенных субдоменах, которые будут синонимами родительского домена:
Как видно по записанному выше правилу, в первой строке правила gitt предлагает извлекать код языка из имени хоста, строго в рамках поддерживаемых языков. Например выше предложены - английский, немецкий, французский, русский, белорусский, украинский.
Затем, в третьей строке правила, извлечённый символьный код языка предлагает добавить в качестве некоего уникального параметра к уже существующим параметрам запроса в том же неизменившемся адресе страницы.
Вторая строка правила служит цели исключить закольцовку, то есть обрывает правило, если на очередном круге анализа адреса в нём уже присутствует добавленный параметр.
Мультиязычный сайт это 2 функции переводчика, интерфейс и контент.
1 Поэтому требуйте дизайнера верстать шаблон только так.
<!DOCTYPE html> <html> ... <body> ... <h6>{ti msg='Привет Мир'}</h6> ... </body> </html>
2 Создать хелпер шаблона с переводческими функциями, контентная пока пустая.
<?php class TemplateEmulator { protected $cms; /* ======================================================================== | | | Конструктор хелпера. | | | ======================================================================== */ public function __construct ( & $cms ) { $this->cms = & $cms; $this->translateContent(); $cms->smarty->registerPlugin('function', 'ti', array($this, 'translateInterface')); } /* ======================================================================== | | | Получить код языка, извлеченный Rewrite-правилом (по умолчанию ru). | | | ======================================================================== */ public function getLang () { $lang = $this->cms->request->getGet('UserLang', ''); $lang = $this->cms->text->lowerCase($lang); switch ($lang) { case 'en': case 'de': case 'fr': case 'by': case 'ua': return $lang; } return 'ru'; } /* ======================================================================== | | | Получить входной параметр шаблонизационной функции. | | | ======================================================================== */ private function getParam ( $name, & $params, $def = null ) { return isset($params[$name]) ? $params[$name] : $def; } /* ======================================================================== | | | Перевести строку интерфейса (указывается в параметре 'msg'). | | | ======================================================================== */ public function translateInterface ( $params = null, & $smarty = null ) { $lang = $this->getLang(); $msg = $this->getParam('msg', $params, ''); switch ($msg) { /* ================================================================ | | | Фраза 1. | | | ================================================================ */ case 'Привет Мир': switch ($lang) { case 'en': return 'Hello World'; case 'de': return 'Hallo Welt'; case 'fr': return 'Bonjour Monde'; case 'by': return 'Прывiтанне Сусвет'; case 'ua': return 'Привiт Свiт'; } break; /* ================================================================ | | | Фраза 2. | | | ================================================================ */ case '...': switch ($lang) { ... } break; /* ================================================================ | | | Фраза 3 и так далее. | | | ================================================================ */ ... } return $msg; } /* ======================================================================== | | | Перевести элементы контента. | | | ======================================================================== */ private function translateContent () { } } ?>
Альтернатива Похожий по смыслу способ 1 описан тут. Фигня честно, почему языковые файлы расположены не в составе шаблона.
От разработчика: Снова поясню. Gitt предлагает все фразы интерфейса выводить с помощью некоторой шаблонизационной функции ti (сокращение от Translate Interface), которая принимает на вход некий текстовый параметр и возвращает его перевод согласно извлечённому коду языка.
1 Дописать контентную функцию.
<?php class TemplateEmulator { ... /* ======================================================================== | | | Перевести элементы контента. | | | ======================================================================== */ private function translateContent () { $this->cms->db->products = new TranslatedProductsDBModel($this->cms); $this->cms->db->sections = new TranslatedSectionsDBModel($this->cms); $this->cms->db->... = new Translated...DBModel($this->cms); ... } } ?>
От разработчика: По сути это перекрытие товарной модели базы данных с целью дополнить метод распаковки полей о товаре собственной функцией перевода этих полей "на лету". Троеточием обозначены названия иных моделей (например статья, новость, статическая страница), которые вы возможно хотели бы перекрыть для перевода.
2 Дописать над хелпером классы переведенных моделей.
<?php /* ============================================================================ | | | Модель базы товаров (расширяем стандартный метод unpack своими действиями).| | | ============================================================================ */ require_once(dirname(__FILE__) . '/../../../objects/.db-models/Products.php'); class TranslatedProductsDBModel extends ProductsDBModel { /* ======================================================================== | | | Чтение перевода товара из базы данных. | | | ======================================================================== */ private function getTranslated ( & $item, $lang ) { $id = $this->getIDField(); $result = $this->cms->db->query('SELECT * ' . 'FROM `products_' . $lang . '` ' . 'WHERE `' . $id . '` = "' . $item->$id . '" ' . 'LIMIT 1'); $translated = $this->cms->db->fetch_object($result); $this->cms->db->free_result($result); return $translated; } /* ======================================================================== | | | Замена содержимого полей исходника полями аддона. | | | ======================================================================== */ private function replaceByFields ( & $src, & $addon ) { if (!is_object($addon)) return; foreach ($addon as $field => $value) { if (isset($src->$field) && !empty($value)) $src->$field = $value; } } /* ======================================================================== | | | Распаковка полей записи (то есть когда уже прочитана из базы). | | | ======================================================================== */ public function unpack ( & $item, $params = null ) { $lang = $this->cms->designer->getLang(); if ($lang != 'ru') { $translated = $this->getTranslated($item, $lang); $this->replaceByFields($item, $translated); } parent::unpack($item, $params); } } /* ============================================================================ | | | Другие модели (если кроме перевода товаров нас интересует что-то еще). | | | ============================================================================ */ require_once(dirname(__FILE__) . '/../../../objects/.db-models/Sections.php'); class TranslatedSectionsDBModel extends SectionsDBModel { ... } require_once(dirname(__FILE__) . '/../../../objects/.db-models/....php'); class Translated...DBModel extends ...DBModel { ... } /* ============================================================================ | | | Хелпер шаблона. | | | ============================================================================ */ class TemplateEmulator { ... } ?>
От разработчика: Обратите внимание, что из перекрытой модели можно обратиться к публичным методам хелпера, если это необходимо, например как в случае с методом getLang.
3 Создать в базе языковые таблицы товаров из колонок, ид товара и только поля, требующие перевода.
4 Наполнить таблицы переводом.
От разработчика: Согласно тому, как выше был написан метод replaceByFields конкретной модели, пустые поля языковых таблиц или даже отсутствие колонок, или вообще отсутствие строк для каких-то идентификаторов записей будет означать, что для такого поля или же всей записи перевода нет и в этом элементе следует оставить текст, как на основном сайте (то есть основном языке).
Ничего себе чуть) Был набросок, а тут модуль почти. Только редактор языков впилить, и вот 100% мультиязычность.