* @package wombat * @subpackage nls */ /** * patI18n Module Wombat * * Translations are stored in table, use Wombat framework for table access * * @version 1.1.0 * @package wombat */ class patI18n_Module_Wombat extends patI18n_Module { /** * corrent language * @var string */ protected $lang = 'C'; /** * table access * @var WBDatasource_Table */ protected $table; /** * cached translation table * @var array */ static $cache = array(); /** * current config * * Options: * - "clang" language representing C (usually en_GB, sometimes en_US) * - "domain" sets the default text domain - if any * - "domains" allows to use additional text domains * - "fuzzy": "hide" (default) or "show" outdated translations * * @var array */ protected $conf = array( 'clang' => 'en_GB', 'domain' => null, 'domains' => array(), 'fuzzy' => 'hide' ); /** * Switch to language * * @param string $string * @return booll true on success */ public function setLocale(&$locale) { // check text domains if (!$this->conf['domain']) { WBClass::load('WBException_Argument'); throw new WBException_Argument('Default domain is required, set config parameter "domain"', 1, __CLASS__); } // allow just five letter language codes 'de_DE' or 'en_GB' if (5 != strlen($locale)) { WBClass::load('WBException_Argument'); throw new WBException_Argument('Locale must be five letter code like "en_GB" or "de_DE".', 2, __CLASS__); } // clear cache self::$cache = array(); $this->lang = $locale; return true; } /** * get acutal text domain string * * validate selected domain string against available text domains * * @param string $domain * @return string */ protected function resolveDomain($domain = null) { if (!$domain || $domain == $this->conf['domain']) { return $this->conf['domain']; } if (!in_array($domain, $this->conf['domains'])) { WBClass::load('WBException_Argument'); throw new WBException_Argument('Invalid text domain "'. $domain .'" selected', 2, __CLASS__); } return $domain; } /** * Gettext interface * * @param string $string * @param string $domain * @return bool false to continue, true if translation is done */ public function gettext(&$string, $domain = null) { $string = trim($string); if (empty($string)) { return true; } $domain = $this->resolveDomain($domain); if (!isset(self::$cache[$domain])) { $this->load($domain); } $md5 = md5($string); if (!isset(self::$cache[$domain][$md5])) { return false; } // find actual translation if (!empty(self::$cache[$domain][$md5]['trans_' . $this->lang])) { $string = self::$cache[$domain][$md5]['trans_' . $this->lang]; return true; } // in case there is no translation, the origin text may have changed. $string = self::$cache[$domain][$md5]['msg']; return false; } /** * load messages and translations from database * * Load all strings from text domain.and store them in cache * * @param string $domain */ private function load($domain) { WBClass::load('WBCache'); $cacheId = __CLASS__ . ':' . $domain . ':' . $this->lang; self::$cache[$domain] = WBCache::get($cacheId); if (!empty(self::$cache[$domain])) { return; } self::$cache[$domain] = array(); $this->initTable(); $clause = array(); $clause[] = array( 'field' => 'domain', 'value' => $domain ); $options = array( 'column' => array( $this->table->getIdentifier('nlsmsg'), 'md5', 'msg', 'msg_org' ) ); // translation column if ('C' != $this->lang && $this->conf['clang'] != $this->lang) { // show or hide outdated translations if ('show' != $this->conf['fuzzy']) { $c = array(); $c[] = array( 'field' => 'changed_' . $this->lang, 'valuetype' => 'foreign', 'foreign' => 'nlsmsg', 'value' => 'changed', 'relation' => 'ge' ); $c[] = array( 'field' => 'changed_' . $this->lang, 'value' => '0000-00-00 00:00:00' ); $clause[] = array( 'type' => 'complex', 'bond' => 'or', 'clause' => $c ); } $options['column'][] = 'trans_' . $this->lang; } $list = $this->table->get('nlsmsg', null, null, $clause, $options); foreach ($list as $l) { self::$cache[$domain][$l['md5']] = $l; } WBCache::set($cacheId, self::$cache[$domain], array('ttl' => 300)); } /** * Gettext interface for plural versions * * @todo implement this * @param string $string * @param string $stringPlural * @param int $count * @param string $domain * @return bool false to continue, true if translation is done */ public function ngettext(&$string, $stringPlural, $count, $domain = null) { // shortcut to avoid useless database queries if ($count <= 1) { return $this->gettext($string, $domain); } $domain = $this->resolveDomain($domain); return false; } /** * Initialize table access * */ protected function initTable() { if ($this->table) { return; } // Start table access, translation does not make any sense here, because we are translation! :-) $this->table = WBClass::create('WBDatasource_Table'); $this->table->switchTranslation(false); $this->table->switchEventTrigger(false); } }