Форум пользователей Impera CMS
Impera CMS - отличный движок для лёгкого создания интернет магазина.
Обладает невероятным количеством функций, необходимых в онлайн торговле.

Следить
Главная
13:20
27 фев
#
?
написал:

День добрый!
Стала актуальной тема сделать интернет-магазин мультиязычным. Когда планируется полнофункционально реализовать данную функцию в Вашем движке.
Спасибо

06:04
10 мар
#
?
gitt написал:

Как я вижу строение шаблонизатора, поддерживается хелпер на PHP. Значит можно сделать что хочется, если на подхвате есть веб мастер с прямыми руками. Для мультиязычности присутствует все. Не пойму причину, почему это надо переложить на CMS, а не отдельный модуль.

08:27
10 мар
#
?
написал:

gitt, так поделитесь кодом, как сделать мультиязычность с помощью хелпера. А заявления, на php можно что хочешь, оставьте тролям.

05:41
14 мар
#
?
gitt написал:

От разработчика: Спасибо 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-а. Он предлагает разместить языковые версии сайта на двухбуквенных субдоменах, которые будут синонимами родительского домена:

  • http://ваш.сайт - реальный сайт
  • http://en.ваш.сайт - на английском
  • http://de.ваш.сайт - на немецком
  • http://fr.ваш.сайт - на французском
  • http://ru.ваш.сайт - на русском
  • http://by.ваш.сайт - на белорусском
  • http://ua.ваш.сайт - на украинском

Как видно по записанному выше правилу, в первой строке правила 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 Создать в базе языковые таблицы товаров из колонок, ид товара и только поля, требующие перевода.

  • products_en
  • products_de
  • products_fr
  • products_by
  • products_ua
    • во всех таблицах одинаковые поля:
      • product_id
      • meta_title
      • meta_keywords
      • meta_description
      • model
      • description
      • body
      • seo_description
  • sections_en
  • sections_de
  • sections_fr
  • sections_by
  • sections_ua
    • во всех таблицах одинаковые поля:
      • section_id
      • meta_title
      • meta_keywords
      • meta_description
      • name
      • header
      • body
      • seo_description
  • ..._en
  • ..._de
  • ..._fr
  • ..._by
  • ..._ua

4 Наполнить таблицы переводом.

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

18:08
14 мар
#
?
gitt написал:

Ничего себе чуть) Был набросок, а тут модуль почти. Только редактор языков впилить, и вот 100% мультиязычность.

Написание ответа

Перед публикацией рекомендуется использовать Предпросмотр, чтобы увидеть конечный вид сообщения.


Обратите внимание! Для противодействия спаму новые посты форума проявляются с задержкой от нескольких минут, пока не пройдут модерацию.