Index: includes/OutputPage.php
===================================================================
--- includes/OutputPage.php	(revision 80026)
+++ includes/OutputPage.php	(working copy)
@@ -1610,6 +1610,9 @@
 
 		// Add base resources
 		$this->addModules( array( 'mediawiki.legacy.wikibits', 'mediawiki.util' ) );
+		
+		// Add language / parser support
+		$this->addModules( array( 'mediawiki.language', 'mediawiki.language.parser' ) );
 
 		// Add various resources if required
 		if ( $wgUseAjax ) {
Index: resources/Resources.php
===================================================================
--- resources/Resources.php	(revision 80026)
+++ resources/Resources.php	(working copy)
@@ -425,6 +425,16 @@
 		),
 	),
 
+	'mediawiki.language.parser' => new ResourceLoaderFileModule( array(
+		'scripts' => 'resources/mediawiki.language/mediawiki.language.parser.js',
+		'dependencies' => array( 'mediawiki.language', 'mediawiki.util' ),
+		'debugScripts' => 'resources/mediawiki.language/mediawiki.language.parserTest.js',
+		// @@FIXME note the messages are only needed for debugScirpts 
+		// It appears that debugScripts can only be direct resource paths not 'modules'		
+		'messages' => array( 'undelete_short', 'category-subcat-count' )
+	) ),
+	
+	
 	/* mediawiki Legacy */
 
 	'mediawiki.legacy.ajax' => array(
Index: resources/mediawiki/mediawiki.js
===================================================================
--- resources/mediawiki/mediawiki.js	(revision 80026)
+++ resources/mediawiki/mediawiki.js	(working copy)
@@ -239,17 +239,106 @@
 			// Return <key> if key does not exist
 			return '<' + this.key + '>';
 		}
-		var text = this.map.get( this.key );
+		var text = this.map.get( this.key );	
+		
+		/**
+		 * @@FIXME we should not have the .toString function return non-strings ( jQuery object ) 
+		 *  maybe we have a jQuery.mw.msg  ( ie jQuery wrapper for message dom object creation ?  )
+		 * 
+		 * @@FIXME Subcomponent conditionals and features should not be managed or called from the core. 
+		 *   Instead the core should be extended by subcomponents
+		 *   
+		 * 
+		 * The basic principal of dynamic interface actions being separated from message content
+		 * is something we should preserve ie:
+		 * 
+		 * 'myMsg' : 'Thanks for the fish, [$1 close dialog]'
+		 * 
+		 *	$target.append( mw.Msg('MyMsg', function(){ $dialog.close() } ) );
+		 */
+		var useSwapIndex = false;
 		var parameters = this.parameters;
+		
+		/** 
+		 * If parsing is enabled pre-swap the links from [$1 link text] into format: <a id="mw_message_swap_index_{inx}>link text</a>
+		 * @@NOTE: This should be moved into the parser but doing that properly requires that 
+		 * the parser handles substitutions not the message.toString() function
+		 */
+
+		// Swap [$1 link text] replacements
+		// @@FIXME parsing links should be integrated with the parser
+		if ( this.format === 'parse' && 'language' in mediaWiki ) {
+			text = text.replace( /\[([^\s]+[\s]+[^\]]*)\]/g, function( string, match ) {
+		    	// Get the mediaWiki link parts: 
+		    	var mwLinkParts = match.split(/ /);			
+		    	// Get the link pars:
+		    	var link = mwLinkParts[0];			      
+		    	mwLinkParts.shift();
+		    	var linkText = mwLinkParts.join(' ');
+		    	
+		    	var indexIdAttribute = '';
+		    	// Check if the link is a swap index or just a string
+		    	if( link[0] == '$' ){
+		    		var index = parseInt( link.replace(/\$/,''), 10 ) -1;		    		
+			    	// If the parameter is a text string directly replace it 
+			    	if( typeof parameters[ index ] == 'string' ){
+			    		link =  parameters[ index ];
+			    	} else {
+			    		indexIdAttribute = ' id="mw_message_swap_index_' + index + '" ';
+			    		useSwapIndex = true;
+			    		link = '#';
+			    	}
+		    	}
+				return '<a href="' + link + '" ' + indexIdAttribute + '>' + linkText + '</a>';
+			});
+		}
+		
+		// Swap $1 replacements:
 		text = text.replace( /\$(\d+)/g, function( string, match ) {
 			var index = parseInt( match, 10 ) - 1;
-			return index in parameters ? parameters[index] : '$' + match;
+			// Check the parameters type
+			if( parameters[index] && ( typeof parameters[index] == 'function' || parameters[index] instanceof jQuery ) ){
+				useSwapIndex = true;
+				return '<span id="mw_message_swap_index_' + index +'"></span>'
+			} else {
+				// directly swap in the index or a missing index indicator ( $1{int}
+				return ( index in parameters ) ? parameters[index] : '$' + match;
+			}
 		} );
-		/* This should be fixed up when we have a parser
-		if ( this.format === 'parse' && 'language' in mediaWiki ) {
-			text = mediaWiki.language.parse( text );
+		
+
+		if ( this.format === 'parse' && 'language' in mediaWiki ) {			
+			// Create a parser object with default set of options:
+			var parserObject = new mediaWiki.language.parser( text, {} );
+			
+			mw.log( 'sending into parser: ' + text);
+			// Get the html representation of wikitext ( all that messages deal with right now ) 
+			text = parserObject.getHTML();			
+			
+		} else if ( this.format === 'plain' ){
+			// don't transform
+		} 
+
+		// If we use a dom swap id replace it here and return a binded jQuery object:
+		if( useSwapIndex ) {			
+			// Add bindings to swap index and return binded html jQuery objects
+			var $text =  $('<span />').html( text );
+			for( var index=0; index < parameters.length; index++ ) {
+				if( typeof parameters[index] == 'function' ){
+					$text.find( '#mw_message_swap_index_' + index ).click( parameters[index] );
+				}
+				if( parameters[index] instanceof jQuery ){			
+					// We get the text for the link from the message text, while 
+					// the interface actions of the link are handled by the jQuery object
+					var $swapIndex = $text.find( '#mw_message_swap_index_' + index );				
+					parameters[ index ].text( $swapIndex.text() );
+					$swapIndex.replaceWith( parameters[ index ] );
+				}
+			}
+			// return the binded element
+			return $text;
 		}
-		*/
+		
 		return text;
 	};
 
@@ -419,14 +508,14 @@
 	 *
 	 * @param key string Key of message to get
 	 * @param parameters mixed First argument in a list of variadic arguments, each a parameter for $
-	 * replacement
+	 * replacement. parameters can be an indexed array of replacements. 
 	 */
 	this.message = function( key, parameters ) {
 		// Support variadic arguments
-		if ( typeof parameters !== 'undefined' ) {
+		if ( typeof parameters !== 'undefined' && ! $.isArray( parameters ) ) {
 			parameters = $.makeArray( arguments );
 			parameters.shift();
-		} else {
+		} else if( ! $.isArray( parameters ) ){
 			parameters = [];
 		}
 		return new Message( mediaWiki.messages, key, parameters );
@@ -444,6 +533,14 @@
 	};
 
 	/**
+	 * Gets a message without transforming it similar to wfMsgNoTrans
+	 */	
+	this.msgNoTrans = function( key ){
+		// @@FIXME I know we should use Message.plain() somehow but the above code is not clear at all. 
+		return mediaWiki.messages.get( key );			
+	};
+	
+	/**
 	 * Client-side module loader which integrates with the MediaWiki ResourceLoader
 	 */
 	this.loader = new ( function() {
Index: resources/mediawiki.language/mediawiki.language.parser.js
===================================================================
--- resources/mediawiki.language/mediawiki.language.parser.js	(revision 0)
+++ resources/mediawiki.language/mediawiki.language.parser.js	(revision 0)
@@ -0,0 +1,240 @@
+/**
+* Mediawiki language text parser for handling mediawiki style {{PLURAL}} i81n template substitution
+* and basic [$1 link text] substitution.
+*/
+	
+/**
+* MediaWiki wikitext "Parser" constructor 
+*
+* @param {String} wikiText the wikitext to be parsed
+* @return {Object} parserObj returns a parser object that has methods:
+*	getHtml() which returns the html representation of the text
+*/	
+mediaWiki.language.parser = function( wikiText, options) {
+	// return the parserObj
+	this.init( wikiText, options );		
+};
+	
+mediaWiki.language.parser.prototype = {		
+	// The parser output string ( lazy init )
+	'_htmlOutput': false,
+	
+	// The wiki text to be parsed ( required parameter of the constructor )
+	'_wikiText' : '',
+	
+	// The default parser options
+	'_defaultParserOptions' : {
+		/**
+		 * Name template processors ( like PLURAL, GENDER )
+		 * 
+		 * Magic named templates are passed off to their associated function
+		 * 
+		 * Dependent functions should be defined BEFORE the parser is included, or 
+		 * passed into the parser as part of the runtime options
+		 */
+		'templateProcessors' : {
+			'PLURAL' :  mw.language.pluralProcessor
+		}
+	},
+	
+	// Internal parser options ( set via parserOptions argument and default parser options )
+	'_options' : {},
+	
+	/** 
+	 * constructor
+	 */
+	'init' : function( wikiText, parserOptions ) {
+		this._wikiText = wikiText;
+		this.options = $.extend( this._defaultParserOptions, parserOptions);	
+	},		
+	 		
+	/**
+	 * Update the wiki text value and invalidate the cache
+	 * 
+	 * @param {string} wikiText
+	 * 		The wiki text string the parser works on. 
+	 */
+	'updateText' : function( wikiText ) {
+		this._wikiText = wikiText;
+		
+		// Invalidate the output ( will force a re-parse )
+		this._htmlOutput = false;
+	},
+	
+	/**
+	 * Recursively parse out template:
+	 * 
+	 * contains a few local scope helper functions:	 
+	 */
+	'parse': function() {
+		var _this = this;
+		
+		// Setup local swap string constants	
+		var JQUERY_SWAP_STRING = 'ZjQuerySwapZ';	
+		var LINK_SWAP_STRING = 'ZreplaceZ';
+		
+		// Local scope functions for parser: 
+		
+		/**
+		 * Recurse through text and tokenize the open and close templates into "node" objects  
+		 */
+		function recurseTokenizeNodes ( text ) {
+			var node = { };
+			mw.log( 'recurseTokenizeNodes:' + text );
+			// Inspect each char
+			for ( var a = 0; a < text.length; a++ ) {
+				if ( text.charAt(a) == '{' && text.charAt(a + 1) == '{' ) {
+					a = a + 2;
+					node['parent'] = node;
+					if ( !node['child'] ) {
+						node['child'] = new Array();
+					}
+
+					node['child'].push( recurseTokenizeNodes( text.substr( a ) ) );
+				} else if ( text.charAt(a) == '}' && text.charAt(a + 1) == '}' ) {
+					a++;
+					if ( !node['parent'] ) {
+						return node;
+					}
+					node = node['parent'];
+				}
+				if ( !node['text'] ) {
+					node['text'] = '';
+				}
+				// Don't put }} closures into output:
+				if ( text.charAt(a) &&  text.charAt(a) != '}' ) {
+					node['text'] += text.charAt(a);
+				}
+			}
+			return node;
+		}
+		
+		/**
+		 * Parse template text as template name and named params
+		 * @param {String} templateString Template String to be parsed 
+		 */
+		function parseTemplateText( templateString ) {
+			var templateObject = { };
+			
+			mw.log( 'parseTemplateText:' + templateString );
+							
+			// Get template name:
+			templateName = templateString.split( '\|' ).shift() ;
+			templateName = templateName.split( '\{' ).shift() ;
+			templateName = templateName.replace( /^\s+|\s+$/g, "" ); //trim
+
+			// Check for arguments:
+			if ( templateName.split( ':' ).length == 1 ) {
+				templateObject["name"] = templateName;
+			} else {
+				templateObject["name"] = templateName.split( ':' ).shift();
+				templateObject["arg"] = templateName.split( ':' ).pop();
+			}
+								
+			var paramSet = templateString.split( '\|' );
+			paramSet.splice( 0, 1 );
+			if ( paramSet.length ) {
+				templateObject.parameters = new Array();
+				for ( var pInx in paramSet ) {
+					var paramString = paramSet[ pInx ];
+					// check for empty param
+					if ( paramString == '' ) {
+						templateObject.parameters[ pInx ] = '';
+						continue;
+					}
+					for ( var b = 0 ; b < paramString.length ; b++ ) {
+						if ( paramString[b] == '=' && b > 0 && b < paramString.length && paramString[b - 1] != '\\' ) {
+							// named param
+							templateObject.parameters[ paramString.split( '=' ).shift() ] =	paramString.split( '=' ).pop();
+						} else {
+							// indexed param
+							templateObject.parameters[ pInx ] = paramString;
+						}
+					}
+				}
+			}		
+			return templateObject;
+		}
+		
+		/**
+		 * Get template text using the templateProcesors
+		 */
+		function getTextFromTemplateNode( node ) {
+			node.templateObject = parseTemplateText ( node.text );
+			// Do magic swap if template key found in this.options.templateProcessors
+			if ( node.templateObject.name in _this.options.templateProcessors ) {
+				var nodeText = _this.options.templateProcessors[ node.templateObject.name ]( node.templateObject );
+				return nodeText;
+			} else {
+				// don't swap just return text
+				return node.text;
+			}
+		};	
+		
+		/**
+		 * recurse_magic_swap
+		 *
+		 * Go the inner most child first then swap upward: 
+		 */
+		var parentNode = null;
+		function recurse_magic_swap( node ) {
+			if ( !parentNode )
+				parentNode = node;
+
+			if ( node['child'] ) {
+				// swap all the children:
+				for ( var i in node['child'] ) {
+					var nodeText = recurse_magic_swap( node['child'][i] );
+					// swap it into current
+					if ( node.text ) {
+						node.text = node.text.replace( node['child'][i].text, nodeText );
+					}
+					// swap into parent
+					parentNode.text  = parentNode.text.replace( node['child'][i].text, nodeText );
+				}
+				// Get the updated node text
+				var nodeText = getTextFromTemplateNode( node );
+				parentNode.text = parentNode.text.replace( node.text , nodeText );
+				
+				// Return the node text
+				return node.text;
+			} else {					
+				return getTextFromTemplateNode( node );
+			}
+		}
+		
+		// Parse out the template node structure:
+		this.parentNode = recurseTokenizeNodes ( this._wikiText );
+
+		// Strip out the parent from the root	
+		this.parentNode['parent'] = null;
+		
+		// Do the recursive magic swap on the node structure
+		this._htmlOutput = recurse_magic_swap( this.parentNode );
+		
+		// Do link swap 
+		this._htmlOutput = this._htmlOutput;						
+	},
+	
+	/**
+	 * Returns the transformed wikitext
+	 * 
+	 * Build output from swappable index 
+	 * 		(all transforms must be expanded in parse stage and linearly rebuilt)
+	 * 
+	 * @@NOTE
+	 * Alternatively we could build output using a place-holder & replace system 
+	 * 		(this lets us be slightly more sloppy with ordering and indexes, but probably slower)
+	 * 
+	 * Ideal: we build a 'wiki DOM' 
+	 * 		When editing you update the data structure directly
+	 * 		Then in output time you just go DOM->html-ish output without re-parsing the whole thing			   
+	 */
+	'getHTML': function() {
+		// wikiText updates should invalidate _htmlOutput
+		if ( ! this._htmlOutput ) {
+			this.parse();
+		}
+		return this._htmlOutput;
+	}
+};
\ No newline at end of file
Index: resources/mediawiki.language/mediawiki.language.js
===================================================================
--- resources/mediawiki.language/mediawiki.language.js	(revision 80026)
+++ resources/mediawiki.language/mediawiki.language.js	(working copy)
@@ -13,19 +13,19 @@
 	 * @param {object} template Template object
 	 * @format template
 	 * 	{
-	 * 		'title': [title of template],
+	 * 		'arg': [template arguments],
 	 * 		'parameters': [template parameters]
 	 * 	}
-	 * @example {{Template:title|params}}
+	 * @example {{Template:arg|parameters}}
 	 */
-	'procPLURAL': function( template ) {
-		if ( template.title && template.parameters && mediaWiki.language.convertPlural ) {
+	'pluralProcessor': function( template ) {
+		if ( template.arg && template.parameters && mediaWiki.language.convertPlural ) {
 			// Check if we have forms to replace
 			if ( template.parameters.length == 0 ) {
 				return '';
 			}
 			// Restore the count into a Number ( if it got converted earlier )
-			var count = mediaWiki.language.convertNumber( template.title, true );
+			var count = mediaWiki.language.convertNumber( template.arg, true );
 			// Do convertPlural call 
 			return mediaWiki.language.convertPlural( parseInt( count ), template.parameters );
 		}
Index: resources/mediawiki.language/mediawiki.language.parserTest.js
===================================================================
--- resources/mediawiki.language/mediawiki.language.parserTest.js	(revision 0)
+++ resources/mediawiki.language/mediawiki.language.parserTest.js	(revision 0)
@@ -0,0 +1,844 @@
+/**
+ * mediaWiki.language.parser.test Test Suite
+ *
+ * This script tests mediaWiki language transform system against the php counterpart.
+ *
+ * Available on "/Special:BlankPage?action=mw.language.parserTest&debug=true")
+ *
+ * @author Michael Dale <mdale@wikimedia.org>
+ */
+
+(function ($, mw) {
+	
+mw.language.parserTest = {
+	'init': function(){
+		// Make sure we are on the test page ( this will change once we explicitly  include test files on test pages ) 
+		if (wgCanonicalSpecialPageName == 'Blankpage' && mw.util.getParamValue('action') === 'mw.language.parserTest') {
+			this.setPageContent();
+			this.setupParseTests();
+		}
+	},
+	'setPageContent': function(){
+		$('#firstHeading').text('Test Javascript plural msg transformations');		
+		mw.util.$content.html(
+			'<span style="float:left;width:400px;padding:3px;">' +
+				'Run Test transform<br />' +
+				'<a id="runAll" href="#">Run all <span id="languageCount">...</span> tests</a> ( takes a while ) <br> '+
+
+				'<a id="runLang" href="#">Run Language Key</a>:<input size="5" id="testLangKey" name = "testLangKey" value="en"/>'+
+			'</span>' +
+					'<span style="float:left;width:300px;">'+
+			'Run Custom transform: <br />'+
+			'Value (separate by comma ): <input size="30" id="customValue" name="customValue" value="4,3"/> <br>'+
+			'Msg Swap Text: '+
+					'<textarea cols="60" rows="2" id="customMsgText" name="customMsgText" >'+
+						'{{PLURAL:$2|This category has only the following subcategory.|'+
+						'This category has the following {{PLURAL:$1|subcategory|$1 subcategories}}, '+
+						'out of $2 total.}}'+
+					'</textarea>'+
+			'<input id="runCustomTransform" type="button" value="Run Custom Transform">'+
+		
+			'</span>'+
+			'<div style="clear:both"></div>'+
+			'<br />'+
+			
+			'<div id="score_card" style="font-size:large"></div>'+
+			'<table style="border:1px solid" id="table_out"></table>'
+		);
+	},
+	
+	
+	/**
+	 * Sets up the parser tests and binds the html actions
+	 */
+	'setupParseTests' : function(){		
+		mw.log('setupParseTests::');
+		// For just setting one or two to test at a time for debug
+		
+		// Update the language count
+		var count=0;
+		for( var i in mw.language.names ){
+			count++;
+		}
+		$('#languageCount').text( count );
+		
+		var headerRowHtml = '<tr style="border:1px solid">' +
+				'<td style="border:1px solid" >$1[,$2]</td>' +
+				'<td style="border:1px solid" width="14%">Msg key</td>' +
+				'<td style="border:1px solid" width="34%">Msg text</td>' +
+				'<td style="border:1px solid" width="24%">Msg Transform JS</td>' +
+				'<td style="border:1px solid" width="24%">Msg Transform Mw</td>' +
+			'</tr>';
+		
+		// Setup bindings: 
+		// Custom transform test
+		$('#runCustomTransform').click( function(){
+			mw.log('runCustomTransform');
+			// Add the custom message: 
+			mediaWiki.messages.set({ 'mwe-custom-msg': $('#customMsgText').val() });
+			
+			// Empty the table
+			$('#table_out,#score_card').empty();
+			
+			// Add  table header:
+			$('#table_out').html( headerRowHtml +
+				'<tr>' +
+					'<td>' + $('#customMsgText').val() + '</td>' + 
+					'<td>mwe-custom-msg</td>' + 
+					'<td>' + $('#customMsgText').val() + '</td>' +
+					'<td id="jsMessageText"></td>' + 
+					'<td id="mwMessageTransform"></td>' + 
+				'<tr>'
+			);
+			
+			// Set the mw message to loading
+			$('#mwMessageTransform').text( 
+				"note custom messages can not be parsed via the mediaWiki api at this point in time" 
+			).css('color', 'red');
+			
+			// Output the js msg: 
+			var msgArgs = $('#customValue').val().split(',');				
+		
+			$('#jsMessageText').append(
+				mediaWiki.msg( 'mwe-custom-msg', msgArgs )
+			);
+			
+		});	
+		
+		$('#runLang').click(function(){
+			mw.log('runLang');
+			$('#table_out,#score_card').empty();
+			if(  !mw.language.names[ $('#testLangKey').val() ] ){
+				alert( escape( $('#testLangKey').val() ) + ' does not appear to be a valid language key' );
+			} else {			
+				doLanguageTransformTable( new Array( $('#testLangKey').val() ) )
+			}
+		});
+		
+		$('#runAll').click(function(){
+			mw.log('runAll');
+			$('#table_out,#score_card').empty();
+			// Build the langTestSet from mw.language.names
+			var langTestSet = []
+			for( var i in mw.language.names ) {
+				langTestSet.push( i ) ;
+			}			
+			doLanguageTransformTable( langTestSet );
+		});
+		
+		// Set-up base convert plural and gender (to restore for non-transform languages ) 
+		var baseConvertPlural = mw.language.convertPlural;
+		 	
+		// Do manual script loaders calls to test multiple languages:
+		function doLanguageTransformTable( langSet ){			
+			$('#table_out').html( '<span class="loadingSpinner">loading...</span>' );
+			//build table output: 
+			var messageTestSet = { 												
+				'undelete_short' : [ 0, 1, 2, 5, 21, 101 ],			
+				//category-subcat-count' has two params:
+				'category-subcat-count' : [ 
+					[0,10], 
+					[1,2],
+					[3,30]
+				]
+			};		
+							
+			var passTest=0;
+			var failTest=0;
+			var testCount=0;	
+	
+			/**
+			* Process a language key test set
+			*/
+			function doProcLangKey( langKey ){		
+				mw.log(" doProcLangKey: " + langKey );
+				// Clear out the old digitTransformTable
+				mw.language.digitTransformTable = null;
+				// Load the current language js file if it has a langKey		
+				var transformLangKey = mw.language.getLangTransformKey ( langKey );
+				if( transformLangKey != 'en' ){
+					mw.log( langKey + " load msg transform" );
+					//var langName = 'Language' +	transformLangKey.substr(0,1).toUpperCase() + transformLangKey.substr( 1, transformLangKey.length ); 	
+					$.getScript( wgScriptPath + '/resources/mediawiki.language/languages/classes/' + langName.toLowerCase() + '.js' , function(){
+						doLangTest();
+					});			
+				} else { 
+					mw.log( langKey + " no msg transform restore base" );				
+					//If no transform, restore base plural
+					mw.language.convertPlural = baseConvertPlural;
+					doLangTest();
+				}
+				
+				function doLangTest(){
+					mw.log("doLangTest::" + langKey);
+					// Load the updated messages for the current language Key
+					$.getScript( wgScriptPath + '/load.php?modules=mediawiki.language.parser&debug=true&only=messages&lang='+langKey, function(){							
+						var o='';
+						o+='<tr><td colspan="6" height="20" style="font-size:large"><b>Lang:' + langKey + '</b></td></tr>';		
+						
+						// Now for each language msg: 
+						$.each(messageTestSet, function(mKey, mTestSet){
+							//output table names:
+							o+= headerRowHtml;
+
+							//for each number value
+							for( var i in mTestSet ){
+								var numVal = mTestSet[i];						
+								var numKey = i;
+								var tkey = mKey + '_' + numKey + '_' + langKey;
+								o+= '<tr style="border:1px solid">' +
+										'<td style="border:1px solid" >' + numVal + '</td>' + 
+										'<td style="border:1px solid" >' + mKey + '</td>' + 
+										'<td style="border:1px solid" >' + mw.msgNoTrans( mKey ) + '</td>' + 
+										'<td style="border:1px solid" id="' + tkey + '_js">' + mw.msg( mKey, numVal ) + '</td>';
+								//show mw col:						
+								if( mKey.substr(0, 5) == 'test_' ){
+									o+='<td style="border:1px solid"> (test msg) </td>';
+								}else{  
+									o+='<td style="border:1px solid" id="' + tkey + '">loading...</td>';					
+									
+									//get transform from mw (& compare and highlight)
+									function doPopWmMsg( mKey, numVal, numKey ){ 
+										// Set the local tkey:
+										var tkey = mKey + '_' + numKey + '_' + langKey;
+										testCount++;
+										$('#score_card').html('Running Tests <span id="perc_done">0</sapn>% done');	
+										var msgparam = (typeof numVal== 'object')? numVal.join( '|' ) : numVal;
+										
+										var request = {
+											'action' : 'query',
+											'format' : 'json',
+											'meta' : 'allmessages',
+											'ammessages' : mKey,
+											'amlang' : langKey,
+											'amargs' : msgparam,
+											'amenableparser' : true
+										};
+										
+										$.getJSON( wgScriptPath + '/api.php', request, function( data ) {		
+											var t =	'#'+ tkey;				
+											var $target = $( t ) ; 								
+											if( data.query && data.query.allmessages && data.query.allmessages[0]){
+												var msgText = data.query.allmessages && data.query.allmessages[0]['*'];
+												if( msgText == '' ) 
+													msgText = ' %missing% ';
+												$target.html( msgText );										
+												var js_txt = $.trim( $(t + '_js').text().replace('\n', '') );
+												var php_txt = $.trim( msgText );											
+												// Just get the part in the <p> to compare with js version
+												if( js_txt != php_txt ){															
+													$target.css('color', 'red');
+													failTest++;
+												}else{
+													$target.css('color', 'green');
+													passTest++;
+												}
+												var perc = ( failTest + passTest ) / testCount
+												if( perc != 1){
+													$('#perc_done').html( Math.round(perc*1000)/1000 + '%');
+												}else{
+													var failHtlm = (failTest == 0)?failTest: '<span style="color:red">'+ failTest+'</span>';
+													$('#score_card').html(
+														'Passed: <span style="color:green">' + passTest + '</span> Failed:' + failHtlm 
+													);
+														
+													// Done with this lang... call outer function if we have lang keys left to proccess:
+													if( langSet.length !=0 ){
+														doProcLangKey( langSet.pop() );
+													}
+												}			
+											}else{
+												$target.html(' error ').css('color', 'red');
+											}
+										});
+									};
+									// pop off an anonymous function call
+									doPopWmMsg(mKey, numVal, numKey);
+								} 
+								o+='</tr>';										
+							}
+							//output a spacer:
+							o+='<tr><td colspan="6" height="20"> </td></tr>';			
+						});
+						// remove the loading text
+						$( '.loadingSpinner').remove();
+						//Put the output into the page: 
+						$('#table_out').append( o );								
+
+					});			
+				}
+			} // process lang key:
+			
+			doProcLangKey( langSet.pop() );
+		}
+	}
+		
+}	
+// Once the dom is ready init the test page: 
+$(function () {
+	mw.language.parserTest.init();
+});
+
+/**
+* Get a language transform key
+* returns default "en" fallback if none found
+* @param String langKey The language key to be checked	
+* 
+
+*/
+
+mw.language.getLangTransformKey = function( langKey ) {		
+	if( mw.language.fallbackTransformMap[ langKey ] ) {
+		langKey = mw.language.fallbackTransformMap[ langKey ];
+	}
+	// Make sure the langKey has a transformClass: 
+	for( var i = 0; i < mw.language.transformClass.length ; i++ ) {
+		if( langKey == mw.language.transformClass[i] ){
+			return langKey
+		}
+	}
+	// By default return the base 'en' class
+	return 'en';
+};
+
+/**
+ * @@FIXME this should be handled dynamically handled in the resource loader 
+ * 	so it keeps up-to-date with php maping. 
+ * 	( not explicitly listed here ) 
+ */
+mw.language.fallbackTransformMap = {
+		'mwl' : 'pt', 
+		'ace' : 'id', 
+		'hsb' : 'de', 
+		'frr' : 'de', 
+		'pms' : 'it', 
+		'dsb' : 'de', 
+		'gan' : 'gan-hant', 
+		'lzz' : 'tr', 
+		'ksh' : 'de', 
+		'kl' : 'da', 
+		'fur' : 'it', 
+		'zh-hk' : 'zh-hant', 
+		'kk' : 'kk-cyrl', 
+		'zh-my' : 'zh-sg', 
+		'nah' : 'es', 
+		'sr' : 'sr-ec', 
+		'ckb-latn' : 'ckb-arab', 
+		'mo' : 'ro', 
+		'ay' : 'es', 
+		'gl' : 'pt', 
+		'gag' : 'tr', 
+		'mzn' : 'fa', 
+		'ruq-cyrl' : 'mk', 
+		'kk-arab' : 'kk-cyrl', 
+		'pfl' : 'de', 
+		'zh-yue' : 'yue', 
+		'ug' : 'ug-latn', 
+		'ltg' : 'lv', 
+		'nds' : 'de', 
+		'sli' : 'de', 
+		'mhr' : 'ru', 
+		'sah' : 'ru', 
+		'ff' : 'fr', 
+		'ab' : 'ru', 
+		'ko-kp' : 'ko', 
+		'sg' : 'fr', 
+		'zh-tw' : 'zh-hant', 
+		'map-bms' : 'jv', 
+		'av' : 'ru', 
+		'nds-nl' : 'nl', 
+		'pt-br' : 'pt', 
+		'ce' : 'ru', 
+		'vep' : 'et', 
+		'wuu' : 'zh-hans', 
+		'pdt' : 'de', 
+		'krc' : 'ru', 
+		'gan-hant' : 'zh-hant', 
+		'bqi' : 'fa', 
+		'as' : 'bn', 
+		'bm' : 'fr', 
+		'gn' : 'es', 
+		'tt' : 'ru', 
+		'zh-hant' : 'zh-hans', 
+		'hif' : 'hif-latn', 
+		'zh' : 'zh-hans', 
+		'kaa' : 'kk-latn', 
+		'lij' : 'it', 
+		'vot' : 'fi', 
+		'ii' : 'zh-cn', 
+		'ku-arab' : 'ckb-arab', 
+		'xmf' : 'ka', 
+		'vmf' : 'de', 
+		'zh-min-nan' : 'nan', 
+		'bcc' : 'fa', 
+		'an' : 'es', 
+		'rgn' : 'it', 
+		'qu' : 'es', 
+		'nb' : 'no', 
+		'bar' : 'de', 
+		'lbe' : 'ru', 
+		'su' : 'id', 
+		'pcd' : 'fr', 
+		'glk' : 'fa', 
+		'lb' : 'de', 
+		'kk-kz' : 'kk-cyrl', 
+		'kk-tr' : 'kk-latn', 
+		'inh' : 'ru', 
+		'mai' : 'hi', 
+		'tp' : 'tokipona', 
+		'kk-latn' : 'kk-cyrl', 
+		'ba' : 'ru', 
+		'nap' : 'it', 
+		'ruq' : 'ruq-latn', 
+		'tt-cyrl' : 'ru', 
+		'lad' : 'es', 
+		'dk' : 'da', 
+		'de-ch' : 'de', 
+		'be-x-old' : 'be-tarask', 
+		'za' : 'zh-hans', 
+		'kk-cn' : 'kk-arab', 
+		'shi' : 'ar', 
+		'crh' : 'crh-latn', 
+		'yi' : 'he', 
+		'pdc' : 'de', 
+		'eml' : 'it', 
+		'uk' : 'ru', 
+		'kv' : 'ru', 
+		'koi' : 'ru', 
+		'cv' : 'ru', 
+		'zh-cn' : 'zh-hans', 
+		'de-at' : 'de', 
+		'jut' : 'da', 
+		'vec' : 'it', 
+		'zh-mo' : 'zh-hk', 
+		'fiu-vro' : 'vro', 
+		'frp' : 'fr', 
+		'mg' : 'fr', 
+		'ruq-latn' : 'ro', 
+		'sa' : 'hi', 
+		'lmo' : 'it', 
+		'kiu' : 'tr', 
+		'tcy' : 'kn', 
+		'srn' : 'nl', 
+		'jv' : 'id', 
+		'vls' : 'nl', 
+		'zea' : 'nl', 
+		'ty' : 'fr', 
+		'szl' : 'pl', 
+		'rmy' : 'ro', 
+		'wo' : 'fr', 
+		'vro' : 'et', 
+		'udm' : 'ru', 
+		'bpy' : 'bn', 
+		'mrj' : 'ru', 
+		'ckb' : 'ckb-arab', 
+		'xal' : 'ru', 
+		'de-formal' : 'de', 
+		'myv' : 'ru', 
+		'ku' : 'ku-latn', 
+		'crh-cyrl' : 'ru', 
+		'gsw' : 'de', 
+		'rue' : 'uk', 
+		'iu' : 'ike-cans', 
+		'stq' : 'de', 
+		'gan-hans' : 'zh-hans', 
+		'scn' : 'it', 
+		'arn' : 'es', 
+		'ht' : 'fr', 
+		'zh-sg' : 'zh-hans', 
+		'bat-smg' : 'lt', 
+		'aln' : 'sq', 
+		'tg' : 'tg-cyrl', 
+		'li' : 'nl', 
+		'simple' : 'en', 
+		'os' : 'ru', 
+		'ln' : 'fr', 
+		'als' : 'gsw', 
+		'zh-classical' : 'lzh', 
+		'arz' : 'ar', 
+		'wa' : 'fr'
+	};	
+
+/**
+ * Language classes ( which have a file in /languages/classes/Language{code}.js )
+ * ( for languages that override default transforms ) 
+ * 
+ * @@FIXME again not needed if the resource loader manages this mapping and gives 
+ * 	us the "right" transform class regardless of what language key we request. 
+ */
+mw.language.transformClass = ['am', 'ar', 'bat_smg', 'be_tarak', 'be', 'bh',
+		'bs', 'cs', 'cu', 'cy', 'dsb', 'fr', 'ga', 'gd', 'gv', 'he', 'hi',
+		'hr', 'hsb', 'hy', 'ksh', 'ln', 'lt', 'lv', 'mg', 'mk', 'mo', 'mt',
+		'nso', 'pl', 'pt_br', 'ro', 'ru', 'se', 'sh', 'sk', 'sl', 'sma',
+		'sr_ec', 'sr_el', 'sr', 'ti', 'tl', 'uk', 'wa' ];
+
+/**
+ * List of all languages mediaWiki supports:
+ * 
+ * Similar to api query: 
+ * http://commons.wikimedia.org/w/api.php?action=query&meta=siteinfo&siprop=languages&format=jsonfm
+ * 
+ * @@FIXME This should be dynamically generated via the resource loader and identified as a dependency of this test file. 
+ * 
+ */
+mediaWiki.language.names = {
+	"aa" : "Qaf\u00e1r af",
+	"ab" : "\u0410\u04a7\u0441\u0443\u0430",
+	"ace" : "Ac\u00e8h",
+	"af" : "Afrikaans",
+	"ak" : "Akan",
+	"aln" : "Geg\u00eb",
+	"als" : "Alemannisch",
+	"am" : "\u12a0\u121b\u122d\u129b",
+	"an" : "Aragon\u00e9s",
+	"ang" : "Anglo-Saxon",
+	"ar" : "\u0627\u0644\u0639\u0631\u0628\u064a\u0629",
+	"arc" : "\u0710\u072a\u0721\u071d\u0710",
+	"arn" : "Mapudungun",
+	"arz" : "\u0645\u0635\u0631\u0649",
+	"as" : "\u0985\u09b8\u09ae\u09c0\u09af\u09bc\u09be",
+	"ast" : "Asturianu",
+	"av" : "\u0410\u0432\u0430\u0440",
+	"avk" : "Kotava",
+	"ay" : "Aymar aru",
+	"az" : "Az\u0259rbaycan",
+	"ba" : "\u0411\u0430\u0448\u04a1\u043e\u0440\u0442",
+	"bar" : "Boarisch",
+	"bat-smg" : "\u017demait\u0117\u0161ka",
+	"bcc" : "\u0628\u0644\u0648\u0686\u06cc \u0645\u06a9\u0631\u0627\u0646\u06cc",
+	"bcl" : "Bikol Central",
+	"be" : "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f",
+	"be-tarask" : "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430)",
+	"be-x-old" : "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430)",
+	"bg" : "\u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438",
+	"bh" : "\u092d\u094b\u091c\u092a\u0941\u0930\u0940",
+	"bi" : "Bislama",
+	"bm" : "Bamanankan",
+	"bn" : "\u09ac\u09be\u0982\u09b2\u09be",
+	"bo" : "\u0f56\u0f7c\u0f51\u0f0b\u0f61\u0f72\u0f42",
+	"bpy" : "\u0987\u09ae\u09be\u09b0 \u09a0\u09be\u09b0\/\u09ac\u09bf\u09b7\u09cd\u09a3\u09c1\u09aa\u09cd\u09b0\u09bf\u09af\u09bc\u09be \u09ae\u09a3\u09bf\u09aa\u09c1\u09b0\u09c0",
+	"bqi" : "\u0628\u062e\u062a\u064a\u0627\u0631\u064a",
+	"br" : "Brezhoneg",
+	"bs" : "Bosanski",
+	"bug" : "\u1a05\u1a14 \u1a15\u1a18\u1a01\u1a17",
+	"bxr" : "\u0411\u0443\u0440\u044f\u0430\u0434",
+	"ca" : "Catal\u00e0",
+	"cbk-zam" : "Chavacano de Zamboanga",
+	"cdo" : "M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304",
+	"ce" : "\u041d\u043e\u0445\u0447\u0438\u0439\u043d",
+	"ceb" : "Cebuano",
+	"ch" : "Chamoru",
+	"cho" : "Choctaw",
+	"chr" : "\u13e3\u13b3\u13a9",
+	"chy" : "Tsets\u00eahest\u00e2hese",
+	"ckb" : "Soran\u00ee \/ \u06a9\u0648\u0631\u062f\u06cc",
+	"ckb-latn" : "\u202aSoran\u00ee (lat\u00een\u00ee)\u202c",
+	"ckb-arab" : "\u202b\u06a9\u0648\u0631\u062f\u06cc (\u0639\u06d5\u0631\u06d5\u0628\u06cc)\u202c",
+	"co" : "Corsu",
+	"cr" : "N\u0113hiyaw\u0113win \/ \u14c0\u1426\u1403\u152d\u140d\u140f\u1423",
+	"crh" : "Q\u0131r\u0131mtatarca",
+	"crh-latn" : "\u202aQ\u0131r\u0131mtatarca (Latin)\u202c",
+	"crh-cyrl" : "\u202a\u041a\u044a\u044b\u0440\u044b\u043c\u0442\u0430\u0442\u0430\u0440\u0434\u0436\u0430 (\u041a\u0438\u0440\u0438\u043b\u043b)\u202c",
+	"cs" : "\u010cesky",
+	"csb" : "Kasz\u00ebbsczi",
+	"cu" : "\u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f",
+	"cv" : "\u0427\u04d1\u0432\u0430\u0448\u043b\u0430",
+	"cy" : "Cymraeg",
+	"da" : "Dansk",
+	"de" : "Deutsch",
+	"de-at" : "\u00d6sterreichisches Deutsch",
+	"de-ch" : "Schweizer Hochdeutsch",
+	"de-formal" : "Deutsch (Sie-Form)",
+	"diq" : "Zazaki",
+	"dk" : "Dansk (deprecated:da)",
+	"dsb" : "Dolnoserbski",
+	"dv" : "\u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0",
+	"dz" : "\u0f47\u0f7c\u0f44\u0f0b\u0f41",
+	"ee" : "E\u028begbe",
+	"el" : "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac",
+	"eml" : "Emili\u00e0n e rumagn\u00f2l",
+	"en" : "English",
+	"en-gb" : "British English",
+	"eo" : "Esperanto",
+	"es" : "Espa\u00f1ol",
+	"et" : "Eesti",
+	"eu" : "Euskara",
+	"ext" : "Estreme\u00f1u",
+	"fa" : "\u0641\u0627\u0631\u0633\u06cc",
+	"ff" : "Fulfulde",
+	"fi" : "Suomi",
+	"fiu-vro" : "V\u00f5ro",
+	"fj" : "Na Vosa Vakaviti",
+	"fo" : "F\u00f8royskt",
+	"fr" : "Fran\u00e7ais",
+	"frc" : "Fran\u00e7ais cadien",
+	"frp" : "Arpetan",
+	"fur" : "Furlan",
+	"fy" : "Frysk",
+	"ga" : "Gaeilge",
+	"gag" : "Gagauz",
+	"gan" : "\u8d1b\u8a9e",
+	"gan-hans" : "\u8d63\u8bed(\u7b80\u4f53)",
+	"gan-hant" : "\u8d1b\u8a9e(\u7e41\u9ad4)",
+	"gd" : "G\u00e0idhlig",
+	"gl" : "Galego",
+	"glk" : "\u06af\u06cc\u0644\u06a9\u06cc",
+	"gn" : "Ava\u00f1e'\u1ebd",
+	"got" : "\ud800\udf32\ud800\udf3f\ud800\udf44\ud800\udf39\ud800\udf43\ud800\udf3a",
+	"grc" : "\u1f08\u03c1\u03c7\u03b1\u03af\u03b1 \u1f11\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u1f74",
+	"gsw" : "Alemannisch",
+	"gu" : "\u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0",
+	"gv" : "Gaelg",
+	"ha" : "\u0647\u064e\u0648\u064f\u0633\u064e",
+	"hak" : "Hak-k\u00e2-fa",
+	"haw" : "Hawai`i",
+	"he" : "\u05e2\u05d1\u05e8\u05d9\u05ea",
+	"hi" : "\u0939\u093f\u0928\u094d\u0926\u0940",
+	"hif" : "Fiji Hindi",
+	"hif-deva" : "\u092b\u093c\u0940\u091c\u0940 \u0939\u093f\u0928\u094d\u0926\u0940",
+	"hif-latn" : "Fiji Hindi",
+	"hil" : "Ilonggo",
+	"ho" : "Hiri Motu",
+	"hr" : "Hrvatski",
+	"hsb" : "Hornjoserbsce",
+	"ht" : "Krey\u00f2l ayisyen",
+	"hu" : "Magyar",
+	"hy" : "\u0540\u0561\u0575\u0565\u0580\u0565\u0576",
+	"hz" : "Otsiherero",
+	"ia" : "Interlingua",
+	"id" : "Bahasa Indonesia",
+	"ie" : "Interlingue",
+	"ig" : "Igbo",
+	"ii" : "\ua187\ua259",
+	"ik" : "I\u00f1upiak",
+	"ike-cans" : "\u1403\u14c4\u1483\u144e\u1450\u1466",
+	"ike-latn" : "inuktitut",
+	"ilo" : "Ilokano",
+	"inh" : "\u0413\u0406\u0430\u043b\u0433\u0406\u0430\u0439 \u011eal\u011faj",
+	"io" : "Ido",
+	"is" : "\u00cdslenska",
+	"it" : "Italiano",
+	"iu" : "\u1403\u14c4\u1483\u144e\u1450\u1466\/inuktitut",
+	"ja" : "\u65e5\u672c\u8a9e",
+	"jbo" : "Lojban",
+	"jut" : "Jysk",
+	"jv" : "Basa Jawa",
+	"ka" : "\u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8",
+	"kaa" : "Qaraqalpaqsha",
+	"kab" : "Taqbaylit",
+	"kg" : "Kongo",
+	"ki" : "G\u0129k\u0169y\u0169",
+	"kiu" : "Kurmanc\u00ee",
+	"kj" : "Kwanyama",
+	"kk" : "\u049a\u0430\u0437\u0430\u049b\u0448\u0430",
+	"kk-arab" : "\u202b\u0642\u0627\u0632\u0627\u0642\u0634\u0627 (\u062a\u0674\u0648\u062a\u06d5)\u202c",
+	"kk-cyrl" : "\u202a\u049a\u0430\u0437\u0430\u049b\u0448\u0430 (\u043a\u0438\u0440\u0438\u043b)\u202c",
+	"kk-latn" : "\u202aQazaq\u015fa (lat\u0131n)\u202c",
+	"kk-cn" : "\u202b\u0642\u0627\u0632\u0627\u0642\u0634\u0627 (\u062c\u06c7\u0646\u06af\u0648)\u202c",
+	"kk-kz" : "\u202a\u049a\u0430\u0437\u0430\u049b\u0448\u0430 (\u049a\u0430\u0437\u0430\u049b\u0441\u0442\u0430\u043d)\u202c",
+	"kk-tr" : "\u202aQazaq\u015fa (T\u00fcrk\u00efya)\u202c",
+	"kl" : "Kalaallisut",
+	"km" : "\u1797\u17b6\u179f\u17b6\u1781\u17d2\u1798\u17c2\u179a",
+	"kn" : "\u0c95\u0ca8\u0ccd\u0ca8\u0ca1",
+	"ko" : "\ud55c\uad6d\uc5b4",
+	"ko-kp" : "\ud55c\uad6d\uc5b4 (\uc870\uc120)",
+	"kr" : "Kanuri",
+	"kri" : "Krio",
+	"krj" : "Kinaray-a",
+	"ks" : "\u0915\u0936\u094d\u092e\u0940\u0930\u0940 - (\u0643\u0634\u0645\u064a\u0631\u064a)",
+	"ksh" : "Ripoarisch",
+	"ku" : "Kurd\u00ee \/ \u0643\u0648\u0631\u062f\u06cc",
+	"ku-latn" : "\u202aKurd\u00ee (lat\u00een\u00ee)\u202c",
+	"ku-arab" : "\u202b\u0643\u0648\u0631\u062f\u064a (\u0639\u06d5\u0631\u06d5\u0628\u06cc)\u202c",
+	"kv" : "\u041a\u043e\u043c\u0438",
+	"kw" : "Kernowek",
+	"ky" : "\u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430",
+	"la" : "Latina",
+	"lad" : "Ladino",
+	"lb" : "L\u00ebtzebuergesch",
+	"lbe" : "\u041b\u0430\u043a\u043a\u0443",
+	"lez" : "\u041b\u0435\u0437\u0433\u0438",
+	"lfn" : "Lingua Franca Nova",
+	"lg" : "Luganda",
+	"li" : "Limburgs",
+	"lij" : "L\u00edguru",
+	"lmo" : "Lumbaart",
+	"ln" : "Ling\u00e1la",
+	"lo" : "\u0ea5\u0eb2\u0ea7",
+	"loz" : "Silozi",
+	"lt" : "Lietuvi\u0173",
+	"lv" : "Latvie\u0161u",
+	"lzh" : "\u6587\u8a00",
+	"mai" : "\u092e\u0948\u0925\u093f\u0932\u0940",
+	"map-bms" : "Basa Banyumasan",
+	"mdf" : "\u041c\u043e\u043a\u0448\u0435\u043d\u044c",
+	"mg" : "Malagasy",
+	"mh" : "Ebon",
+	"mhr" : "\u041e\u043b\u044b\u043a \u041c\u0430\u0440\u0438\u0439",
+	"mi" : "M\u0101ori",
+	"mk" : "\u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438",
+	"ml" : "\u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02",
+	"mn" : "\u041c\u043e\u043d\u0433\u043e\u043b",
+	"mo" : "\u041c\u043e\u043b\u0434\u043e\u0432\u0435\u043d\u044f\u0441\u043a\u044d",
+	"mr" : "\u092e\u0930\u093e\u0920\u0940",
+	"ms" : "Bahasa Melayu",
+	"mt" : "Malti",
+	"mus" : "Mvskoke",
+	"mwl" : "Mirand\u00e9s",
+	"my" : "\u1019\u103c\u1014\u103a\u1019\u102c\u1018\u102c\u101e\u102c",
+	"myv" : "\u042d\u0440\u0437\u044f\u043d\u044c",
+	"mzn" : "\u0645\u064e\u0632\u0650\u0631\u0648\u0646\u064a",
+	"na" : "Dorerin Naoero",
+	"nah" : "N\u0101huatl",
+	"nan" : "B\u00e2n-l\u00e2m-g\u00fa",
+	"nap" : "Nnapulitano",
+	"nb" : "\u202aNorsk (bokm\u00e5l)\u202c",
+	"nds" : "Plattd\u00fc\u00fctsch",
+	"nds-nl" : "Nedersaksisch",
+	"ne" : "\u0928\u0947\u092a\u093e\u0932\u0940",
+	"new" : "\u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e",
+	"ng" : "Oshiwambo",
+	"niu" : "Niu\u0113",
+	"nl" : "Nederlands",
+	"nn" : "\u202aNorsk (nynorsk)\u202c",
+	"no" : "\u202aNorsk (bokm\u00e5l)\u202c",
+	"nov" : "Novial",
+	"nrm" : "Nouormand",
+	"nso" : "Sesotho sa Leboa",
+	"nv" : "Din\u00e9 bizaad",
+	"ny" : "Chi-Chewa",
+	"oc" : "Occitan",
+	"om" : "Oromoo",
+	"or" : "\u0b13\u0b21\u0b3c\u0b3f\u0b06",
+	"os" : "\u0418\u0440\u043e\u043d\u0430\u0443",
+	"pa" : "\u0a2a\u0a70\u0a1c\u0a3e\u0a2c\u0a40",
+	"pag" : "Pangasinan",
+	"pam" : "Kapampangan",
+	"pap" : "Papiamentu",
+	"pcd" : "Picard",
+	"pdc" : "Deitsch",
+	"pdt" : "Plautdietsch",
+	"pfl" : "Pf\u00e4lzisch",
+	"pi" : "\u092a\u093e\u093f\u0934",
+	"pih" : "Norfuk \/ Pitkern",
+	"pl" : "Polski",
+	"pms" : "Piemont\u00e8is",
+	"pnb" : "\u067e\u0646\u062c\u0627\u0628\u06cc",
+	"pnt" : "\u03a0\u03bf\u03bd\u03c4\u03b9\u03b1\u03ba\u03ac",
+	"ps" : "\u067e\u069a\u062a\u0648",
+	"pt" : "Portugu\u00eas",
+	"pt-br" : "Portugu\u00eas do Brasil",
+	"qu" : "Runa Simi",
+	"rif" : "Tarifit",
+	"rm" : "Rumantsch",
+	"rmy" : "Romani",
+	"rn" : "Kirundi",
+	"ro" : "Rom\u00e2n\u0103",
+	"roa-rup" : "Arm\u00e3neashce",
+	"roa-tara" : "Tarand\u00edne",
+	"ru" : "\u0420\u0443\u0441\u0441\u043a\u0438\u0439",
+	"ruq" : "Vl\u0103he\u015fte",
+	"ruq-cyrl" : "\u0412\u043b\u0430\u0445\u0435\u0441\u0442\u0435",
+	"ruq-latn" : "Vl\u0103he\u015fte",
+	"rw" : "Kinyarwanda",
+	"sa" : "\u0938\u0902\u0938\u094d\u0915\u0943\u0924",
+	"sah" : "\u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430",
+	"sc" : "Sardu",
+	"scn" : "Sicilianu",
+	"sco" : "Scots",
+	"sd" : "\u0633\u0646\u068c\u064a",
+	"sdc" : "Sassaresu",
+	"se" : "S\u00e1megiella",
+	"sei" : "Cmique Itom",
+	"sg" : "S\u00e4ng\u00f6",
+	"sh" : "Srpskohrvatski \/ \u0421\u0440\u043f\u0441\u043a\u043e\u0445\u0440\u0432\u0430\u0442\u0441\u043a\u0438",
+	"shi" : "Ta\u0161l\u1e25iyt",
+	"si" : "\u0dc3\u0dd2\u0d82\u0dc4\u0dbd",
+	"simple" : "Simple English",
+	"sk" : "Sloven\u010dina",
+	"sl" : "Sloven\u0161\u010dina",
+	"sli" : "Schl\u00e4sch",
+	"sm" : "Gagana Samoa",
+	"sma" : "\u00c5arjelsaemien",
+	"sn" : "chiShona",
+	"so" : "Soomaaliga",
+	"sq" : "Shqip",
+	"sr" : "\u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski",
+	"sr-ec" : "\u0421\u0440\u043f\u0441\u043a\u0438 (\u045b\u0438\u0440\u0438\u043b\u0438\u0446\u0430)",
+	"sr-el" : "Srpski (latinica)",
+	"srn" : "Sranantongo",
+	"ss" : "SiSwati",
+	"st" : "Sesotho",
+	"stq" : "Seeltersk",
+	"su" : "Basa Sunda",
+	"sv" : "Svenska",
+	"sw" : "Kiswahili",
+	"szl" : "\u015al\u016fnski",
+	"ta" : "\u0ba4\u0bae\u0bbf\u0bb4\u0bcd",
+	"tcy" : "\u0ca4\u0cc1\u0cb3\u0cc1",
+	"te" : "\u0c24\u0c46\u0c32\u0c41\u0c17\u0c41",
+	"tet" : "Tetun",
+	"tg" : "\u0422\u043e\u04b7\u0438\u043a\u04e3",
+	"tg-cyrl" : "\u0422\u043e\u04b7\u0438\u043a\u04e3",
+	"tg-latn" : "tojik\u012b",
+	"th" : "\u0e44\u0e17\u0e22",
+	"ti" : "\u1275\u130d\u122d\u129b",
+	"tk" : "T\u00fcrkmen\u00e7e",
+	"tl" : "Tagalog",
+	"tn" : "Setswana",
+	"to" : "lea faka-Tonga",
+	"tokipona" : "Toki Pona",
+	"tp" : "Toki Pona (deprecated:tokipona)",
+	"tpi" : "Tok Pisin",
+	"tr" : "T\u00fcrk\u00e7e",
+	"ts" : "Xitsonga",
+	"tt" : "\u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a",
+	"tt-cyrl" : "\u0422\u0430\u0442\u0430\u0440\u0447\u0430",
+	"tt-latn" : "Tatar\u00e7a",
+	"tum" : "chiTumbuka",
+	"tw" : "Twi",
+	"ty" : "Reo M\u0101`ohi",
+	"tyv" : "\u0422\u044b\u0432\u0430 \u0434\u044b\u043b",
+	"udm" : "\u0423\u0434\u043c\u0443\u0440\u0442",
+	"ug" : "Uyghurche\u200e \/ \u0626\u06c7\u064a\u063a\u06c7\u0631\u0686\u06d5",
+	"ug-arab" : "\u0626\u06c7\u064a\u063a\u06c7\u0631\u0686\u06d5",
+	"ug-latn" : "Uyghurche\u200e",
+	"uk" : "\u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430",
+	"ur" : "\u0627\u0631\u062f\u0648",
+	"uz" : "O'zbek",
+	"ve" : "Tshivenda",
+	"vec" : "V\u00e8neto",
+	"vep" : "Vepsan kel'",
+	"vi" : "Ti\u1ebfng Vi\u1ec7t",
+	"vls" : "West-Vlams",
+	"vo" : "Volap\u00fck",
+	"vro" : "V\u00f5ro",
+	"wa" : "Walon",
+	"war" : "Winaray",
+	"wo" : "Wolof",
+	"wuu" : "\u5434\u8bed",
+	"xal" : "\u0425\u0430\u043b\u044c\u043c\u0433",
+	"xh" : "isiXhosa",
+	"xmf" : "\u10db\u10d0\u10e0\u10d2\u10d0\u10da\u10e3\u10e0\u10d8",
+	"yi" : "\u05d9\u05d9\u05b4\u05d3\u05d9\u05e9",
+	"yo" : "Yor\u00f9b\u00e1",
+	"yue" : "\u7cb5\u8a9e",
+	"za" : "Vahcuengh",
+	"zea" : "Ze\u00eauws",
+	"zh" : "\u4e2d\u6587",
+	"zh-classical" : "\u6587\u8a00",
+	"zh-cn" : "\u202a\u4e2d\u6587(\u4e2d\u56fd\u5927\u9646)\u202c",
+	"zh-hans" : "\u202a\u4e2d\u6587(\u7b80\u4f53)\u202c",
+	"zh-hant" : "\u202a\u4e2d\u6587(\u7e41\u9ad4)\u202c",
+	"zh-hk" : "\u202a\u4e2d\u6587(\u9999\u6e2f)\u202c",
+	"zh-min-nan" : "B\u00e2n-l\u00e2m-g\u00fa",
+	"zh-mo" : "\u202a\u4e2d\u6587(\u6fb3\u9580)\u202c",
+	"zh-my" : "\u202a\u4e2d\u6587(\u9a6c\u6765\u897f\u4e9a)\u202c",
+	"zh-sg" : "\u202a\u4e2d\u6587(\u65b0\u52a0\u5761)\u202c",
+	"zh-tw" : "\u202a\u4e2d\u6587(\u53f0\u7063)\u202c",
+	"zh-yue" : "\u7cb5\u8a9e",
+	"zu" : "isiZulu"
+};
+
+
+})(jQuery, mediaWiki);
