/** * translateString - a gettextWrapper * * tries to do gettext or falls back on File_Gettext * This has !!!NO!!! error handling - if it fails you just get english.. * no questions asked!!! * * @param string string to translate * * @return string translated string.. * @access public */ function translateString($string) { if ($this->options['Translation2'] instanceof Translation2) { $result = $this->options['Translation2']->get($string); if (!empty($result)) { return $result; } return $string; } // note this stuff may have been broken by removing the \n replacement code // since i dont have a test for it... it may remain broken.. // use Translation2 - it has gettext backend support // and should sort out the mess that \n etc. entail. $prefix = basename($GLOBALS['_FLY_FLEXY']['filename']) . ':'; if (@$this->options['debug']) { echo __CLASS__ . ":TRANSLATING {$string}<BR>\n"; } if (function_exists('gettext') && !$this->options['textdomain']) { if (@$this->options['debug']) { echo __CLASS__ . ":USING GETTEXT?<BR>"; } $t = gettext($string); if ($t != $string) { return $t; } $tt = gettext($prefix . $string); if ($tt != $prefix . $string) { return $tt; } // give up it's not translated anywhere... return $string; } if (!$this->options['textdomain'] || !$this->options['textdomainDir']) { // text domain is not set.. if (@$this->options['debug']) { echo __CLASS__ . ":MISSING textdomain settings<BR>"; } return $string; } $pofile = $this->options['textdomainDir'] . '/' . $this->options['locale'] . '/LC_MESSAGES/' . $this->options['textdomain'] . '.po'; // did we try to load it already.. if (@$GLOBALS['_' . __CLASS__]['PO'][$pofile] === false) { if (@$this->options['debug']) { echo __CLASS__ . ":LOAD failed (Cached):<BR>"; } return $string; } if (!@$GLOBALS['_' . __CLASS__]['PO'][$pofile]) { // default - cant load it.. $GLOBALS['_' . __CLASS__]['PO'][$pofile] = false; if (!file_exists($pofile)) { if (@$this->options['debug']) { echo __CLASS__ . ":LOAD failed: {$pofile}<BR>"; } return $string; } if (!@(include_once 'File/Gettext.php')) { if (@$this->options['debug']) { echo __CLASS__ . ":LOAD no File_gettext:<BR>"; } return $string; } $GLOBALS['_' . __CLASS__]['PO'][$pofile] = File_Gettext::factory('PO', $pofile); $GLOBALS['_' . __CLASS__]['PO'][$pofile]->load(); //echo '<PRE>'.htmlspecialchars(print_r($GLOBALS['_'.__CLASS__]['PO'][$pofile]->strings,true)); } $po =& $GLOBALS['_' . __CLASS__]['PO'][$pofile]; // we should have it loaded now... // this is odd - data is a bit messed up with CR's $string = str_replace('\\n', "\n", $string); if (isset($po->strings[$prefix . $string])) { return $po->strings[$prefix . $string]; } if (!isset($po->strings[$string])) { if (@$this->options['debug']) { echo __CLASS__ . ":no match:<BR>"; } return $string; } if (@$this->options['debug']) { echo __CLASS__ . ":MATCHED: {$po->strings[$string]}<BR>"; } // finally we have a match!!! return $po->strings[$string]; }
/** * Save MO file * * @param string $file File path to write to * * @access public * @return mixed Returns true on success or PEAR_Error on failure. */ function save($file = null) { if (!isset($file)) { $file = $this->file; } $tmpfile = $file . "." . getmypid(); // open MO file if (!is_resource($this->_handle = @fopen($tmpfile, 'wb'))) { return parent::raiseError($php_errormsg . ' ' . $file); } // lock MO file exclusively if (!@flock($this->_handle, LOCK_EX)) { @fclose($this->_handle); return parent::raiseError($php_errormsg . ' ' . $file); } // write magic number if ($this->writeBigEndian) { $this->_write(pack('c*', 0x95, 0x4, 0x12, 0xde)); } else { $this->_write(pack('c*', 0xde, 0x12, 0x4, 0x95)); } // write file format revision $this->_writeInt(0); $count = count($this->strings) + ($meta = count($this->meta) ? 1 : 0); // write count of strings $this->_writeInt($count); $hash_tab_size = self::_nextPrime($count * 4 / 3); /* Ensure M > 2. */ if ($hash_tab_size <= 2) { $hash_tab_size = 3; } $offset = 28; // write offset of orig. strings hash table $this->_writeInt($offset); $offset += $count * 8; // write offset transl. strings hash table $this->_writeInt($offset); // write size of hash table (we currently ommit the hash table) $this->_writeInt($hash_tab_size); // orig: 0 $offset += $count * 8; // write offset of hash table $this->_writeInt($offset); $offset += $hash_tab_size * 4; // unshift meta info if ($meta) { $meta = ''; foreach ($this->meta as $key => $val) { $meta .= $key . ': ' . $val . "\n"; } $strings = array('' => $meta) + $this->strings; } else { $strings = $this->strings; } $hash_tab = array(); $j = 0; foreach ($strings as $key => $value) { $hash_val = self::_hashpjw($key); $idx = $hash_val % $hash_tab_size; if (!empty($hash_tab[$idx])) { $incr = 1 + $hash_val % ($hash_tab_size - 2); do { if ($idx >= $hash_tab_size - $incr) { $idx -= $hash_tab_size - $incr; } else { $idx += $incr; } } while (!empty($hash_tab[$idx])); } $hash_tab[$idx] = $j + 1; $j++; } // write offsets for original strings foreach (array_keys($strings) as $o) { $len = strlen($o); $this->_writeInt($len); $this->_writeInt($offset); $offset += $len + 1; } // write offsets for translated strings foreach ($strings as $t) { $len = strlen($t); $this->_writeInt($len); $this->_writeInt($offset); $offset += $len + 1; } for ($j = 0; $j < $hash_tab_size; $j++) { if (empty($hash_tab[$j])) { $this->_writeInt(0); } else { $this->_writeInt($hash_tab[$j]); } } // write original strings foreach (array_keys($strings) as $o) { $this->_writeStr($o); } // write translated strings foreach ($strings as $t) { $this->_writeStr($t); } // done @flock($this->_handle, LOCK_UN); @fclose($this->_handle); @rename($tmpfile, $file); @unlink($tmpfile); return true; }
/** * Save MO file * * @access public * @return mixed Returns true on success or PEAR_Error on failure. * @param string $file */ function save($file = null) { if (!isset($file)) { $file = $this->file; } // open MO file if (!is_resource($this->_handle = @fopen($file, 'wb'))) { return parent::raiseError($php_errormsg . ' ' . $file); } // lock MO file exclusively if (!@flock($this->_handle, LOCK_EX)) { @fclose($this->_handle); return parent::raiseError($php_errormsg . ' ' . $file); } // write magic number if ($this->writeBigEndian) { $this->_write(pack('c*', 0x95, 0x4, 0x12, 0xde)); } else { $this->_write(pack('c*', 0xde, 0x12, 0x4, 0x95)); } // write file format revision $this->_writeInt(0); $count = count($this->strings) + ($meta = count($this->meta) ? 1 : 0); // write count of strings $this->_writeInt($count); $offset = 28; // write offset of orig. strings hash table $this->_writeInt($offset); $offset += $count * 8; // write offset transl. strings hash table $this->_writeInt($offset); // write size of hash table (we currently ommit the hash table) $this->_writeInt(0); $offset += $count * 8; // write offset of hash table $this->_writeInt($offset); // unshift meta info if ($meta) { $meta = ''; foreach ($this->meta as $key => $val) { $meta .= $key . ': ' . $val . "\n"; } $strings = array('' => $meta) + $this->strings; } else { $strings = $this->strings; } // write offsets for original strings foreach (array_keys($strings) as $o) { $len = strlen($o); $this->_writeInt($len); $this->_writeInt($offset); $offset += $len + 1; } // write offsets for translated strings foreach ($strings as $t) { $len = strlen($t); $this->_writeInt($len); $this->_writeInt($offset); $offset += $len + 1; } // write original strings foreach (array_keys($strings) as $o) { $this->_writeStr($o); } // write translated strings foreach ($strings as $t) { $this->_writeStr($t); } // done @flock($this->_handle, LOCK_UN); @fclose($this->_handle); return true; }
/** * Save PO file * * @access public * @return mixed Returns true on success or PEAR_Error on failure. * @param string $file */ function save($file = null) { if (!isset($file)) { $file = $this->file; } // open PO file if (!is_resource($fh = @fopen($file, 'w'))) { return parent::raiseError($php_errormsg . ' ' . $file); } // lock PO file exclusively if (!@flock($fh, LOCK_EX)) { @fclose($fh); return parent::raiseError($php_errormsg . ' ' . $file); } // write meta info if (count($this->meta)) { $meta = 'msgid ""' . "\nmsgstr " . '""' . "\n"; foreach ($this->meta as $k => $v) { $meta .= '"' . $k . ': ' . $v . '\\n"' . "\n"; } fwrite($fh, $meta . "\n"); } // write strings foreach ($this->strings as $o => $t) { fwrite($fh, 'msgid "' . parent::prepare($o, true) . '"' . "\n" . 'msgstr "' . parent::prepare($t, true) . '"' . "\n\n"); } //done @flock($fh, LOCK_UN); @fclose($fh); return true; }
/** * poFile2moFile * * That's a simple fake of the 'msgfmt' console command. It reads the * contents of a GNU PO file and saves them to a GNU MO file. * * @param string $pofile path to GNU PO file * @param string $mofile path to GNU MO file * * @static * @access public * @return mixed Returns true on success or PEAR_Error on failure. */ function poFile2moFile($pofile, $mofile) { if (!is_file($pofile)) { return File_Gettext::raiseError("File {$pofile} doesn't exist."); } include_once 'File/Gettext/PO.php'; $PO = new File_Gettext_PO($pofile); if (true !== ($e = $PO->load())) { return $e; } $MO =& $PO->toMO(); if (true !== ($e = $MO->save($mofile))) { return $e; } unset($PO, $MO); return true; }
/** * Get all the strings from a domain (parsing the .mo file) * * @param string $pageID page/group ID * @param string $langID language ID * * @return array|PEAR_Error */ function getPage($pageID = null, $langID = null) { $oldLang = $this->_switchLang($langID); $curLang = $this->currentLang['id']; if (empty($pageID) || $pageID == TRANSLATION2_DEFAULT_PAGEID) { $pageID = $this->options['default_domain']; } if (isset($this->cachedDomains[$curLang][$pageID])) { $this->_switchLang($oldLang); return $this->cachedDomains[$curLang][$pageID]; } if (!isset($this->_domains[$pageID])) { $this->_switchLang($oldLang); return $this->raiseError(sprintf('The domain "%s" was not specified in the domains INI ' . 'file "%s" [%s on line %d]', $pageID, $this->options['domains_path_file'], __FILE__, __LINE__), TRANSLATION2_ERROR_DOMAIN_NOT_SET); } include_once 'File/Gettext.php'; $gtFile =& File_Gettext::factory($this->options['file_type']); $path = $this->_domains[$pageID] . '/' . $curLang . '/LC_MESSAGES/'; $file = $path . $pageID . '.' . $this->options['file_type']; if (PEAR::isError($e = $gtFile->load($file))) { if (is_file($file)) { $this->_switchLang($oldLang); return $this->raiseError(sprintf('%s [%s on line %d]', $e->getMessage(), __FILE__, __LINE__), TRANSLATION2_ERROR, PEAR_ERROR_RETURN); } $this->_switchLang($oldLang); return $this->raiseError(sprintf('Cannot find file "%s" [%s on line %d]', $file, __FILE__, __LINE__), TRANSLATION2_ERROR_CANNOT_FIND_FILE, PEAR_ERROR_RETURN); } $this->cachedDomains[$curLang][$pageID] = $gtFile->strings; $this->_switchLang($oldLang); return $gtFile->strings; }
/** * Remove * * @param array &$bulk array('pageID' => array([languages])) * * @return true|PEAR_Error on failure. * @access private */ function _remove(&$bulk) { include_once 'File/Gettext.php'; $gtFile =& File_Gettext::factory($this->options['file_type']); foreach ($this->getLangs('ids') as $lang) { foreach ((array) $bulk as $pageID => $stringIDs) { $file = sprintf('%s/%s/LC_MESSAGES/%s.%s', $this->_domains[$pageID], $lang, $pageID, $this->options['file_type']); if (is_file($file)) { if (PEAR::isError($e = $gtFile->load($file))) { return $e; } foreach (array_keys($stringIDs) as $stringID) { unset($gtFile->strings[$stringID]); } if (PEAR::isError($e = $gtFile->save($file))) { return $e; } //refresh cache $this->cachedDomains[$lang][$pageID] = $gtFile->strings; } } } $bulk = null; return true; }
if (!file_exists($argv[2]) or !is_readable($argv[2])) { echo ".POT or .PO File: " . $argv[2] . " does not exists or is not readable!\n"; } else { $source_file = $argv[2]; } if ($create_source == TRUE) { $outfile = $argv[3]; $infile = NULL; } else { $infile = $argv[3]; $outfile = $argv[4]; } echo "In File: {$infile}\n"; echo "Out File: {$outfile}\n"; //Use Pears FILE_GetText package $gtFile = File_Gettext::factory('PO'); $gtFile->load($source_file); if ($create_source == TRUE) { $batch_size = 1000; $batch = 0; $prev_batch = 0; $i = 0; $out = NULL; $max = count($gtFile->strings) - 1; echo "Max: {$max}\n"; foreach ($gtFile->strings as $msgid => $msgstr) { //echo "$i. $msgid\n"; if ($i == 0 or $out == NULL) { echo "I = 0 OR Batch = 0\n"; $out = "<html>\n"; $out .= "<body><pre>\n";
/** * Returns the translation for the given message, * as contained in some translation catalog (MO file). * * \param string $file * Path to the translation catalog to use. * * \param string $message * The message to translate. * * \param string $mode * Either "MO" or "PO", indicating whether * the given file refers to a MO or PO catalog. * * \retval string * The translation matching the given message. * * \retval null * The message could not be found in the translation * catalog. * * \note * This method implements a caching strategy * so that the translation catalog is not read * again every time this method is called * but only when the catalog actually changed. */ protected function getTranslation($component, $message) { $time = time(); $locale = $this->locales[self::LC_MESSAGES]; if (!isset(self::$cache[$component][$locale]) || $time > self::$cache[$component][$locale]['added'] + self::EXPIRE_CACHE) { if (isset(self::$cache[$component][$locale]['file'])) { $file = self::$cache[$component][$locale]['file']; } else { try { $file = $this->getBaseDir($component); } catch (Exception $e) { return null; } $catalog = str_replace('\\', '_', ltrim($component, '\\')); $file .= DIRECTORY_SEPARATOR . $locale . DIRECTORY_SEPARATOR . 'LC_MESSAGES' . DIRECTORY_SEPARATOR . $catalog . '.mo'; if (!file_exists($file)) { $file = substr($file, 0, -3) . '.po'; } if (!file_exists($file)) { return null; } } /** * FIXME: filemtime() raises a warning if the given file * could not be stat'd (such as when is does not exist). * An error_reporting level of E_ALL & ~E_DEPRECATED * would otherwise be fine for File_Gettext. */ $oldErrorReporting = error_reporting(E_ERROR); if (version_compare(PHP_VERSION, '5.3.0', '>=')) { clearstatcache(false, $file); } else { clearstatcache(); } $mtime = false; if ($file !== false) { $mtime = filemtime($file); } if ($mtime === false) { // We also cache failures to avoid // harassing the CPU too much. self::$cache[$component][$locale] = array('mtime' => $time, 'string' => array(), 'added' => $time, 'file' => false); } elseif (!isset(self::$cache[$component][$locale]) || $mtime !== self::$cache[$component][$locale]['mtime']) { $parser = \File_Gettext::factory(substr($file, -2), $file); $parser->load(); self::$cache[$component][$locale] = array('mtime' => $mtime, 'strings' => $parser->strings, 'added' => $time, 'file' => $file); } error_reporting($oldErrorReporting); } if (isset(self::$cache[$component][$locale]['strings'][$message])) { return self::$cache[$component][$locale]['strings'][$message]; } return null; }
function _getStrings($_format) { $oCache = KTCache::getSingleton(); list($bCached, $stuff) = $oCache->get("i18nstrings", $this->sFilename); if (empty($bCached)) { require_once 'File/Gettext.php'; $this->oLang = File_Gettext::factory($_format, $this->sFilename); $bLoaded = $this->oLang->load(); $stuff = $this->oLang->toArray(); $oCache->set("i18nstrings", $this->sFilename, $stuff); } $this->aMeta = $stuff['meta']; $this->aStrings = $stuff['strings']; }
<?php require_once "../../config/dmsDefaults.php"; require_once 'File/Gettext.php'; $aExpected = array('© 2009 <a href="http://www.knowledgetree.com/">KnowledgeTree Inc.</a>' => '© 2009 <a href="http://www.knowledgetree.com/">KnowledgeTree Inc.</a> Todos los Derechos Reservados - <a href="http://www.oriondatacenter.com/">Orion Datacenter.</a> Bussines Partner para Colombia', 'Document "%s" renamed.' => 'El documento "%s" ha sido renombrado.', 'Document archived: %s' => 'Documento archivados: %s', 'Document checked in' => 'Documento liberado'); $sFilename = "test2.po"; $foo = File_Gettext::factory('po', $sFilename); $res = $foo->load(); var_dump("t"); foreach ($aExpected as $sSrc => $sExpected) { $sGot = $foo->strings[$sSrc]; if ($sGot != $sExpected) { print "Expected {$sExpected}, but got {$sGot}\n"; } }