Багатомовний сайт за допомогою Zend Framework

Виникла в мене потреба створити багатомовний сайт використовуючи Zend Framework. Створив :). Нижче розкажу як.

Значить маємо умовний сайт http://mysite.com, який перекладено трьома мовами українською (uk), російською (ru) і англійською (en). Приходить на наш сайт користувач. Що ми зазвичай робимо? Або показуємо йому сайт з мовою по замовчуванню (в нас буде українська), або спробуємо спочатку визначити яка ж мова буде для нього кращою. На другому варіанті зупинюся детальніше.
Сучасні браузери (не берусь говорити про старі) передають серверу параметр HTTP_ACCEPT_LANGUAGE. В мене там “uk,ru;q=0.8,en-us;q=0.5,en;q=0.3”. Це значить, що краще за все я сприймаю сайти на українській, або російській мові, а потім вже на англійській, при цьому надаю перевагу “американській версії” :).
В Zend Framework для того, щоб визначити яка ж мова буде найбільш вдалою можна використати Zend_Locale. Наприклад:

$locale = new Zend_Locale('auto');
$lang = $locale->getLanguage();

Але, що якщо наш сайт не підтримує цю мову? Потрібно зробити перевірку. Для цього в файлі конфігурації (я використовую Zend_Config_Ini) збережемо перелік локалей, які підтримуються сайтом.

; allowed locales (first locale - default)
locales.uk = uk_UA
locales.ru = ru_RU
locales.en = en_GB

І робимо перевірку (в bootstrap):

$locales = $config->locales->toArray();
$locale = new Zend_Locale('auto');
 
$lang = array_key_exists($locale->getLanguage(), $locales)
    ? $locale->getLanguage() : $config->locales->key();

А як зробити, щоб http://mysite.com/uk/user/auth відображався на українській, http://mysite.com/ru/user/auth – на російській, а http://mysite.com/user/auth – на тій мові, яка зручніша для користувача (або на дефолтній)? Для цього потрібно перевизначити дефолтний роутер (додати йому параметр lang) і створити ще один, який буде витягувати мову з url (якщо вона там є).

// change default router
$frontController->getRouter()->addRoute('default', 
    new Zend_Controller_Router_Route(
        ':module/:controller/:action/*',
        array(
            'module' => 'default',
            'controller' => 'index',
            'action' => 'index',
            'lang' => $lang
        )
    )
);
 
// add multilingual route
$frontController->getRouter()->addRoute('default_multilingual', 
    new Zend_Controller_Router_Route(
        ':lang/:module/:controller/:action/*',
        array(
            'module' => 'default',
            'controller' => 'index',
            'action' => 'index',
            'lang' => $lang
        ),
        array(
            'lang' => 'w{2}'
        )
    )
);

Але й це ще не все. Юзер може спробувати перейти за адресою http://mysite.com/de/user/auth, а наш сайт ніхт шпрехен зе дойч… Що ж робити? Для того, щоб вже остаточно визначитись якою мовою показувати сайт, створимо спеціальний helper (приклад я піддивився в книжці “Zend Framework in Action“).

<?php
 
class Site_Controller_Action_Helper_Language extends Zend_Controller_Action_Helper_Abstract {
 
    protected $_sDefaultLanguage;
    protected $_aLocales;
    protected $_sLanguagesDirectoryPath;
 
    /**
     * @param array $aLocales - Available locales
     * @param string $sLanguagesDirectoryPath
     */
    public function __construct(array $aLocales, $sLanguagesDirectoryPath) {
        $this->_sLanguagesDirectoryPath = $sLanguagesDirectoryPath;
        $this->_aLocales = $aLocales;
        $this->_sDefaultLanguage = key($aLocales); // get first language
    }
 
    public function init() {
        // try get current language from url
        $sLang = $this->getRequest()->getParam('lang');
 
        if(! array_key_exists($sLang, $this->_aLocales)) {
            $sLang = $this->_sDefaultLanguage;
        }
 
        // generate path to the gettext language file
        $sLanguageFilePath = $this->_sLanguagesDirectoryPath . '/'. $sLang . '/LC_MESSAGES/' . $sLang . '.mo';
        if(! file_exists($sLanguageFilePath)) {
            $sLanguageFilePath = $this->_sLanguagesDirectoryPath . '/' . $this->_sDefaultLanguage . '/LC_MESSAGES/' . $this->_sDefaultLanguage . '.mo';
            $sLang = $this->_sDefaultLanguage;
        }
 
        // get current locale by current language
        $sLocale = $this->_aLocales[$sLang];
 
        // setup translate object
        $oTranslate = new Zend_Translate('gettext', $sLanguageFilePath, $sLang);
        Zend_Form::setDefaultTranslator($oTranslate); // translated Zend_Form
 
        $this->_actionController->_locale = $sLocale;
        $this->_actionController->_lang = $sLang;
        $this->_actionController->_translate = $oTranslate;
 
        $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
        $viewRenderer->view->locale = $sLocale;
        $viewRenderer->view->lang = $sLang;
        $viewRenderer->view->translate = $oTranslate;
    }
}

Цей хелпер робить останню перевірку і підвантажує потрібний мовний файл. Наприклад, для url http://mysite.com/de/user/auth сайт буде відображатись на українській мові.
Для того, щоб хелпер запрацював, достатньо додати в наш bootstrap файл дві стрічки:

$languageHelper = new Site_Controller_Action_Helper_Language($locales, APPLICATION_PATH . '/languages');
Zend_Controller_Action_HelperBroker::addHelper($languageHelper);

Ну ніби все :). Дякую за увагу.

6 thoughts on “Багатомовний сайт за допомогою Zend Framework

  1. Небольшое такое дополнение: если в Zend_Translate вы будете скармливать CSV файлы в UTF-8 – то для адекватного русского Вам понадобится выставить локаль ручками:
    setlocale(LC_ALL, ‘ru_RU.UTF-8’);

  2. Дня доброго!
    Возникла необходимость в реализации данной “идеи” и я нашел Вашу статью. Прочитал на рус. и на укр:).
    Все ОК, но …
    | Для того, щоб хелпер запрацював, достатньо додати в наш bootstrap файл дві стрічки: |
    И вот тут я прописываю в bootstrap’е (в одно из _initFunction() )

    $languageHelper = new Zend_Controller_Action_Helper_Language($locales, APPLICATION_PATH.’/languages’);
    Zend_Controller_Action_HelperBroker::addHelper($languageHelper);

    также явно указываю и путь где лежат эти ActionHelper’ы по типу:

    Zend_Controller_Action_HelperBroker::addPath(APPLICATION_PATH.’/controllers/helpers’);

    и в итоге получаю ошибочку, что:
    Fatal error: Class ‘Zend_Controller_Action_Helper_Language’ not found in X:/…/htdocs\bvcom_ZF\application\Bootstrap.php on line 65

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

    P.S.: Пробовал и в ./library ложить сам helper, но тоже что-то не сильно соглашается.

    Спасибо, Павел!

Leave a Reply

Your email address will not be published. Required fields are marked *