Seditio Source
Root |
./othercms/b2evolution_7.2.3/inc/locales/_pofile.class.php
<?php
/**
 * This file implements the {@link POFile} and {@link POTFile} classes, used to handle gettext style
 * .PO and .POT files.
 *
 * b2evolution - {@link http://b2evolution.net/}
 * Released under GNU GPL License - {@link http://b2evolution.net/about/gnu-gpl-license}
 * @copyright (c)2003-2020 by Francois Planque - {@link http://fplanque.com/}
 * Parts of this file are copyright (c)2004 by Daniel HAHLER - {@link http://thequod.de/contact}.
 *
 * @package internal
 * @author blueyed: Daniel HAHLER
 */


/**
 * A quick and dirty class for PO/POT files
 *
 * @package internal
 */
class POFile
{
    var
$msgids = array();

    function
__construct( $filename=nulll )
    {
       
// We probably don't need the windows backslashes replacing any more but leave it for safety because it doesn't hurt:
       
$this->filename = str_replace( '\\', '/', $filename );
    }

   
/**
     * Add a MSGID for a specific source file
     */
   
function addmsgid( $msgid, $sourcefile = '', $trans = '' )
    {
        if(
in_array($msgid, array('trans_locale', 'trans_charset', 'trans_available')) )
        {
// don't put those into POT file
           
return;
        }

       
// replace links
       
$msgid = preg_replace('/<a\s+([^>]*)>/', '<a %s>', $msgid);
       
// replace newlines, tabs, carriage returns and double quotes:
       
$msgid = str_replace( array( "\n", "\t", "\r", '"' ),
                              array(
'\n', '\t', '\r', '\"' ), $msgid );

        if( !isset(
$this->msgids[ $msgid ]) )
        {
           
$this->msgids[ $msgid ] = '';
        }
        if( !empty(
$sourcefile) )
        {
           
$this->msgids[ $msgid ]['source'][] = $sourcefile;
        }
       
$this->msgids[ $msgid ]['trans'][] = $trans;
    }

   
/**
     * Translate msgid
     * @param string MSGID
     */
   
function translate( $msgid )
    {
       
$omsgid = $msgid;  // remember

       
if( preg_match_all('/<a\s+([^>]*)>/', $msgid, $matches) )
        {
// we have to replace links
            // remember a-tag params
           
$aparams = $matches[1];

           
// generate clean msgid like in .po files
           
$msgid = preg_replace('/<a\s+([^>]*)>/', '<a %s>', $msgid);
        }
       
// replace newlines, tabs, carriage returns and double quotes:
       
$msgid = str_replace( array( "\n", "\t", "\r", '"' ),
                              array(
'\n', '\t', '\r', '\"' ), $msgid );

        if( isset(
$this->msgids[ $msgid ]) )
        {
           
$trans = $this->msgids[ $msgid ]['trans'];

            if( isset(
$aparams) )
            {
               
$trans = vsprintf($trans, $aparams);
            }

            return
str_replace( array( '\n', '\t', '\r', '\"' ),
                                array(
"\n", "\t", "\r", '"' ), $trans );
        }
        else
        {
           
#pre_dump( $msgid, 'not translated!' );
           
return TRANSTAG_OPEN.$omsgid.TRANSTAG_CLOSE;
        }
    }


   
/**
     * Read a .po file
     *
     * @param boolean Log source info to {@link $Messages}?
     * @return array with msgids => array( 'trans' => msgstr )
     */
   
function read( $log_source_info = true )
    {
       
$lines = file( $this->filename );
       
$lines[] = '';    // Adds a blank line at the end in order to ensure complete handling of the file
       
$all = 0;
       
$fuzzy = 0;
       
$untranslated = 0;
       
$translated = 0;
       
$status = '-';
       
$matches = array();
       
$sources = array();
       
$loc_vars = array();
       
$this->msgids = array();
       
$is_fuzzy = false;
        foreach (
$lines as $line)
        {
           
// echo 'LINE:', $line, '<br />';
           
if(trim($line) == '' )
            {    
// Blank line, go back to base status:
               
if( $status == 't' )
                {    
// ** End of a translation **:
                   
if( $msgstr == '' )
                    {
                       
$untranslated++;
                       
// echo 'untranslated: ', $msgid, '<br />';
                   
}
                    elseif(
$is_fuzzy )
                    {
                       
$fuzzy++;
                       
// echo 'fuzzy: ', $msgid, "<br />\n";
                   
}
                    else
                    {
                       
$translated++;

                       
// Inspect where the string is used
                       
$sources = array_unique( $sources );
                       
// echo '<p>sources: ', implode( ', ', $sources ), '</p>';
                       
foreach( $sources as $source )
                        {
                            if( !isset(
$loc_vars[$source]  ) ) $loc_vars[$source] = 1;
                            else
$loc_vars[$source] ++;
                        }

                       
// Save the string
                       
$this->msgids[$msgid]['trans'] = $msgstr;
                    }
                }
               
$status = '-';
               
$msgid = '';
               
$msgstr = '';
               
$sources = array();
               
$is_fuzzy = false;
            }
            elseif( (
$status=='-') && preg_match( '#^msgid "(.*)"#', $line, $matches))
            {    
// Encountered an original text
               
$status = 'o';
               
$msgid = $matches[1];
               
// echo 'original: "', $msgid, '"<br />';
               
$all++;
            }
            elseif( (
$status=='o') && preg_match( '#^msgstr "(.*)"#', $line, $matches))
            {    
// Encountered a translated text
               
$status = 't';
               
$msgstr = $matches[1];
               
// echo 'translated: "', $msgstr, '"<br />';
           
}
            elseif(
preg_match( '#^"(.*)"#', $line, $matches))
            {    
// Encountered a followup line
               
if ($status=='o')
                   
$msgid .= $matches[1];
                elseif (
$status=='t')
                   
$msgstr .= $matches[1];
            }
            elseif( (
$status=='-') && preg_match( '@^#:(.*)@', $line, $matches))
            {    
// Encountered a source code location comment
                // echo $matches[0],'<br />';
               
$sourcefiles = preg_replace( '@\\\\@', '/', $matches[1] );
               
// $c = preg_match_all( '@ ../../../([^:]*):@', $sourcefiles, $matches);
               
$c = preg_match_all( '@ ../../../([^/:]*/?)@', $sourcefiles, $matches);
                for(
$i = 0; $i < $c; $i++ )
                {
                   
$sources[] = $matches[1][$i];
                }
               
// echo '<br />';
           
}
            elseif(
strpos($line,'#, fuzzy') === 0)
            {
               
$is_fuzzy = true;
            }
        }

        if(
$loc_vars && $log_source_info )
        {
            global
$Messages;
           
ksort( $loc_vars );

           
$list_counts = '';
            foreach(
$loc_vars as $source => $c )
            {
               
$Messages->add_to_group( "<code>${source}</code>: ${c}", 'note', sprintf( TB_('Sources and number of strings (%s):'), '<code>'.basename( $this->filename ).'</code>' ) );
            }
        }

        return
$this->msgids;
    }


   
/**
     * Write POFile::$msgids into $file_path.
     *
     * @return true|string True on success, string with error on failure
     */
   
function write_evo_trans( $file_path, $locale, $params = array() )
    {
       
$fp = fopen( $file_path, 'w+' );

        if( !
$fp )
        {
            return
"Could not open $file_path for writing!";
        }

       
$params = array_merge( array(
               
'title'   => 'Global lang file',
               
'source'  => 'messages.po',
               
'type'    => 'global',
            ),
$params );

       
fwrite( $fp, "<?php\n" );
       
fwrite( $fp, "/*\n" );
       
fwrite( $fp, " * ".$params['title']."\n" );
       
fwrite( $fp, " * This file was generated automatically from ".$params['source']."\n" );
       
fwrite( $fp, " */\n" );
       
fwrite( $fp, "if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );" );
       
fwrite( $fp, "\n\n" );

        if(
$params['type'] == 'global' )
        {
           
fwrite( $fp, '$trans[\''.$locale."'] = array(\n" );
        }
        else
        {
           
fwrite( $fp, '$trans_'.$params['type'].'[\''.$locale."'] = array(\n" );
        }

       
// Write meta/format info:
       
$charset = 'utf-8'; // default
       
if( isset($this->msgids['']) )
        {
            if(
preg_match( '~\\\nContent-Type: text/plain; charset=(.*?);?\\\n~', $this->msgids['']['trans'], $match ) )
            {
               
$charset = strtolower($match[1]);
            }
        }
       
fwrite( $fp, "'__meta__' => array('format_version'=>1, 'charset'=>'$charset'),\n" );

        foreach(
$this->msgids as $msgid => $msginfo )
        {
           
$msgstr = $msginfo['trans'];

           
fwrite( $fp, POFile::quote( $msgid ).' => '.POFile::quote( $msgstr ).",\n" );
        }
       
fwrite( $fp, "\n);\n?>" );
       
fclose( $fp );

        return
true;
    }


   
/**
     * Quote a msgid/msgstr, preferrable with single quotes.
     *
     * Single quotes are preferred, as PHP just handles them as strings and
     * does no extra parsing.
     * Double quotes are used, if there's \n, \r or \t in the string.
     *
     * @param string
     * @return string Quoted string (either using double or single quotes (preferred))
     */
   
function quote($s)
    {
        if(
preg_match('~\\\\[nrt]~', $s) ) // \r, \n or \t in there
       
{
           
// NOTE: no need to escape '"', as its escaped in .po files already
           
return '"'.str_replace( '$', '\$', $s ).'"';
        }
        else
        {
            return
"'".str_replace( array("'", '\"'), array("\'", '"'), $s )."'";
        }
    }

}


/**
 * A class build upon class POFile to provide specific POT actions (write)
 *
 * @package internal
 */
class POTFile extends POFile
{
   
/**
     * @return boolean
     */
   
function write()
    {
        global
$targets, $locales;

       
log_('Writing POTFile '.$this->filename.'..');
       
$fh = @fopen( $this->filename, 'w' );
        if( !
$fh )
        {
           
log_( sprintf('<p class="error">Could not open %s for writing.</p>', $this->filename) );
            return
false;
        }
       
fwrite($fh, '# SOME DESCRIPTIVE TITLE.'."\n"
           
.'# Copyright (C) YEAR Francois PLANQUE'."\n"
           
.'# This file is distributed under the same license as the PACKAGE package.'."\n"
           
.'# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.'."\n"
           
.'#'."\n"
           
.'#, fuzzy'."\n"
           
.'msgid ""'."\n"
           
.'msgstr ""'."\n"
           
.'"Project-Id-Version: PACKAGE VERSION\n"'."\n"
           
.'"Report-Msgid-Bugs-To: http://fplanque.net/\n"'."\n"
           
.'"POT-Creation-Date: 2004-04-26 03:00+0200\n"'."\n"
           
.'"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"'."\n"
           
.'"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"'."\n"
           
.'"Language-Team: LANGUAGE <LL@li.org>\n"'."\n"
           
.'"MIME-Version: 1.0\n"'."\n"
           
.'"Content-Type: text/plain; charset=CHARSET\n"'."\n"
           
.'"Content-Transfer-Encoding: 8bit\n"'."\n"
       
);

       
$count = 0;

        foreach(
$this->msgids as $msgid => $arr )
        {
            if( isset(
$arr['source']) )
            {
// write sources of string
               
foreach( $arr['source'] as $source )
                {
                   
fwrite( $fh, '#: ../../'.$source."\n" );
                }
            }
           
fwrite( $fh, 'msgid "'.$msgid.'"'."\nmsgstr ".'""'."\n\n" );

           
$count++;

        }

       
fclose( $fh );

       
log_($count.' msgids written.');
        return
true;
    }


}

?>