Location: PHPKode > projects > Mocovie web framework > mocovi/library/autoload/Translator.php
<?php
/**
 *  Copyright (C) 2010  Kai Dorschner
 *
 *  This program 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.
 *
 *  This program 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/>.
 *
 * @author Kai Dorschner <the-hide@address.com>
 * @copyright Copyright 2010, Kai Dorschner
 * @license http://www.gnu.org/licenses/gpl.html GPLv3
 * @package mocovi
 * @subpackage helpers
 */

/**
 * Token-based translation.
 *
 * Every word or sentence is saved in an XML file as a token which contains
 * each translation language. With this class you can choose your token and
 * specify a language which results in a distinct text. Therefor use the
 * {@link translateToken()} function.
 *
 * @package mocovi
 */
class Translator
{
	/**
	 * Translations Pool.
	 *
	 * Contains all tokens in each language in a 2d array.
	 * It's calles by using the pattern $translation[token][language].
	 *
	 * For more information look at {@link getTranslationByLanguage()}
	 *
	 * @var array Contains all translations
	 * @see getTranslationByLanguage()
	 * @access protected
	 */
	protected static $translation = array();

	/**
	 * This is the base language in which all texts are being translated.
	 *
	 * @var string Contains the default/base language
	 * @access protected
	 */
	protected static $baselanguage;

	/**
	 * Private constructor
	 *
	 * @access private
	 */
	private function __construct() {}

	/**
	 * Adds new translation table.
	 *
	 * If a translation token already exists, all containing translations will be replaced.
	 *
	 * @param DomDocument $xml XML Object with translation table
	 * @see $translation
	 * @access public
	 */
	public static function setTranslation(DomDocument $xml)
	{
		$xpath = new DomXpath($xml);
		foreach($xpath->query('//token/translation') as $node)
			self::$translation[$node->parentNode->getAttribute('name')][$node->getAttribute('lang')] = $node;
	}

	public static function setTranslationFile($path)
	{
		if(!is_file($path))
			throw new MvcException('Can\'t find translation file "' . $path . '"');
		$dom = new DomDocument();
		$dom->load($path);
		self::setTranslation($dom);
	}

	public static function setTranslations(Array $xmlarray)
	{
		foreach($xmlarray as $xml)
			self::setTranslation($xml);
	}

	/**
	 * Sets the base language.
	 *
	 * Valid types are de, de-au, en, es, fr, cs,...
	 *
	 * @see $baselanguage
	 * @param string $baselanguage Language Token.
	 * @access public
	 */
	public static function setLanguage($baselanguage)
	{
		self::$baselanguage = (String)$baselanguage;
	}

	/**
	 * Returns the base language.
	 *
	 * @see $baselanguage
	 * @return string The base language token
	 * @access public
	 */
	public static function getLanguage()
	{
		return self::$baselanguage;
	}

	public static function translateToken($token, $context = null)
	{
		if(count(self::$translation) <= 0)
			throw new MvcException('Translation-table not set or empty.');
		if(empty(self::$baselanguage))
			throw new MvcException('No base language defined.');
		if(self::tokenExists($token))
		{
			$t = self::getTranslationByLanguage($token, self::$baselanguage);
			if(empty($t->nodeValue) || $t->nodeValue == $token)
				$t = self::getTranslationByLanguage($token, 'all');
			if(is_null($context))
				return $t;
			// else format text according to the count of the context.
			//return  new DomElement('translation', sprintf(self::translateTokenByCount($token, $context), $context));
		}
		return new DomElement('translation', $token);
	}

	public static function translateTokenByCount($token, $count)
	{
		$node = self::translateToken($token)->cloneNode(true); // if not cloned it would be overwritten!
		foreach($node->childNodes as $child)
			if($child->nodeType == XML_TEXT_NODE)
				$node->replaceChild(new DomText(self::getTextByCount($child->nodeValue, $count)), $child);
		return $node;
	}

	/**
	 * Returns singular or plural of a text determined by the value of {@see $count}.
	 *
	 * Example: If you have the text value "tree(s)" and you prepend an amount
	 * like 1 or 2 to it you'll get something like "1 tree(s)" or "2 tree(s)".
	 * This function determines singular and plurals by the amount. This results
	 * in "1 tree" and "2 trees".
	 * The value inside the brackets is the plural appendix.
	 *
	 * @access protected
	 * @return String Singular or plural text.
	 * @param String $text Unquantified text.
	 * @param Integer $count Amount to be quantified.
	 */
	protected static function getTextByCount($text, $count)
	{
		if(strlen($text) > 0)
		{
			preg_match('/\((.+)\)/', $text, $regs, PREG_OFFSET_CAPTURE);
			$fill = '';
			if(isset($regs[1][0]))
			{
				$x = explode('|', $regs[1][0]); // If there are different notations for singular and plural
				if($count != 1)
					$fill = $x[count($x) - 1]; // if is not 1 then choose last element (plural)
				elseif(count($x) > 1)
					$fill = $x[0];
			}
			else
			{
				$regs[0][0] = null;
				$regs[0][1] = null;
			}
			return substr_replace($text, $fill, $regs[0][1], strlen($regs[0][0]));
		}
		return null;
	}

	/**
	 * Returns a text-token in one language.
	 *
	 * @access public
	 * @return String The translated text
	 * @param string $token The token which will be translated
	 * @param string $language
	 * @see $translation
	 */
	public static function getTranslationByLanguage($token, $language)
	{
		if(isset(self::$translation[$token][$language]))
			return self::$translation[$token][$language];
		return new DomElement('translation', $token);
	}

	/**
	 * Get user preferred language sent by the browser HTTP-header.
	 *
	 * @access public
	 * @return String
	 */
	public static function getPreferredLanguage()
	{
		return $GLOBALS['filesystem']->getDefaultLanguage();
	}

	public static function tokenExists($token)
	{
		return array_key_exists($token, self::$translation);
	}
}
Return current item: Mocovie web framework