Побудова списку неперекладених фраз в Zend_Translate
Пн, 9 Лют 2009Zend_Translate чудова компонента Zend Framework для створення інтерфейсу перекладеного багатьма мовами. Я спробував підняти багатомовний інтерфейс використовуючи цей інструмент, але зіткнувся з певними архітектурними проблемами для вирішення яких мені випало поспілкуватися на Issue Tracker з Томасом Вейднером (Thomas Weidner) лідером команди інтернаціоналізації Zend Framework I18N. Але про все по порядку.
На етапі розробки/тестування багатомовного інтерфейсу хотілося вивести список фраз що не мають перекладу для поточної локалі (Locale).
Переглянувши вихідний код Zend_Translate_Adapter я зрозумів що Zend Framework не надає ніяких засобів для збору неперекладених фраз окрім скупого методу isTranslated().
Хотілося б щоб адаптер перекладів сам автоматично фіксував неперекладені фрази і давав можливість отримати їх перелік
Дивувало те що такої важливої функції ніхто ніде не обговорював/не розглядав і оскільки мої пошуки готового рішення не увінчалися успіхом – вирішив описати цю проблему детально в темі “Allow to build the list of untranslated message IDs” на Zend Framework Issue Tracker.
Я використовую Action Helper щоб додати необхідний функціонал до мого Front Page Controller-а.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | /** * Initiate internationalization * * @return Trc_Initializer */ private function _initL10n() { $translate = new Zend_Translate('tmx', $this->_root . '/languages/general.tmx'); // get locale $locale = Zend_Registry::get('Zend_Locale'); $current_lang = $locale->getLanguage(); if (!$translate->isAvailable($current_lang)) { $locale->setLocale('en'); } $translate->setLocale($locale); // save locale state into user session $user = Wise_User_Session::getInstance(); $user->locale = $locale->getLanguage(); Zend_Registry::set('Zend_Translate', $translate); return $this; } |
Ініціалізований об’єкт Zend_Translate_Adapter_xxx зберігаю в реєстрі під зарезервованим за ним простором імен “Zend_Translate”.
Першим власним рішенням в мене було звертатися до Zend_Translate через написаний мною ViewHelper що має наступний вигляд:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | /** * T (stands for Translation) Helper * * The main goal of this view helper is to collect the list * of untranslated Message Ids and provide them as an array */ class Zend_View_Helper_T { /** * The list of messageIds without translation for current locale * @var array */ static public $missedTranslations = null; /** * Zend_View * * @var Zend_View_Interface */ protected $_view = null; /** * Set the view object */ public function setView(Zend_View_Interface $view) { $this->_view = $view; } /** * Translates provided message Id * * You can give multiple params or an array of params. * If you want to output another locale just set it as last single parameter * Example 1: translate('%1\$s + %2\$s', $value1, $value2, $locale); * Example 2: translate('%1\$s + %2\$s', array($value1, $value2), $locale); * * @param string $messageid Id of the message to be translated * @return string Translated message */ public function T($messageid = null) { /** * Process the arguments */ $options = func_get_args(); array_shift($options); $count = count($options); $locale = null; if ($count > 0) { if (Zend_Locale::isLocale($options[($count - 1)], null, false) !== false) { $locale = array_pop($options); } } if ((count($options) === 1) and (is_array($options[0]) === true)) { $options = $options[0]; } /** * Get Zend_Translate_Adapter */ $translator = $this->_view->translate() // get Zend_View_Helper_Translate ->getTranslator(); // Get Zend_Translate_Adapter /** * Collect the list of untranslated Message Ids into array */ if (false === $translator->isTranslated($messageid)) { self::$missedTranslations[] = $messageid; } /** * Proxify the call to Zend_Translate_Adapter */ $message = $translator->translate($messageid, $locale); /** * If no any options provided then just return message */ if ($count === 0) { return $message; } /** * Apply options in case we have them */ return vsprintf($message, $options); } } |
Вище приведене рішення працює в мене і до тепер, однак недолік такого підходу в тому що при звертанні до Zend_Translate_Adapter безпосередньо (наприклад в Model або Controller Action, поза межами файлів представлення) – неперекладені фрагменти не потрапляють в наш чорний список
.
Томас Вейднер спочатку відхилив мою пропозицію ZF-5547, мотивуючи відповідь тим що єдиним найпрактичнішим рішенням є використання методу isTranslated().
Однак через два тижні він все таки видав нову редакцію Zend_Translate_Adapter що реалізовувала можливість використання Zend_Log для фіксування неперекладених фраз. Цей файл можна знайти в SVN репозиторії ось тут: svn://framework.zend.com/svn/framework/standard/incubator/library/Zend/Translate/Adapter.php, адаптувавши мою початкову ідею у відповідності до ідеології Zend Framework.
Зараз тестую новий функціонал. Результати тестування можна відслідковувати на Issue Tracker.
Вт, 10 Лют 2009 о 21:10
Почему не сделать просто статический метод, который будет реализововать приведенный вами пример?
Объект вида всегда можно получить через ViewRender
Ср, 11 Лют 2009 о 19:58
Не зовсім зрозумів, що саме пане Романе Ви маєте на увазі. Приведіть приклад.
Варіант з View Helper як на мене є оптимальним в плані легкості застосування в шаблонах представлення, ось так:
Оскільки була потреба лише в тимчасовому робочому рішенні – це перше і найпростіше що спало на думку та як на мене найкраще відповідає ідеології MVC.
Зараз я відмовився від view helper на користь експериментальної версії Zend_Translate в SVN інкубаторі з підтримкою потібного функціоналу.
До слова, вчора отримав повідомлення про те що запропонований функціонал одобрено dev-team але ще не одобрено з боку community. Є ймовірність що можливо нововведення може бути включено до дистрибутиву, якщо буде корисним спільноті zend framework. Тішуся дурницею як дитина, їй-богу
.
Пн, 23 Лют 2009 о 12:21
Побудова списку не перекладених фраз буде доступна в Zend Framework 1.8 !
Можна прочитати статтю Томаса на його персональному блозі