CRM-14769: Extension translation: bugfix and add support for phpgettext.
authorMathieu Lutfy <mathieu@bidon.ca>
Fri, 30 May 2014 19:33:19 +0000 (15:33 -0400)
committerMathieu Lutfy <mathieu@bidon.ca>
Fri, 30 May 2014 19:33:19 +0000 (15:33 -0400)
CRM/Core/I18n.php

index e1ca11a95eaf181baab494921edeba2ec01d79db..f34f5f3dc82ed5ae1af027de838b86b513bdfbe4 100644 (file)
@@ -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;
   }
 
   /**