День добрый!
Стала актуальной тема сделать интернет-магазин мультиязычным. Когда планируется полнофункционально реализовать данную функцию в Вашем движке.
Спасибо
День добрый!
Стала актуальной тема сделать интернет-магазин мультиязычным. Когда планируется полнофункционально реализовать данную функцию в Вашем движке.
Спасибо
Как я вижу строение шаблонизатора, поддерживается хелпер на 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% мультиязычность.