From 204e6a3ed21a55d4f3b990d044ce5933f9a08850 Mon Sep 17 00:00:00 2001 From: Jan Schneider Date: Fri, 22 Oct 2010 16:10:16 +0200 Subject: [PATCH] Implement Horde_Translation as static per-library wrapper. --- framework/Translation/lib/Horde/Translation.php | 81 ++++++++++++++++++++-- .../lib/Horde/Translation/Exception.php | 13 ++++ .../Translation/lib/Horde/Translation/Handler.php | 41 +++++++++++ .../Horde/Translation/{ => Handler}/Gettext.php | 6 +- framework/Translation/package.xml | 52 +++++++++++--- .../test/Horde/Translation/GettextTest.php | 38 ++-------- .../test/Horde/Translation/TestBase.php | 42 +++++++++++ .../test/Horde/Translation/WrapperTest.php | 37 ++++++++++ 8 files changed, 262 insertions(+), 48 deletions(-) create mode 100644 framework/Translation/lib/Horde/Translation/Exception.php create mode 100644 framework/Translation/lib/Horde/Translation/Handler.php rename framework/Translation/lib/Horde/Translation/{ => Handler}/Gettext.php (90%) create mode 100644 framework/Translation/test/Horde/Translation/TestBase.php create mode 100644 framework/Translation/test/Horde/Translation/WrapperTest.php diff --git a/framework/Translation/lib/Horde/Translation.php b/framework/Translation/lib/Horde/Translation.php index 257e9bc0d..4d9cf5d1e 100644 --- a/framework/Translation/lib/Horde/Translation.php +++ b/framework/Translation/lib/Horde/Translation.php @@ -9,15 +9,74 @@ */ /** - * The Horde_Translation interface defines the interface for any classes - * providing translations. + * Horde_Translation is the base class for any translation wrapper classes in + * libraries that want to utilize the Horde_Translation library for + * translations. * * @author Jan Schneider * @package Translation */ -interface Horde_Translation +abstract class Horde_Translation { /** + * The translation domain, e.g. the library name, for the default gettext + * handler. + * + * @var string + */ + static protected $_domain; + + /** + * The relative path to the translations for the default gettext handler. + * + * This path is relative to the + * + * @var string + */ + static protected $_directory; + + /** + * The handler providing the actual translations. + * + * @var Horde_Translation_Handler + */ + static protected $_handler; + + /** + * Loads a translation handler class pointing to the library's translations + * and assigns it to $_handler. + * + * @param string $handlerClass The name of a class implementing the + * Horde_Translation_Handler interface. + */ + static public function loadHandler($handlerClass) + { + if (!self::$_domain || !self::$_directory) { + throw new Horde_Translation_Exception('The domain and directory properties must be set by the class that extends Horde_Translation.'); + } + $backtrace = debug_backtrace(); + $directory = dirname($backtrace[1]['file']) . '/' . self::$_directory; + self::setHandler(new $handlerClass(self::$_domain, $directory)); + } + + /** + * Assigns a translation handler object to $_handler. + * + * Type hinting isn't used on purpose. You should extend a custom + * translation handler passed here from the Horde_Translation interface, + * but technically it's sufficient if you provide the API of that + * interface. + * + * @param Horde_Translation_Handler $handler An object implementing the + * Horde_Translation_Handler + * interface. + */ + static public function setHandler($handler) + { + self::$_handler = $handler; + } + + /** * Returns the translation of a message. * * @var string $message The string to translate. @@ -25,7 +84,13 @@ interface Horde_Translation * @return string The string translation, or the original string if no * translation exists. */ - public function t($message); + static public function t($message) + { + if (!self::$_handler) { + self::loadHandler('Horde_Translation_Handler_Gettext'); + } + return self::$_handler->t($message); + } /** * Returns the plural translation of a message. @@ -37,5 +102,11 @@ interface Horde_Translation * @return string The string translation, or the original string if no * translation exists. */ - public function ngettext($singular, $plural, $number); + static public function ngettext($singular, $plural, $number) + { + if (!self::$_handler) { + self::loadHandler(); + } + return self::$_handler->ngettext($singular, $plural, $number); + } } diff --git a/framework/Translation/lib/Horde/Translation/Exception.php b/framework/Translation/lib/Horde/Translation/Exception.php new file mode 100644 index 000000000..237fa484e --- /dev/null +++ b/framework/Translation/lib/Horde/Translation/Exception.php @@ -0,0 +1,13 @@ + + * @package Translation + */ +class Horde_Translation_Exception extends Horde_Exception { } diff --git a/framework/Translation/lib/Horde/Translation/Handler.php b/framework/Translation/lib/Horde/Translation/Handler.php new file mode 100644 index 000000000..1ba35f580 --- /dev/null +++ b/framework/Translation/lib/Horde/Translation/Handler.php @@ -0,0 +1,41 @@ + + * @package Translation + */ +interface Horde_Translation_Handler +{ + /** + * Returns the translation of a message. + * + * @var string $message The string to translate. + * + * @return string The string translation, or the original string if no + * translation exists. + */ + public function t($message); + + /** + * Returns the plural translation of a message. + * + * @param string $singular The singular version to translate. + * @param string $plural The plural version to translate. + * @param integer $number The number that determines singular vs. plural. + * + * @return string The string translation, or the original string if no + * translation exists. + */ + public function ngettext($singular, $plural, $number); +} diff --git a/framework/Translation/lib/Horde/Translation/Gettext.php b/framework/Translation/lib/Horde/Translation/Handler/Gettext.php similarity index 90% rename from framework/Translation/lib/Horde/Translation/Gettext.php rename to framework/Translation/lib/Horde/Translation/Handler/Gettext.php index a5078dba7..18364aec2 100644 --- a/framework/Translation/lib/Horde/Translation/Gettext.php +++ b/framework/Translation/lib/Horde/Translation/Handler/Gettext.php @@ -9,13 +9,13 @@ */ /** - * The Horde_Translation_Gettext provides translations through the gettext - * extension, but fails gracefully if gettext is not installed. + * The Horde_Translation_Handler_Gettext provides translations through the + * gettext extension, but fails gracefully if gettext is not installed. * * @author Jan Schneider * @package Translation */ -class Horde_Translation_Gettext implements Horde_Translation +class Horde_Translation_Handler_Gettext implements Horde_Translation_Handler { /** * The translation domain, e.g. package name. diff --git a/framework/Translation/package.xml b/framework/Translation/package.xml index 6ab343ecd..005dac51e 100644 --- a/framework/Translation/package.xml +++ b/framework/Translation/package.xml @@ -1,5 +1,5 @@ - + Translation pear.horde.org Horde translation library @@ -10,8 +10,8 @@ jan@horde.org yes - 2010-10-05 - + 2010-10-22 + 0.1.0 0.1.0 @@ -29,11 +29,35 @@ - - + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + @@ -54,7 +78,17 @@ - + + + + + + + + + + + @@ -67,7 +101,7 @@ beta beta - 2010-10-05 + 2010-10-22 LGPL * Initial release. diff --git a/framework/Translation/test/Horde/Translation/GettextTest.php b/framework/Translation/test/Horde/Translation/GettextTest.php index bc3c327a5..959063f63 100644 --- a/framework/Translation/test/Horde/Translation/GettextTest.php +++ b/framework/Translation/test/Horde/Translation/GettextTest.php @@ -1,4 +1,7 @@ * @license http://www.fsf.org/copyleft/lgpl.html LGPL @@ -6,28 +9,16 @@ * @package Translation * @subpackage UnitTests */ - -class Horde_Translation_GettextTest extends PHPUnit_Framework_TestCase +class Horde_Translation_GettextTest extends Horde_Translation_TestBase { private $_dict; private $_otherDict; - private $_env; public function setUp() { - try { - $this->setLocale(LC_ALL, 'de_DE.UTF-8'); - } catch (PHPUnit_Framework_Exception $e) { - $this->markTestSkipped('Setting the locale failed. de_DE.UTF-8 might not be supported.'); - } - $this->_setEnv('de_DE.UTF-8'); - $this->_dict = new Horde_Translation_Gettext('Horde_Translation', dirname(__FILE__) . '/locale'); - $this->_otherDict = new Horde_Translation_Gettext('Horde_Other', dirname(__FILE__) . '/locale'); - } - - public function tearDown() - { - $this->_restoreEnv(); + parent::setUp(); + $this->_dict = new Horde_Translation_Handler_Gettext('Horde_Translation', dirname(__FILE__) . '/locale'); + $this->_otherDict = new Horde_Translation_Handler_Gettext('Horde_Other', dirname(__FILE__) . '/locale'); } public function testGettext() @@ -43,19 +34,4 @@ class Horde_Translation_GettextTest extends PHPUnit_Framework_TestCase $this->assertEquals('1 Woche', sprintf($this->_dict->ngettext('%d week', '%d weeks', 1), 1)); $this->assertEquals('2 Wochen', sprintf($this->_dict->ngettext('%d week', '%d weeks', 2), 2)); } - - private function _setEnv($value) - { - foreach (array('LC_ALL', 'LANG', 'LANGUAGE') as $env) { - $this->_env[$env] = getenv($env); - putenv($env . '=' . $value); - } - } - - private function _restoreEnv() - { - foreach (array('LC_ALL', 'LANG', 'LANGUAGE') as $env) { - putenv($env . '=' . $this->_env[$env]); - } - } } diff --git a/framework/Translation/test/Horde/Translation/TestBase.php b/framework/Translation/test/Horde/Translation/TestBase.php new file mode 100644 index 000000000..de61d446c --- /dev/null +++ b/framework/Translation/test/Horde/Translation/TestBase.php @@ -0,0 +1,42 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @category Horde + * @package Translation + * @subpackage UnitTests + */ +class Horde_Translation_TestBase extends PHPUnit_Framework_TestCase +{ + private $_env; + + public function setUp() + { + try { + $this->setLocale(LC_ALL, 'de_DE.UTF-8'); + } catch (PHPUnit_Framework_Exception $e) { + $this->markTestSkipped('Setting the locale failed. de_DE.UTF-8 might not be supported.'); + } + $this->_setEnv('de_DE.UTF-8'); + } + + public function tearDown() + { + $this->_restoreEnv(); + } + + private function _setEnv($value) + { + foreach (array('LC_ALL', 'LANG', 'LANGUAGE') as $env) { + $this->_env[$env] = getenv($env); + putenv($env . '=' . $value); + } + } + + private function _restoreEnv() + { + foreach (array('LC_ALL', 'LANG', 'LANGUAGE') as $env) { + putenv($env . '=' . $this->_env[$env]); + } + } +} diff --git a/framework/Translation/test/Horde/Translation/WrapperTest.php b/framework/Translation/test/Horde/Translation/WrapperTest.php new file mode 100644 index 000000000..53402e6c3 --- /dev/null +++ b/framework/Translation/test/Horde/Translation/WrapperTest.php @@ -0,0 +1,37 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @category Horde + * @package Translation + * @subpackage UnitTests + */ +class Horde_Translation_WrapperTest extends Horde_Translation_TestBase +{ + public function testWrappers() + { + $this->assertEquals('Heute', Horde_Translation_TestWrapper::t('Today')); + $this->assertEquals('1 Woche', sprintf(Horde_Translation_TestWrapper::ngettext('%d week', '%d weeks', 1), 1)); + } +} + +class Horde_Translation_TestWrapper extends Horde_Translation +{ + /** + * Returns the translation of a message. + * + * @var string $message The string to translate. + * + * @return string The string translation, or the original string if no + * translation exists. + */ + static public function t($message) + { + self::$_domain = 'Horde_Translation'; + self::$_directory = 'locale'; + return parent::t($message); + } +} -- 2.11.0