Локализация самописного сайта средствами WordPress

Локализация самописного сайта средствами WordPress

Одним из последних проектов над которым я работал около месяца — разработка социальной сети. Сайт не такой уж сложный. Но был (и есть один момент) который мне не дает покоя — это поддержка языков. В WordPress, данный вопрос давно и хорошо проработан. И если ты имеешь навыки работы за компьютером, писать и набирать текст. То перевести тему или плагин большого труда не составит. Но для самописной CMS, которую я использую практически во всех разработках — это проблема. Если изначально, поддержка языков не была проработано на должном уровне.По наивности, я решил использовать тот функционал локализации, который предоставляет фреймворк Kohana (собственно на котором и написан мой движок). По умолчанию, фразы и слова с переводом хранятся в обычном php файле в виде массива. Пример перевода пагинации ниже:

return array(
	'First' 	=> 'Первая',
	'Last' 		=> 'Последняя',
	'Previous' 	=> '<',
	'Next' 		=> '>',
);

Преимущество данного подхода одно — производительность. Какое еще? Да кажется все. Но в высоко нагруженных проектах это важно!Если конечно дорабатывать, ранее созданный сайт с такой локализацией не планируется. То подобный способ вполне пригоден. Или если существует (или пишется под заказ) специально ПО, позволяющее сформировать вышеуказанный массив из функции «__(...)», то данный подход так же сгодится (об этой идее я кстати прочел на хабаре).Так вот. Я как представил себе, сколько это правок придется вносить в код и в текст во время доработок. Сколько нервов я потрачу с этими языками (а их на данный момент пять). Что «сразу» же решил отказаться от данного подхода.Потратив некоторое время, я пришел к следующему выводу.

  1. Можно использовать расширение PHP «gettext»
  2. Использовать наработки существующих CMS (WP, Drupal, Joomla)

Начал с первого. Честно сказать оказалось не так все просто. Всякие заморочки с установкой текущей локализации, непонятные пути к файлам и установкой кодировки. В общем, ничего у меня не вышло. К тому же! У клиента, на сервере данное расширение отсутствовало. В следствии чего, от данного подхода пришлось отказаться.Хотя с gettext разобраться все же нужно.Пункт второй. К счастью, на тот момент у меня был небольшой опыт работы с WP. И я решил в нем покопаться. Изучив как в нем реализован данный механизм. Было принято решение использовать именно его.Проанализировав последовательность вызовов функций «load_theme_textdomain()» и «__()» был разработан простенький класс работы с языками. Который был успешно внедрен (но окончательно не протестирован).

Как подключить POMO WordPress к своему движку

От самого WordPress нам понадобится пять файлов из каталога «/wp-includes/pomo/» (а именно — entry.php, mo.php, po.php, streams.php, translations.php). Возможно все файлы и не нужны, дело в том, что логику работы классов я не изучал, поэтому взял все и не стал «париться».Ниже, пример класса, выполняющего те же задачи что и функции «load_theme_textdomain()» и «__()» в WP.

<?php 
class Lng
{
	/**
	 * Массив языковых файлов
	 * @var array
	 */
	private static $_lang_ar = array();

	/**
	 * Возвращает перевод строки
	 * @param string $s переводимая строка. Пример "Hello from {site}"
	 * @param strings $l языковый файл
	 * @param array $a массив замены подстрок. Пример - array('{site}' => 'wp2fl.com')
	 * @return strings
	 */
	public static function _($s, $l = 'default', $a = NULL)
	{
		$l = Lng::l().'-'.$l.'.mo';

		if(isset(Lng::$_lang_ar[$l]) == FALSE)
		{
			Lng::$_lang_ar[$l] = new NOOP_Translations;
		}

		$s = Lng::$_lang_ar[$l] -> translate($s);

		return empty($a) ? $s : strtr($s, $a);
	}
	
	/**
	 * Загружает языковый файл
	 * @param string $l название файла
	 * @param string $p путь к каталогу где храняться языковые файлы
	 */
	public static function load($l, $p)
	{
		$l = Lng::l().'-'.$l.'.mo';

		if(class_exists('MO', FALSE) == FALSE)
		{
			throw new Exception('The "MO" library does not included');
		}

		try
		{
			$MO = new MO();
			if($MO -> import_from_file($p.$l) == FALSE)
			{
				return FALSE;
			}

			if(isset(Lng::$_lang_ar[$l]))
			{
				$MO -> merge_with(Lng::$_lang_ar[$l]);
			}

			Lng::$_lang_ar[$l] = &$MO;
		}

		catch (Exception $e)
		{
			throw new Exception('The language file "'.$l.'" does not exist');
		}
		
		return TRUE;
	}
	
	/**
	 * Возвращает текущий язык
	 * @return string
	 */
	public static function l()
	{
		return 'ru';
	}
}

А еще ниже, пример использования:

<?php
header('Content-Type: text/html; charset=utf-8');

try 
{
	/* Подключаем библиотеки */
	require_once('vendor/pomo/mo.php');
	require_once('library/lng.php');
	/* Подключаем первый языковый файл */
	Lng::load('first','languages/');
	/* Подключаем второй языковый файл */
	Lng::load('second','languages/');
}

catch(Exception $e)
{
	echo $e -> getMessage();
}
$name_first = 'Андрей';
$name_second = 'Алексей';
?>

<p><?php echo Lng::_('Hello {name}, how are you?','first',array('{name}' => $name_first))?></p>
<p><?php echo Lng::_('I am fine, thx {name}. And you?','second',array('{name}' => $name_second))?></p>

Не думаю что код нуждается в описании, т. к. везде есть комментарии. Обращу лишь ваше внимание на то, что языковые файлы должны храниться в каталоге «languages» и иметь названия «first» и «second».Результат работы кода следующий:

Привет Андрей, как ты?
Нормально, спасибо Алексей. А как ты?

Рабочий пример можно скачать по этой ссылке. Удачных вам переводов 🙂

Поделиться в соцсетях:
Статьи на похожую тематику

С вашим WordPress сайтом проблемы? нужен дополнительный функционал? нестандартный плагин или сверстать новую страницу?
Тогда напишите мне через форму обратной связи, и я постараюсь вам помочь.

Комментарии
  1. Сергей Назаров

    Не понял а что мешает создать простенькую функцию, например:

    function lang($s){ global $lang; return isset($lang[$s]) ? $lang[$s] : $s; }

    где $lang тот самый массив, о котором вы упоминали в начале. Его можно прописать в отдельном файле, например: langs/ru.php - ну и подключать нужные файлы по необходимости.

    С переменными в строке тоже как бы проблем не должно возникнуть, если слегка дописать функцию, но суть вы, думаю, уловили. Или я не уловил сути сказанного вами?

    ответить
    1. Pavel
      15.06.2015 в 08:39 автор блога

      Здравствуйте, Сергей!
      Возможно я плохо изложил суть проблемы. Проблема не в возможности отображать преводимые фразы. Проблема в удобстве поиска фраз которые необходимо пеоевести. А редактор poedit ее очень хорошо решает. А использование poedit, "тянет" за собой расширение php gettext или pomo от WordPress.

      ответить
Оставить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *