<?php // Document this before generating the doxygen docu.
// http://www.phpclasses.org/browse.html/package/542.html
// there is a perl script available for doxygen and php also. Use it if you have it and know how to use ti as well.
/*!
\class Translator merlini18n.h "INCLUDEDIR/merlini18n.h"
\brief The Translator class provides internationalization support for text output.
\image html kmago.png "Project merlin_i18n" width=10cm
\version 1.0.0.1
\author Dipl.-Ing. Matthias Schulze, mschulze_99@yahoo.com, mschulze@infocable.biz
*/
//define("_DEBUG_LOCAL",1);
//define("_DEBUG_LOAD",1);
class Translator
{
// those functions are ment to be treated as public.
//public: // Undocument this before generating the doxygen docu.
//! Default constructor.
/*!
Calls a special member function for class variable initialization.
\sa init()
*/
function Translator()
{
$this->init();
}
//! A member function taking no arguments and returning a string value.
/*!
-# Tries to find out the prefered language of the client (browser).
-# Tries to get the environment variable RC_LANG.
-# Tries to get the environment variable LANG.
This function can also be used without having an instance of the class e.g. Translator::local();.
\return A string representing the current language.
*/
function local()
{
if($browser_lang = explode(',',getenv('HTTP_ACCEPT_LANGUAGE')))
{
$lang = str_replace('-', '_',$browser_lang[0]);
if(defined("_DEBUG_LOCAL")):
print($lang);
endif;
return $lang;
}
else if($lang = getenv('RC_LANG'))
return $lang;
else if($lang = getenv('LANG'))
return $lang;
else
return $lang = "en";
}
//! A member function taking four arguments and returning a bool value.
/*!
Loads $filename, which may be an absolute file name or relative to $directory. The previous contents of this translator object is discarded.
If the full file name does not exist, other file names are tried in the following order.
-# File name with $suffix appended (".ts" if $suffix is NULL and $filename is given without file extension).
-# File name with $suffix stripped (if $filename is given with file extension).
-# File name with text after a character in $search_delimiters stripped ("_." is the default for $search_delimiters if it is NULL).
-# File name stripped and $suffix appended.
-# File name stripped further, etc.
For example, an application running in the en_US locale (English-speaking US) might call load("trans_en_US", "/yourproyect/i18n"), which would then try to open these files.
-# /yourproyect/i18n/trans_en_US
-# /yourproyect/i18n/trans_en_US.ts
-# /yourproyect/i18n/trans_en
-# /yourproyect/i18n/trans_en.ts
-# /yourproyect/i18n/trans
-# /yourproyect/i18n/trans.ts
\param $filename string Terminated with or without file extension.
\param $directory string Optional and terminated with or without appended slash ("./" if NULL).
\param $search_delimiters string Optional ("_." if NULL).
\param $suffix string Optional (".ts" if NULL).
\return TRUE on success otherwise FALSE.
*/
function load($filename, $directory=NULL, $search_delimiters=NULL, $suffix=NULL)
{
clearstatcache();
if($directory == NULL) $directory = "./";
if($directory != NULL && !strrchr($directory,"/")) $directory = $directory . "/";
if($search_delimiters == NULL) $search_delimiters = "_.";
if($suffix == NULL) $suffix = ".ts";
if(defined("_DEBUG_LOAD")):
print("suffix = $suffix<br>");
print("directory = $directory<br>");
print("1.0 test : filename = $filename<br>");
endif;
if(!$this->bool = is_file($directory . $filename))
{
$tmpSuffix = substr($filename,-3,3);
if(defined("_DEBUG_LOAD")):
print("tmpSuffix = $tmpSuffix<br>");
endif;
if($tmpSuffix[0] == ".")
{
$filename = substr($filename,0,strrpos($filename,"."));
if(defined("_DEBUG_LOAD")):
print("2.0 test : filename = $filename<br>");
endif;
$this->bool = is_file($directory . $filename);
}
else
{
if(defined("_DEBUG_LOAD")):
print("2.0 test : filename = $filename$suffix<br>");
endif;
$this->bool = is_file($directory . $filename . $suffix);
}
if(!$this->bool)
{
for($i=0;$i<strlen($search_delimiters);$i++)
{
$testFileName = $filename;
for($j=0;$j<substr_count($filename,$search_delimiters[$i]);$j++)
{
$testFileName = substr($filename,0,strrpos($testFileName,$search_delimiters[$i]));
if(defined("_DEBUG_LOAD")):
print(($i+3) . "." . ($j+1) . " test : testFileName = $testFileName<br>");
endif;
if($this->bool = is_file($directory . $testFileName))
{
$this->data = implode("",file($directory . $testFileName));
if(defined("_DEBUG_LOAD")):
print("found : $directory$testFileName<br>");
endif;
break;
}
else
{
if(defined("_DEBUG_LOAD")):
print(($i+3) . "." . ($j+1) . " test : testFileName = $testFileName$suffix<br>");
endif;
if($this->bool = is_file($directory . $testFileName . $suffix))
{
$this->data = implode("",file($directory . $testFileName . $suffix));
if(defined("_DEBUG_LOAD")):
print("found : $directory$testFileName$suffix<br>");
endif;
break;
}
}
}
if($this->bool) break; else continue;
}
}
else
$this->data = implode("",file($directory . $filename . $suffix));
}
else
$this->data = implode("",file($directory . $filename));
return $this->bool;
}
//! A member function taking two optional arguments and returning a string value.
/*!
Using this member function the complete XML translation file will be looked up by the XML parser for a suitable translation of $sourceText.
Depending on the lookup result it either returns the corresponding source text translation or $sourceText.
In order to be able to distinguish between two or more identical source text occurences inside the translation file,
each having a different translation, the function takes an optional second parameter $comment which helps the translater to identify
the corresponding translation of $sourceText.
To make the function failsafe both parameters are optional and if those are left to NULL the function immediately returns $sourceText
without looking up any translation file or doing other actions.
\param $sourceText string Optional text or phrase to translate.
\param $comment string Optional comment to distinguish between different translations for identical source text.
\return The corresponding translation of $sourceText or $sourceText if no translation was found.
\sa translate($context=NULL,$sourceText=NULL,$comment=NULL)
*/
function tr($sourceText=NULL,$comment=NULL)
{
if($sourceText)
{
$this->action = "tr";
$this->st = $sourceText;
$this->cm = $comment;
$this->translation = "";
if($this->bool) $this->translate_str();
}
return !empty($this->translation) ? $this->translation : $sourceText;
}
//! A member function taking three optional arguments and returning a string value.
/*!
Using this member function a certain part of the XML translation file will be looked up by the XML parser for a suitable translation of $sourceText.
Depending on the lookup result it either returns the corresponding source text translation or $sourceText.
In order to be able to distinguish between two or more identical source text occurences inside the translation file,
each having a different translation, the function takes an optional third parameter $comment which helps the translater to identify
the corresponding translation of $sourceText.
To make the function failsafe all parameters are optional.\n
-# If $context is the only given parameter the functions immediately returns $sourceText.
-# if $context and $sourceText are both given, the function looksup the translation file for the corresponding translation of
$sourceText with in $context.
-# If $context, $sourceText and $comment are all given, the function looksup the translation file for the corresponding translation
of $sourceText with in $context, using $comment to distinguish between different translations which correspond to $sourceText.
If an empty string is passed to $context the function will return immediately $sourceText.
\param $context string Optional context for faster XML file lookups.
\param $sourceText string Optional text or phrase to translate.
\param $comment string Optional comment to distinguish between different translations for identical source text.
\return The corresponding translation of $sourceText or $sourceText if no translation was found.
\sa tr($sourceText=NULL,$comment=NULL)
*/
function translate($context=NULL,$sourceText=NULL,$comment=NULL)
{
if($context && $sourceText && !empty($context))
{
$this->action = "translate";
$this->cx = $context;
$this->st = $sourceText;
$this->cm = $comment;
$this->translation = "";
if($this->bool) $this->translate_str();
}
return !empty($this->translation) ? $this->translation : $sourceText;
}
// those functions are ment to be treated as protected.
//protected: // Undocument this before generating the doxygen docu.
//! A member function taking no arguments.
/*!
This is the function which initializes all class variables to its default values.\n
It is called by the default constructor up on class instance generation using the "new" command.
\return void
\sa Translator()
*/
function init()
{
$this->trdb = array();
$this->trans = array();
$this->mvalues = array();
$this->st = "";
$this->cx = "";
$this->cm = "";
$this->data = "";
$this->action = "";
$this->translation = "";
$this->bool = FALSE;
clearstatcache();
}
//! A member function taking no arguments and returning an bool value.
/*!
\return TRUE or FALSE
*/
function parseMsgBlock()
{
$bool = TRUE;
$this->mvalues = array_reverse($this->mvalues);
//print_r($this->mvalues);
for($i=0;$i<count($this->mvalues);$i++)
{
if(isset($this->mvalues[$i]["attributes"]) &&
$this->mvalues[$i]["attributes"]["type"] == "unfinished")
{
$bool = FALSE;
break;
}
else
$this->trans[$this->mvalues[$i]["tag"]] = $this->mvalues[$i]["value"];
}
//print_r($this->trans);
return $bool;
}
//! A member function taking no arguments and returning void.
/*!
\return void
\sa Translator()
*/
function searchXMLfile()
{
$parser = xml_parser_create("UTF-8");
xml_parser_set_option($parser,XML_OPTION_TARGET_ENCODING,"UTF-8");
xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,1);
xml_parse_into_struct($parser,$this->data,$values,$tags);
xml_parser_free($parser);
//print_r($values);
$name = $tags["name"];
//print_r($name);
$context = $tags["context"];
//print_r($context);
$message = $tags["message"];
//print_r($message);
switch($this->action)
{
case "translate":
for($i=0;$i<count($name);$i++)
if($this->cx == $values[$name[$i]]["value"])
{
$context_val_begin = $name[$i] - 1;
$context_val_end = $context[array_search($context_val_begin,$context) + 1];
//print $context_val_end;
$msg_val_begin = $name[$i] + 1;
//print "msg_val_begin = $msg_val_begin<br>";
$msg_val_end = $context_val_end - 1; // 21
//print "msg_val_end = $msg_val_end<br>";
$msg_key_begin = array_search($msg_val_begin,$message);
//print "msg_key_begin = $msg_key_begin<br>";
$msg_key_end = array_search($msg_val_end,$message);
//print "msg_key_end = $msg_key_end<br>";
$num_msg = (($msg_key_end + 1) - ($msg_key_begin));
//print "num_msg = $num_msg<br>";
for($k=0;$k<$num_msg;$k+=2)
{
$offset = $message[$msg_key_begin + $k] + 1;
//print "offset = $offset<br>";
$len = $message[$msg_key_begin + $k + 1] - $offset;
//print "len = $len<br>";
$this->mvalues = array_slice($values, $offset, $len);
//print_r($this->mvalues);
if($this->parseMsgBlock())
$this->trdb[] = $this->$trans;
else
continue;
unset($this->mvalues);
unset($this->$trans);
}
}
else
continue;
break;
case "tr":
for($i=0;$i<count($message);$i+=2)
{
$offset = $message[$i] + 1;
//print "offset = $offset<br>";
$len = $message[$i + 1] - $offset;
//print "len = $len<br>";
$this->mvalues = array_slice($values, $offset, $len);
if($this->parseMsgBlock())
$this->trdb[] = $this->$trans;
else
continue;
}
break;
default:
break;
}
}
//! A member function taking no arguments and returning void.
/*!
\return void
\sa Translator()
*/
function translate_str()
{
$this->searchXMLfile();
//print_r($this->trdb);
for($i=0;$i<count($this->trdb);$i++)
{
if(!empty($this->cm))
{
if($this->trdb[$i]["source"] == $this->st &&
isset($this->trdb[$i]["comment"]) &&
$this->trdb[$i]["comment"] == $this->cm)
{
$this->translation = $this->trdb[$i]["translation"];
break;
}
else
continue;
}
else
{
if($this->trdb[$i]["source"] == $this->st && !isset($this->trdb[$i]["comment"]))
{
$this->translation = $this->trdb[$i]["translation"];
break;
}
else
continue;
}
}
}
// those variables are ment to be treated as private.
// private: // Undocument this before generating the doxygen docu.
var $trdb;
var $trans;
var $mvalues;
var $st;
var $cx;
var $cm;
var $data;
var $bool;
var $action;
var $source;
var $translation;
}
?> // Document this before generating the doxygen docu.
|