Мультиязычность в Smarty — Организация мультиязычности на сайте

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

Существует множество способов реализации мультиязычности ,наиболее простым из них является:

  1.  Создание несколько типов файлов с языковыми константами или переменными. Константы прописываются жестко в файле вида.
  2. «Изощренные» умы создают несколько полных копий сайтов на разных языках.
  3.  Организация мультиязычности через Gettext

Каждый из этих способов имеет как плюсы так и минусы ,мой способ ближе скорей всего к Gettext ,но попроще )

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

Алгоритм работы:

  1. Все заключенное между тегами {t}{/t} в шаблонах ,отправляем на проверку.
  2. Проверяем если язык русский то отправляем обратно без перевода ,если не русский отправляем на перевод.
  3. Создаем массив типа ключ — значение ,в котором ключ фраза на русском языке ,в данном случае это данные заключенные между тегов {t}{/t}
  4. Проверяем если данная фраза — ключ имеет непустое значение выдаем значение(т.е перевод данного слова) ,иначе отправляем обратно без перевода.

Преимущества:

  1. Простота ,для перевода просто используем теги {t}{/t} в шаблонах
  2. Если слова нет в базе ,то оно добавиться автоматом ,вам лишь затем следует его дополнительно перевести на другой язык через phpmyadmin, или написать оболочку для админки что очень просто )
  3. Если слово не найдено ,то оно вернется просто без перевода.
  4. При использовании кеширования ,практически отсутствие нагрузки.
  5. Удобство перевода и поддержания его соответствующем состоянии.

Для этого создадим  файл: block.t.php в директории smarty/plugins:

</p>
<p><?php
/**
 * @package Smarty
 * @subpackage {t}{/t}
*/
function smarty_block_t($params, $content, &$smarty)
{
/**
 * Получаем глобальные переменные
 */
$settings = Registry::get('settings');
$cache = Registry::get('cache');
$db = Registry::get('db');
if ($content!=NULL) {
$content=trim($content);
 if ($settings->language_translate)<br />
 {<br />
 /**<br />
 * Русский язык стандартный для всех шаблонов<br />
 * Он не переводится<br />
 */<br />
 if ($settings->lng == 'rus') {<br />
 return $content;<br />
 } else {<br />
 /**<br />
 * Получаем переведенные слова<br />
 */<br />
 return language::get_words($content, $settings, $cache, $db);<br />
 }<br />
 } else {<br />
 return $content;<br />
 }<br />
} else {<br />
return $content;<br />
}</p>
<p>}<br />
?></p>
<p>

В объекте — $settings находятся настройки сайта.
Объект — $cache экземпляр класса кэширования
Объект — $db экземпляр класса соединения с базой

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

</p>
<p><?php
/**
 * Класс мультиязычности
*/
abstract class Language {
     static function get_words($content ,$settings, $cache, $db)
     {
         /**
         * Для уменьшения нагрузки используем класс для работы с кешированием
         */
	 if (!$language = $cache -> get('language.'.$settings->lng))<br />
	 {<br />
            foreach ($db->query('SELECT `default`, `'.$settings->lng.'` FROM `language_'.$settings>lng.'`') as $row) {<br />
            $language[$row['default']] =  $row[$settings->lng];<br />
            }<br />
	   $cache -> set('language.'.$settings->lng, $language , 3600*24);<br />
	 }</p>
<p>	   if (!empty($language[$content]))<br />
	   {<br />
            /**<br />
            * Если выбранная нами фраза на русском языке существует в базе ,то выдать его аналог на другом языке ,инача или добавить фразу в словарь и вывести слово без перевода<br />
            */<br />
	    return $language[$content];<br />
	   } else {</p>
<p>		  if ($settings->language_add_words)<br />
		  {<br />
                  /**<br />
                  * Сохранение неизвестного нам слова в словаре.<br />
                  */<br />
		   self::save_default_words($content, $settings, $db);<br />
		  }</p>
<p>	   return $content;<br />
	   }</p>
<p>     }</p>
<p>     static function save_default_words($content,$settings, $db)<br />
     {<br />
     /**<br />
     * Добавления слов в словарь<br />
     */<br />
	    if (!$db->query('SELECT COUNT(*) FROM `language_'.$settings->lng.'` WHERE `default` = "'.$content.'" LIMIT 1')->fetchColumn())<br />
	    {<br />
           $db->exec('INSERT INTO `language_'.$settings->lng.'` (`default`) VALUES ("'.$content.'")');<br />
		}<br />
     }<br />
}<br />
?><br />

Структура таблиц в базе такая ,название таблицы language_’выбранный нами язык в настройках’

<br />
CREATE TABLE IF NOT EXISTS `language_eng` (<br />
  `default` varchar(1024) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'Тест',<br />
  `eng` varchar(1024) COLLATE utf8_unicode_ci NOT NULL<br />
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;<br />

Мой код конечно требует реставрации под ваш код ,я его выдрал кусками у себя из проекта. Но я думаю общий алгоритм понятен и переделка кода не составит труда даже под другой шаблонизатор.

Благодарю за внимание ). Вопросы пишем в комментариях ).