Index: /CKEditor/branches/prototype/_source/core/config.js
===================================================================
--- /CKEditor/branches/prototype/_source/core/config.js	(revision 2364)
+++ /CKEditor/branches/prototype/_source/core/config.js	(revision 2365)
@@ -88,4 +88,27 @@
 
 	/**
+	 * Instructs the editor to automatically localize the editor to the user
+	 * language, if possible. If set to false, the [@link #defaultLanguage]
+	 * language is used.
+	 * @default true
+	 * @type Boolean
+	 * @example
+	 * // Forces the editor to always load the German interface.
+	 * config.autoLanguage = false;
+	 * config.defaultLanguage = 'de';
+	 */
+	autoLanguage : true,
+
+	/**
+	 * The language to be used if [@link #autoLanguage] is set to false, or
+	 * when it's not possible to localize the editor to the user language.
+	 * @default 'en'
+	 * @type String
+	 * @example
+	 * config.defaultLanguage = 'it';
+	 */
+	defaultLanguage : 'en',
+
+	/**
 	 * A comma separated list of plugins that are not related to editor
 	 * instances. Reserved to plugins that extend the core code only.<br /><br />
Index: /CKEditor/branches/prototype/_source/core/editor.js
===================================================================
--- /CKEditor/branches/prototype/_source/core/editor.js	(revision 2364)
+++ /CKEditor/branches/prototype/_source/core/editor.js	(revision 2365)
@@ -50,5 +50,5 @@
 			return false;
 
-		var loadedConfig = loadConfigLoaded[ customConfig ] || ( loadConfigLoaded[ customConfig ] = { editors : [] } );
+		var loadedConfig = loadConfigLoaded[ customConfig ] || ( loadConfigLoaded[ customConfig ] = {} );
 
 		// If the custom config has already been downloaded, reuse it.
@@ -66,7 +66,4 @@
 		else
 		{
-			// Add the editor to the list of editors waiting for this config.
-			loadedConfig.editors.push( editor );
-
 			// Load the custom configuration file.
 			CKEDITOR.scriptLoader.load( customConfig, function()
@@ -79,14 +76,7 @@
 						loadedConfig.fn = function(){};
 
-					delete CKEDITOR.editorConfig;
-
-					for ( var i = 0, length = loadedConfig.editors.length ; i < length ; i++ )
-					{
-						// Call the load config again. This time the custom
-						// config is already cached and so it will get loaded.
-						loadConfig( loadedConfig.editors[ i ] );
-					}
-
-					delete loadedConfig.editors;
+					// Call the load config again. This time the custom
+					// config is already cached and so it will get loaded.
+					loadConfig( editor );
 				});
 		}
@@ -107,6 +97,5 @@
 				editor.fireOnce( 'configLoaded' );
 
-				// Start loading the plugins.
-				loadPlugins( editor );
+				loadLang( editor );
 			});
 
@@ -121,10 +110,20 @@
 	};
 
-	// Basic config class to inherit the default settings from CKEDITOR.config.
-	var config = function()
-	{};
-	config.prototype = CKEDITOR.config;
-
 	// ##### END: Config Privates
+
+	var loadLang = function( editor )
+	{
+		CKEDITOR.lang.load( editor.config.defaultLanguage, editor.config.autoLanguage, function( languageCode, lang )
+			{
+				editor.langCode = languageCode;
+
+				// As we'll be adding plugin specific entries that could come
+				// from different language code files, we need a copy of lang,
+				// not a direct reference to it.
+				editor.lang = CKEDITOR.tools.prototypedCopy( lang );
+
+				loadPlugins( editor );
+			});
+	};
 
 	var loadPlugins = function( editor )
@@ -133,21 +132,80 @@
 		CKEDITOR.plugins.load( editor.config.plugins.split( ',' ), function( plugins )
 			{
+				// The list of plugins.
+				var pluginsArray = [];
+
+				// The language code to get loaded for each plugin. Null
+				// entries will be appended for plugins with no language files.
+				var languageCodes = [];
+
+				// The list of URLs to language files.
+				var languageFiles = [];
+
 				// Cache the loaded plugin names.
 				editor.plugins = plugins;
 
-				// Initialize all plugins that have the "beforeInit" and "init" methods defined.
-				var methods = [ 'beforeInit', 'init' ];
-				for ( var m = 0 ; m < methods.length ; m++ )
+				// Loop through all plugins, to build the list of language
+				// files to get loaded.
+				for ( var pluginName in plugins )
 				{
-					for ( var pluginName in plugins )
+					var plugin = plugins[ pluginName ],
+						pluginLangs = plugin.lang,
+						pluginPath = CKEDITOR.plugins.getPath( pluginName ),
+						lang = null;
+
+					// Set the plugin path in the plugin.
+					plugin.path = pluginPath;
+
+					// If the plugin has "lang".
+					if ( pluginLangs )
 					{
-						var plugin = plugins[ pluginName ];
-						if ( plugin && plugin[ methods[ m ] ] )
-							plugin[ methods[ m ] ]( editor, CKEDITOR.plugins.getPath( pluginName ) );
+						// Resolve the plugin language. If the current language
+						// is not available, get the first one (default one).
+						lang = ( CKEDITOR.tools.indexOf( pluginLangs, editor.langCode ) >= 0 ? editor.langCode : pluginLangs[ 0 ] );
+
+						if ( !plugin.lang[ lang ] )
+						{
+							// Put the language file URL into the list of files to
+							// get downloaded.
+							languageFiles.push( CKEDITOR.getUrl( pluginPath + 'lang/' + lang + '.js' ) );
+						}
+						else
+						{
+							CKEDITOR.tools.extend( editor.lang, plugin.lang[ lang ] );
+							lang = null;
+						}
 					}
+
+					// Save the language code, so we know later which
+					// language has been resolved to this plugin.
+					languageCodes.push( lang );
+
+					pluginsArray.push( plugin );
 				}
 
-				// Load the editor skin and theme.
-				loadSkinTheme( editor );
+				// Load all plugin specific language files in a row.
+				CKEDITOR.scriptLoader.load( languageFiles, function()
+					{
+						// Initialize all plugins that have the "beforeInit" and "init" methods defined.
+						var methods = [ 'beforeInit', 'init' ];
+						for ( var m = 0 ; m < methods.length ; m++ )
+						{
+							for ( var i = 0 ; i < pluginsArray.length ; i++ )
+							{
+								var plugin = pluginsArray[ i ];
+
+								// Uses the first loop to update the language entries also.
+								if ( m === 0 && languageCodes[ i ] && plugin.lang )
+									CKEDITOR.tools.extend( editor.lang, plugin.lang[ languageCodes[ i ] ] );
+
+								// Call the plugin method (beforeInit and init).
+								if ( plugin[ methods[ m ] ] )
+									plugin[ methods[ m ] ]( editor );
+							}
+						}
+
+						// Load the editor skin and theme.
+						loadSkinTheme( editor );
+					});
 			});
 	};
@@ -162,6 +220,7 @@
 		CKEDITOR.themes.load( theme, function()
 			{
-				editor.theme = CKEDITOR.themes.get( theme );
-				editor.theme.build( editor, CKEDITOR.themes.getPath( theme ) );
+				var editorTheme = editor.theme = CKEDITOR.themes.get( theme );
+				editorTheme.path = CKEDITOR.themes.getPath( theme );
+				editorTheme.build( editor );
 			});
 	};
@@ -218,5 +277,5 @@
 			 * alert( <b>editor.config.theme</b> );  "default" e.g.
 			 */
-			this.config = new config();
+			this.config = CKEDITOR.tools.prototypedCopy( CKEDITOR.config );
 
 			/**
Index: /CKEditor/branches/prototype/_source/core/lang.js
===================================================================
--- /CKEditor/branches/prototype/_source/core/lang.js	(revision 2365)
+++ /CKEditor/branches/prototype/_source/core/lang.js	(revision 2365)
@@ -0,0 +1,111 @@
+﻿/*
+ * CKEditor - The text editor for Internet - http://ckeditor.com
+ * Copyright (C) 2003-2008 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ *  - GNU General Public License Version 2 or later (the "GPL")
+ *    http://www.gnu.org/licenses/gpl.html
+ *
+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ *    http://www.gnu.org/licenses/lgpl.html
+ *
+ *  - Mozilla Public License Version 1.1 or later (the "MPL")
+ *    http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ */
+
+(function()
+{
+	var loadedLangs = {};
+
+	CKEDITOR.lang =
+	{
+		/**
+		 * The list of languages available in the editor core.
+		 * @type Object
+		 * @example
+		 * alert( CKEDITOR.lang.en );  // "true"
+		 */
+		languages :
+		{
+			'ar'	: 1,
+			'en'	: 1,
+			'it'	: 1,
+			'pt-br'	: 1
+		},
+
+		/**
+		 * Loads a specific language file, or auto detect it. A callback is
+		 * then called when the file gets loaded.
+		 * @param {String} languageCode The code of the language file to be
+		 *		loaded. If "autoDetect" is set to true, this language will be
+		 *		used as the default one, if the detect language is not
+		 *		available in the core.
+		 * @param {Boolean} autoDetect Indicates that the function must try to
+		 *		detect the user language and load it instead.
+		 * @param {Function} callback The function to be called once the
+		 *		language file is loaded. Two parameters are passed to this
+		 *		function: the language code and the loaded language entries.
+		 * @example
+		 */
+		load : function( languageCode, autoDetect, callback )
+		{
+			if ( autoDetect )
+				languageCode = this.detect( languageCode );
+
+			if ( !this[ languageCode ] )
+			{
+				CKEDITOR.scriptLoader.load( CKEDITOR.getUrl(
+					'_source/' +	// TODO: Add @-Packager.RemoveLine to the final build process.
+					'lang/' + languageCode + '.js' ),
+					function()
+						{
+							callback( languageCode, this[ languageCode ] );
+						}
+						, this );
+			}
+			else
+				callback( this[ languageCode ] );
+		},
+
+		/**
+		 * Returns the language that best fit the user language. For example,
+		 * suppose that the user language is "pt-br". If this language is
+		 * supported by the editor, it is returned. Otherwise, if only "pt" is
+		 * supported, it is returned instead. If none of the previous are
+		 * supported, a default language is then returned.
+		 * @param {String} defaultLanguage The default language to be returned
+		 *		if the user language is not supported.
+		 * @returns {String} The detected language code.
+		 * @example
+		 * alert( CKEDITOR.lang.detect( 'en' ) );  // e.g., in a German browser: "de"
+		 */
+		detect : function( defaultLanguage )
+		{
+			var languages = this.languages;
+
+			var parts = ( navigator.userLanguage || navigator.language )
+					.toLowerCase()
+					.match( /([a-z]+)(?:-([a-z]+))?/ ),
+				lang = parts[1],
+				locale = parts[2];
+
+			if ( languages[ lang + '-' + locale ] )
+				lang = lang + '-' + locale;
+			else if ( !languages[ lang ] )
+				lang = null;
+
+			CKEDITOR.lang.detect = lang ?
+				function() { return lang; } :
+				function( defaultLanguage ) { return defaultLanguage; };
+
+			return lang || defaultLanguage;
+		}
+	};
+
+})();
Index: /CKEditor/branches/prototype/_source/core/loader.js
===================================================================
--- /CKEditor/branches/prototype/_source/core/loader.js	(revision 2364)
+++ /CKEditor/branches/prototype/_source/core/loader.js	(revision 2365)
@@ -40,6 +40,4 @@
 		var scripts =
 		{
-			'lang/en'				: [],	// TODO: Remove me. This should be handled by the localization code.
-
 			'core/_bootstrap'		: [ 'core/config', 'core/ckeditor', 'core/plugins', 'core/scriptLoader', 'core/tools', /* The following are entries that we wnat to force loading to at the end to avoid dependence recursion */ 'core/dom/text' ],
 			'core/ajax'				: [ 'core/xml' ],
@@ -57,5 +55,5 @@
 			'core/dom/window'		: [ 'core/dom/domobject' ],
 			'core/dtd'				: [ 'core/tools' ],
-			'core/editor'			: [ 'core/config', 'core/editor_basic', 'core/plugins', 'core/skins', 'core/themes', 'core/tools', 'core/ui' ],
+			'core/editor'			: [ 'core/config', 'core/editor_basic', 'core/lang', 'core/plugins', 'core/skins', 'core/themes', 'core/tools', 'core/ui' ],
 			'core/editor_basic'		: [ 'core/event' ],
 			'core/env'				: [],
@@ -66,9 +64,10 @@
 			'core/htmlparser/fragment'	: [ 'core/htmlparser', 'core/htmlparser/comment', 'core/htmlparser/text' ],
 			'core/htmlparser/text'		: [ 'core/htmlparser' ],
+			'core/lang'				: [],
 			'core/plugins'			: [ 'core/resourceManager' ],
 			'core/resourceManager'	: [ 'core/scriptLoader', 'core/tools' ],
 			'core/scriptLoader'		: [ 'core/dom/element', 'core/env' ],
 			'core/skins'			: [],
-			'core/themes'			: [ 'lang/en', 'core/resourceManager' ],
+			'core/themes'			: [ 'core/resourceManager' ],
 			'core/tools'			: [ 'core/env' ],
 			'core/ui'				: [],
Index: /CKEditor/branches/prototype/_source/core/plugins.js
===================================================================
--- /CKEditor/branches/prototype/_source/core/plugins.js	(revision 2364)
+++ /CKEditor/branches/prototype/_source/core/plugins.js	(revision 2365)
@@ -32,5 +32,5 @@
  */
 CKEDITOR.plugins = new CKEDITOR.resourceManager(
-	'_source/' +	// @Packager.RemoveLine
+	'_source/' +	// TODO: Set @-Packager.RemoveLine
 	'plugins/', 'plugin' );
 
@@ -75,2 +75,8 @@
 		};
 	});
+
+CKEDITOR.plugins.setLang = function( pluginName, languageCode, languageEntries )
+{
+	var plugin = this.get( pluginName );
+	plugin.lang[ languageCode ] = languageEntries;
+};
Index: /CKEditor/branches/prototype/_source/core/resourcemanager.js
===================================================================
--- /CKEditor/branches/prototype/_source/core/resourcemanager.js	(revision 2364)
+++ /CKEditor/branches/prototype/_source/core/resourcemanager.js	(revision 2365)
@@ -127,5 +127,5 @@
 	getPath : function( name )
 	{
-		return this.loaded[ name ] || null;
+		return this.externals[ name ] || this.basePath + name + '/';
 	},
 
@@ -158,83 +158,54 @@
 	 * <b>CKEDITOR.plugins.load</b>( 'myplugin', function( plugins )
 	 *     {
-	 *         alert( plugins[0] );  // "myplugin"
+	 *         alert( plugins['myplugin'] );  // "object"
 	 *     });
 	 */
-	load : function( name, callback, scope )
-	{
-		// Ensure that we have an Array of names.
-		var names = CKEDITOR.tools.isArray( name ) ? name : name ? [ name ] : [],
-			total = names.length,
+	load : function( names, callback, scope )
+	{
+		// Ensure that we have an array of names.
+		if ( !CKEDITOR.tools.isArray( names ) )
+			names = names ? [ names ] : [];
+
+		var loaded = this.loaded,
+			registered = this.registered,
+			urls = [],
+			urlsNames = {},
 			resources = {};
-
-		// Nothing to load, just call the callback.
-		if ( !total )
-		{
-			callback.call( scope || window, resources );
-			return;
-		}
-
-		// This function is used to count the loaded plugins and call the
-		// callback when finished loading.
-		callback._loaded = 0;
-		callback._total = total;
-		var loadCheck = function( callback )
-		{
-			if ( ++callback._loaded == callback._total )
-				callback.call( scope || window, resources );
-		};
-
-		var loaded = this.loaded,
-			waitingList = this._.waitingList;
-
-		var loadPlugin = function( name )
-		{
-			// Calculate the plugin script path.
-			var path = this.externals[ name ] || ( this.basePath + name + '/' ),
-				filePath = CKEDITOR.getUrl( path + this.fileName + '.js' );
-
-			// Load the plugin script.
-			CKEDITOR.scriptLoader.load( filePath, function( success )
-				{
-					if ( !success )
-						throw '[CKEDITOR.resourceManager.load] Resource name "' + name + '" was not found at "' + filePath + '".';
-
-					loaded[ name ] = path;
-
-					resources[ name ] = this.get( name );
-
-					// Check all callbacks that were waiting for this
-					// resource.
-					for ( var j = 0 ; j < waitingInfo.length ; j++ )
-						loadCheck( waitingInfo[ j ] );
-
-					delete waitingList[ name ];
-				}, this);
-		};
 
 		// Loop through all names.
 		for ( var i = 0 ; i < names.length ; i++ )
 		{
-			name = names[ i ];
-
-			if ( name && typeof resources[ name ] == 'undefined' )
+			var name = names[ i ];
+
+			if ( !name )
+				continue;
+
+			// If not available yet.
+			if ( !loaded[ name ] && !registered[ name ] )
 			{
+				var url = CKEDITOR.getUrl( this.getPath( name ) + this.fileName + '.js' );
+				urls.push( url );
+				urlsNames[ url ] = name;
+			}
+			else
 				resources[ name ] = this.get( name );
-
-				// If not loaded already.
-				if ( !loaded[ name ] && !this.registered[ name ] )
+		}
+
+		CKEDITOR.scriptLoader.load( urls, function( completed, failed )
+			{
+				if ( failed.length )
+					throw '[CKEDITOR.resourceManager.load] Resource name "' + urlsNames[ failed[ 0 ] ] + '" was not found at "' + failed[ 0 ] + '".';
+
+				for ( var i = 0 ; i < completed.length ; i++ )
 				{
-					var waitingInfo = waitingList[ name ] || ( waitingList[ name ] = [] );
-					waitingInfo.push( callback );
-
-					// If this is the first call for it, go ahead loading.
-					if ( waitingInfo.length == 1 )
-						loadPlugin.call( this, name );
-
-					continue;
+					var name = urlsNames[ completed[ i ] ];
+					resources[ name ] = this.get( name );
+
+					loaded[ name ] = 1;
 				}
+
+				callback.call( scope, resources );
 			}
-			loadCheck( callback );
-		}
+			, this);
 	}
 };
Index: /CKEditor/branches/prototype/_source/core/scriptloader.js
===================================================================
--- /CKEditor/branches/prototype/_source/core/scriptloader.js	(revision 2364)
+++ /CKEditor/branches/prototype/_source/core/scriptloader.js	(revision 2365)
@@ -33,19 +33,23 @@
 {
 	var uniqueScripts = {};
+	var waitingList = {};
 
 	return /** @lends CKEDITOR.scriptLoader */ {
 		/**
-		 * Loads an external script checking if it hasn't been already loaded
+		 * Loads one or more external script checking if not already loaded
 		 * previously by this function.
-		 * @param {String} scriptUrl The URL pointing to the external script to
-		 *		be loaded.
+		 * @param {String|Array} scriptUrl One or more URLs pointing to the
+		 *		scripts to be loaded.
 		 * @param {Function} [callback] A function to be called when the script
-		 *		is loaded and executed
+		 *		is loaded and executed. If a string is passed to "scriptUrl", a
+		 *		boolean parameter is passed to the callback, indicating the
+		 *		success of the load. If an array is passed instead, two array
+		 *		parameters are passed to the callback; the first contains the
+		 *		URLs that have been properly loaded, and the second the failed
+		 *		ones.
 		 * @param {Object} [scope] The scope ("this" reference) to be used for
 		 *		the callback call. Default to {@link CKEDITOR}.
 		 * @param {Boolean} [noCheck] Indicates that the script must be loaded
 		 *		anyway, not checking if it has already loaded.
-		 * @returns {Boolean} A boolean indicating that the script has been
-		 *		loaded. Returns false if it has already been loaded previously.
 		 * @example
 		 * CKEDITOR.scriptLoader.load( '/myscript.js' );
@@ -57,64 +61,129 @@
 		 *         alert( success );
 		 *     });
+		 * @example
+		 * CKEDITOR.scriptLoader.load( [ '/myscript1.js', '/myscript2.js' ], function( completed, failed )
+		 *     {
+		 *         alert( 'Number of scripts loaded: ' + completed.length );
+		 *         alert( 'Number of failures: ' + failed.length );
+		 *     });
 		 */
 		load : function( scriptUrl, callback, scope, noCheck )
 		{
-			if ( noCheck !== true )
-			{
-				if ( uniqueScripts[ scriptUrl ] )
-					return false;
-
-				uniqueScripts[ scriptUrl ] = true;
+			var isString = ( typeof scriptUrl == 'string' );
+
+			if ( isString )
+				scriptUrl = [ scriptUrl ];
+
+			if ( !scope )
+				scope = CKEDITOR;
+
+			var scriptCount = scriptUrl.length,
+				completed = [],
+				failed = [];
+
+			var doCallback = function( success )
+			{
+				if ( callback )
+				{
+					if ( isString )
+						callback.call( scope, success );
+					else
+						callback.call( scope, completed, failed );
+				}
+			};
+
+			if ( scriptCount === 0 )
+			{
+				doCallback( true );
+				return;
 			}
 
-			// Create the <script> element.
-			var script = new CKEDITOR.dom.element( 'script' );
-			script.setAttributes( {
-				type : 'text/javascript',
-				src : scriptUrl } );
-
-			if ( callback )
-			{
-				if ( !scope )
-					scope = CKEDITOR;
-
-				if ( CKEDITOR.env.ie )
+			var checkLoaded = function( url, success )
+			{
+				( success ? completed : failed).push( url );
+
+				if ( --scriptCount <= 0 )
+					doCallback( success );
+			};
+
+			var onLoad = function( url, success )
+			{
+				// Mark this script as loaded.
+				uniqueScripts[ url ] = 1;
+
+				// Get the list of callback checks waiting for this file.
+				var waitingInfo = waitingList[ url ];
+				delete waitingList[ url ];
+
+				// Check all callbacks waiting for this file.
+				for ( var i = 0 ; i < waitingInfo.length ; i++ )
+					waitingInfo[ i ]( url, success );
+			};
+
+			var loadScript = function( url )
+			{
+				if ( noCheck !== true && uniqueScripts[ url ] )
 				{
-					// FIXME: For IE, we are not able to return false on error (like 404).
-
-					/** @ignore */
-					script.$.onreadystatechange = function ()
+					checkLoaded( url, true );
+					return;
+				}
+
+				var waitingInfo = waitingList[ url ] || ( waitingList[ url ] = [] );
+				waitingInfo.push( checkLoaded );
+
+				// Load it only for the first request.
+				if ( waitingInfo.length > 1 )
+					return;
+
+				// Create the <script> element.
+				var script = new CKEDITOR.dom.element( 'script' );
+				script.setAttributes( {
+					type : 'text/javascript',
+					src : url } );
+
+				if ( callback )
+				{
+					if ( CKEDITOR.env.ie )
 					{
-						if ( script.$.readyState == 'loaded' || script.$.readyState == 'complete' )
+						// FIXME: For IE, we are not able to return false on error (like 404).
+
+						/** @ignore */
+						script.$.onreadystatechange = function ()
 						{
-							script.$.onreadystatechange = null;
-							callback.call( scope, true );
-						}
-					};
+							if ( script.$.readyState == 'loaded' || script.$.readyState == 'complete' )
+							{
+								script.$.onreadystatechange = null;
+								onLoad( url, true );
+							}
+						};
+					}
+					else
+					{
+						/** @ignore */
+						script.$.onload = function()
+						{
+							onLoad( url, true );
+						};
+
+						// FIXME: Opera and Safari will not fire onerror.
+
+						/** @ignore */
+						script.$.onerror = function()
+						{
+							onLoad( url, false );
+						};
+					}
 				}
-				else
-				{
-					/** @ignore */
-					script.$.onload = function()
-					{
-						callback.call( scope, true );
-					};
-
-					// FIXME: Opera and Safari will not fire onerror.
-
-					/** @ignore */
-					script.$.onerror = function()
-					{
-						callback.call( scope, false );
-					};
-				}
+
+				// Append it to <head>.
+				script.appendTo( CKEDITOR.document.getHead() );
+
+				CKEDITOR.fire( 'download', url );		// @Packager.RemoveLine
+			};
+
+			for ( var i = 0 ; i < scriptCount ; i++ )
+			{
+				loadScript( scriptUrl[ i ] );
 			}
-
-			// Append it to <head>.
-			script.appendTo( CKEDITOR.document.getHead() );
-
-			CKEDITOR.fire( 'download', scriptUrl );		// @Packager.RemoveLine
-
-			return true;
 		},
 
Index: /CKEditor/branches/prototype/_source/core/tools.js
===================================================================
--- /CKEditor/branches/prototype/_source/core/tools.js	(revision 2364)
+++ /CKEditor/branches/prototype/_source/core/tools.js	(revision 2365)
@@ -119,4 +119,21 @@
 
 		return target;
+	},
+
+	/**
+	 * Creates an object which is an instance of a class which prototype is a
+	 * predefined object. All properties defined in the source object are
+	 * automatically inherited by the resulting object, including future
+	 * changes to it.
+	 * @param {Object} source The source object to be used as the prototype for
+	 *		the final object.
+	 * @returns {Object} The resulting copy.
+	 */
+	prototypedCopy : function( source )
+	{
+		var copy = function()
+		{};
+		copy.prototype = source;
+		return new copy();
 	},
 
@@ -323,4 +340,24 @@
 			return str.replace( trimRegex, '' ) ;
 		};
-	})()
+	})(),
+
+	/**
+	 * Returns the index of an element in an array.
+	 * @param {Array} array The array to be searched.
+	 * @param {Object} entry The element to be found.
+	 * @returns {Number} The (zero based) index of the first entry that matches
+	 *		the entry, or -1 if not found.
+	 * @example
+	 * var letters = [ 'a', 'b', 'c' ];
+	 * alert( CKEDITOR.tools.indexOf( letters, 'b' ) );  "1"
+	 */
+	indexOf : function( array, entry )
+	{
+		for ( var i = 0, len = array.length ; i < len ; i++ )
+		{
+			if ( array[ i ] == entry )
+				return i;
+		}
+		return -1;
+	}
 };
Index: /CKEditor/branches/prototype/_source/lang/ar.js
===================================================================
--- /CKEditor/branches/prototype/_source/lang/ar.js	(revision 2365)
+++ /CKEditor/branches/prototype/_source/lang/ar.js	(revision 2365)
@@ -0,0 +1,49 @@
+﻿/*
+ * CKEditor - The text editor for Internet - http://ckeditor.com
+ * Copyright (C) 2003-2008 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ *  - GNU General Public License Version 2 or later (the "GPL")
+ *    http://www.gnu.org/licenses/gpl.html
+ *
+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ *    http://www.gnu.org/licenses/lgpl.html
+ *
+ *  - Mozilla Public License Version 1.1 or later (the "MPL")
+ *    http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ */
+
+/**
+ * @fileOverview Defines the {@link CKEDITOR.lang} object, for the English
+ *		language. This is the base file for all translations.
+ */
+
+/**#@+
+   @type String
+   @example
+*/
+
+/**
+ * Constains the dictionary of language entries.
+ * @namespace
+ */
+CKEDITOR.lang['ar'] =
+{
+	/**
+	 * The language reading direction. Possible values are "rtl" for
+	 * Right-To-Left languages (like Arabic) and "ltr" for Left-To-Right
+	 * languages (like English).
+	 * @default 'ltr'
+	 */
+	dir : 'rtl',
+
+	// Toolbar buttons.
+	bold	: 'غامق',
+	italic	: 'مائل'
+};
Index: /CKEditor/branches/prototype/_source/lang/en.js
===================================================================
--- /CKEditor/branches/prototype/_source/lang/en.js	(revision 2364)
+++ /CKEditor/branches/prototype/_source/lang/en.js	(revision 2365)
@@ -34,5 +34,5 @@
  * @namespace
  */
-CKEDITOR.lang =
+CKEDITOR.lang['en'] =
 {
 	/**
@@ -42,4 +42,8 @@
 	 * @default 'ltr'
 	 */
-	dir : 'ltr'
+	dir : 'ltr',
+
+	// Toolbar buttons.
+	bold	: 'Bold',
+	italic	: 'Italic'
 };
Index: /CKEditor/branches/prototype/_source/lang/it.js
===================================================================
--- /CKEditor/branches/prototype/_source/lang/it.js	(revision 2365)
+++ /CKEditor/branches/prototype/_source/lang/it.js	(revision 2365)
@@ -0,0 +1,28 @@
+﻿/*
+ * CKEditor - The text editor for Internet - http://ckeditor.com
+ * Copyright (C) 2003-2008 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ *  - GNU General Public License Version 2 or later (the "GPL")
+ *    http://www.gnu.org/licenses/gpl.html
+ *
+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ *    http://www.gnu.org/licenses/lgpl.html
+ *
+ *  - Mozilla Public License Version 1.1 or later (the "MPL")
+ *    http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ */
+
+CKEDITOR.lang['it'] =
+{
+	dir : 'ltr',
+
+	bold	: 'Grassetto',
+	italic	: 'Corsivo'
+};
Index: /CKEditor/branches/prototype/_source/lang/pt-br.js
===================================================================
--- /CKEditor/branches/prototype/_source/lang/pt-br.js	(revision 2365)
+++ /CKEditor/branches/prototype/_source/lang/pt-br.js	(revision 2365)
@@ -0,0 +1,28 @@
+﻿/*
+ * CKEditor - The text editor for Internet - http://ckeditor.com
+ * Copyright (C) 2003-2008 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ *  - GNU General Public License Version 2 or later (the "GPL")
+ *    http://www.gnu.org/licenses/gpl.html
+ *
+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ *    http://www.gnu.org/licenses/lgpl.html
+ *
+ *  - Mozilla Public License Version 1.1 or later (the "MPL")
+ *    http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ */
+
+CKEDITOR.lang['pt-br'] =
+{
+	dir : 'ltr',
+
+	bold	: 'Negrito',
+	italic	: 'Itálico'
+};
Index: /CKEditor/branches/prototype/_source/plugins/basicstyles/plugin.js
===================================================================
--- /CKEditor/branches/prototype/_source/plugins/basicstyles/plugin.js	(revision 2364)
+++ /CKEditor/branches/prototype/_source/plugins/basicstyles/plugin.js	(revision 2365)
@@ -31,6 +31,14 @@
 		editor.addCommand( 'italic', commands.italic );
 
-		editor.ui.addButton( 'Bold', ui.bold );
-		editor.ui.addButton( 'Italic', ui.italic );
+		editor.ui.addButton( 'Bold',
+			{
+				label : editor.lang.bold,
+				command : 'bold'
+			});
+		editor.ui.addButton( 'Italic',
+			{
+				label : editor.lang.italic,
+				command : 'italic'
+			});
 	}
 });
@@ -65,19 +73,4 @@
 			}
 		}
-	},
-
-	ui :
-	{
-		bold :
-		{
-			label : 'Bold',
-			command : 'bold'
-		},
-
-		italic :
-		{
-			label : 'Italic',
-			command : 'italic'
-		}
 	}
 };
Index: /CKEditor/branches/prototype/_source/plugins/button/plugin.js
===================================================================
--- /CKEditor/branches/prototype/_source/plugins/button/plugin.js	(revision 2364)
+++ /CKEditor/branches/prototype/_source/plugins/button/plugin.js	(revision 2365)
@@ -69,5 +69,5 @@
 	 */
 	this.command = definition.command;
-	
+
 	this.className = definition.className || ( definition.command && 'cke_button_' + definition.command ) || '';
 
Index: /CKEditor/branches/prototype/_source/plugins/sourcearea/lang/ar.js
===================================================================
--- /CKEditor/branches/prototype/_source/plugins/sourcearea/lang/ar.js	(revision 2365)
+++ /CKEditor/branches/prototype/_source/plugins/sourcearea/lang/ar.js	(revision 2365)
@@ -0,0 +1,26 @@
+﻿/*
+ * CKEditor - The text editor for Internet - http://ckeditor.com
+ * Copyright (C) 2003-2008 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ *  - GNU General Public License Version 2 or later (the "GPL")
+ *    http://www.gnu.org/licenses/gpl.html
+ *
+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ *    http://www.gnu.org/licenses/lgpl.html
+ *
+ *  - Mozilla Public License Version 1.1 or later (the "MPL")
+ *    http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ */
+
+CKEDITOR.plugins.setLang( 'sourcearea', 'ar',
+{
+	source		: 'شفرة المصدر',
+	underline	: 'تسطير'
+});
Index: /CKEditor/branches/prototype/_source/plugins/sourcearea/lang/it.js
===================================================================
--- /CKEditor/branches/prototype/_source/plugins/sourcearea/lang/it.js	(revision 2365)
+++ /CKEditor/branches/prototype/_source/plugins/sourcearea/lang/it.js	(revision 2365)
@@ -0,0 +1,26 @@
+﻿/*
+ * CKEditor - The text editor for Internet - http://ckeditor.com
+ * Copyright (C) 2003-2008 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ *  - GNU General Public License Version 2 or later (the "GPL")
+ *    http://www.gnu.org/licenses/gpl.html
+ *
+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ *    http://www.gnu.org/licenses/lgpl.html
+ *
+ *  - Mozilla Public License Version 1.1 or later (the "MPL")
+ *    http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ */
+
+CKEDITOR.plugins.setLang( 'sourcearea', 'it',
+{
+	source		: 'Codice Sorgente',
+	underline	: 'Sottolineato'
+});
Index: /CKEditor/branches/prototype/_source/plugins/sourcearea/lang/pt-br.js
===================================================================
--- /CKEditor/branches/prototype/_source/plugins/sourcearea/lang/pt-br.js	(revision 2365)
+++ /CKEditor/branches/prototype/_source/plugins/sourcearea/lang/pt-br.js	(revision 2365)
@@ -0,0 +1,26 @@
+﻿/*
+ * CKEditor - The text editor for Internet - http://ckeditor.com
+ * Copyright (C) 2003-2008 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ *  - GNU General Public License Version 2 or later (the "GPL")
+ *    http://www.gnu.org/licenses/gpl.html
+ *
+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ *    http://www.gnu.org/licenses/lgpl.html
+ *
+ *  - Mozilla Public License Version 1.1 or later (the "MPL")
+ *    http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ */
+
+CKEDITOR.plugins.setLang( 'sourcearea', 'pt-br',
+{
+	source		: 'Codigo Fonte',
+	underline	: 'Sublinhado'
+});
Index: /CKEditor/branches/prototype/_source/plugins/sourcearea/plugin.js
===================================================================
--- /CKEditor/branches/prototype/_source/plugins/sourcearea/plugin.js	(revision 2364)
+++ /CKEditor/branches/prototype/_source/plugins/sourcearea/plugin.js	(revision 2365)
@@ -28,4 +28,6 @@
 {
 	requires : [ 'editingblock' ],
+
+	lang : [ 'it', 'ar', 'pt-br' ],
 
 	init : function( editor, pluginPath )
@@ -89,5 +91,9 @@
 
 		editor.addCommand( 'source', sourcearea.commands.source );
-		editor.ui.addButton( 'Source', sourcearea.ui.source );
+		editor.ui.addButton( 'Source',
+			{
+				label : editor.lang.source,
+				command : 'source'
+			});
 	}
 });
@@ -109,13 +115,4 @@
 			}
 		}
-	},
-
-	ui :
-	{
-		source :
-		{
-			label : 'Source',
-			command : 'source'
-		}
 	}
 };
Index: /CKEditor/branches/prototype/_source/skins/default/toolbar.css
===================================================================
--- /CKEditor/branches/prototype/_source/skins/default/toolbar.css	(revision 2364)
+++ /CKEditor/branches/prototype/_source/skins/default/toolbar.css	(revision 2365)
@@ -35,4 +35,9 @@
 }
 
+.cke_skin_default.cke_rtl .cke_separator
+{
+	float:right;
+}
+
 .cke_skin_default a.cke_button
 {
@@ -48,4 +53,9 @@
 	float: left;
 	height: 18px;
+}
+
+.cke_skin_default.cke_rtl a.cke_button
+{
+	float: right;
 }
 
@@ -65,4 +75,9 @@
 }
 
+.cke_skin_default.cke_rtl a:hover.cke_button
+{
+	float: right;
+}
+
 .cke_skin_default a.cke_button .cke_icon
 {
@@ -77,4 +92,9 @@
 }
 
+.cke_skin_default.cke_rtl a.cke_button .cke_icon
+{
+	float: right;
+}
+
 .cke_skin_default a.cke_button .cke_label
 {
@@ -84,4 +104,9 @@
 	padding-left: 3px;
 	padding-top:3px;
+}
+
+.cke_skin_default.cke_rtl a.cke_button .cke_label
+{
+	float: right;
 }
 
Index: /CKEditor/branches/prototype/_source/themes/default/theme.js
===================================================================
--- /CKEditor/branches/prototype/_source/themes/default/theme.js	(revision 2364)
+++ /CKEditor/branches/prototype/_source/themes/default/theme.js	(revision 2365)
@@ -61,5 +61,5 @@
 		// differently by the browsers ("semi-inline").
 		var container = CKEDITOR.dom.element.createFromHtml( [
-			'<span id="cke_', name, '" class="cke_container cke_skin_', editor.config.skin, ' cke_', CKEDITOR.lang.dir, '" dir="', CKEDITOR.lang.dir, '">' +
+			'<span id="cke_', name, '" class="cke_container cke_skin_', editor.config.skin, ' cke_', editor.lang.dir, '" dir="', editor.lang.dir, '">' +
 				'<table class="cke_editor" border="0" cellspacing="0" cellpadding="0" style="width:', width, ';height:', height, '"><tbody>' +
 					'<tr', topHtml		? '' : ' style="display:none"', '><td id="cke_top_'		, name, '" class="cke_top">'		, topHtml		, '</td></tr>' +
Index: /CKEditor/branches/prototype/config.js
===================================================================
--- /CKEditor/branches/prototype/config.js	(revision 2364)
+++ /CKEditor/branches/prototype/config.js	(revision 2365)
@@ -23,4 +23,5 @@
 {
 	// Define changes to default configuration here. For example:
-	// config.theme = 'mytheme';
+	// config.autoLanguage = false;
+	// config.defaultLanguage = 'pt-br';
 };
