Location: PHPKode > scripts > Universal Language Tool for PHP > universal-language-tool-for-php/ult.php
<?php

/********************************************************************
 *
 *  Project: UNIVERSAL LANGUAGE TOOL
 *  Version: 0.4.1
 *  
 *  The goal of this library is to provide complete, feature rich 
 *  but easy to use API for multilanguage support.
 *
 *  Features:
 *  
 *  - single file library
 *  - it does not depend on any other library
 *  - allows use of unlimited number of languages
 *  - allows using different scripts for the same language 
 *    (conversion from cyrillic to latin characters, for instance)
 *  - to add new language, you do not have to write any code, but just to 
 *    create language definition, dictionaires and conversion tables 
 *  - library does not just replace predefined macros with language 
 *    expressions but also does character conversions if necessary
 *
 *  This is free software. You may use it and redistribute it. You 
 *  may change code to suit your needs but you may not distribute 
 *  changed code.
 *
 *  Author: Predrag Supurovic
 *
 *  (c)2004 Copyright by DataVoyage, http://www.datavoyage.com/
 *
/********************************************************************/


  define ('LANG_DEF_FILE', 'ldef_');
  define ('LANG_DICT_FILE', 'ldct');
  
  define ('ERROR_NO_LNG_DEF_FILE', 'Cannot find language definition file');
  define ('ERROR_NO_LNG_DICT_FILE', 'Cannot find language dictionary file');
  

  class ULT {  

    var $source_language = ''; 
	// language used in design mode for text, and naming documents
	// When you create site you create it as it is single language butuse this language.
	// Also, when you need to load external documents use this language in naming them (document has to be ended with =<langid>=
	
	var $display_language = '';	
	// language that should be displayed for current user. Library will know how to handle 
	// contents prepared in source language and display it in current language
	
	var $lang_defs;
    // Global var $lang_defs contains info about supported language definitions and dictionaires. 
    // Definitions are stored as multidimensional array. The top array is indexed by language id, 
	// and each record contains arrays with definitions for specific language. Language definition 
	// is also multidimensional array
    // Structure:
	//  $lang_defs;
    //  [language id] => Array
    //     [id] => language id
    //     [name] => language name, used for description
	//     [codepage] => codepage that should be seto for HTML document to present text using this language
	//     [is_source_lng] => 1, if this language is source language for site
	//     [parent] => languge id of parent language
    //     [dictionary] => Array
    //        [dictionary item] => value
    //        [dictionary item] => value
    //        [dictionary item] => value
    //        [dictionary itm] => value
	//     [parent_conversion_table] => Array
    //        [source string] => replacement string
    //        [source string] => replacement string
    //        [source string] => replacement string
    //        [source string] => replacement string
    //
    // This allows using multiple languages on the same page. It is not recomended to store complete dictionaires 
    // for multiple languages to preserve memory resources. Store only limited number of items which are needed to be
    // presented in several lanbguages on the same page like language names
	

    // function ULT($p_lang_dir = 'lang/')
    // Constructor function. Call this to create object. Optional parameter 
    // is path to directory where language definition files are stored. 
    function ULT($p_lang_dir = 'lang/') {
      $this->lang_dir = $p_lang_dir;
      $this->load_language_defs();
	  
    }

    //
    // function process($tpl_source)
    //
    // Do all language processing:
    //  - replaces all language macros with items according to dictionary
    //  - replaces all family id's in document (targeted to urls to external documents and links)
    //  - replaces all language id's in document (targeted to urls to external documents and links)
    //  - tanscribes characters and phrases from one language to another (or one language script to another)
    function process($tpl_source) {
      $m_slng = $this->source_language;
      $m_dlng = $this->display_language;
      $m_slngf = $this->get_family ($this->source_language);
      $m_dlngf = $this->get_family ($this->display_language);
	  

      // Replace the matched language strings with the entry in the file 
      $m_result = preg_replace_callback('/##(.+?)##/', array(&$this, '_compile_lang'), $tpl_source); 

      $m_file_lng_pattern = "/=%25$m_slngf=/";
      $m_file_lng_replace = "=%25$m_dlngf=";

	  $m_result = preg_replace($m_file_lng_pattern, $m_file_lng_replace, $m_result); 

      $m_file_lng_pattern = "/=$m_slng=/";
      $m_file_lng_replace = "=$m_dlng=";
	  $m_result = preg_replace($m_file_lng_pattern, $m_file_lng_replace, $m_result); 
	  
      $m_result = $this->transcribe_document($m_result);
      return $m_result;
    }

  
    //
    // _compile_lang 
    // Called by language_process to replace each language macro with actual text
    //
    function _compile_lang($p_key) { 
      //global $lang_defs;
	  
      if ($this->lang_defs[$this->display_language]['dictionary'] 
	      and ($this->lang_defs[$this->display_language]['dictionary'][$p_key[1]])) 
	  {
        $m_result = $this->lang_defs[$this->display_language]['dictionary'][$p_key[1]];
      } else {
        $m_result = $p_key[0];
      }
      return $m_result;
    }


    // 
    // set_display_language ($p_lang)
    // Set display language to $p_lang. If invalid language, set to source language.
    //
    function set_display_language ($p_lang) {
	  //global $lang_defs;

	  if ($this->language_defined ($p_lang)) {
	    $this->display_language = $p_lang;
	  } else {
        $this->display_language = $this->source_language;
	  }
	}

	
    // 
    // set_default_language ($p_lang)
    // Set default language to $p_lang. If invalid language, set first language in array.
    //
    function set_source_language ($p_lang) {
   	  //global $lang_defs;
	  
	  if ($this->language_defined ($p_lang)) {
	    $this->source_language = $p_lang;
	  } else {
	    $m_keys = array_keys($this->lang_defs);
   	    $this->source_language = $m_keys[0];
	  }
	}
	

    // 
    // set_language ($p_lang, $p_lang_dir)
    // Set language definition (add sub_array to $lang_defs)
    //
    function set_language_def ($p_lang, $p_lang_dir = '') {
      //global $lang_defs;
	  
  	  if (! $p_lang_dir) $p_lang_dir = $this->lang_dir;
	  
      $m_langdef = $p_lang_dir . '/' . LANG_DEF_FILE . $p_lang . '.php';
	  
      if (file_exists($m_langdef)) {
        include ($m_langdef);
		$this->lang_defs[$p_lang] = $lng_def;

		if ($this->lang_defs[$p_lang]['is_source_lng'] == 1) {
		  $this->set_source_language ($p_lang);
		  $this->set_display_language ($p_lang);
		}
      } else {
	    echo ERROR_NO_LNG_DEF_FILE . ' (' . $m_langdef . ')';
      }
    }
	
	//
	// load_language_defs($p_lang_dir = '')
	// Load definitions from all language definition files in target directory.
	// If directory is not specified, current directory is used.
	//
	function load_language_defs($p_lang_dir = '') {
      //global $lang_defs;
	  	
  	  if (! $p_lang_dir) $p_lang_dir = $this->lang_dir;

      if ($handle = opendir($p_lang_dir)) {
        while (false !== ($file = readdir($handle))) { 
          if (preg_match ("/^" . LANG_DEF_FILE ."(.*).php/i", $file)) {
		    $m_lang = substr($file, strlen(LANG_DEF_FILE), strlen($file)-strlen(LANG_DEF_FILE)-4);
            $this->set_language_def ($m_lang, $p_lang_dir);
			$m_lang_dict = $p_lang_dir . '/' . LANG_DICT_FILE . '_';
			$this->set_dictionary ($m_lang_dict, $m_lang);
		  }  
        }
		
		asort ($this->lang_defs);
		
        if (! $this->source_language) {
		  $this->set_source_language ('');
		  $this->set_display_language ($this->source_language);
		}

      } else {
	    echo ERROR_LOADING_LANG_DEFS . ' (Directory: ' . $p_lang_dir . ')';
	  }
	}
	
	
	//  
	//  function language_defined ($p_lang)
	//  Returns true if language definition is loaded
	//
	function language_defined ($p_lang) {
	  //global $lang_defs;
	  if ($p_lang) {
	    return isset ($this->lang_defs[$p_lang]);
	  } else {
	    return false;
	  }
	}
	
	
	//
	// function display_language_has_parent()
	// returnbs true if display language has parent
	//
	function display_language_has_parent() {
      //global $lang_defs;
	  
	  $m_disp_lang = $this->lang_defs[$this-$display_language];
	  return $m_disp_lang['parent'] and $this->language_defined ($m_disp_lang['parent']);
	}

    //
	// transcribe ($p_text, $p_trans_table)
	// Convert characters from one script to another using transcription table
	//
	function transcribe ($p_text, $p_trans_table) {
	  if ($p_trans_table) {
  	    return strtr ($p_text, $p_trans_table);
	  } else {
  	    return $p_text;
	  }
	}


    //
	// transcribe_dictionary ($p_lang, $p_dictionary)
	// Convert dictionary array from parent language to current. Used to transcribe from 
	// different codepage or script. If dictionary for the language may be created by 
	// transcribing parent's dictionary then do this a nd do not define whole ditionary again.
	// That will make dictionary maintenance easier.
	//
	function transcribe_dictionary ($p_lang, $p_dictionary) {
	  //global $lang_defs;
	  
	  if ($p_dictionary) {
	    foreach ($p_dictionary as $key => $value) {
	      $p_dictionary[$key] = $this->transcribe($value, $this->lang_defs[$p_lang]['parent_conversion_table']);
	    }
	  }
	  return $p_dictionary;
	}

    //
	// transcribe_parent_language_dictionary ($p_lang)
	// Convert dictionary of loaded parent language to current. Used to transcribe from different codepage or script.
	//
	function transcribe_parent_language_dictionary ($p_lang) {
	  //global $lang_defs;
	  
	  $this->lang_defs[$p_lang]['dictionary'] = $this->transcribe_dictionary ($p_lang, $this->lang_defs[$p_lang]['dictionary']);
	  
//	  foreach ($lang_defs[$p_lang]['dictionary'] as $key => $value) {
//	    $this->lang_defs[$p_lang]['dictionary'][$key] = $this->transcribe($value, $this->lang_defs[$p_lang]['parent_conversion_table']);
//	  }
	  
	}
	
    //
	// transcribe_document ($p_lang)
	// If display language has parent language and source document is written in parent language then we should 
	//  transcribe document contents from parent language to display language
	//
	function transcribe_document($p_doc) {
	  //global $lang_defs;
	  
	  $m_disp_lang = $this->lang_defs[$this->display_language];
	  $m_src_lang = $this->lang_defs[$this->source_language];
	  
	  if ($m_disp_lang['parent']
	      and ($m_disp_lang['id'] != $m_src_lang['id'])
		  and ($m_disp_lang['parent'] == $m_src_lang['id'])) 
	  {
        return $this->transcribe($p_doc, $m_disp_lang['parent_conversion_table']);
  	  } else {
	    return $p_doc;
	  }
	}
	

    //
	// function filename_from_template ($p_dict_filename, $p_lang)
	// Creates full file name based on template and language
	// If language has parent then filename will be created due to parent language
	// Always use this to load files that corresponds to needed language.
	//
	function filename_from_template ($p_dict_filename, $p_lang, $do_parent = true) {
	  //global $lang_defs;
	  
      $m_fname = $p_dict_filename;
	  if ($do_parent and $this->lang_defs[$p_lang]['parent']) {
	    $m_fname .= $this->lang_defs[$p_lang]['parent'];
	  } else {
  	    $m_fname .= $p_lang;
	  }
	  $m_fname .= '.php';
	  
	  return $m_fname;
    }
	
	
    // 
    // load_dictionary ($p_dict_filename, $p_lang, $p_add = false)
    // Load dictionary table from specified file into specified language definition. 
	// If $p_add is true then definition is appended to alerady existing definitions.
    // 
    function load_dictionary ($p_dict_filename, $p_lang, $p_add = false) {
   	  //global $lang_defs;
	  
      if (file_exists($p_dict_filename)) {
        include ($p_dict_filename);
		
        $this->lang_defs[$p_lang]['parent_conversion_table'] = array_merge ($this->lang_defs[$p_lang]['parent_conversion_table'], $lngt);
	    if ($this->lang_defs[$p_lang]['parent']) {
		  $lng = $this->transcribe_dictionary ($p_lang, $lng);
	    }

        if ($p_add == 0) {
          $this->lang_defs[$p_lang]['dictionary'] = $lng;
	    } else {
    	  $this->lang_defs[$p_lang]['dictionary'] = array_merge ($this->lang_defs[$p_lang]['dictionary'], $lng);
		}
      }
   }
	


    // 
    // set_dictionary ($p_dict_filename, $p_lang, $p_add = false)
    // Load dictionary table from specified file into specified language definition. 
	// If $p_add is true then definition is appended to alerady existing definitions.
	// If language has parent, then parent's file will be loaded first and after that 
	// child's file. This helps dictionary maintenance. Most of the items may be stored in 
	// parent's dictionary and only differences in childs dictionary (example, for 'en' as parent and 
	// 'en-us' as a child, most of the items are the same but some are not, like 
	// 'color'/'colour' pair. This allows you to have item 'colour' in parent dictionary of 'en' among 
	// all others and just item 'color' for 'child 'en-us'.
	// 
    // 
    function set_dictionary ($p_dict_filename, $p_lang, $p_add = false) {
   	  //global $lang_defs;

      $m_dictdef = $this->filename_from_template ($p_dict_filename, $p_lang);
	  
	  $this->load_dictionary ($m_dictdef, $p_lang, $p_add);
	  
	  if ($this->lang_defs[$p_lang]['parent']) {
  	    $m_dictdef = $this->filename_from_template ($p_dict_filename, $p_lang, false);
	    $this->load_dictionary ($m_dictdef, $p_lang, true);
	  }
   }
	
	
    // 
    // add_dictionary ($p_dict_filename, $p_lang)
    // Load dictionary table from specified file into specified language definition. 
	// It appends new definition to existing one.
    // 
    function add_dictionary ($p_dict_filename, $p_lang) {	
      $this->set_dictionary ($p_dict_filename, $p_lang, true);
	}
	
	
	//
	// sync_child_dictionary ($p_lang)
	// Synchronize child language dictionary with parent's
	// This will replace child dictionary with parent's (but transcribing it)
	//
	function sync_child_dictionary ($p_lang) {
  	  //global $lang_defs;
	  
	  if ($this->lang_defs[$p_lang]['parent'] 
		  and $this->language_defined($this->lang_defs[$p_lang]['parent'])) 
	  {
		$this->lang_defs[$p_lang]['dictionary'] = $this->lang_defs[$this->lang_defs[$p_lang]['parent']]['dictionary'];
		$this->transcribe_parent_language_dictionary ($p_lang);
	  }
	}
	
	//
	// is_family ($p_lang, $p_parent)
	// Check if language belongs to the family of languages (is parent or one of languages with same parent)
	//
	function is_family ($p_lang, $p_parent) {
	  //global $lang_defs;
	  
	  $m_lang = $this->lang_defs[$p_lang];
	  
	  return ($m_lang['id'] == $p_parent) or ($m_lang['parent'] == $p_parent);
	}


	//
	// get_family ($p_lang)
	// Return family which language belongs to
	//
	function get_family ($p_lang) {
	  //global $lang_defs;
	  
	  $m_lang = $this->lang_defs[$p_lang];
	  
	  if ($m_lang['parent']) {
	    return $m_lang['parent'];
	  } else {
 	    return $m_lang['id'];
	  }
	}
	
	
	//
	// block_start()
	// Begin output buffering. All output after this will be buffered so language replacements may be made.
	// 
	function block_start() {
      ob_start();
	}
	
	//
	// block_end()
	// End output buffering, do necessary language processing and display altered document.
	//
	function block_end() {
      $page_contents = ob_get_contents();
	  ob_end_clean();
      echo $this->process ($page_contents);
	}
 
  } // class ULT

?>
Return current item: Universal Language Tool for PHP