[geeklog-cvs] geeklog-2/lib/Translations getstrings,NONE,1.1 mergeversions,NONE,1.1 StringExtractor.class.php,NONE,1.1 Translator.class.php,NONE,1.1
geeklog-cvs-admin at lists.geeklog.net
geeklog-cvs-admin at lists.geeklog.net
Fri Apr 18 16:13:11 EDT 2003
Update of /usr/cvs/geeklog/geeklog-2/lib/Translations
In directory internal.geeklog.net:/tmp/cvs-serv14419
Added Files:
getstrings mergeversions StringExtractor.class.php
Translator.class.php
Log Message:
Initial import of translation library
--- NEW FILE: getstrings ---
#!/usr/local/bin/php -q
<?php
/**
* Translations Library - getstrings
*
* This source file is subject to version 2.02 of the PHP license,
* that is bundled with this package in the file LICENSE, and is
* available at through the world-wide-web at
* http://www.php.net/license/2_02.txt.
* If you did not receive a copy of the PHP license and are unable to
* obtain it through the world-wide-web, please send a note to
* license at php.net so we can mail you a copy immediately.
*
* Here's an example of how to use this command:
* ./getstrings --lang=en --source=./tmp/ --target=./output/
* --appname=Geeklog --appversion=2.0 --author="Tony Bibbs"
* --email=tony at geeklog.net
*
* @author Tony Bibbs <tony AT geeklog DOT net>
* @copyright Tony Bibbs 2003
* @package net.geeklog.translations
* @version $Id: getstrings,v 1.1 2003/04/18 20:13:09 tony Exp $
*
*/
require_once 'StringExtractor.class.php';
$argArray = array();
foreach ($argv as $curArg) {
$tmpArray = array();
if (strstr($curArg,'=')) {
$tmpArray = explode('=', $curArg);
$argArray[strtolower($tmpArray[0])] = $tmpArray[1];
}
}
if (empty($argArray['--lang'])) {
$argArray['--lang'] == 'en';
}
$extractor = new StringExtractor($argArray['--lang']);
$extractor->getStrings($argArray);
?>
--- NEW FILE: mergeversions ---
#!/usr/local/bin/php -q
<?php
/**
* Translations Library - VersionMerge.class.php
*
* This source file is subject to version 2.02 of the PHP license,
* that is bundled with this package in the file LICENSE, and is
* available at through the world-wide-web at
* http://www.php.net/license/2_02.txt.
* If you did not receive a copy of the PHP license and are unable to
* obtain it through the world-wide-web, please send a note to
* license at php.net so we can mail you a copy immediately.
*
* @author Tony Bibbs <tony AT geeklog DOT net>
* @copyright Tony Bibbs 2003
* @package net.geeklog.translations
* @version $Id: mergeversions,v 1.1 2003/04/18 20:13:09 tony Exp $
*
*/
/**
* Take an outdated XML translation file and merges strings into
* the new, untranslated XML file.
*
* This class makes updating a language file for an application from
* one version to the next easy by taking the old values and merging them
* into the new, untranslated XML file. From there the translator only
* needs to edit the resulting XML file and add the new strings.
*
* @author Tony Bibbs <tony AT geeklog DOT net>
* @package net.geeklog.translations
*
*/
class VersionMerge {
/**
* @access private
* @var string
*/
var $_oldFile = null;
/**
* @access private
* @var string
*/
var $_newFile = null;
/**
* @access private
* @var string
*/
var $_outputFile = null;
/**
* @access private
* @var object
*/
var $_outputFp = null;
/**
* @access private
* @var array
*/
var $_oldStrings = null;
/**
* @access private
* @var array
*/
var $_newStrings = null;
/**
* @access private
* @var boolean
*/
var $_isOld = null;
/**
* @access private
* @var string
*/
var $_curElement = null;
/**
* @access private
* @var string
*/
var $_curId = null;
/**
* @access private
* @var array
*/
var $_appName = null;
/**
* @access private
* @var array
*/
var $_appVersion = null;
/**
* @access private
* @var array
*/
var $_authorName = null;
/**
* @access private
* @var array
*/
var $_authorEmail = null;
/**
* @access private
* @var array
*/
var $_nativeLang = null;
/**
* Constructor
*
* Initializes some class properties
*
* @author Tony Bibbs <tony at geeklog.net>
* @access public
*
*/
function VersionMerge()
{
$this->_oldStrings = array();
$this->_newStrings = array();
}
/**
* Creates the header entries for XML file
*
* @author Tony Bibbs <tony at geeklog.net>
* @access private
*
*/
function _addXMLHeaders()
{
fwrite($this->_outputFp,
sprintf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<APPLICATION name=\"%s\" version=\"%s\">\n <TRANSLATOR name=\"%s\" email=\"%s\" />\n <TRANSLATION language=\"%s\">\n",
$this->_appName,
$this->_appVersion,
$this->_authorName,
$this->_authorEmail,
$this->_nativeLang));
}
/**
* Adds XML footer entries to XML file
*
* @author Tony Bibbs <tony at geeklog.net>
*
*/
function _addXMLFooters()
{
fwrite($this->_outputFp," </TRANSLATION>\n</APPLICATION>");
fclose($this->_outputFp);
}
/**
* Writes a set of strings to an XML file
*
* @author Tony Bibbs <tony at geeklog.net>
* @access private
* @param string $strId ID of string to add
* @param string $translation Translated string
*
*/
function _addString($strId, $translation)
{
$translation = htmlspecialchars($translation, ENT_NOQUOTES);
fwrite($this->_outputFp,
sprintf(" <ENTRY>\n <STRING_ID>%s</STRING_ID>\n <STRING>%s</STRING>\n </ENTRY>\n",
$strId, $translation));
}
/**
* Prints help text for commandline interface
*
* @author Tony Bibbs <tony at geeklog.net>
* @access private
*
*/
function _getHelp()
{
echo "\n--old Name of your existing translated XML file\n\n";
echo "--new Name of the new, untranslated XML file\n\n";
echo "--target Fully qualified name for resulting XML file\n\n";
}
/**
* Handler that is called when a beginning XML tag is
* encountered
*
* Caches the element so when we get to the data handler we
* know if we should ignore the data or not.
*
* @author Tony Bibbs <tony at geeklog.net>
* @access private
* @param object $parser Expat parser object
* @param string $name Name of XML element encountered
* @param array $attributes XML attributes for current element
*
*/
function _handleStartElement($parser, $name, $attributes)
{
$this->_curElement = $name;
if ($name == 'APPLICATION') {
if (!$this->_isOld) {
$this->_appName = $attributes['NAME'];
$this->_appVersion = $attributes['VERSION'];
}
}
if ($name == 'TRANSLATOR' AND $this->_isOld) {
$this->_authorName = $attributes['NAME'];
$this->_authorEmail = $attributes['EMAIL'];
}
if ($name == 'TRANSLATION' and $this->_isOld) {
$this->_nativeLang = $attributes['LANGUAGE'];
}
}
/**
* Handler that is called when an end XML tag is
* encountered
*
* This will clear out the current element being worked
* on as well as the current string ID
*
* @author Tony Bibbs <tony at geeklog.net>
* @access private
*
*/
function _handleEndElement()
{
$this->_curElement = '';
}
/**
* Handles data found while parsing XML
*
* @author Tony Bibbs <tony at geeklog.net>
* @access private
* @param object $parser Expat parser
* @param string $data Data that was encountered
*
*/
function _handleData($parser, $data)
{
if (empty($this->_curElement)) {
return;
}
switch ($this->_curElement) {
case 'STRING_ID':
if (!$this->_isOld) {
$this->_newStrings[$data] = '';
} else {
$this->_curId = $data;
}
break;
case 'STRING':
if ($this->_isOld) {
print "Found string: $data\n";
$this->_oldStrings[$this->_curId] = $data;
}
break;
default:
continue;
}
}
/**
* Replaces special characters: '&', '<', '>' because
* Expat parser interprets them (unfortunately).
*
* Replaces special characters with a token so the Expat parser can
* process normally. Don't worry, we replace the tokens for you
* when we go to write the new file
*
* @author Tony Bibbs <tony at geeklog.net>
* @access private
* @param string $inputString String to operate on
* @return string Modified string
*
*/
function _replaceSpecialChars($inputString)
{
$inputString = str_replace('&','**_amp_**', $inputString);
$inputString = str_replace('<','**_lt_**', $inputString);
$inputString = str_replace('>','**_gt_**', $inputString);
return $inputString;
}
/**
* This undoes anything that _replaceSpecialChars may have done
*
* Replaces special tokens with their HTML special characters so that
* we can write the data to the output file
*
* @author Tony Bibbs <tony at geeklog.net>
* @access private
* @param string $inputString String to operate on
* @return string Modified string
*
*/
function _reinsertSpecialChars($inputString)
{
$inputString = str_replace('**_amp_**', '&', $inputString);
$inputString = str_replace('**_lt_**', '<', $inputString);
$inputString = str_replace('**_gt_**', '>', $inputString);
return $inputString;
}
/**
* Loads the strings for a given language code into memory
*
* @author Tony Bibbs <tony AT geeklog DOT net>
* @access private
* @param string $filename Name of file to get strings from
* @param boolean $isOld Indicator that lets us know which array to put strings in
*
*/
function _loadStrings($filename, $isOld)
{
$this->_isOld = $isOld;
if ($this->_isOld) {
print "\nProcesing old file: $filename\n\n";
} else {
print "\nProcessing new file: $filename\n\n";
}
$this->_strings = array();
// Make sure we have a valid translation file
if (!file_exists($filename)) {
trigger_error("Bad translation file, $filename, in Translator::_loadStrings");
exit;
}
// Load the XML
$xmlData = file_get_contents($filename);
// The Expat XML parser does not handle special characters the way they
// should so we need to replace them with a token until we are done processing
// and them jam them back in.
$xmlData = $this->_replaceSpecialChars($xmlData);
// Create Expat parser object
$this->_parser = xml_parser_create();
// Lets expat know this class will handle the parsing
xml_set_object($this->_parser, &$this);
xml_set_element_handler($this->_parser, '_handleStartElement', '_handleEndElement');
xml_set_character_data_handler($this->_parser, '_handleData');
// Actually parse the XML now.
if (!xml_parse($this->_parser, $xmlData)) {
trigger_error(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($this->_parser)),
xml_get_current_line_number($this->_parser)));
exit;
}
xml_parser_free($this->_parser);
return true;
}
/**
* When called from the command line this function will
* take any arguments passed to the getstrings shell script
* and set up this object for processing
*
* @author Tony Bibbs <tony at geeklog.net>
* @access private
* @param array $args Argument passed to getstring commandline
*
*/
function _handleCommandLineArgs($args)
{
$validOptions = array('--old'=>1,'--new'=>1,'--target'=>1);
$optionNames = array_keys($validOptions);
// If they asked for help, give it now and ignore
// all other arguments
if (in_array('--help',array_keys($args))) {
$this->_getHelp();
exit;
}
// Make sure we have a set of valid arguments
foreach ($args as $curArg) {
if (!in_array(key($args),$optionNames)) {
echo "Invalid argument: $curArg\n";
$this->_getHelp();
exit;
}
}
// Make sure all required arguments were provided.
foreach ($optionNames as $curName) {
if ($validOptions[$curName] == 1 AND empty($args[$curName])) {
echo "Missing required argument: $curName\n";
$this->_getHelp();
exit;
}
}
reset($args);
foreach ($args as $curArg) {
switch (key($args)) {
case '--old':
$this->_loadStrings($curArg, true);
break;
case '--new':
$this->_loadStrings($curArg, false);
break;
case '--target':
$this->_outputFile = $curArg;
$this->_outputFp = fopen($this->_outputFile,'w');
break;
default:
continue;
}
next($args);
}
return;
}
/**
* Merges entries from old translation into a new
* translation file
*
* @author Tony Bibbs <tony at geeklog.net>
* @access public
*
*/
function mergeVersions($args)
{
// Validate arguments and load set-up data
$this->_handleCommandLineArgs($args);
$this->_addXMLHeaders();
$idArray = array_keys($this->_newStrings);
foreach ($idArray as $curId) {
print "Processing ID: $curId\n";
// NOTE: the call to _reinsertSpecialChars is to replace tokens we added in order to
// allow Expat parser to handle HTML special chars properly
if (!empty($this->_oldStrings[$curId])) {
$this->_addString($this->_reinsertSpecialChars($curId), $this->_oldStrings[$curId]);
} else {
$tmpString = $this->_reinsertSpecialChars($curId);
print "Found new string: $tmpString\n";
$this->_addString($this->_reinsertSpecialChars($curId), '');
}
next($this->_newStrings);
}
$this->_addXMLFooters();
}
}
// To avoid having to send translators multiple files we include the main command line code
// here instead of doing a require_once in a separate file.
$argArray = array();
// Parse arguments
foreach ($argv as $curArg) {
$tmpArray = array();
if (strstr($curArg,'=')) {
$tmpArray = explode('=', $curArg);
$argArray[strtolower($tmpArray[0])] = $tmpArray[1];
}
}
// Perform the merge
$versionMerge = new VersionMerge();
$versionMerge->mergeVersions($argArray);
?>
--- NEW FILE: StringExtractor.class.php ---
<?php
/**
* Translations Library - StringExtractor.class.php
*
* This source file is subject to version 2.02 of the PHP license,
* that is bundled with this package in the file LICENSE, and is
* available at through the world-wide-web at
* http://www.php.net/license/2_02.txt.
* If you did not receive a copy of the PHP license and are unable to
* obtain it through the world-wide-web, please send a note to
* license at php.net so we can mail you a copy immediately.
*
* @author Tony Bibbs <tony AT geeklog DOT net>
* @copyright Tony Bibbs 2003
* @package net.geeklog.translations
* @version $Id: StringExtractor.class.php,v 1.1 2003/04/18 20:13:09 tony Exp $
*
*/
/**
* Extracts native language strings from code files
*
* The string extractor is very similar to xgettext in that it will
* recursively parse the code files in a given directory, get the native
* string from all calls to the translate() method and output an XML file
* that can be distributed to translators. Simply put all strings needing
* to be translated are extracted from the PHP code itself and inserted
* into an XML file. The XML file is what project administrators would
* send to their translators. To help incremental updates, the commandline
* program mergeversions will assist translators by taking all previously
* translated text in their old XML file and adding it to a copy of the new
* file leaving only the new entries empty.
*
* @author Tony Bibbs <tony AT geeklog DOT net>
* @package net.geeklog.translations
*
*/
class StringExtractor {
/**
* @access private
* @var string
*/
var $_nativeLang = null;
/**
* @access private
* @var string
*/
var $_codeDir = null;
/**
* @access private
* @var array
*/
var $_validExtensions = null;
/**
* @access private
* @var array
*/
var $_outputDir = null;
/**
* @access private
* @var array
*/
var $_codeDirs = null;
/**
* @access private
* @var array
*/
var $_outputFp = null;
/**
* @access private
* @var array
*/
var $_appName = null;
/**
* @access private
* @var array
*/
var $_appVersion = null;
/**
* @access private
* @var array
*/
var $_authorName = null;
/**
* @access private
* @var array
*/
var $_authorEmail = null;
/**
* @access private
* @var array
*/
var $_commandLineMode = null;
/**
* Constructor
*
* Initializes a few private variables
*
* @author Tony Bibbs <tony AT geeklog DOT net>
* @param string $nativeLang Native language used in code files
*
*/
function StringExtractor($nativeLang)
{
$this->_validExtensions = Array();
$this->_codeDirs = Array();
$this->_nativeLang = $nativeLang;
$this->_commandLineMode = false;
}
/**
* Gets all the directories that need to be traversed
*
* Recursively traverses _codeDir looking for all directories
* that should be searched
*
* @author Tony Bibbs <tony AT geeklog DOT net>
* @access private
* @param string $curDir Current working directory
*
*/
function _getDirs($curDir = '')
{
$dirsFound = array();
if (empty($curDir)) {
$curDir = $this->_codeDir;
}
$this->_codeDirs[] = $curDir;
$fd = opendir($curDir);
while (($dir = @readdir( $fd )) == TRUE) {
if (is_dir($curDir . $dir) AND $dir <> '.' AND $dir <> '..' AND $dir <> 'CVS' AND substr($dir, 0 , 1) <> '.' ) {
clearstatcache();
$dirsFound[] = $curDir . $dir . '/';
}
}
foreach ($dirsFound as $nextDir) {
$this->_getDirs($nextDir);
}
closedir($fd);
}
/**
* Extracts all the strings from the PHP files in the given
* directory.
*
* Takes all strings found in PHP files in the given directory
* and adds them to the default language XML file
*
* @author Tony Bibbs <tony at geeklog.net>
* @access private
* @param string $dirName name of directory to parse (must end with '/')
* @todo Need to have this file check _validExtensions so that files other than
* .php can be used.
*
*/
function _processFiles($dirName)
{
$results = array();
$fd = opendir($dirName);
while (($curFile = @readdir($fd)) == true) {
if (is_file($dirName . $curFile) AND stristr($curFile,'.php')) {
$fileContents = file_get_contents($dirName . $curFile);
preg_match_all("/.->translate\(['\"](.*)['\"]\);/im", $fileContents, $results);
$matches = $results[1];
if ($this->_commandLineMode) {
echo 'processing file: ' . $dirName . $curFile . "\n";
echo 'found ' . count($matches) . " strings\n";
}
$this->_addStrings($matches);
}
}
closedir($fd);
}
/**
* Writes a set of strings to the native XML file
*
* This function is called as we find strings needing translation in the
* code files. This method will actually add the appropriate XML for the
* string found.
*
* @author Tony Bibbs <tony at geeklog.net>
* @access private
* @param array $matches Array of strings
*
*/
function _addStrings($matches)
{
foreach ($matches as $curString) {
// NOTE: following line will convert only &,< and >
// quotes are going to be OK within XML tags
$curString = htmlspecialchars($curString, ENT_NOQUOTES);
fwrite($this->_outputFp,
sprintf(" <ENTRY>\n <STRING_ID>%s</STRING_ID>\n <STRING></STRING>\n </ENTRY>\n",
$curString));
}
}
/**
* Creates the header entries for XML file
*
* The XML schema adds the APPLICATION, TRANSLATOR and
* TRANSLATION XML tags along with their attributes
*
* @author Tony Bibbs <tony at geeklog.net>
* @access private
*
*/
function _addXMLHeaders()
{
fwrite($this->_outputFp,
sprintf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<APPLICATION name=\"%s\" version=\"%s\">\n <TRANSLATOR name=\"%s\" email=\"%s\" />\n <TRANSLATION language=\"%s\">\n",
$this->_appName,
$this->_appVersion,
$this->_authorName,
$this->_authorEmail,
$this->_nativeLang));
}
/**
* Adds XML footer entries to XML file
*
* This method simply closes the TRANSLATION and APPLICATION
* tags.
*
* @author Tony Bibbs <tony at geeklog.net>
*
*/
function _addXMLFooters()
{
fwrite($this->_outputFp," </TRANSLATION>\n</APPLICATION>");
fclose($this->_outputFp);
}
/**
* When called from the command line this function will
* take any arguments passed to the getstrings shell script
* and set up this object for processing
*
* This validates arguments given to the command line script. When
* an error is encountered the help page is displayed
*
* @author Tony Bibbs <tony at geeklog.net>
* @access private
* @param array $args Argument passed to getstring commandline
*
*/
function _handleCommandLineArgs($args)
{
// This array hold valid arguments and whether or not they are required
// where 1 = required.
$validOptions = array('--lang'=>1,'--source'=>1,'--target'=>1,'--appname'=>1,
'--appversion'=>0,'--author'=>0,'--email'=>0,'--help'=>0);
$optionNames = array_keys($validOptions);
// If they asked for help, give it now and ignore
// all other arguments
if (in_array('--help',array_keys($args))) {
$this->_getHelp();
return;
}
// Make sure we have a set of valid arguments
foreach ($args as $curArg) {
if (!in_array(key($args),$optionNames)) {
echo "Invalid argument: $curArg\n";
$this->_getHelp();
return;
}
}
// Make sure all required arguments were provided.
foreach ($optionNames as $curName) {
if ($validOptions[$curName] == 1 AND empty($args[$curName])) {
echo "Missing required argument: $curName\n";
$this->_getHelp();
return;
}
}
// Validation is done so now we can go ahead and start setting up the
// object.
reset($args);
$appName = '';
$appVersion = '';
$author = '';
$email = '';
foreach ($args as $curArg) {
switch (key($args)) {
case '--source':
$this->setCodeDir($curArg);
break;
case '--target':
$this->setOutputDir($curArg);
break;
case '--appname':
if (!empty($appVersion)) {
$this->setAppProperties($curArg, $appVersion);
} else {
$appName = $curArg;
}
break;
case '--appversion':
if (!empty($appName)) {
$this->setAppProperties($appName, $curArg);
} else {
$appVersion = $curArg;
}
break;
case '--author':
if (!empty($email)) {
$this->setAuthorProperties($curArg, $email);
} else {
$name = $curArg;
}
break;
case '--email':
if (!empty($name)) {
$this->setAuthorProperties($name, $curArg);
} else {
$email = $curArg;
}
break;
default:
continue;
}
next($args);
}
return;
}
/**
* Prints help text for commandline interface
*
* When the commandline is used and --help is passed to it
* or an error occurs this will be called to show a list of
* all options along with a description of the option.
*
* @author Tony Bibbs <tony at geeklog.net>
* @access private
*
*/
function _getHelp()
{
echo "\n--lang Native language used in code. This is used to\n";
echo " set the name of the outputted XML file. So if\n";
echo " you pass 'en' the XML file is named en.xml\n\n";
echo "--source Top level directory where PHP source code can\n";
echo " be found\n\n";
echo "--target Directory to store the XML file\n\n";
echo "--appname Name of your PHP application\n\n";
echo "--appversion Version number for your PHP application\n\n";
echo "--author Name of the author(s) of your PHP application\n\n";
echo "--email Email of the author(s) of your PHP application\n\n";
}
/**
* Sets the application properties which are put into the
* translation XML file you will need to send to translators
*
* @author Tony Bibbs <tony at geeklog.net>
* @access public
* @param string $appName Name of the application
* @param string $appVersion Application version
*
*/
function setAppProperties($appName, $appVersion)
{
$this->_appName = $appName;
$this->_appVersion = $appVersion;
}
/**
* Sets the author properties which are put into the translation
* XML file you will need to send to translators
*
* @author Tony Bibbs <tony at geeklog.net>
* @access public
* @param string $authorName Name of author
* @param string $authorEmail
*
*/
function setAuthorProperties($authorName, $authorEmail)
{
$this->_authorName = $authorName;
$this->_authorEmail = $authorEmail;
}
/**
* Sets the main directory where code resides
*
* @author Tony Bibbs <tony AT geeklog DOT net>
* @access public
* @param string $path Path of base code directory
*
*/
function setCodeDir($path)
{
$this->_codeDir = $path;
}
/**
* Sets the output directory where the resulting XML file should
* be placed
*
* @author Tony Bibbs <tony AT geeklog DOT net>
* @access public
* @param string $path Path where XML file should be placed
*
*/
function setOutputDir($path = './') {
if (!is_dir($path) OR !is_writable($path)) {
trigger_error('Specified Output Directory ' . $path . ' is not writeable');
exit;
}
$this->_outputDir = $path;
$this->_outputFile = $path . $this->_nativeLang . '.xml';
$this->_outputFp = fopen($this->_outputFile,'w');
}
/**
* Sets valid file extensions for code
*
* This allows developers to set what extensions to parse for
* strings. The default is php only
*
* @author Tony Bibbs <tony AT geeklog DOT net>
* @access public
* @param array $extensionArray Array of valid file extensions
* @todo While this function exists, the code needed to actually
* use the valid extension array needs to be built
*
*/
function setValidExtensions($extensionArray)
{
if (count($extensionArray) == 0) {
$extensionArray = Array('php');
}
$this->_validExtensions = $extensionArray;
}
/*
* Starts the extraction process
*
* This starts the process of traversing the code files and
* pulling out the strings into an XML file that could be
* translated
*
* @author Tony Bibbs <tony At geeklog DOT net>
* @access public
*
*/
function getStrings($args = '')
{
if (is_array($args)) {
$this->_commandLineMode = true;
$this->_handleCommandLineArgs($args);
}
if (empty($this->_outputDir)) {
$this->setOutputDir();
}
if (empty($this->_codeDir)) {
trigger_error('No code directory specified');
exit;
}
if (empty($this->_validExtensions)) {
$this->setValidExtensions(Array());
}
$this->_getDirs();
$this->_addXMLHeaders();
foreach ($this->_codeDirs as $nextDir) {
$this->_processFiles($nextDir);
}
$this->_addXMLFooters();
if ($this->_commandLineMode) {
echo "Done processing strings. XML file generated can be found in " . $this->_outputDir . $this->_nativeLang . ".xml\n";
}
}
}
?>
--- NEW FILE: Translator.class.php ---
<?php
/**
* Translations Library - Translator.class.php
*
* This source file is subject to version 2.02 of the PHP license,
* that is bundled with this package in the file LICENSE, and is
* available at through the world-wide-web at
* http://www.php.net/license/2_02.txt.
* If you did not receive a copy of the PHP license and are unable to
* obtain it through the world-wide-web, please send a note to
* license at php.net so we can mail you a copy immediately.
*
* @author Tony Bibbs <tony AT geeklog DOT net>
* @copyright Tony Bibbs 2003
* @package net.geeklog.translations
* @version $Id: Translator.class.php,v 1.1 2003/04/18 20:13:09 tony Exp $
*
*/
/**
* This class translates English text to the user's desired language
*
* @author Tony Bibs <tony AT geeklog DOT net>
* @package net.geeklog.translations
*
*/
class Translator {
/**
* @access private
* @var string
*/
var $_strings = null;
/**
* @access private
* @var string
*/
var $_nativeLang = null;
/**
* @access private
* @var string
*/
var $_userLang = null;
/**
* @access private
* @var string
*/
var $_translationDir = null;
/**
* @access private
* @var string
*/
var $_parser = null;
/**
* @access private
* @var string
*/
var $_curElement = null;
/**
* @access private
* @var string
*/
var $_curID = null;
/**
* Constructor
*
* Sets up the native language and defaults the user
* language to the native language if the user lang
* doesn't already exist
*
* @author Tony Bibbs <tony AT geeklog DOT net>
* @access public
*
*/
function Translator($nativeLangCode = 'en')
{
$this->_nativeLang = $nativeLangCode;
if (empty($this->_userLang)) {
$this->_userLang = $nativeLangCode;
}
}
/**
* Handler that is called when a beginning XML tag is
* encountered
*
* Caches the element so when we get to the data handler we
* know if we should ignore the data or not.
*
* @author Tony Bibbs <tony at geeklog.net>
* @access private
* @param object $parser Expat parser object
* @param string $name Name of XML element encountered
* @param array $attributes XML attributes for current element
*
*/
function _handleStartElement($parser, $name, $attributes)
{
$this->_curElement = $name;
}
/**
* Handler that is called when an end XML tag is
* encountered
*
* This will clear out the current element being worked
* on as well as the current string ID
*
* @author Tony Bibbs <tony at geeklog.net>
* @access private
*
*/
function _handleEndElement()
{
$this->_curElement = '';
}
/**
* Handles data found while parsing XML
*
* @author Tony Bibbs <tony at geeklog.net>
* @access private
* @param object $parser Expat parser
* @param string $data Data that was encountered
*
*/
function _handleData($parser, $data)
{
if (empty($this->_curElement) OR !trim($data)) return;
// Grab the native language string from the XML
if ($this->_curElement == 'STRING_ID') {
$this->_curID = $data;
}
// OK, store the new translation
if ($this->_curElement == 'STRING') {
$this->_strings[$this->_curID] = $data;
}
}
/**
* Loads the strings for a given language code into memory
*
* @author Tony Bibbs <tony AT geeklog DOT net>
* @access private
*
*/
function _loadStrings()
{
$this->_strings = array();
// Make sure we have a valid translation file
$filename = $this->_translationDir . $this->_userLang . '.xml';
if (!file_exists($filename)) {
trigger_error('Bad translation file in Translator::_loadStrings');
exit;
}
// Load the XML
$xmlData = file_get_contents($filename);
// Create Expat parser object
$this->_parser = xml_parser_create();
// Lets expat know this class will handle the parsing
xml_set_object($this->_parser, &$this);
xml_set_element_handler($this->_parser, '_handleStartElement', '_handleEndElement');
xml_set_character_data_handler($this->_parser, '_handleData');
// Actually parse the XML now.
if (!xml_parse($this->_parser, $xmlData)) {
trigger_error(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($this->_parser)),
xml_get_current_line_number($this->_parser)));
exit;
}
xml_parser_free($this->_parser);
return true;
}
/**
* Sets the language the user wants site translated to
*
* NOTE: this does not effect he default language. This is
* the language the user wants in order to process the current
* request.
*
* @author Tony Bibbs <tony AT geeklog DOT net>
* @access public
* @param string $langCode Language to translate strings to
*
*/
function setUserLanguage($langCode = '')
{
// Default the user language to the native
// language if none was provided
if (empty($langCode)) {
$langCode = $this->_nativeLang;
}
$this->_userLang = $langCode;
}
/**
* Sets base directory where all
* translations can be found
*
* @author Tony Bibbs <tony at geeklog.net>
* @access public
* @param string $path Path to base translation directory
*
*/
function setTranslationDir($path)
{
if (is_dir($path)) {
$this->_translationDir = $path;
}
}
/**
* Translates an given string
*
* NOTE: the native language can be set up to be something
* besides english. If you are using this translation package
* it will be important that you set the native language to the
* one used most on the site as that will reduce the I/O and
* memory usage. That same language should be the one used for
* string passed to this method.
*
* @author Tony Bibbs <tony AT geeklog DOT net>
* @access public
* @param string $originalText Text in _nativeLang language
* @return string Translated text
*
*/
function translate($originalText)
{
// Of course if they are asking for native language then we are
// already done.
if ($this->_userLang == $this->_nativeLang) {
return $originalText;
}
if (!$this->_loadStrings()) {
return $originalText;
}
return $this->_strings[$originalText];
}
}
More information about the geeklog-cvs
mailing list