.
*/
class it_text
{
var $actlanguage; # Selected language
var $defaultlanguage; # Browser language
var $languages = array(); # Active languages
var $languages_available = array(); # Available languages
var $statictext = array(); # Text array, read from php file on init
/**
* Constructor
* Loads all texts.php in include path for translated labels. Singleton; if instanciated mutiple times, texts are merged
* Example texts.php: array('en'=>"English", 'de'=>"Deutsch"), 'edit'=>array('en'=>"Edit", 'de'=>("Editieren")));
* @param $p['fallbacklanguage'] optional language to use for undefined texts (useful for partially translated projects)
* @param $p['forcelanguage'] optional language to use instead of user's preferred language
* @param $p['global'] store text object in global it_text for global functions (default: true)
* @param $p['phpfile'] optional texts file(s), default: all texts.php in include path
* @param $p['phpfiles'] text files to load in addition to $p['phpfile'] (Note: $p['phpfile'] defaults to all texts.php files in include path)
*/
function it_text($p = array())
{
if (!$p['phpfile'])
{
# Find all texts.php in path (abs path in case we need to save)
foreach (explode(PATH_SEPARATOR, ini_get('include_path')) as $dir)
if (file_exists($phpfile = "$dir/texts.php"))
$p['phpfiles'][] = $phpfile;
}
$this->p = ($p += array(
'global' => true,
'phpfiles' => array_unique(array_merge((array)$p['phpfiles'], (array)$p['phpfile'])),
));
# Read and merge texts from php files if none defined yet
foreach ($p['phpfiles'] as $phpfile)
{
$oldtext = $this->statictext;
if (is_array($ret = include($phpfile)))
$this->statictext += $ret;
else
$this->statictext = $oldtext + $this->statictext; # FIXME: compatibility mode
}
# Get array of supported languages and their names
$this->languages_available = (array)$this->statictext['_'];
foreach ($this->languages_available as $code => $languagename)
{
# Only use a language in browser detection below if it's not disabled by a leading '-'
if (substr($languagename, 0, 1) != '-')
{
$this->languages[$code] = $languagename;
if (!$this->actlanguage)
$this->initlang($code, "setting failsafe language");
}
}
# Set our default language according to browser preference
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
{
foreach (explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']) as $code)
if ($this->initlang($code, "setting language from browser") || $this->initlang(substr($code, 0, 2), "setting language family from browser"))
break;
}
$this->defaultlanguage = $this->actlanguage;
$this->initlang(it::match('\.([a-z]{2})\.[^./]+$', $_SERVER['PHP_SELF']), "setting language from url override");
$this->initlang($p['forcelanguage'], "setting language from programmer override");
# Create empty array to activate sampling; dont kill any existing one
if (!it::is_live() || rand(1, 100) == 1)
$GLOBALS['it_text_sampling'] = (array)$GLOBALS['it_text_sampling'];
# Make this object available under $GLOBALS['it_text'], or add my texts to $GLOBALS['it_text'] if it exists
if ($p['global'])
{
if (!$GLOBALS['it_text'])
$GLOBALS['it_text'] =& $this;
else
$GLOBALS['it_text']->statictext += $this->statictext;
}
}
# internal: overwrite language setting if code is valid, return success
function initlang($code)
{
if ($this->languages[$code])
$this->actlanguage = $code;
return $this->languages[$code];
}
/**
* Instanciate singleton if necessary
*/
function init()
{
if (!$GLOBALS['it_text'])
new it_text;
}
/**
* INTERNAL function for T(): : Return translated text in the selected language
*/
function text($label, $language = null)
{
if (!$language)
$language = $this->actlanguage;
$text = $this->statictext[$label][$language];
if (!isset($text))
{
$text = $this->statictext[$label][$this->p['fallbacklanguage']];
if (!isset($text))
{
$text = "1, 'skipfiles'=>"text|auto_prepend")) . ")") . "'>" . Q($label) . "";
it::error(array('title'=>"unknown label $label language $language - see /tmp/alertdata/alert.log", 'backtraceskip'=>2, 'blockmail'=>21600));
}
}
if ($GLOBALS['debug_texts'] && !preg_match('/submit|button/i', $label) && (!$_GET['it_texts_mark'] || $label == $_GET['it_texts_mark']))
$text = "1, 'skipfiles'=>"text|auto_prepend")) . ")'>" . ($text ? $text : $label) . "";
if (isset($GLOBALS['it_text_sampling']))
$GLOBALS['it_text_sampling'][$label] = true;
return $text;
}
/**
* INTERNAL function for ET(): Return translated text with values replaced
*/
function etext($label, $values = null, $language = null)
{
return $this->transmogrify($this->text($label, $language), $values);
}
/**
* INTERNAL function for T_set_language()
*/
function set_language($language)
{
$this->actlanguage = $this->languages_available[$language] ? $language : $this->defaultlanguage;
}
/**
* INTERNAL function for T_lang(): Get active language
*/
function get_language()
{
return $this->actlanguage;
}
/**
* INTERNAL function for T_lang(): Get active language
*/
function get_defaultlanguage()
{
return $this->defaultlanguage;
}
/**
* INTERNAL function for T_exists(): Check if a text entry for a specific label exists
*/
function text_exists($label, $language = null)
{
return isset($this->statictext[$label][isset($language) ? $language : $this->actlanguage]) || $this->p['fallbacklanguage'] && isset($this->statictext[$label][$this->p['fallbacklanguage']]);
}
/**
* Create / overwrite a text in the selected language. Call dump_php() to make the change permanent.
* @param $label Label of text to change
* @param $text New text to set
* @param $language Optional language that is to be manipulated
*/
function set($label, $text = null, $language = null)
{
if (!isset($language))
$language = $this->actlanguage;
$this->statictext[$label][$language] = $text;
}
/**
* Replaces variables of the form {obj.var} with value, e.g. {user.name}
* NOTE: Invalid object names or non-existing variables are simply deleted.
*/
function transmogrify($text, $values = null)
{
while (preg_match('/{([\w.]+)}/', $text, $regs))
{
$path = explode('.', $regs[1]);
if ($values)
$value =& $values;
else
$value =& $GLOBALS;
# Recurse into nested arrays/object members
foreach ($path as $key)
{
if (is_object($value))
$value =& $value->$key;
else
$value =& $value[$key];
}
$text = str_replace($regs[0], $value, $text);
}
return $text;
}
/**
* Re-create php text file from $this->statictext
* @return true if successful, false if not (usually if file is not writeable by user www)
*/
function dump_php()
{
$result = false;
# Special sorting: natural, but _ is the first entry
uksort($this->statictext, "strnatcmp");
$this->statictext = array_merge(array('_' => $this->statictext['_']), $this->statictext);
$oldmask = umask(002);
if ((count($this->p['phpfiles']) == 1) && ($f = fopen($this->p['phpfiles'][0], 'w')))
{
$result = (fputs($f, 'statictext, true), array("=> \n array (" => "=> array(", "array (\n '_'" => "array(\n'_'", "\n ),\n " => "\n),\n", "\n ),\n" => "\n),\n", "\r" => "")) . ";\n?>\n") !== false);
fclose($f);
}
umask($oldmask);
return $result;
}
} /* End class it_text */
?>