Index: trunk/phpgwapi/inc/class.expressolivre.inc.php
===================================================================
--- trunk/phpgwapi/inc/class.expressolivre.inc.php	(revision 2704)
+++ trunk/phpgwapi/inc/class.expressolivre.inc.php	(revision 2712)
@@ -27,4 +27,30 @@
 		);
 	}
+
+	function lang( $param )
+	{
+		$lang = ( array_key_exists( 'lang', $param ) ) ? $param[ 'lang' ] : false;
+		$module = ( array_key_exists( 'module', $param ) ) ? $param[ 'module' ] : false;
+
+		if ( ! ( $lang && $module ) )
+			return '{}';
+
+		$array_keys = array( );
+		$fn = dirname( __FILE__ ) . "/../../{$module}/setup/phpgw_{$lang}.lang";
+		$lang = array( );
+
+		if ( file_exists( $fn ) )
+		{
+			$fp = fopen( $fn, 'r' );
+			while ( $data = fgets( $fp, 16000 ) )
+			{
+				list( $message_id, $app_name, $null, $content ) = explode( "\t", substr( $data, 0, -1 ) );
+				$lang[ ] = '"' . str_replace( '"', '\"', strtolower( $message_id ) ) . '" : "' . str_replace( '"', '\"', $content ) . '"';
+			}
+			fclose( $fp );
+		}
+
+		return '{' . implode( ",\n", $lang ) . '}';
+	}
 }
 
Index: trunk/phpgwapi/js/tools/xlink.js
===================================================================
--- trunk/phpgwapi/js/tools/xlink.js	(revision 2710)
+++ trunk/phpgwapi/js/tools/xlink.js	(revision 2712)
@@ -17,5 +17,7 @@
 			_action = window.location.protocol + '//' + window.location.host + _action;
 
-		if ( _action == _last_request )
+		var _post = ( arguments.length == 3 && arguments[ 2 ] && arguments[ 2 ].constructor == String ) ? arguments[ 2 ] : null;
+
+		if ( _post == null && _action == _last_request )
 			return false;
 
@@ -36,5 +38,6 @@
 			'access' : _action,
 			'cache' : _cache,
-			'handler' : _handler
+			'handler' : _handler,
+			'post' : _post
 		} );
 
@@ -148,6 +151,10 @@
 		_click( arguments[ 0 ],
 			(
-				( arguments.length > 1 && arguments[ 1 ].constructor == Boolean ) ?
+				( arguments.length > 1 && arguments[ 1 ] && arguments[ 1 ].constructor == Boolean ) ?
 					arguments[ 1 ] : false
+			),
+			(
+				( arguments.length > 2 && arguments[ 2 ] && arguments[ 2 ].constructor == String ) ?
+					arguments[ 2 ] : null
 			)
 		);
Index: trunk/phpgwapi/js/tools/xobject.js
===================================================================
--- trunk/phpgwapi/js/tools/xobject.js	(revision 2665)
+++ trunk/phpgwapi/js/tools/xobject.js	(revision 2712)
@@ -21,5 +21,5 @@
 	String.prototype.trim = function( )
 	{
-		return this.replace( /^ +| +$/g, '' );
+		return this.replace( /^\s+|\s+$/g, '' );
 	};
 
Index: trunk/phpgwapi/js/tools/xconnector.js
===================================================================
--- trunk/phpgwapi/js/tools/xconnector.js	(revision 2685)
+++ trunk/phpgwapi/js/tools/xconnector.js	(revision 2712)
@@ -218,5 +218,5 @@
 			'_ACCESS'	: _argv.access,
 			'_HANDLER'	: { },
-			'_POST'		: ( ( _argv.post ) ? _argv.post : false ),  // [GET | POST]
+			'_POST'		: ( ( _argv.post && _argv.post != null ) ? _argv.post : false ),  // [GET | POST]
 			'_MODE'		: 'TEXT', // [XML | TEXT]
 			'_TYPE'		: null,	// [4 for request | 3 for stream]
Index: trunk/phpgwapi/js/expressolivre/expressolivre.js
===================================================================
--- trunk/phpgwapi/js/expressolivre/expressolivre.js	(revision 2707)
+++ trunk/phpgwapi/js/expressolivre/expressolivre.js	(revision 2712)
@@ -6,7 +6,30 @@
 	var _xlink = null;
 
+	window.array_lang = [ ];
+
+	var _language = [ ]
+
 	function _go( )
 	{
 		_xconnector.go.apply( _xconnector, arguments );
+	}
+
+	function _lang( )
+	{
+		if ( ! ( arguments.length && arguments[ 0 ].constructor == String ) )
+			return false;
+
+		var module = arguments[ 0 ];
+		var lang = document.getElementsByTagName( 'html' ).item( 0 ).getAttribute( 'xml:lang' );
+
+		_xconnector.go( {
+			'access' : 'phpgwapi.expressolivre.lang&lang=' + lang + '&module=' + module,
+			'handler' : function( data )
+			{
+				data = data.JSON( );
+				for ( var key in data )
+					window.array_lang[ key ] = _language[ key ] = data[ key ];
+			}
+		} );
 	}
 
@@ -31,4 +54,17 @@
 	}
 
+	function _translate( )
+	{
+		if ( ! ( arguments.length && arguments[ 0 ].constructor == String ) )
+			return false;
+
+		var _phrase = arguments[ 0 ];
+
+		if ( _language[ _phrase.toLowerCase( ) ] )
+			return _language[ _phrase.toLowerCase( ) ];
+		else
+			return _phrase + '*';
+	}
+
 	function _ExpressoLivre( )
 	{
@@ -36,8 +72,10 @@
 		{
 			this.go = _go;
+			this.lang = _lang;
 			this.link = _link;
 			this.path = _path;
 			this.theme = _theme;
 			this.template = _template;
+			this.translate = _translate;
 		} );
 	}
