From 74eb462fec499660fd861b2d0235b9287b413d80 Mon Sep 17 00:00:00 2001 From: Mathieu Lutfy Date: Fri, 30 May 2014 15:33:19 -0400 Subject: [PATCH] CRM-14769: Extension translation: bugfix and add support for phpgettext. --- CRM/Core/I18n.php | 52 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/CRM/Core/I18n.php b/CRM/Core/I18n.php index e1ca11a95e..f34f5f3dc8 100644 --- a/CRM/Core/I18n.php +++ b/CRM/Core/I18n.php @@ -45,6 +45,13 @@ class CRM_Core_I18n { */ private $_nativegettext = FALSE; + /** + * Gettext cache for extension domains/streamers, depending on if native or phpgettext. + * - native gettext: we cache the value for textdomain() + * - phpgettext: we cache the file streamer. + */ + private $_extensioncache = array(); + /** * A locale-based constructor that shouldn't be called from outside of this class (use singleton() instead). * @@ -74,6 +81,7 @@ class CRM_Core_I18n { textdomain('civicrm'); $this->_phpgettext = new CRM_Core_I18n_NativeGettext(); + $this->_extensioncache['civicrm'] = 'civicrm'; return; } @@ -93,6 +101,7 @@ class CRM_Core_I18n { $streamer = new FileReader($mo_file); $this->_phpgettext = new gettext_reader($streamer); + $this->_extensioncache['civicrm'] = $this->_phpgettext; } } @@ -242,7 +251,7 @@ class CRM_Core_I18n { // gettext domain for extensions $domain_changed = FALSE; - if (isset($params['domain'])) { + if (! empty($params['domain'])) { if ($this->setGettextDomain($params['domain'])) { $domain_changed = TRUE; } @@ -388,13 +397,11 @@ class CRM_Core_I18n { * * @param $key Key of the extension (can be 'civicrm', or 'org.example.foo'). * - * @return void + * @return Boolean True if the domain was changed for an extension. */ function setGettextDomain($key) { - static $cache = array(); - - // It's only necessary to find once - if (! isset($cache[$key])) { + // It's only necessary to find/bind once + if (! isset($this->_extensioncache[$key])) { $config = CRM_Core_Config::singleton(); try { @@ -403,19 +410,38 @@ class CRM_Core_I18n { $info = $mapper->keyToInfo($key); $domain = $info->file; - bindtextdomain($domain, $path . DIRECTORY_SEPARATOR . 'l10n'); - bind_textdomain_codeset($domain, 'UTF-8'); - $cache[$key] = $domain; + if ($this->_nativegettext) { + bindtextdomain($domain, $path . DIRECTORY_SEPARATOR . 'l10n'); + bind_textdomain_codeset($domain, 'UTF-8'); + $this->_extensioncache[$key] = $domain; + } + else { + // phpgettext + $mo_file = $path . DIRECTORY_SEPARATOR . 'l10n' . DIRECTORY_SEPARATOR . $config->lcMessages . DIRECTORY_SEPARATOR . 'LC_MESSAGES' . DIRECTORY_SEPARATOR . $domain . '.mo'; + $streamer = new FileReader($mo_file); + $this->_extensioncache[$key] = new gettext_reader($streamer); + } } catch (CRM_Extension_Exception $e) { - // There's not much we can do at this point - $cache[$key] = FALSE; + // Intentionally not translating this string to avoid possible infinit loops + // Only developers should see this string, if they made a mistake in their ts() usage. + CRM_Core_Session::setStatus('Unknown extension key in a translation string: ' . $key, '', 'error'); + $this->_extensioncache[$key] = FALSE; } } - if (isset($cache[$key]) && $cache[$key]) { - textdomain($cache[$key]); + if (isset($this->_extensioncache[$key]) && $this->_extensioncache[$key]) { + if ($this->_nativegettext) { + textdomain($this->_extensioncache[$key]); + } + else { + $this->_phpgettext = $this->_extensioncache[$key]; + } + + return TRUE; } + + return FALSE; } /** -- 2.25.1