diff options
Diffstat (limited to 'devel-utf8/it_text.class')
-rw-r--r-- | devel-utf8/it_text.class | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/devel-utf8/it_text.class b/devel-utf8/it_text.class new file mode 100644 index 0000000..86e6a75 --- /dev/null +++ b/devel-utf8/it_text.class @@ -0,0 +1,268 @@ +<?php +/* +** $Id$ +** +** Copyright (C) 1995-2008 by the ITools Authors. +** This file is part of ITools - the Internet Tools Library +** +** ITools is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 3 of the License, or +** (at your option) any later version. +** +** ITools is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +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: <?php return array('_' => 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 = "<span style='background:#F88' title='" . Q("$label (" . it_debug::backtrace(array('levels'=>1, 'skipfiles'=>"text|auto_prepend")) . ")") . "'>" . Q($label) . "</span>"; + 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|servicedomain/i', $label) && (!$_GET['it_texts_mark'] || $label == $_GET['it_texts_mark'])) + $text = "<span style='background:#8F8' title='$label (" . it_debug::backtrace(array('levels'=>1, 'skipfiles'=>"text|auto_prepend")) . ")'>" . ($text ? $text : $label) . "</span><a href='/admin.html?edit=$label'>.</a>"; + + 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, $label); +} + + +/** + * 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, $label = null) +{ + foreach (preg_split('/{([\w.]+)}/', $text, -1, PREG_SPLIT_DELIM_CAPTURE) as $i => $part) + { + if ($i % 2) # odd offsets are delimiters, i.e. braces to be replaced + { + $value = $values ? $values : $GLOBALS; + foreach (explode(".", $part) as $key) + { + $value = is_object($value) ? $value->$key : $value[$key]; + if ($value === null && $values && $label) # do not test in $GLOBALS mode + it::error(array('title' => "No value given for text variable {" . $key ."} in label $label", 'backtraceskip' => 3)); + } + + $result .= $value; + } + else + $result .= $part; + } + + return $result; +} + + + +/** + * 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, '<?php return ' . strtr(var_export($this->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 */ +?> |