Локалізація самописного сайту засобами 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 до власного рушія

Нам знадобляться 5 файлів із каталогу «/wp-includes/pomo/»:
entry.php, mo.php, po.php, streams.php, translations.php
Можливо, не всі потрібні — я просто взяв усі.

Нижче приклад класу, який повторює функціональність «load_theme_textdomain()» і «__()» у WP:

<?php 
class Lng
{
    private static $_lang_ar = array();

    public static function _($s, $l = 'default', $a = NULL)
    {
        $l = Lng::l().'-'.$l.'.mo';

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

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

        return empty($a) ? $s : strtr($s, $a);
    }

    public static function load($l, $p)
    {
        $l = Lng::l().'-'.$l.'.mo';

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

        try {
            $MO = new MO();
            if (!$MO->import_from_file($p.$l)) {
                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;
    }

    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 сайтом проблеми? потрібний додатковий функціонал? нестандартний плагін чи згорнути нову сторінку?
Тоді напишіть мені через форму зворотного зв'язку, і я намагатимусь вам допомогти.

Напишіть коментар

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *