r70393 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r70392‎ | r70393 | r70394 >
Date:18:28, 3 August 2010
Author:dale
Status:deferred
Tags:
Comment:
* moved mw.Parser and mw.Language into component
* moved Api Helper calls into separate component
Modified paths:
  • /trunk/extensions/JS2Support/mwEmbed/components (added) (history)
  • /trunk/extensions/JS2Support/mwEmbed/components/README (added) (history)
  • /trunk/extensions/JS2Support/mwEmbed/components/mw.Api.js (added) (history)
  • /trunk/extensions/JS2Support/mwEmbed/components/mw.Language.js (added) (history)
  • /trunk/extensions/JS2Support/mwEmbed/components/mw.Parser.js (added) (history)
  • /trunk/extensions/JS2Support/mwEmbed/languages/mw.Language.js (deleted) (history)
  • /trunk/extensions/JS2Support/mwEmbed/languages/mw.Parser.js (deleted) (history)

Diff [purge]

Index: trunk/extensions/JS2Support/mwEmbed/components/mw.Language.js
@@ -0,0 +1,1131 @@
 2+/**
 3+* Core Language mw.Language object
 4+*
 5+* Localized Language support attempts to mirror some of the functionality of Language.php in MediaWiki
 6+* It contains methods for loading and transforming msg text
 7+
 8+*/
 9+
 10+( function( mw ) {
 11+
 12+ // Setup the global mw.Language var:
 13+ mw.Language = { };
 14+
 15+ /**
 16+ * Setup the lang object
 17+ */
 18+ var messageCache = { };
 19+ var gRuleSet = { };
 20+
 21+ /**
 22+ * mw.addMessages function
 23+ * Loads a set of json messages into the messegeCache object.
 24+ *
 25+ * @param {JSON} msgSet The set of msgs to be loaded
 26+ */
 27+ mw.addMessages = function( msgSet ) {
 28+ for ( var i in msgSet ) {
 29+ messageCache[ i ] = msgSet[i];
 30+ }
 31+ }
 32+ // By default set the current class missing messages flag to default.
 33+ mw.currentClassMissingMessages = false;
 34+
 35+ /**
 36+ * mw.addMessagesKey function
 37+ * Adds a messageKey to be pulled in remotely.
 38+ *
 39+ * NOTE the script-loader should replace addMessageKeys with localized addMessages calls
 40+ *
 41+ * If addMessagesKey is called then we are running in raw file debug mode.
 42+ * it populates the messegeKeyQueue and loads the values in a separate request callback
 43+ *
 44+ * @param {Array} msgSet The set of msgs to be loaded
 45+ */
 46+ mw.addMessageKeys = function( msgSet ) {
 47+ // Check if any msg key from this class is missing
 48+ for( i=0; i < msgSet.length; i++ ){
 49+ msgKey = msgSet[i];
 50+ if( ! messageCache[ msgKey ] ) {
 51+ // Set the missing messages flag
 52+ mw.currentClassMissingMessages = true;
 53+ return false;
 54+ }
 55+ }
 56+ return true;
 57+ }
 58+
 59+ /**
 60+ * Special function to register that all of the module messages need to be loaded.
 61+ */
 62+ mw.includeAllModuleMessages = function (){
 63+ mw.currentClassMissingMessages = true;
 64+ }
 65+
 66+ /**
 67+ * Load messages for a given named javascript class.
 68+ * This worked in conjunction with the scriptLoader
 69+ * @param {string} className Name of class file to be loaded
 70+ * @param {function} callback Function to be called once class messages are loaded.
 71+ */
 72+ mw.loadResourceMessages = function( className, callback ) {
 73+ // Check if wgScriptLoaderPath is set ( else guess the path relative to mwEmbed)
 74+ if ( typeof wgScriptLoaderLocation == 'undefined' || ! wgScriptLoaderLocation ){
 75+ wgScriptLoaderLocation = mw.getMwEmbedPath() + 'ResourceLoader.php';
 76+ }
 77+ // Run the addMessages script-loader call
 78+ mw.getScript( wgScriptLoaderLocation + '?class=' + className + '&format=messages', callback);
 79+ }
 80+
 81+
 82+ /**
 83+ * Returns a transformed msg string
 84+ *
 85+ * it take a msg key and array of replacement values of form
 86+ * $1, $2 and does relevant messageKey transformation returning
 87+ * the user msg.
 88+ *
 89+ * @param {String} messageKey The msg key as set by mw.addMessages
 90+ * @param {Mixed} args A string|jQuery Object or array of string|jQuery Objects
 91+ *
 92+ * extra parameters are appended to the args array as numbered replacements
 93+ *
 94+ * @return string
 95+ */
 96+ mw.getMsg = function( messageKey , args ) {
 97+
 98+ // Check for missing message key
 99+ if ( ! messageCache[ messageKey ] ){
 100+ return '[' + messageKey + ']';
 101+ }
 102+ // Check if we need to do args replacements:
 103+ if( typeof args != 'undefined' ) {
 104+
 105+ // Make arg into an array if its not already an array
 106+ if ( typeof args == 'string'
 107+ || typeof args == 'number'
 108+ || args instanceof jQuery )
 109+ {
 110+ args = [ args ];
 111+ }
 112+
 113+ // Put any extra arguments into the args array
 114+ var extraArgs = $j.makeArray( arguments );
 115+ for(var i=2; i < extraArgs.length; i ++ ) {
 116+ args.push( extraArgs[ i ] );
 117+ }
 118+ }
 119+ // Fast check message text return ( no arguments and no parsing needed )
 120+ if( ( !args || args.length == 0 )
 121+ && messageCache[ messageKey ].indexOf( '{{' ) === -1
 122+ && messageCache[ messageKey ].indexOf( '[' ) === -1
 123+ ) {
 124+ return messageCache[ messageKey ];
 125+ }
 126+
 127+ // Else Setup the messageSwap object:
 128+ var messageSwap = new mw.Language.messageSwapObject( messageCache[ messageKey ], args );
 129+
 130+ // Return the jQuery object or message string
 131+ return messageSwap.getMsg();
 132+ }
 133+
 134+ /**
 135+ * A message Swap Object
 136+ * Swap object manages message type swapping and returns jQuery or text output
 137+ *
 138+ * @param {String} message The text of the message
 139+ * @param {array} arguments A set of swap arguments
 140+ */
 141+
 142+ mw.Language.messageSwapObject = function( message, arguments ){
 143+ this.init( message, arguments );
 144+ }
 145+
 146+ mw.Language.messageSwapObject.prototype= {
 147+ /* constructor */
 148+ init: function( message, arguments ){
 149+ this.message = message;
 150+ this.arguments = arguments;
 151+
 152+ // Set the includesjQueryArgs flag to false
 153+ includesjQueryArgs: false;
 154+ },
 155+
 156+ // Return the transformed message text or jQuery object
 157+ getMsg: function(){
 158+ // Get message with string swap
 159+ this.replaceStringArgs();
 160+
 161+ // Check if we need to parse the string
 162+ if( this.message.indexOf( '{{' ) === -1
 163+ && this.message.indexOf( '[' ) === -1
 164+ && ! this.includesjQueryArgs )
 165+ {
 166+ // replaceStringArgs is all we need, return the msg
 167+ return this.message
 168+ }
 169+
 170+ // Else Send the messageText through the parser
 171+ var pObj = new mw.Parser( this.message );
 172+
 173+ // Get template and link transformed text:
 174+ this.message = pObj.getHTML();
 175+
 176+ // if jQuery arguments is false return message string
 177+ if(! this.includesjQueryArgs ){
 178+ //Do string link substitution
 179+ return this.message;
 180+ }
 181+
 182+ // jQuery arguments exist swap and return jQuery object
 183+ return this.getJQueryArgsReplace();
 184+
 185+ },
 186+
 187+ /**
 188+ * Swap in an array of values for $1, $2, $n for a given msg key
 189+ *
 190+ * @param string messageKey The msg key to lookup
 191+ * @param {Array} args An array of string or jQuery objects to be swapped in
 192+ * @return string
 193+ */
 194+ replaceStringArgs : function() {
 195+ if( ! this.arguments ) {
 196+ return ;
 197+ }
 198+ // Replace Values
 199+ for ( var v = 0; v < this.arguments.length; v++ ) {
 200+ if( typeof this.arguments[v] == 'undefined' ) {
 201+ continue;
 202+ }
 203+ var replaceValue = this.arguments[ v ];
 204+
 205+ // Convert number if applicable
 206+ if( parseInt( replaceValue ) == replaceValue ) {
 207+ replaceValue = mw.Language.convertNumber( replaceValue );
 208+ }
 209+
 210+ // Message test replace arguments start at 1 instead of zero:
 211+ var argumentRegExp = new RegExp( '\\$' + ( parseInt( v ) + 1 ), 'g' );
 212+
 213+ // Check if we got passed in a jQuery object:
 214+ if( replaceValue instanceof jQuery) {
 215+ // Set the jQuery msg flag
 216+ this.includesjQueryArgs = true;
 217+ // Swap in a jQuery span place holder:
 218+ this.message = this.message.replace( argumentRegExp,
 219+ '<span id="' + JQUERY_SWAP_STRING + v +'"></span>' );
 220+ } else {
 221+ // Assume replaceValue is a string
 222+ this.message = this.message.replace( argumentRegExp, replaceValue );
 223+ }
 224+ }
 225+ },
 226+
 227+ /**
 228+ * Return a jquery element with resolved swapped arguments.
 229+ * return {Element}
 230+ */
 231+ getJQueryArgsReplace: function() {
 232+ var $jQueryMessage = false;
 233+ mw.log( 'msgReplaceJQueryArgs' );
 234+ for ( var v = 0; v < this.arguments.length; v++ ) {
 235+ if( typeof this.arguments[v] == 'undefined' ) {
 236+ continue;
 237+ }
 238+ var $replaceValue = this.arguments[ v ];
 239+ // Only look for jQuery replacements
 240+ if( $replaceValue instanceof jQuery) {
 241+ // Setup the jqueryMessage if not set
 242+ if( !$jQueryMessage ){
 243+ // Setup the message as html to search for jquery swap points
 244+ $jQueryMessage = $j( '<span />' ).html( this.message );
 245+ }
 246+ mw.log(" current jQueryMessage::: " + $jQueryMessage.html() );
 247+ // Find swap target
 248+ var $swapTarget = $jQueryMessage.find( '#' + JQUERY_SWAP_STRING + v );
 249+ // Now we try and find the jQuerySwap points and replace with jQuery object preserving bindings.
 250+ if( ! $swapTarget.length ){
 251+ mw.log( "Error could not find jQuery Swap target: " + v + ' by id: '+ JQUERY_SWAP_STRING + v
 252+ + ' In string: ' + this.message ) ;
 253+ continue;
 254+ }
 255+
 256+ if( $swapTarget.html() != '' ) {
 257+ $replaceValue.html( $swapTarget.html() );
 258+ }
 259+
 260+ // Swap for $swapTarget for $replaceValue swap target * preserving the jQuery binding )
 261+ $swapTarget.replaceWith( $replaceValue );
 262+ }
 263+ }
 264+ // Return the jQuery object ( if no jQuery substitution occurred we return false )
 265+ return $jQueryMessage;
 266+ }
 267+ }
 268+
 269+ /**
 270+ * Get msg content without transformation
 271+ *
 272+ * @returns string The msg key without transforming it
 273+ */
 274+ mw.Language.msgNoTrans = function( key ) {
 275+ if ( messageCache[ key ] )
 276+ return messageCache[ key ]
 277+
 278+ // Missing key placeholder
 279+ return '&lt;' + key + '&gt;';
 280+ }
 281+ /**
 282+ * Check if a message key is defined
 283+ * @return {Boolean} true if msg is defined, false if msg is not set
 284+ */
 285+ mw.Language.isMsgKeyDefined = function( msgKey ){
 286+ if( messageCache[ msgKey ] ){
 287+ return true
 288+ }
 289+ return false;
 290+ }
 291+
 292+ /**
 293+ * Add Supported Magic Words to parser
 294+ */
 295+ // Set the setupflag to false:
 296+ mw.Language.doneSetup = false;
 297+ mw.Language.magicSetup = function() {
 298+ if ( !mw.Language.doneSetup ) {
 299+ mw.addTemplateTransform ( {
 300+ 'PLURAL' : mw.Language.procPLURAL,
 301+ 'GENDER' : mw.Language.procGENDER
 302+ } )
 303+
 304+ mw.Language.doneSetup = true;
 305+ }
 306+
 307+ }
 308+
 309+ /**
 310+ * Plural form transformations, needed for some languages.
 311+ * For example, there are 3 form of plural in Russian and Polish,
 312+ * depending on "count mod 10". See [[w:Plural]]
 313+ * For English it is pretty simple.
 314+ *
 315+ * Invoked by putting {{plural:count|wordform1|wordform2}}
 316+ * or {{plural:count|wordform1|wordform2|wordform3}}
 317+ *
 318+ * Example: {{plural:{{NUMBEROFARTICLES}}|article|articles}}
 319+ *
 320+ * @param count Integer: non-localized number
 321+ * @param forms Array: different plural forms
 322+ * @return string Correct form of plural for count in this language
 323+ */
 324+
 325+ /**
 326+ * Base gender transform function
 327+ */
 328+ mw.Language.gender = function( gender, forms ) {
 329+ if ( ! forms.length ) {
 330+ return '';
 331+ }
 332+ forms = mw.Language.preConvertPlural( forms, 2 );
 333+ if ( gender === 'male' ) return forms[0];
 334+ if ( gender === 'female' ) return forms[1];
 335+ return ( forms[2] ) ? forms[2] : forms[0];
 336+ };
 337+
 338+ /**
 339+ * Process the PLURAL template substitution
 340+ * @param {Object} template Template object
 341+ *
 342+ * {{Template:argument|params}}
 343+ *
 344+ * Template object should include:
 345+ * [arg] The argument sent to the template
 346+ * [params] The template parameters
 347+ */
 348+ mw.Language.procPLURAL = function( templateObject ) {
 349+ // Setup shortcuts
 350+ // ( gRuleSet is loaded from script-loader to contains local ruleset )
 351+ var rs = gRuleSet[ 'PLURAL' ];
 352+
 353+ if( templateObject.arg && templateObject.param && mw.Language.convertPlural) {
 354+ // Check if we have forms to replace
 355+ if ( templateObject.param.length == 0 ) {
 356+ return '';
 357+ }
 358+ // Restore the count into a Number ( if it got converted earlier )
 359+ var count = mw.Language.convertNumber( templateObject.arg, true );
 360+
 361+ // Do convertPlural call
 362+ return mw.Language.convertPlural( parseInt( count ), templateObject.param );
 363+
 364+ }
 365+ // Could not process plural return first form or nothing
 366+ if( templateObject.param[0] ) {
 367+ return templateObject.param[0];
 368+ }
 369+ return '';
 370+ };
 371+
 372+ // NOTE:: add gender support here
 373+ mw.Language.procGENDER = function( templateObject ){
 374+ return 'gender-not-supported-in-js-yet';
 375+ }
 376+ /*
 377+ * Base convertPlural function:
 378+ */
 379+ mw.Language.convertPlural = function( count, forms ){
 380+ if ( !forms || forms.length == 0 ) {
 381+ return '';
 382+ }
 383+ return ( parseInt( count ) == 1 ) ? forms[0] : forms[1];
 384+ };
 385+ /**
 386+ * Checks that convertPlural was given an array and pads it to requested
 387+ * amount of forms by copying the last one.
 388+ *
 389+ * @param {Array} forms Forms given to convertPlural
 390+ * @param {Integer} count How many forms should there be at least
 391+ * @return {Array} Padded array of forms or an exception if not an array
 392+ */
 393+ mw.Language.preConvertPlural = function( forms, count ) {
 394+ while ( forms.length < count ) {
 395+ forms.push( forms[ forms.length-1 ] );
 396+ }
 397+ return forms;
 398+ };
 399+
 400+ /**
 401+ * Init the digitTransformTable ( populated by language classes where applicable )
 402+ */
 403+ mw.Language.digitTransformTable = null;
 404+
 405+ /**
 406+ * Convert a number using the digitTransformTable
 407+ * @param Number number to be converted
 408+ * @param Bollean typeInt if we should return a number of type int
 409+ */
 410+ mw.Language.convertNumber = function( number, typeInt ) {
 411+ if( !mw.Language.digitTransformTable )
 412+ return number;
 413+
 414+ // Set the target Transform table:
 415+ var transformTable = mw.Language.digitTransformTable;
 416+
 417+ // Check if the "restore" to latin number flag is set:
 418+ if( typeInt ) {
 419+ if( parseInt( number ) == number )
 420+ return number;
 421+ var tmp = [];
 422+ for( var i in transformTable ) {
 423+ tmp[ transformTable[ i ] ] = i;
 424+ }
 425+ transformTable = tmp;
 426+ }
 427+
 428+ var numberString = '' + number;
 429+ var convertedNumber = '';
 430+ for( var i =0; i < numberString.length; i++) {
 431+ if( transformTable[ numberString[i] ] ) {
 432+ convertedNumber += transformTable[ numberString[i] ];
 433+ }else{
 434+ convertedNumber += numberString[i];
 435+ }
 436+ }
 437+ return ( typeInt )? parseInt( convertedNumber) : convertedNumber;
 438+ }
 439+
 440+ /**
 441+ * Checks if a language key is valid ( is part of languageCodeList )
 442+ * @param {String} langKey Language key to be checked
 443+ * @return true if valid language, false if not
 444+ */
 445+ mw.isValidLang = function( langKey ) {
 446+ return ( mw.Language.names[ langKey ] )? true : false;
 447+ }
 448+
 449+ /**
 450+ * Get a language transform key
 451+ * returns default "en" fallback if none found
 452+ * @param String langKey The language key to be checked
 453+ */
 454+ mw.getLangTransformKey = function( langKey ) {
 455+ if( mw.Language.fallbackTransformMap[ langKey ] ) {
 456+ langKey = mw.Language.fallbackTransformMap[ langKey ];
 457+ }
 458+ // Make sure the langKey has a transformClass:
 459+ for( var i = 0; i < mw.Language.transformClass.length ; i++ ) {
 460+ if( langKey == mw.Language.transformClass[i] ){
 461+ return langKey
 462+ }
 463+ }
 464+ // By default return the base 'en' class
 465+ return 'en';
 466+ }
 467+
 468+ /**
 469+ * getRemoteMsg loads remote msg strings
 470+ *
 471+ * @param {Mixed} msgSet the set of msg to load remotely
 472+ * @param function callback the callback to issue once string is ready
 473+ */
 474+ mw.getRemoteMsg = function( msgSet, callback ) {
 475+ var ammessages = '';
 476+ if ( typeof msgSet == 'object' ) {
 477+ for ( var i in msgSet ) {
 478+ if( !messageCache[ i ] ) {
 479+ ammessages += msgSet[i] + '|';
 480+ }
 481+ }
 482+ } else if ( typeof msgSet == 'string' ) {
 483+ if( !messageCache[ i ] ) {
 484+ ammessages += msgSet;
 485+ }
 486+ }
 487+ if ( ammessages == '' ) {
 488+ mw.log( 'no remote msgs to get' );
 489+ callback();
 490+ return false;
 491+ }
 492+ var request = {
 493+ 'meta': 'allmessages',
 494+ 'ammessages': ammessages
 495+ }
 496+ mw.getJSON( request, function( data ) {
 497+ if ( data.query.allmessages ) {
 498+ var msgs = data.query.allmessages;
 499+ for ( var i in msgs ) {
 500+ var ld = { };
 501+ ld[ msgs[i]['name'] ] = msgs[i]['*'];
 502+ mw.addMessages( ld );
 503+ }
 504+ }
 505+ callback();
 506+ } );
 507+ }
 508+
 509+ /**
 510+ * Format a size in bytes for output, using an appropriate
 511+ * unit (B, KB, MB or GB) according to the magnitude in question
 512+ *
 513+ * @param size Size to format
 514+ * @return string Plain text (not HTML)
 515+ */
 516+ mw.Language.formatSize = function ( size ) {
 517+ // For small sizes no decimal places are necessary
 518+ var round = 0;
 519+ var msg = '';
 520+ if ( size > 1024 ) {
 521+ size = size / 1024;
 522+ if ( size > 1024 ) {
 523+ size = size / 1024;
 524+ // For MB and bigger two decimal places are smarter
 525+ round = 2;
 526+ if ( size > 1024 ) {
 527+ size = size / 1024;
 528+ msg = 'mwe-size-gigabytes';
 529+ } else {
 530+ msg = 'mwe-size-megabytes';
 531+ }
 532+ } else {
 533+ msg = 'mwe-size-kilobytes';
 534+ }
 535+ } else {
 536+ msg = 'mwe-size-bytes';
 537+ }
 538+ // JavaScript does not let you choose the precision when rounding
 539+ var p = Math.pow( 10, round );
 540+ size = Math.round( size * p ) / p;
 541+ return gM( msg , size );
 542+ };
 543+
 544+ /**
 545+ * Format a number
 546+ * @param {Number} num Number to be formated
 547+ * NOTE: add il8n support to lanuages/class/Language{langCode}.js
 548+ */
 549+ mw.Language.formatNumber = function( num ) {
 550+ /*
 551+ * addSeparatorsNF
 552+ * @param Str: The number to be formatted, as a string or number.
 553+ * @param outD: The decimal character for the output, such as ',' for the number 100,2
 554+ * @param sep: The separator character for the output, such as ',' for the number 1,000.2
 555+ */
 556+ function addSeparatorsNF( nStr, outD, sep ) {
 557+ nStr += '';
 558+ var dpos = nStr.indexOf( '.' );
 559+ var nStrEnd = '';
 560+ if ( dpos != -1 ) {
 561+ nStrEnd = outD + nStr.substring( dpos + 1, nStr.length );
 562+ nStr = nStr.substring( 0, dpos );
 563+ }
 564+ var rgx = /(\d+)(\d{3})/;
 565+ while ( rgx.test( nStr ) ) {
 566+ nStr = nStr.replace( rgx, '$1' + sep + '$2' );
 567+ }
 568+ return nStr + nStrEnd;
 569+ }
 570+ // @@todo read language code and give periods or comas:
 571+ return addSeparatorsNF( num, '.', ',' );
 572+ }
 573+
 574+
 575+ /**
 576+ * List of all languages mediaWiki supports ( Avoid an api call to get this same info )
 577+ * http://commons.wikimedia.org/w/api.php?action=query&meta=siteinfo&siprop=languages&format=jsonfm
 578+ */
 579+ mw.Language.names = {
 580+ "aa" : "Qaf\u00e1r af",
 581+ "ab" : "\u0410\u04a7\u0441\u0443\u0430",
 582+ "ace" : "Ac\u00e8h",
 583+ "af" : "Afrikaans",
 584+ "ak" : "Akan",
 585+ "aln" : "Geg\u00eb",
 586+ "als" : "Alemannisch",
 587+ "am" : "\u12a0\u121b\u122d\u129b",
 588+ "an" : "Aragon\u00e9s",
 589+ "ang" : "Anglo-Saxon",
 590+ "ar" : "\u0627\u0644\u0639\u0631\u0628\u064a\u0629",
 591+ "arc" : "\u0710\u072a\u0721\u071d\u0710",
 592+ "arn" : "Mapudungun",
 593+ "arz" : "\u0645\u0635\u0631\u0649",
 594+ "as" : "\u0985\u09b8\u09ae\u09c0\u09af\u09bc\u09be",
 595+ "ast" : "Asturianu",
 596+ "av" : "\u0410\u0432\u0430\u0440",
 597+ "avk" : "Kotava",
 598+ "ay" : "Aymar aru",
 599+ "az" : "Az\u0259rbaycan",
 600+ "ba" : "\u0411\u0430\u0448\u04a1\u043e\u0440\u0442",
 601+ "bar" : "Boarisch",
 602+ "bat-smg" : "\u017demait\u0117\u0161ka",
 603+ "bcc" : "\u0628\u0644\u0648\u0686\u06cc \u0645\u06a9\u0631\u0627\u0646\u06cc",
 604+ "bcl" : "Bikol Central",
 605+ "be" : "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f",
 606+ "be-tarask" : "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430)",
 607+ "be-x-old" : "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430)",
 608+ "bg" : "\u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438",
 609+ "bh" : "\u092d\u094b\u091c\u092a\u0941\u0930\u0940",
 610+ "bi" : "Bislama",
 611+ "bm" : "Bamanankan",
 612+ "bn" : "\u09ac\u09be\u0982\u09b2\u09be",
 613+ "bo" : "\u0f56\u0f7c\u0f51\u0f0b\u0f61\u0f72\u0f42",
 614+ "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",
 615+ "bqi" : "\u0628\u062e\u062a\u064a\u0627\u0631\u064a",
 616+ "br" : "Brezhoneg",
 617+ "bs" : "Bosanski",
 618+ "bug" : "\u1a05\u1a14 \u1a15\u1a18\u1a01\u1a17",
 619+ "bxr" : "\u0411\u0443\u0440\u044f\u0430\u0434",
 620+ "ca" : "Catal\u00e0",
 621+ "cbk-zam" : "Chavacano de Zamboanga",
 622+ "cdo" : "M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304",
 623+ "ce" : "\u041d\u043e\u0445\u0447\u0438\u0439\u043d",
 624+ "ceb" : "Cebuano",
 625+ "ch" : "Chamoru",
 626+ "cho" : "Choctaw",
 627+ "chr" : "\u13e3\u13b3\u13a9",
 628+ "chy" : "Tsets\u00eahest\u00e2hese",
 629+ "ckb" : "Soran\u00ee \/ \u06a9\u0648\u0631\u062f\u06cc",
 630+ "ckb-latn" : "\u202aSoran\u00ee (lat\u00een\u00ee)\u202c",
 631+ "ckb-arab" : "\u202b\u06a9\u0648\u0631\u062f\u06cc (\u0639\u06d5\u0631\u06d5\u0628\u06cc)\u202c",
 632+ "co" : "Corsu",
 633+ "cr" : "N\u0113hiyaw\u0113win \/ \u14c0\u1426\u1403\u152d\u140d\u140f\u1423",
 634+ "crh" : "Q\u0131r\u0131mtatarca",
 635+ "crh-latn" : "\u202aQ\u0131r\u0131mtatarca (Latin)\u202c",
 636+ "crh-cyrl" : "\u202a\u041a\u044a\u044b\u0440\u044b\u043c\u0442\u0430\u0442\u0430\u0440\u0434\u0436\u0430 (\u041a\u0438\u0440\u0438\u043b\u043b)\u202c",
 637+ "cs" : "\u010cesky",
 638+ "csb" : "Kasz\u00ebbsczi",
 639+ "cu" : "\u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f",
 640+ "cv" : "\u0427\u04d1\u0432\u0430\u0448\u043b\u0430",
 641+ "cy" : "Cymraeg",
 642+ "da" : "Dansk",
 643+ "de" : "Deutsch",
 644+ "de-at" : "\u00d6sterreichisches Deutsch",
 645+ "de-ch" : "Schweizer Hochdeutsch",
 646+ "de-formal" : "Deutsch (Sie-Form)",
 647+ "diq" : "Zazaki",
 648+ "dk" : "Dansk (deprecated:da)",
 649+ "dsb" : "Dolnoserbski",
 650+ "dv" : "\u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0",
 651+ "dz" : "\u0f47\u0f7c\u0f44\u0f0b\u0f41",
 652+ "ee" : "E\u028begbe",
 653+ "el" : "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac",
 654+ "eml" : "Emili\u00e0n e rumagn\u00f2l",
 655+ "en" : "English",
 656+ "en-gb" : "British English",
 657+ "eo" : "Esperanto",
 658+ "es" : "Espa\u00f1ol",
 659+ "et" : "Eesti",
 660+ "eu" : "Euskara",
 661+ "ext" : "Estreme\u00f1u",
 662+ "fa" : "\u0641\u0627\u0631\u0633\u06cc",
 663+ "ff" : "Fulfulde",
 664+ "fi" : "Suomi",
 665+ "fiu-vro" : "V\u00f5ro",
 666+ "fj" : "Na Vosa Vakaviti",
 667+ "fo" : "F\u00f8royskt",
 668+ "fr" : "Fran\u00e7ais",
 669+ "frc" : "Fran\u00e7ais cadien",
 670+ "frp" : "Arpetan",
 671+ "fur" : "Furlan",
 672+ "fy" : "Frysk",
 673+ "ga" : "Gaeilge",
 674+ "gag" : "Gagauz",
 675+ "gan" : "\u8d1b\u8a9e",
 676+ "gan-hans" : "\u8d63\u8bed(\u7b80\u4f53)",
 677+ "gan-hant" : "\u8d1b\u8a9e(\u7e41\u9ad4)",
 678+ "gd" : "G\u00e0idhlig",
 679+ "gl" : "Galego",
 680+ "glk" : "\u06af\u06cc\u0644\u06a9\u06cc",
 681+ "gn" : "Ava\u00f1e'\u1ebd",
 682+ "got" : "\ud800\udf32\ud800\udf3f\ud800\udf44\ud800\udf39\ud800\udf43\ud800\udf3a",
 683+ "grc" : "\u1f08\u03c1\u03c7\u03b1\u03af\u03b1 \u1f11\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u1f74",
 684+ "gsw" : "Alemannisch",
 685+ "gu" : "\u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0",
 686+ "gv" : "Gaelg",
 687+ "ha" : "\u0647\u064e\u0648\u064f\u0633\u064e",
 688+ "hak" : "Hak-k\u00e2-fa",
 689+ "haw" : "Hawai`i",
 690+ "he" : "\u05e2\u05d1\u05e8\u05d9\u05ea",
 691+ "hi" : "\u0939\u093f\u0928\u094d\u0926\u0940",
 692+ "hif" : "Fiji Hindi",
 693+ "hif-deva" : "\u092b\u093c\u0940\u091c\u0940 \u0939\u093f\u0928\u094d\u0926\u0940",
 694+ "hif-latn" : "Fiji Hindi",
 695+ "hil" : "Ilonggo",
 696+ "ho" : "Hiri Motu",
 697+ "hr" : "Hrvatski",
 698+ "hsb" : "Hornjoserbsce",
 699+ "ht" : "Krey\u00f2l ayisyen",
 700+ "hu" : "Magyar",
 701+ "hy" : "\u0540\u0561\u0575\u0565\u0580\u0565\u0576",
 702+ "hz" : "Otsiherero",
 703+ "ia" : "Interlingua",
 704+ "id" : "Bahasa Indonesia",
 705+ "ie" : "Interlingue",
 706+ "ig" : "Igbo",
 707+ "ii" : "\ua187\ua259",
 708+ "ik" : "I\u00f1upiak",
 709+ "ike-cans" : "\u1403\u14c4\u1483\u144e\u1450\u1466",
 710+ "ike-latn" : "inuktitut",
 711+ "ilo" : "Ilokano",
 712+ "inh" : "\u0413\u0406\u0430\u043b\u0433\u0406\u0430\u0439 \u011eal\u011faj",
 713+ "io" : "Ido",
 714+ "is" : "\u00cdslenska",
 715+ "it" : "Italiano",
 716+ "iu" : "\u1403\u14c4\u1483\u144e\u1450\u1466\/inuktitut",
 717+ "ja" : "\u65e5\u672c\u8a9e",
 718+ "jbo" : "Lojban",
 719+ "jut" : "Jysk",
 720+ "jv" : "Basa Jawa",
 721+ "ka" : "\u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8",
 722+ "kaa" : "Qaraqalpaqsha",
 723+ "kab" : "Taqbaylit",
 724+ "kg" : "Kongo",
 725+ "ki" : "G\u0129k\u0169y\u0169",
 726+ "kiu" : "Kurmanc\u00ee",
 727+ "kj" : "Kwanyama",
 728+ "kk" : "\u049a\u0430\u0437\u0430\u049b\u0448\u0430",
 729+ "kk-arab" : "\u202b\u0642\u0627\u0632\u0627\u0642\u0634\u0627 (\u062a\u0674\u0648\u062a\u06d5)\u202c",
 730+ "kk-cyrl" : "\u202a\u049a\u0430\u0437\u0430\u049b\u0448\u0430 (\u043a\u0438\u0440\u0438\u043b)\u202c",
 731+ "kk-latn" : "\u202aQazaq\u015fa (lat\u0131n)\u202c",
 732+ "kk-cn" : "\u202b\u0642\u0627\u0632\u0627\u0642\u0634\u0627 (\u062c\u06c7\u0646\u06af\u0648)\u202c",
 733+ "kk-kz" : "\u202a\u049a\u0430\u0437\u0430\u049b\u0448\u0430 (\u049a\u0430\u0437\u0430\u049b\u0441\u0442\u0430\u043d)\u202c",
 734+ "kk-tr" : "\u202aQazaq\u015fa (T\u00fcrk\u00efya)\u202c",
 735+ "kl" : "Kalaallisut",
 736+ "km" : "\u1797\u17b6\u179f\u17b6\u1781\u17d2\u1798\u17c2\u179a",
 737+ "kn" : "\u0c95\u0ca8\u0ccd\u0ca8\u0ca1",
 738+ "ko" : "\ud55c\uad6d\uc5b4",
 739+ "ko-kp" : "\ud55c\uad6d\uc5b4 (\uc870\uc120)",
 740+ "kr" : "Kanuri",
 741+ "kri" : "Krio",
 742+ "krj" : "Kinaray-a",
 743+ "ks" : "\u0915\u0936\u094d\u092e\u0940\u0930\u0940 - (\u0643\u0634\u0645\u064a\u0631\u064a)",
 744+ "ksh" : "Ripoarisch",
 745+ "ku" : "Kurd\u00ee \/ \u0643\u0648\u0631\u062f\u06cc",
 746+ "ku-latn" : "\u202aKurd\u00ee (lat\u00een\u00ee)\u202c",
 747+ "ku-arab" : "\u202b\u0643\u0648\u0631\u062f\u064a (\u0639\u06d5\u0631\u06d5\u0628\u06cc)\u202c",
 748+ "kv" : "\u041a\u043e\u043c\u0438",
 749+ "kw" : "Kernowek",
 750+ "ky" : "\u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430",
 751+ "la" : "Latina",
 752+ "lad" : "Ladino",
 753+ "lb" : "L\u00ebtzebuergesch",
 754+ "lbe" : "\u041b\u0430\u043a\u043a\u0443",
 755+ "lez" : "\u041b\u0435\u0437\u0433\u0438",
 756+ "lfn" : "Lingua Franca Nova",
 757+ "lg" : "Luganda",
 758+ "li" : "Limburgs",
 759+ "lij" : "L\u00edguru",
 760+ "lmo" : "Lumbaart",
 761+ "ln" : "Ling\u00e1la",
 762+ "lo" : "\u0ea5\u0eb2\u0ea7",
 763+ "loz" : "Silozi",
 764+ "lt" : "Lietuvi\u0173",
 765+ "lv" : "Latvie\u0161u",
 766+ "lzh" : "\u6587\u8a00",
 767+ "mai" : "\u092e\u0948\u0925\u093f\u0932\u0940",
 768+ "map-bms" : "Basa Banyumasan",
 769+ "mdf" : "\u041c\u043e\u043a\u0448\u0435\u043d\u044c",
 770+ "mg" : "Malagasy",
 771+ "mh" : "Ebon",
 772+ "mhr" : "\u041e\u043b\u044b\u043a \u041c\u0430\u0440\u0438\u0439",
 773+ "mi" : "M\u0101ori",
 774+ "mk" : "\u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438",
 775+ "ml" : "\u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02",
 776+ "mn" : "\u041c\u043e\u043d\u0433\u043e\u043b",
 777+ "mo" : "\u041c\u043e\u043b\u0434\u043e\u0432\u0435\u043d\u044f\u0441\u043a\u044d",
 778+ "mr" : "\u092e\u0930\u093e\u0920\u0940",
 779+ "ms" : "Bahasa Melayu",
 780+ "mt" : "Malti",
 781+ "mus" : "Mvskoke",
 782+ "mwl" : "Mirand\u00e9s",
 783+ "my" : "\u1019\u103c\u1014\u103a\u1019\u102c\u1018\u102c\u101e\u102c",
 784+ "myv" : "\u042d\u0440\u0437\u044f\u043d\u044c",
 785+ "mzn" : "\u0645\u064e\u0632\u0650\u0631\u0648\u0646\u064a",
 786+ "na" : "Dorerin Naoero",
 787+ "nah" : "N\u0101huatl",
 788+ "nan" : "B\u00e2n-l\u00e2m-g\u00fa",
 789+ "nap" : "Nnapulitano",
 790+ "nb" : "\u202aNorsk (bokm\u00e5l)\u202c",
 791+ "nds" : "Plattd\u00fc\u00fctsch",
 792+ "nds-nl" : "Nedersaksisch",
 793+ "ne" : "\u0928\u0947\u092a\u093e\u0932\u0940",
 794+ "new" : "\u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e",
 795+ "ng" : "Oshiwambo",
 796+ "niu" : "Niu\u0113",
 797+ "nl" : "Nederlands",
 798+ "nn" : "\u202aNorsk (nynorsk)\u202c",
 799+ "no" : "\u202aNorsk (bokm\u00e5l)\u202c",
 800+ "nov" : "Novial",
 801+ "nrm" : "Nouormand",
 802+ "nso" : "Sesotho sa Leboa",
 803+ "nv" : "Din\u00e9 bizaad",
 804+ "ny" : "Chi-Chewa",
 805+ "oc" : "Occitan",
 806+ "om" : "Oromoo",
 807+ "or" : "\u0b13\u0b21\u0b3c\u0b3f\u0b06",
 808+ "os" : "\u0418\u0440\u043e\u043d\u0430\u0443",
 809+ "pa" : "\u0a2a\u0a70\u0a1c\u0a3e\u0a2c\u0a40",
 810+ "pag" : "Pangasinan",
 811+ "pam" : "Kapampangan",
 812+ "pap" : "Papiamentu",
 813+ "pcd" : "Picard",
 814+ "pdc" : "Deitsch",
 815+ "pdt" : "Plautdietsch",
 816+ "pfl" : "Pf\u00e4lzisch",
 817+ "pi" : "\u092a\u093e\u093f\u0934",
 818+ "pih" : "Norfuk \/ Pitkern",
 819+ "pl" : "Polski",
 820+ "pms" : "Piemont\u00e8is",
 821+ "pnb" : "\u067e\u0646\u062c\u0627\u0628\u06cc",
 822+ "pnt" : "\u03a0\u03bf\u03bd\u03c4\u03b9\u03b1\u03ba\u03ac",
 823+ "ps" : "\u067e\u069a\u062a\u0648",
 824+ "pt" : "Portugu\u00eas",
 825+ "pt-br" : "Portugu\u00eas do Brasil",
 826+ "qu" : "Runa Simi",
 827+ "rif" : "Tarifit",
 828+ "rm" : "Rumantsch",
 829+ "rmy" : "Romani",
 830+ "rn" : "Kirundi",
 831+ "ro" : "Rom\u00e2n\u0103",
 832+ "roa-rup" : "Arm\u00e3neashce",
 833+ "roa-tara" : "Tarand\u00edne",
 834+ "ru" : "\u0420\u0443\u0441\u0441\u043a\u0438\u0439",
 835+ "ruq" : "Vl\u0103he\u015fte",
 836+ "ruq-cyrl" : "\u0412\u043b\u0430\u0445\u0435\u0441\u0442\u0435",
 837+ "ruq-latn" : "Vl\u0103he\u015fte",
 838+ "rw" : "Kinyarwanda",
 839+ "sa" : "\u0938\u0902\u0938\u094d\u0915\u0943\u0924",
 840+ "sah" : "\u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430",
 841+ "sc" : "Sardu",
 842+ "scn" : "Sicilianu",
 843+ "sco" : "Scots",
 844+ "sd" : "\u0633\u0646\u068c\u064a",
 845+ "sdc" : "Sassaresu",
 846+ "se" : "S\u00e1megiella",
 847+ "sei" : "Cmique Itom",
 848+ "sg" : "S\u00e4ng\u00f6",
 849+ "sh" : "Srpskohrvatski \/ \u0421\u0440\u043f\u0441\u043a\u043e\u0445\u0440\u0432\u0430\u0442\u0441\u043a\u0438",
 850+ "shi" : "Ta\u0161l\u1e25iyt",
 851+ "si" : "\u0dc3\u0dd2\u0d82\u0dc4\u0dbd",
 852+ "simple" : "Simple English",
 853+ "sk" : "Sloven\u010dina",
 854+ "sl" : "Sloven\u0161\u010dina",
 855+ "sli" : "Schl\u00e4sch",
 856+ "sm" : "Gagana Samoa",
 857+ "sma" : "\u00c5arjelsaemien",
 858+ "sn" : "chiShona",
 859+ "so" : "Soomaaliga",
 860+ "sq" : "Shqip",
 861+ "sr" : "\u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski",
 862+ "sr-ec" : "\u0421\u0440\u043f\u0441\u043a\u0438 (\u045b\u0438\u0440\u0438\u043b\u0438\u0446\u0430)",
 863+ "sr-el" : "Srpski (latinica)",
 864+ "srn" : "Sranantongo",
 865+ "ss" : "SiSwati",
 866+ "st" : "Sesotho",
 867+ "stq" : "Seeltersk",
 868+ "su" : "Basa Sunda",
 869+ "sv" : "Svenska",
 870+ "sw" : "Kiswahili",
 871+ "szl" : "\u015al\u016fnski",
 872+ "ta" : "\u0ba4\u0bae\u0bbf\u0bb4\u0bcd",
 873+ "tcy" : "\u0ca4\u0cc1\u0cb3\u0cc1",
 874+ "te" : "\u0c24\u0c46\u0c32\u0c41\u0c17\u0c41",
 875+ "tet" : "Tetun",
 876+ "tg" : "\u0422\u043e\u04b7\u0438\u043a\u04e3",
 877+ "tg-cyrl" : "\u0422\u043e\u04b7\u0438\u043a\u04e3",
 878+ "tg-latn" : "tojik\u012b",
 879+ "th" : "\u0e44\u0e17\u0e22",
 880+ "ti" : "\u1275\u130d\u122d\u129b",
 881+ "tk" : "T\u00fcrkmen\u00e7e",
 882+ "tl" : "Tagalog",
 883+ "tn" : "Setswana",
 884+ "to" : "lea faka-Tonga",
 885+ "tokipona" : "Toki Pona",
 886+ "tp" : "Toki Pona (deprecated:tokipona)",
 887+ "tpi" : "Tok Pisin",
 888+ "tr" : "T\u00fcrk\u00e7e",
 889+ "ts" : "Xitsonga",
 890+ "tt" : "\u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a",
 891+ "tt-cyrl" : "\u0422\u0430\u0442\u0430\u0440\u0447\u0430",
 892+ "tt-latn" : "Tatar\u00e7a",
 893+ "tum" : "chiTumbuka",
 894+ "tw" : "Twi",
 895+ "ty" : "Reo M\u0101`ohi",
 896+ "tyv" : "\u0422\u044b\u0432\u0430 \u0434\u044b\u043b",
 897+ "udm" : "\u0423\u0434\u043c\u0443\u0440\u0442",
 898+ "ug" : "Uyghurche\u200e \/ \u0626\u06c7\u064a\u063a\u06c7\u0631\u0686\u06d5",
 899+ "ug-arab" : "\u0626\u06c7\u064a\u063a\u06c7\u0631\u0686\u06d5",
 900+ "ug-latn" : "Uyghurche\u200e",
 901+ "uk" : "\u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430",
 902+ "ur" : "\u0627\u0631\u062f\u0648",
 903+ "uz" : "O'zbek",
 904+ "ve" : "Tshivenda",
 905+ "vec" : "V\u00e8neto",
 906+ "vep" : "Vepsan kel'",
 907+ "vi" : "Ti\u1ebfng Vi\u1ec7t",
 908+ "vls" : "West-Vlams",
 909+ "vo" : "Volap\u00fck",
 910+ "vro" : "V\u00f5ro",
 911+ "wa" : "Walon",
 912+ "war" : "Winaray",
 913+ "wo" : "Wolof",
 914+ "wuu" : "\u5434\u8bed",
 915+ "xal" : "\u0425\u0430\u043b\u044c\u043c\u0433",
 916+ "xh" : "isiXhosa",
 917+ "xmf" : "\u10db\u10d0\u10e0\u10d2\u10d0\u10da\u10e3\u10e0\u10d8",
 918+ "yi" : "\u05d9\u05d9\u05b4\u05d3\u05d9\u05e9",
 919+ "yo" : "Yor\u00f9b\u00e1",
 920+ "yue" : "\u7cb5\u8a9e",
 921+ "za" : "Vahcuengh",
 922+ "zea" : "Ze\u00eauws",
 923+ "zh" : "\u4e2d\u6587",
 924+ "zh-classical" : "\u6587\u8a00",
 925+ "zh-cn" : "\u202a\u4e2d\u6587(\u4e2d\u56fd\u5927\u9646)\u202c",
 926+ "zh-hans" : "\u202a\u4e2d\u6587(\u7b80\u4f53)\u202c",
 927+ "zh-hant" : "\u202a\u4e2d\u6587(\u7e41\u9ad4)\u202c",
 928+ "zh-hk" : "\u202a\u4e2d\u6587(\u9999\u6e2f)\u202c",
 929+ "zh-min-nan" : "B\u00e2n-l\u00e2m-g\u00fa",
 930+ "zh-mo" : "\u202a\u4e2d\u6587(\u6fb3\u9580)\u202c",
 931+ "zh-my" : "\u202a\u4e2d\u6587(\u9a6c\u6765\u897f\u4e9a)\u202c",
 932+ "zh-sg" : "\u202a\u4e2d\u6587(\u65b0\u52a0\u5761)\u202c",
 933+ "zh-tw" : "\u202a\u4e2d\u6587(\u53f0\u7063)\u202c",
 934+ "zh-yue" : "\u7cb5\u8a9e",
 935+ "zu" : "isiZulu"
 936+ };
 937+
 938+ // Language classes ( has a file in /languages/classes/Language{code}.js )
 939+ // ( for languages that override default transforms )
 940+ mw.Language.transformClass = ['am', 'ar', 'bat_smg', 'be_tarak', 'be', 'bh',
 941+ 'bs', 'cs', 'cu', 'cy', 'dsb', 'fr', 'ga', 'gd', 'gv', 'he', 'hi',
 942+ 'hr', 'hsb', 'hy', 'ksh', 'ln', 'lt', 'lv', 'mg', 'mk', 'mo', 'mt',
 943+ 'nso', 'pl', 'pt_br', 'ro', 'ru', 'se', 'sh', 'sk', 'sl', 'sma',
 944+ 'sr_ec', 'sr_el', 'sr', 'ti', 'tl', 'uk', 'wa'
 945+ ];
 946+
 947+ // Language fallbacks listed from language -> fallback language
 948+ mw.Language.fallbackTransformMap = {
 949+ 'mwl' : 'pt',
 950+ 'ace' : 'id',
 951+ 'hsb' : 'de',
 952+ 'frr' : 'de',
 953+ 'pms' : 'it',
 954+ 'dsb' : 'de',
 955+ 'gan' : 'gan-hant',
 956+ 'lzz' : 'tr',
 957+ 'ksh' : 'de',
 958+ 'kl' : 'da',
 959+ 'fur' : 'it',
 960+ 'zh-hk' : 'zh-hant',
 961+ 'kk' : 'kk-cyrl',
 962+ 'zh-my' : 'zh-sg',
 963+ 'nah' : 'es',
 964+ 'sr' : 'sr-ec',
 965+ 'ckb-latn' : 'ckb-arab',
 966+ 'mo' : 'ro',
 967+ 'ay' : 'es',
 968+ 'gl' : 'pt',
 969+ 'gag' : 'tr',
 970+ 'mzn' : 'fa',
 971+ 'ruq-cyrl' : 'mk',
 972+ 'kk-arab' : 'kk-cyrl',
 973+ 'pfl' : 'de',
 974+ 'zh-yue' : 'yue',
 975+ 'ug' : 'ug-latn',
 976+ 'ltg' : 'lv',
 977+ 'nds' : 'de',
 978+ 'sli' : 'de',
 979+ 'mhr' : 'ru',
 980+ 'sah' : 'ru',
 981+ 'ff' : 'fr',
 982+ 'ab' : 'ru',
 983+ 'ko-kp' : 'ko',
 984+ 'sg' : 'fr',
 985+ 'zh-tw' : 'zh-hant',
 986+ 'map-bms' : 'jv',
 987+ 'av' : 'ru',
 988+ 'nds-nl' : 'nl',
 989+ 'pt-br' : 'pt',
 990+ 'ce' : 'ru',
 991+ 'vep' : 'et',
 992+ 'wuu' : 'zh-hans',
 993+ 'pdt' : 'de',
 994+ 'krc' : 'ru',
 995+ 'gan-hant' : 'zh-hant',
 996+ 'bqi' : 'fa',
 997+ 'as' : 'bn',
 998+ 'bm' : 'fr',
 999+ 'gn' : 'es',
 1000+ 'tt' : 'ru',
 1001+ 'zh-hant' : 'zh-hans',
 1002+ 'hif' : 'hif-latn',
 1003+ 'zh' : 'zh-hans',
 1004+ 'kaa' : 'kk-latn',
 1005+ 'lij' : 'it',
 1006+ 'vot' : 'fi',
 1007+ 'ii' : 'zh-cn',
 1008+ 'ku-arab' : 'ckb-arab',
 1009+ 'xmf' : 'ka',
 1010+ 'vmf' : 'de',
 1011+ 'zh-min-nan' : 'nan',
 1012+ 'bcc' : 'fa',
 1013+ 'an' : 'es',
 1014+ 'rgn' : 'it',
 1015+ 'qu' : 'es',
 1016+ 'nb' : 'no',
 1017+ 'bar' : 'de',
 1018+ 'lbe' : 'ru',
 1019+ 'su' : 'id',
 1020+ 'pcd' : 'fr',
 1021+ 'glk' : 'fa',
 1022+ 'lb' : 'de',
 1023+ 'kk-kz' : 'kk-cyrl',
 1024+ 'kk-tr' : 'kk-latn',
 1025+ 'inh' : 'ru',
 1026+ 'mai' : 'hi',
 1027+ 'tp' : 'tokipona',
 1028+ 'kk-latn' : 'kk-cyrl',
 1029+ 'ba' : 'ru',
 1030+ 'nap' : 'it',
 1031+ 'ruq' : 'ruq-latn',
 1032+ 'tt-cyrl' : 'ru',
 1033+ 'lad' : 'es',
 1034+ 'dk' : 'da',
 1035+ 'de-ch' : 'de',
 1036+ 'be-x-old' : 'be-tarask',
 1037+ 'za' : 'zh-hans',
 1038+ 'kk-cn' : 'kk-arab',
 1039+ 'shi' : 'ar',
 1040+ 'crh' : 'crh-latn',
 1041+ 'yi' : 'he',
 1042+ 'pdc' : 'de',
 1043+ 'eml' : 'it',
 1044+ 'uk' : 'ru',
 1045+ 'kv' : 'ru',
 1046+ 'koi' : 'ru',
 1047+ 'cv' : 'ru',
 1048+ 'zh-cn' : 'zh-hans',
 1049+ 'de-at' : 'de',
 1050+ 'jut' : 'da',
 1051+ 'vec' : 'it',
 1052+ 'zh-mo' : 'zh-hk',
 1053+ 'fiu-vro' : 'vro',
 1054+ 'frp' : 'fr',
 1055+ 'mg' : 'fr',
 1056+ 'ruq-latn' : 'ro',
 1057+ 'sa' : 'hi',
 1058+ 'lmo' : 'it',
 1059+ 'kiu' : 'tr',
 1060+ 'tcy' : 'kn',
 1061+ 'srn' : 'nl',
 1062+ 'jv' : 'id',
 1063+ 'vls' : 'nl',
 1064+ 'zea' : 'nl',
 1065+ 'ty' : 'fr',
 1066+ 'szl' : 'pl',
 1067+ 'rmy' : 'ro',
 1068+ 'wo' : 'fr',
 1069+ 'vro' : 'et',
 1070+ 'udm' : 'ru',
 1071+ 'bpy' : 'bn',
 1072+ 'mrj' : 'ru',
 1073+ 'ckb' : 'ckb-arab',
 1074+ 'xal' : 'ru',
 1075+ 'de-formal' : 'de',
 1076+ 'myv' : 'ru',
 1077+ 'ku' : 'ku-latn',
 1078+ 'crh-cyrl' : 'ru',
 1079+ 'gsw' : 'de',
 1080+ 'rue' : 'uk',
 1081+ 'iu' : 'ike-cans',
 1082+ 'stq' : 'de',
 1083+ 'gan-hans' : 'zh-hans',
 1084+ 'scn' : 'it',
 1085+ 'arn' : 'es',
 1086+ 'ht' : 'fr',
 1087+ 'zh-sg' : 'zh-hans',
 1088+ 'bat-smg' : 'lt',
 1089+ 'aln' : 'sq',
 1090+ 'tg' : 'tg-cyrl',
 1091+ 'li' : 'nl',
 1092+ 'simple' : 'en',
 1093+ 'os' : 'ru',
 1094+ 'ln' : 'fr',
 1095+ 'als' : 'gsw',
 1096+ 'zh-classical' : 'lzh',
 1097+ 'arz' : 'ar',
 1098+ 'wa' : 'fr'
 1099+ };
 1100+
 1101+
 1102+}) ( window.mw );
 1103+
 1104+
 1105+// Load in js2 stopgap global msgs into proper location:
 1106+if ( typeof gMsg != 'undefined' ) {
 1107+ mw.addMessages( gMsg )
 1108+}
 1109+
 1110+// Set global gM shortcut:
 1111+window[ 'gM' ] = mw.getMsg;
 1112+
 1113+
 1114+/**
 1115+* Add the core mvEmbed Messages ( will be localized by script server )
 1116+*/
 1117+mw.addMessages( {
 1118+ "mwe-loading_txt" : "Loading ...",
 1119+ "mwe-size-gigabytes" : "$1 GB",
 1120+ "mwe-size-megabytes" : "$1 MB",
 1121+ "mwe-size-kilobytes" : "$1 K",
 1122+ "mwe-size-bytes" : "$1 B",
 1123+ "mwe-error_load_lib" : "Error: JavaScript $1 was not retrievable or does not define $2",
 1124+ "mwe-apiproxy-setup" : "Setting up API proxy",
 1125+ "mwe-load-drag-item" : "Loading dragged item",
 1126+ "mwe-ok" : "OK",
 1127+ "mwe-cancel" : "Cancel",
 1128+ "mwe-enable-gadget" : "Enable multimedia beta ( mwEmbed ) for all pages",
 1129+ "mwe-enable-gadget-done" : "multimedia beta gadget has been enabled",
 1130+ "mwe-must-login-gadget" : "To enable gadget you must <a target=\"_new\" href=\"$1\">login</a>",
 1131+ "mwe-test-plural" : "I ran {{PLURAL:$1|$1 test|$1 tests}}"
 1132+} );
\ No newline at end of file
Property changes on: trunk/extensions/JS2Support/mwEmbed/components/mw.Language.js
___________________________________________________________________
Added: svn:eol-style
11133 + native
Added: svn:executable
21134 + *
Index: trunk/extensions/JS2Support/mwEmbed/components/mw.Api.js
@@ -0,0 +1,370 @@
 2+/**
 3+* API Helper functions
 4+*/
 5+
 6+( function( mw ) {
 7+ // xxx note we should namespace the following helper functions into Api class.
 8+ mw.Api = {};
 9+
 10+ /**
 11+ *
 12+ * Helper function to get revision text for a given title
 13+ *
 14+ * Assumes "follow redirects"
 15+ *
 16+ * $j.getTitleText( [apiUrl], title, callback )
 17+ *
 18+ * @param {String} url or title key
 19+ * @parma {Mixed} title or callback function
 20+ * @param {Function} callback Function or NULL
 21+ *
 22+ * @return callback is called with:
 23+ * {Boolean} false if no page found
 24+ * {String} text of wiki page
 25+ */
 26+ mw.getTitleText = function( apiUrl, title, callback ) {
 27+ // Check if optional apiURL was not included
 28+ if( !callback ) {
 29+ title = apiUrl;
 30+ callback = title;
 31+ apiUrl = mw.getLocalApiUrl();
 32+ }
 33+ var request = {
 34+ // Normalize the File NS (ie sometimes its present in apiTitleKey other times not
 35+ 'titles' : title,
 36+ 'prop' : 'revisions',
 37+ 'rvprop' : 'content'
 38+ };
 39+
 40+ mw.getJSON( apiUrl , request, function( data ) {
 41+ if( !data || !data.query || !data.query.pages ) {
 42+ callback( false );
 43+ }
 44+ var pages = data.query.pages;
 45+ for(var i in pages) {
 46+ page = pages[ i ];
 47+ if( page[ 'revisions' ] && page[ 'revisions' ][0]['*'] ) {
 48+ callback( page[ 'revisions' ][0]['*'] );
 49+ }
 50+ }
 51+ } );
 52+ }
 53+
 54+ /**
 55+ * Issues the wikitext parse call
 56+ *
 57+ * @param {String} wikitext Wiki Text to be parsed by mediaWiki api call
 58+ * @param {String} title Context title of the content to be parsed
 59+ * @param {Function} callback Function called with api parser output
 60+ */
 61+ mw.parseWikiText = function( wikitext, title, callback ) {
 62+ mw.log("mw.parseWikiText text length: " + wikitext.length + ' title context: ' + title );
 63+ mw.load( 'JSON', function(){
 64+ $j.ajax({
 65+ type: 'POST',
 66+ url: mw.getLocalApiUrl(),
 67+ // Give the wiki 60 seconds to parse the wiki-text
 68+ timeout : 60000,
 69+ data: {
 70+ 'action': 'parse',
 71+ 'format': 'json',
 72+ 'title' : title,
 73+ 'text': wikitext
 74+ },
 75+ dataType: 'text',
 76+ success: function( data ) {
 77+ var jsonData = JSON.parse( data ) ;
 78+ // xxx should handle other failures
 79+ callback( jsonData.parse.text['*'] );
 80+ },
 81+ error: function( XMLHttpRequest, textStatus, errorThrown ){
 82+ // xxx should better handle failures
 83+ mw.log( "Error: mw.parseWikiText:" + textStatus );
 84+ callback( "Error: failed to parse wikitext " );
 85+ }
 86+ });
 87+ });
 88+ }
 89+
 90+ /**
 91+ * mediaWiki JSON a wrapper for jQuery getJSON:
 92+ * ( could also be named mw.apiRequest )
 93+ *
 94+ * The mwEmbed version lets you skip the url part
 95+ * mw.getJSON( [url], data, callback, [timeoutCallback] );
 96+ *
 97+ * Lets you assume:
 98+ * url is optional
 99+ * ( If the first argument is not a string we assume a local mediaWiki api request )
 100+ * callback parameter is not needed for the request data
 101+ * url param 'action'=>'query' is assumed ( if not set to something else in the "data" param
 102+ * format is set to "json" automatically
 103+ * automatically issues request over "POST" if the request api post type
 104+ * automatically will setup apiProxy where request is cross domain
 105+ *
 106+ * @param {Mixed} url or data request
 107+ * @param {Mixed} data or callback
 108+ * @param {Function} callbcak function called on success
 109+ * @param {Function} callbackTimeout - optional function called on timeout
 110+ * Setting timeout callback also avoids default timed-out dialog for proxy requests
 111+ */
 112+ mw.getJSON = function() {
 113+ // Process the arguments:
 114+
 115+ // Set up the url
 116+ var url = false;
 117+ url = ( typeof arguments[0] == 'string' ) ? arguments[0] : mw.getLocalApiUrl();
 118+
 119+ // Set up the data:
 120+ var data = null;
 121+ data = ( typeof arguments[0] == 'object' ) ? arguments[0] : null;
 122+ if( !data && typeof arguments[1] == 'object' ) {
 123+ data = arguments[1];
 124+ }
 125+
 126+ // Setup the callback
 127+ var callback = false;
 128+ callback = ( typeof arguments[1] == 'function') ? arguments[1] : false;
 129+ var cbinx = 1;
 130+ if( ! callback && ( typeof arguments[2] == 'function') ) {
 131+ callback = arguments[2];
 132+ cbinx = 2;
 133+ }
 134+
 135+ // Setup the timeoutCallback ( function after callback index )
 136+ var timeoutCallback = false;
 137+ timeoutCallback = ( typeof arguments[ cbinx + 1 ] == 'function' ) ? arguments[ cbinx + 1 ] : false;
 138+
 139+ // Make sure we got a url:
 140+ if( !url ) {
 141+ mw.log( 'Error: no api url for api request' );
 142+ return false;
 143+ }
 144+
 145+ // Add default action if unset:
 146+ if( !data['action'] ) {
 147+ data['action'] = 'query';
 148+ }
 149+
 150+ // Add default format if not set:
 151+ if( !data['format'] ) {
 152+ data['format'] = 'json';
 153+ }
 154+
 155+ // Setup callback wrapper for timeout
 156+ var requestTimeOutFlag = false;
 157+ var ranCallback = false;
 158+
 159+ /**
 160+ * local callback function to control timeout
 161+ * @param {Object} data Result data
 162+ */
 163+ var myCallback = function( data ){
 164+ if( ! requestTimeOutFlag ){
 165+ ranCallback = true;
 166+ callback( data );
 167+ }
 168+ }
 169+ // Set the local timeout call based on defaultRequestTimeout
 170+ setTimeout( function( ) {
 171+ if( ! ranCallback ) {
 172+ requestTimeOutFlag = true;
 173+ mw.log( "Error:: request timed out: " + url );
 174+ if( timeoutCallback ){
 175+ timeoutCallback();
 176+ }
 177+ }
 178+ }, mw.getConfig( 'defaultRequestTimeout' ) * 1000 );
 179+
 180+ mw.log("run getJSON: " + mw.replaceUrlParams( url, data ) );
 181+
 182+ // Check if the request requires a "post"
 183+ if( mw.checkRequestPost( data ) ) {
 184+
 185+ // Check if we need to setup a proxy
 186+ if( ! mw.isLocalDomain( url ) ) {
 187+
 188+ //Set local scope ranCallback to true
 189+ // ( ApiProxy handles timeouts internally )
 190+ ranCallback = true;
 191+
 192+ // Load the proxy and issue the request
 193+ mw.load( 'ApiProxy', function( ) {
 194+ mw.ApiProxy.doRequest( url, data, callback, timeoutCallback);
 195+ } );
 196+
 197+ } else {
 198+
 199+ // Do the request an ajax post
 200+ $j.post( url, data, myCallback, 'json');
 201+ }
 202+ return ;
 203+ }
 204+
 205+ // If cross domain setup a callback:
 206+ if( ! mw.isLocalDomain( url ) ) {
 207+ if( url.indexOf( 'callback=' ) == -1 || data[ 'callback' ] == -1 ) {
 208+ // jQuery specific jsonp format: ( second ? is replaced with the callback )
 209+ url += ( url.indexOf('?') == -1 ) ? '?callback=?' : '&callback=?';
 210+ }
 211+ }
 212+ // Pass off the jQuery getJSON request:
 213+ $j.getJSON( url, data, myCallback );
 214+ }
 215+
 216+ /**
 217+ * Checks if a mw request data requires a post request or not
 218+ * @param {Object}
 219+ * @return {Boolean}
 220+ * true if the request requires a post request
 221+ * false if the request does not
 222+ */
 223+ mw.checkRequestPost = function ( data ) {
 224+ if( $j.inArray( data['action'], mw.getConfig( 'apiPostActions' ) ) != -1 ) {
 225+ return true;
 226+ }
 227+ if( data['prop'] == 'info' && data['intoken'] ) {
 228+ return true;
 229+ }
 230+ if( data['meta'] == 'userinfo' ) {
 231+ return true;
 232+ }
 233+ return false;
 234+ }
 235+
 236+ /**
 237+ * Check if the url is a request for the local domain
 238+ * relative paths are "local" domain
 239+ * @param {String} url Url for local domain
 240+ * @return {Boolean}
 241+ * true if url domain is local or relative
 242+ * false if the domain is
 243+ */
 244+ mw.isLocalDomain = function( url ) {
 245+ if( mw.parseUri( document.URL ).host == mw.parseUri( url ).host
 246+ || url.indexOf( '://' ) == -1 )
 247+ {
 248+ return true;
 249+ }
 250+ return false;
 251+ }
 252+
 253+ /**
 254+ * Api helper to grab an edit token
 255+ *
 256+ * @param {String} [apiUrl] Optional target API URL (uses default local api if unset)
 257+ * @param {String} title The wiki page title you want to edit
 258+ * @param {callback} callback Function to pass the token to.
 259+ * issues callback with "false" if token not retrieved
 260+ */
 261+ mw.getToken = function( apiUrl, title, callback ) {
 262+ // Make the apiUrl be optional:
 263+ if( typeof title == 'function' ) {
 264+ callback = title;
 265+ title = apiUrl;
 266+ apiUrl = mw.getLocalApiUrl();
 267+ }
 268+
 269+ mw.log( 'mw:getToken' );
 270+
 271+ var request = {
 272+ 'prop': 'info',
 273+ 'intoken': 'edit',
 274+ 'titles': title
 275+ };
 276+ mw.getJSON( apiUrl, request, function( data ) {
 277+ for ( var i in data.query.pages ) {
 278+ if ( data.query.pages[i]['edittoken'] ) {
 279+ callback ( data.query.pages[i]['edittoken'] );
 280+ return ;
 281+ }
 282+ }
 283+ // No token found:
 284+ callback ( false );
 285+ } );
 286+ }
 287+
 288+ /**
 289+ * Api helper to grab the username
 290+ * @param {String} [apiUrl] Optional target API url (uses default local api if unset)
 291+ * @param {Function} callback Function to callback with username or false if not found
 292+ * @param {Boolean} fresh A fresh check is issued.
 293+ */
 294+ // Stub feature apiUserNameCache to avoid multiple calls
 295+ // ( a more general api framework should be developed )
 296+ var apiUserNameCache = {};
 297+ mw.getUserName = function( apiUrl, callback, fresh ){
 298+ if( typeof apiUrl == 'function' ){
 299+ var callback = apiUrl;
 300+ var apiUrl = mw.getLocalApiUrl();
 301+ }
 302+
 303+ // If apiUrl is local check wgUserName global
 304+ // before issuing the api request.
 305+ if( mw.isLocalDomain( apiUrl ) ){
 306+ if( typeof wgUserName != 'undefined' && wgUserName !== null ) {
 307+ callback( wgUserName )
 308+ // In case someone called this function without a callback
 309+ return wgUserName;
 310+ }
 311+ }
 312+ if( ! fresh && apiUserNameCache[ apiUrl ] ) {
 313+ callback( apiUserNameCache[ apiUrl ] );
 314+ return ;
 315+ }
 316+
 317+ // Setup the api request
 318+ var request = {
 319+ 'action':'query',
 320+ 'meta':'userinfo'
 321+ }
 322+
 323+ // Do request
 324+ mw.getJSON( apiUrl, request, function( data ) {
 325+ if( !data || !data.query || !data.query.userinfo || !data.query.userinfo.name ){
 326+ // Could not get user name user is not-logged in
 327+ mw.log( " No userName in response " );
 328+ callback( false );
 329+ return ;
 330+ }
 331+ // Check for "not logged in" id == 0
 332+ if( data.query.userinfo.id == 0 ){
 333+ callback( false );
 334+ return ;
 335+ }
 336+ apiUserNameCache[ apiUrl ] = data.query.userinfo.name;
 337+ // Else return the username:
 338+ callback( data.query.userinfo.name );
 339+ }, function(){
 340+ // Timeout also results in callback( false ) ( no user found)
 341+ callback( false );
 342+ } );
 343+ }
 344+
 345+ /**
 346+ * Get the api url for a given content provider key
 347+ * @return {Mixed}
 348+ * url for the provider
 349+ * local wiki api if no apiProvider is set
 350+ */
 351+ mw.getApiProviderURL = function( providerId ) {
 352+ if( mw.getConfig( providerId + '_apiurl') ) {
 353+ return mw.getConfig( providerId + '_apiurl');
 354+ }
 355+ return mw.getLocalApiUrl();
 356+ };
 357+
 358+ /**
 359+ * Get Api URL from mediaWiki page defined variables
 360+ * @return {Mixed}
 361+ * api url
 362+ * false
 363+ */
 364+ mw.getLocalApiUrl = function() {
 365+ if ( typeof wgServer != 'undefined' && typeof wgScriptPath != 'undefined' ) {
 366+ return wgServer + wgScriptPath + '/api.php';
 367+ }
 368+ return false;
 369+ };
 370+
 371+}) ( window.mw );
\ No newline at end of file
Property changes on: trunk/extensions/JS2Support/mwEmbed/components/mw.Api.js
___________________________________________________________________
Added: svn:eol-style
1372 + native
Added: svn:executable
2373 + *
Index: trunk/extensions/JS2Support/mwEmbed/components/mw.Parser.js
@@ -0,0 +1,323 @@
 2+/**
 3+* Mediawiki language text parser
 4+*/
 5+
 6+// Setup swap string constants
 7+var JQUERY_SWAP_STRING = 'ZjQuerySwapZ';
 8+var LINK_SWAP_STRING = 'ZreplaceZ';
 9+
 10+( function( mw ) {
 11+
 12+ // The parser magic global
 13+ var pMagicSet = { };
 14+
 15+ /**
 16+ * addTemplateTransform to the parser
 17+ *
 18+ * Lets you add a set template key to be transformed by a callback function
 19+ *
 20+ * @param {Object} magicSet key:callback
 21+ */
 22+ mw.addTemplateTransform = function( magicSet ) {
 23+ for ( var i in magicSet ) {
 24+ pMagicSet[ i ] = magicSet[i];
 25+ }
 26+ };
 27+
 28+ /**
 29+ * MediaWiki wikitext "Parser" constructor
 30+ *
 31+ * @param {String} wikiText the wikitext to be parsed
 32+ * @return {Object} parserObj returns a parser object that has methods for getting at
 33+ * things you would want
 34+ */
 35+ mw.Parser = function( wikiText, options) {
 36+ // return the parserObj
 37+ this.init( wikiText, options ) ;
 38+ };
 39+
 40+ mw.Parser.prototype = {
 41+
 42+ // the parser output string container
 43+ pOut: false,
 44+
 45+ init: function( wikiText, parserOptions ) {
 46+ this.wikiText = wikiText;
 47+ },
 48+
 49+ // Update the text value
 50+ updateText : function( wikiText ) {
 51+ this.wikiText = wikiText;
 52+
 53+ // invalidate the output ( will force a re-parse )
 54+ this.pOut = false;
 55+ },
 56+
 57+ /**
 58+ * Quickly recursive / parse out templates:
 59+ */
 60+ parse: function() {
 61+ function recurseTokenizeNodes ( text ) {
 62+ var node = { };
 63+ // Inspect each char
 64+ for ( var a = 0; a < text.length; a++ ) {
 65+ if ( text[a] == '{' && text[a + 1] == '{' ) {
 66+ a = a + 2;
 67+ node['parent'] = node;
 68+ if ( !node['child'] ) {
 69+ node['child'] = new Array();
 70+ }
 71+
 72+ node['child'].push( recurseTokenizeNodes( text.substr( a ) ) );
 73+ } else if ( text[a] == '}' && text[a + 1] == '}' ) {
 74+ a++;
 75+ if ( !node['parent'] ) {
 76+ return node;
 77+ }
 78+ node = node['parent'];
 79+ }
 80+ if ( !node['text'] ) {
 81+ node['text'] = '';
 82+ }
 83+ // Don't put }} closures into output:
 84+ if ( text[a] && text[a] != '}' ) {
 85+ node['text'] += text[a];
 86+ }
 87+ }
 88+ return node;
 89+ }
 90+
 91+ /**
 92+ * Parse template text as template name and named params
 93+ * @param {String} templateString Template String to be parsed
 94+ */
 95+ function parseTmplTxt( templateString ) {
 96+ var templateObject = { };
 97+
 98+ // Get template name:
 99+ templateName = templateString.split( '\|' ).shift() ;
 100+ templateName = templateName.split( '\{' ).shift() ;
 101+ templateName = templateName.replace( /^\s+|\s+$/g, "" ); //trim
 102+
 103+ // Check for arguments:
 104+ if ( templateName.split( ':' ).length == 1 ) {
 105+ templateObject["name"] = templateName;
 106+ } else {
 107+ templateObject["name"] = templateName.split( ':' ).shift();
 108+ templateObject["arg"] = templateName.split( ':' ).pop();
 109+ }
 110+
 111+ var paramSet = templateString.split( '\|' );
 112+ paramSet.splice( 0, 1 );
 113+ if ( paramSet.length ) {
 114+ templateObject.param = new Array();
 115+ for ( var pInx in paramSet ) {
 116+ var paramString = paramSet[ pInx ];
 117+ // check for empty param
 118+ if ( paramString == '' ) {
 119+ templateObject.param[ pInx ] = '';
 120+ continue;
 121+ }
 122+ for ( var b = 0 ; b < paramString.length ; b++ ) {
 123+ if ( paramString[b] == '=' && b > 0 && b < paramString.length && paramString[b - 1] != '\\' ) {
 124+ // named param
 125+ templateObject.param[ paramString.split( '=' ).shift() ] = paramString.split( '=' ).pop();
 126+ } else {
 127+ // indexed param
 128+ templateObject.param[ pInx ] = paramString;
 129+ }
 130+ }
 131+ }
 132+ }
 133+ return templateObject;
 134+ }
 135+
 136+ /**
 137+ * Get the Magic text from a template node
 138+ */
 139+ function getMagicTxtFromTempNode( node ) {
 140+ node.templateObject = parseTmplTxt ( node.text );
 141+ // Do magic swap if template key found in pMagicSet
 142+ if ( node.templateObject.name in pMagicSet ) {
 143+ var nodeText = pMagicSet[ node.templateObject.name ]( node.templateObject );
 144+ return nodeText;
 145+ } else {
 146+ // don't swap just return text
 147+ return node.text;
 148+ }
 149+ }
 150+
 151+ /**
 152+ * swap links of form [ ] for html a links or jquery helper spans
 153+ * NOTE: this could be integrated into the tokenizer but for now
 154+ * is a staged process.
 155+ *
 156+ * @param text to swapped
 157+ */
 158+ function linkSwapText( text ) {
 159+ //mw.log( "linkSwapText::" + text );
 160+ var re = new RegExp( /\[([^\s]+[\s]+[^\]]*)\]/g );
 161+ var matchSet = text.match( re );
 162+
 163+ if( !matchSet ){
 164+ return text;
 165+ }
 166+
 167+ text = text.replace( re , LINK_SWAP_STRING );
 168+
 169+ for( var i=0; i < matchSet.length; i++ ) {
 170+ // Strip the leading [ and trailing ]
 171+ var matchParts = matchSet[i].substr(1, matchSet[i].length-2);
 172+
 173+ // Check for special jQuery type swap and replace inner JQUERY_SWAP_STRING not value
 174+ if( matchParts.indexOf( JQUERY_SWAP_STRING ) !== -1 ) {
 175+ // parse the link as html
 176+ var $matchParts = $j('<span>' + matchParts + '</span>' );
 177+
 178+ $jQuerySpan = $matchParts.find('#' +JQUERY_SWAP_STRING + i );
 179+
 180+ var linkText = $matchParts.text();
 181+ //mw.log(" going to swap in linktext: " + linkText );
 182+ $jQuerySpan.text( linkText );
 183+
 184+ text = text.replace( LINK_SWAP_STRING, $j('<span />' ).append( $jQuerySpan ).html() );
 185+ } else {
 186+ // do text string replace
 187+ matchParts = matchParts.split(/ /);
 188+ var link = matchParts[0];
 189+ matchParts.shift();
 190+ var linkText = matchParts.join(' ');
 191+
 192+ text = text.replace( LINK_SWAP_STRING, '<a href="' + link + '">' + linkText + '</a>' );
 193+ }
 194+ }
 195+ return text;
 196+ }
 197+
 198+ /**
 199+ * recurse_magic_swap
 200+ *
 201+ * Go last child first swap upward:
 202+ */
 203+ var pNode = null;
 204+ function recurse_magic_swap( node ) {
 205+ if ( !pNode )
 206+ pNode = node;
 207+
 208+ if ( node['child'] ) {
 209+ // swap all the kids:
 210+ for ( var i in node['child'] ) {
 211+ var nodeText = recurse_magic_swap( node['child'][i] );
 212+ // swap it into current
 213+ if ( node.text ) {
 214+ node.text = node.text.replace( node['child'][i].text, nodeText );
 215+ }
 216+ // swap into parent
 217+ pNode.text = pNode.text.replace( node['child'][i].text, nodeText );
 218+ }
 219+ // Get the updated node text
 220+ var nodeText = getMagicTxtFromTempNode( node );
 221+ pNode.text = pNode.text.replace( node.text , nodeText );
 222+ // return the node text
 223+ return node.text;
 224+ } else {
 225+ return getMagicTxtFromTempNode( node );
 226+ }
 227+ }
 228+
 229+ // Parse out the template node structure:
 230+ this.pNode = recurseTokenizeNodes ( this.wikiText );
 231+
 232+ // Strip out the parent from the root
 233+ this.pNode['parent'] = null;
 234+
 235+ // Do the recursive magic swap text:
 236+ this.pOut = recurse_magic_swap( this.pNode );
 237+
 238+ // Do link swap
 239+ this.pOut = linkSwapText( this.pOut );
 240+ },
 241+
 242+ /**
 243+ * templates
 244+ *
 245+ * Get a requested template from the wikitext (if available)
 246+ * @param templateName
 247+ */
 248+ templates: function( templateName ) {
 249+ this.parse();
 250+ var tmplSet = new Array();
 251+ function getMatchingTmpl( node ) {
 252+ if ( node['child'] ) {
 253+ for ( var i in node['child'] ) {
 254+ getMatchingTmpl( node['child'] );
 255+ }
 256+ }
 257+ if ( templateName && node.templateObject ) {
 258+ if ( node.templateObject['name'] == templateName )
 259+ tmplSet.push( node.templateObject );
 260+ } else if ( node.templateObject ) {
 261+ tmplSet.push( node.templateObject );
 262+ }
 263+ }
 264+ getMatchingTmpl( this.pNode );
 265+ return tmplSet;
 266+ },
 267+
 268+ /**
 269+ * getTemplateVars
 270+ * returns a set of template values in a given wikitext page
 271+ *
 272+ * NOTE: should be integrated with the usability wikitext parser
 273+ */
 274+ getTemplateVars: function() {
 275+ //mw.log('matching against: ' + wikiText);
 276+ templateVars = new Array();
 277+ var tempVars = wikiText.match(/\{\{\{([^\}]*)\}\}\}/gi);
 278+
 279+ // Clean up results:
 280+ for(var i=0; i < tempVars.length; i++) {
 281+ //match
 282+ var tvar = tempVars[i].replace('{{{','').replace('}}}','');
 283+
 284+ // Strip anything after a |
 285+ if(tvar.indexOf('|') != -1) {
 286+ tvar = tvar.substr(0, tvar.indexOf('|'));
 287+ }
 288+
 289+ // Check for duplicates:
 290+ var do_add=true;
 291+ for(var j=0; j < templateVars.length; j++) {
 292+ if( templateVars[j] == tvar)
 293+ do_add=false;
 294+ }
 295+
 296+ // Add the template vars to the output obj
 297+ if(do_add)
 298+ templateVars.push( tvar );
 299+ }
 300+ return templateVars;
 301+ },
 302+
 303+ /**
 304+ * Returns the transformed wikitext
 305+ *
 306+ * Build output from swappable index
 307+ * (all transforms must be expanded in parse stage and linearly rebuilt)
 308+ * Alternatively we could build output using a place-holder & replace system
 309+ * (this lets us be slightly more sloppy with ordering and indexes, but probably slower)
 310+ *
 311+ * Ideal: we build a 'wiki DOM'
 312+ * When editing you update the data structure directly
 313+ * Then in output time you just go DOM->html-ish output without re-parsing anything
 314+ */
 315+ getHTML: function() {
 316+ // wikiText updates should invalidate pOut
 317+ if ( ! this.pOut ) {
 318+ this.parse();
 319+ }
 320+ return this.pOut;
 321+ }
 322+ };
 323+
 324+}) ( window.mw );
\ No newline at end of file
Property changes on: trunk/extensions/JS2Support/mwEmbed/components/mw.Parser.js
___________________________________________________________________
Added: svn:eol-style
1325 + native
Added: svn:executable
2326 + *
Index: trunk/extensions/JS2Support/mwEmbed/components/README
@@ -0,0 +1,3 @@
 2+Components are parts of the core mwEmbed package that have been separated into different files for easy maintainability.
 3+
 4+Default included Components are listed in the main loader.js file.
\ No newline at end of file
Property changes on: trunk/extensions/JS2Support/mwEmbed/components/README
___________________________________________________________________
Added: svn:executable
15 + *
Index: trunk/extensions/JS2Support/mwEmbed/languages/mw.Language.js
@@ -1,1114 +0,0 @@
2 -/**
3 -* Core Language mw.Language object
4 -*
5 -* Localized Language support attempts to mirror some of the functionality of Language.php in MediaWiki
6 -* It contains methods for loading and transforming msg text
7 -
8 -*/
9 -
10 -( function( mw ) {
11 -
12 - // Setup the global mw.Language var:
13 - mw.Language = { };
14 -
15 - /**
16 - * Setup the lang object
17 - */
18 - var messageCache = { };
19 - var gRuleSet = { };
20 -
21 - /**
22 - * mw.addMessages function
23 - * Loads a set of json messages into the messegeCache object.
24 - *
25 - * @param {JSON} msgSet The set of msgs to be loaded
26 - */
27 - mw.addMessages = function( msgSet ) {
28 - for ( var i in msgSet ) {
29 - messageCache[ i ] = msgSet[i];
30 - }
31 - }
32 - // By default set the current class missing messages flag to default.
33 - mw.currentClassMissingMessages = false;
34 -
35 - /**
36 - * mw.addMessagesKey function
37 - * Adds a messageKey to be pulled in remotely.
38 - *
39 - * NOTE the script-loader should replace addMessageKeys with localized addMessages calls
40 - *
41 - * If addMessagesKey is called then we are running in raw file debug mode.
42 - * it populates the messegeKeyQueue and loads the values in a separate request callback
43 - *
44 - * @param {Array} msgSet The set of msgs to be loaded
45 - */
46 - mw.addMessageKeys = function( msgSet ) {
47 - // Check if any msg key from this class is missing
48 - for( var i in msgSet ){
49 - if( ! messageCache[ i ] ) {
50 - // Set the missing messages flag ( script-loader is probably off)
51 - mw.currentClassMissingMessages = true;
52 - return false;
53 - }
54 - }
55 - return true;
56 - }
57 -
58 - /**
59 - * Special function to register that all of the module messages need to be loaded.
60 - */
61 - mw.includeAllModuleMessages = function (){
62 - mw.currentClassMissingMessages = true;
63 - }
64 -
65 - /**
66 - * Load messages for a given named javascript class.
67 - * This worked in with the resourceLoader
68 - * @param {string} className Name of class file to be loaded
69 - * @param {function} callback Function to be called once class messages are loaded.
70 - */
71 - mw.loadResourceMessages = function( className, callback ) {
72 - // Check if wgScriptLoaderPath is set ( else guess the path relative to mwEmbed)
73 - if ( typeof wgScriptLoaderLocation == 'undefined' || ! wgScriptLoaderLocation ){
74 - wgScriptLoaderLocation = mw.getMwEmbedPath() + 'ResourceLoader.php';
75 - }
76 - // Run the addMessages script-loader call
77 - mw.getScript( wgScriptLoaderLocation + '?class=' + className + '&format=messages', callback);
78 - }
79 -
80 -
81 - /**
82 - * Returns a transformed msg string
83 - *
84 - * it take a msg key and array of replacement values of form
85 - * $1, $2 and does relevant messageKey transformation returning
86 - * the user msg.
87 - *
88 - * @param {String} messageKey The msg key as set by mw.addMessages
89 - * @param {Mixed} args A string|jQuery Object or array of string|jQuery Objects
90 - *
91 - * extra parameters are appended to the args array as numbered replacements
92 - *
93 - * @return string
94 - */
95 - mw.getMsg = function( messageKey , args ) {
96 -
97 - // Check for missing message key
98 - if ( ! messageCache[ messageKey ] ){
99 - return '[' + messageKey + ']';
100 - }
101 - // Check if we need to do args replacements:
102 - if( typeof args != 'undefined' ) {
103 -
104 - // Make arg into an array if its not already an array
105 - if ( typeof args == 'string'
106 - || typeof args == 'number'
107 - || args instanceof jQuery )
108 - {
109 - args = [ args ];
110 - }
111 -
112 - // Put any extra arguments into the args array
113 - var extraArgs = $j.makeArray( arguments );
114 - for(var i=2; i < extraArgs.length; i ++ ) {
115 - args.push( extraArgs[ i ] );
116 - }
117 - }
118 - // Fast check message text return ( no arguments and no parsing needed )
119 - if( ( !args || args.length == 0 )
120 - && messageCache[ messageKey ].indexOf( '{{' ) === -1
121 - && messageCache[ messageKey ].indexOf( '[' ) === -1
122 - ) {
123 - return messageCache[ messageKey ];
124 - }
125 -
126 - // Else Setup the messageSwap object:
127 - var messageSwap = new mw.Language.messageSwapObject( messageCache[ messageKey ], args );
128 -
129 - // Return the jQuery object or message string
130 - return messageSwap.getMsg();
131 - }
132 -
133 - /**
134 - * A message Swap Object
135 - * Swap object manages message type swapping and returns jQuery or text output
136 - *
137 - * @param {String} message The text of the message
138 - * @param {array} arguments A set of swap arguments
139 - */
140 -
141 - mw.Language.messageSwapObject = function( message, arguments ){
142 - this.init( message, arguments );
143 - }
144 -
145 - mw.Language.messageSwapObject.prototype= {
146 - /* constructor */
147 - init: function( message, arguments ){
148 - this.message = message;
149 - this.arguments = arguments;
150 -
151 - // Set the includesjQueryArgs flag to false
152 - includesjQueryArgs: false;
153 - },
154 -
155 - // Return the transformed message text or jQuery object
156 - getMsg: function(){
157 - // Get message with string swap
158 - this.replaceStringArgs();
159 -
160 - // Check if we need to parse the string
161 - if( this.message.indexOf( '{{' ) === -1
162 - && this.message.indexOf( '[' ) === -1
163 - && ! this.includesjQueryArgs )
164 - {
165 - // replaceStringArgs is all we need, return the msg
166 - return this.message
167 - }
168 -
169 - // Else Send the messageText through the parser
170 - var pObj = new mw.Parser( this.message );
171 -
172 - // Get template and link transformed text:
173 - this.message = pObj.getHTML();
174 -
175 - // if jQuery arguments is false return message string
176 - if(! this.includesjQueryArgs ){
177 - //Do string link substitution
178 - return this.message;
179 - }
180 -
181 - // jQuery arguments exist swap and return jQuery object
182 - return this.getJQueryArgsReplace();
183 -
184 - },
185 -
186 - /**
187 - * Swap in an array of values for $1, $2, $n for a given msg key
188 - *
189 - * @param string messageKey The msg key to lookup
190 - * @param {Array} args An array of string or jQuery objects to be swapped in
191 - * @return string
192 - */
193 - replaceStringArgs : function() {
194 - if( ! this.arguments ) {
195 - return ;
196 - }
197 - // Replace Values
198 - for ( var v = 0; v < this.arguments.length; v++ ) {
199 - if( typeof this.arguments[v] == 'undefined' ) {
200 - continue;
201 - }
202 - var replaceValue = this.arguments[ v ];
203 -
204 - // Convert number if applicable
205 - if( parseInt( replaceValue ) == replaceValue ) {
206 - replaceValue = mw.Language.convertNumber( replaceValue );
207 - }
208 -
209 - // Message test replace arguments start at 1 instead of zero:
210 - var argumentRegExp = new RegExp( '\\$' + ( parseInt( v ) + 1 ), 'g' );
211 -
212 - // Check if we got passed in a jQuery object:
213 - if( replaceValue instanceof jQuery) {
214 - // Set the jQuery msg flag
215 - this.includesjQueryArgs = true;
216 - // Swap in a jQuery span place holder:
217 - this.message = this.message.replace( argumentRegExp,
218 - '<span id="' + JQUERY_SWAP_STRING + v +'"></span>' );
219 - } else {
220 - // Assume replaceValue is a string
221 - this.message = this.message.replace( argumentRegExp, replaceValue );
222 - }
223 - }
224 - },
225 -
226 - /**
227 - * Return a jquery element with resolved swapped arguments.
228 - * return {Element}
229 - */
230 - getJQueryArgsReplace: function() {
231 - var $jQueryMessage = false;
232 - mw.log( 'msgReplaceJQueryArgs' );
233 - for ( var v = 0; v < this.arguments.length; v++ ) {
234 - if( typeof this.arguments[v] == 'undefined' ) {
235 - continue;
236 - }
237 - var $replaceValue = this.arguments[ v ];
238 - // Only look for jQuery replacements
239 - if( $replaceValue instanceof jQuery) {
240 - // Setup the jqueryMessage if not set
241 - if( !$jQueryMessage ){
242 - // Setup the message as html to search for jquery swap points
243 - $jQueryMessage = $j( '<span />' ).html( this.message );
244 - }
245 - mw.log(" current jQueryMessage::: " + $jQueryMessage.html() );
246 - // Find swap target
247 - var $swapTarget = $jQueryMessage.find( '#' + JQUERY_SWAP_STRING + v );
248 - // Now we try and find the jQuerySwap points and replace with jQuery object preserving bindings.
249 - if( ! $swapTarget.length ){
250 - mw.log( "Error could not find jQuery Swap target: " + v + ' by id: '+ JQUERY_SWAP_STRING + v
251 - + ' In string: ' + this.message ) ;
252 - continue;
253 - }
254 -
255 - if( $swapTarget.html() != '' ) {
256 - $replaceValue.html( $swapTarget.html() );
257 - }
258 -
259 - // Swap for $swapTarget for $replaceValue swap target * preserveing the jQuery binding )
260 - $swapTarget.replaceWith( $replaceValue );
261 - }
262 - }
263 - // Return the jQuery object ( if no jQuery substitution occurred we return false )
264 - return $jQueryMessage;
265 - }
266 - }
267 -
268 - /**
269 - * Get msg content without transformation
270 - *
271 - * @returns string The msg key without transforming it
272 - */
273 - mw.Language.msgNoTrans = function( key ) {
274 - if ( messageCache[ key ] )
275 - return messageCache[ key ]
276 -
277 - // Missing key placeholder
278 - return '&lt;' + key + '&gt;';
279 - }
280 -
281 - /**
282 - * Add Supported Magic Words to parser
283 - */
284 - // Set the setupflag to false:
285 - mw.Language.doneSetup = false;
286 - mw.Language.magicSetup = function() {
287 - if ( !mw.Language.doneSetup ) {
288 - mw.addTemplateTransform ( {
289 - 'PLURAL' : mw.Language.procPLURAL,
290 - 'GENDER' : mw.Language.procGENDER
291 - } )
292 -
293 - mw.Language.doneSetup = true;
294 - }
295 -
296 - }
297 -
298 - /**
299 - * List of all languages mediaWiki supports ( Avoid an api call to get this same info )
300 - * http://commons.wikimedia.org/w/api.php?action=query&meta=siteinfo&siprop=languages&format=jsonfm
301 - */
302 - mw.Language.names = {
303 - "aa" : "Qaf\u00e1r af",
304 - "ab" : "\u0410\u04a7\u0441\u0443\u0430",
305 - "ace" : "Ac\u00e8h",
306 - "af" : "Afrikaans",
307 - "ak" : "Akan",
308 - "aln" : "Geg\u00eb",
309 - "als" : "Alemannisch",
310 - "am" : "\u12a0\u121b\u122d\u129b",
311 - "an" : "Aragon\u00e9s",
312 - "ang" : "Anglo-Saxon",
313 - "ar" : "\u0627\u0644\u0639\u0631\u0628\u064a\u0629",
314 - "arc" : "\u0710\u072a\u0721\u071d\u0710",
315 - "arn" : "Mapudungun",
316 - "arz" : "\u0645\u0635\u0631\u0649",
317 - "as" : "\u0985\u09b8\u09ae\u09c0\u09af\u09bc\u09be",
318 - "ast" : "Asturianu",
319 - "av" : "\u0410\u0432\u0430\u0440",
320 - "avk" : "Kotava",
321 - "ay" : "Aymar aru",
322 - "az" : "Az\u0259rbaycan",
323 - "ba" : "\u0411\u0430\u0448\u04a1\u043e\u0440\u0442",
324 - "bar" : "Boarisch",
325 - "bat-smg" : "\u017demait\u0117\u0161ka",
326 - "bcc" : "\u0628\u0644\u0648\u0686\u06cc \u0645\u06a9\u0631\u0627\u0646\u06cc",
327 - "bcl" : "Bikol Central",
328 - "be" : "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f",
329 - "be-tarask" : "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430)",
330 - "be-x-old" : "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430)",
331 - "bg" : "\u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438",
332 - "bh" : "\u092d\u094b\u091c\u092a\u0941\u0930\u0940",
333 - "bi" : "Bislama",
334 - "bm" : "Bamanankan",
335 - "bn" : "\u09ac\u09be\u0982\u09b2\u09be",
336 - "bo" : "\u0f56\u0f7c\u0f51\u0f0b\u0f61\u0f72\u0f42",
337 - "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",
338 - "bqi" : "\u0628\u062e\u062a\u064a\u0627\u0631\u064a",
339 - "br" : "Brezhoneg",
340 - "bs" : "Bosanski",
341 - "bug" : "\u1a05\u1a14 \u1a15\u1a18\u1a01\u1a17",
342 - "bxr" : "\u0411\u0443\u0440\u044f\u0430\u0434",
343 - "ca" : "Catal\u00e0",
344 - "cbk-zam" : "Chavacano de Zamboanga",
345 - "cdo" : "M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304",
346 - "ce" : "\u041d\u043e\u0445\u0447\u0438\u0439\u043d",
347 - "ceb" : "Cebuano",
348 - "ch" : "Chamoru",
349 - "cho" : "Choctaw",
350 - "chr" : "\u13e3\u13b3\u13a9",
351 - "chy" : "Tsets\u00eahest\u00e2hese",
352 - "ckb" : "Soran\u00ee \/ \u06a9\u0648\u0631\u062f\u06cc",
353 - "co" : "Corsu",
354 - "cr" : "N\u0113hiyaw\u0113win \/ \u14c0\u1426\u1403\u152d\u140d\u140f\u1423",
355 - "crh" : "Q\u0131r\u0131mtatarca",
356 - "crh-latn" : "\u202aQ\u0131r\u0131mtatarca (Latin)\u202c",
357 - "crh-cyrl" : "\u202a\u041a\u044a\u044b\u0440\u044b\u043c\u0442\u0430\u0442\u0430\u0440\u0434\u0436\u0430 (\u041a\u0438\u0440\u0438\u043b\u043b)\u202c",
358 - "cs" : "\u010cesky",
359 - "csb" : "Kasz\u00ebbsczi",
360 - "cu" : "\u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f",
361 - "cv" : "\u0427\u04d1\u0432\u0430\u0448\u043b\u0430",
362 - "cy" : "Cymraeg",
363 - "da" : "Dansk",
364 - "de" : "Deutsch",
365 - "de-at" : "\u00d6sterreichisches Deutsch",
366 - "de-ch" : "Schweizer Hochdeutsch",
367 - "de-formal" : "Deutsch (Sie-Form)",
368 - "diq" : "Zazaki",
369 - "dk" : "Dansk (deprecated:da)",
370 - "dsb" : "Dolnoserbski",
371 - "dv" : "\u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0",
372 - "dz" : "\u0f47\u0f7c\u0f44\u0f0b\u0f41",
373 - "ee" : "E\u028begbe",
374 - "el" : "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac",
375 - "eml" : "Emili\u00e0n e rumagn\u00f2l",
376 - "en" : "English",
377 - "en-gb" : "British English",
378 - "eo" : "Esperanto",
379 - "es" : "Espa\u00f1ol",
380 - "et" : "Eesti",
381 - "eu" : "Euskara",
382 - "ext" : "Estreme\u00f1u",
383 - "fa" : "\u0641\u0627\u0631\u0633\u06cc",
384 - "ff" : "Fulfulde",
385 - "fi" : "Suomi",
386 - "fiu-vro" : "V\u00f5ro",
387 - "fj" : "Na Vosa Vakaviti",
388 - "fo" : "F\u00f8royskt",
389 - "fr" : "Fran\u00e7ais",
390 - "frc" : "Fran\u00e7ais cadien",
391 - "frp" : "Arpetan",
392 - "fur" : "Furlan",
393 - "fy" : "Frysk",
394 - "ga" : "Gaeilge",
395 - "gag" : "Gagauz",
396 - "gan" : "\u8d1b\u8a9e",
397 - "gan-hans" : "\u8d63\u8bed(\u7b80\u4f53)",
398 - "gan-hant" : "\u8d1b\u8a9e(\u7e41\u9ad4)",
399 - "gd" : "G\u00e0idhlig",
400 - "gl" : "Galego",
401 - "glk" : "\u06af\u06cc\u0644\u06a9\u06cc",
402 - "gn" : "Ava\u00f1e'\u1ebd",
403 - "got" : "\ud800\udf32\ud800\udf3f\ud800\udf44\ud800\udf39\ud800\udf43\ud800\udf3a",
404 - "grc" : "\u1f08\u03c1\u03c7\u03b1\u03af\u03b1 \u1f11\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u1f74",
405 - "gsw" : "Alemannisch",
406 - "gu" : "\u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0",
407 - "gv" : "Gaelg",
408 - "ha" : "\u0647\u064e\u0648\u064f\u0633\u064e",
409 - "hak" : "Hak-k\u00e2-fa",
410 - "haw" : "Hawai`i",
411 - "he" : "\u05e2\u05d1\u05e8\u05d9\u05ea",
412 - "hi" : "\u0939\u093f\u0928\u094d\u0926\u0940",
413 - "hif" : "Fiji Hindi",
414 - "hif-deva" : "\u092b\u093c\u0940\u091c\u0940 \u0939\u093f\u0928\u094d\u0926\u0940",
415 - "hif-latn" : "Fiji Hindi",
416 - "hil" : "Ilonggo",
417 - "ho" : "Hiri Motu",
418 - "hr" : "Hrvatski",
419 - "hsb" : "Hornjoserbsce",
420 - "ht" : "Krey\u00f2l ayisyen",
421 - "hu" : "Magyar",
422 - "hy" : "\u0540\u0561\u0575\u0565\u0580\u0565\u0576",
423 - "hz" : "Otsiherero",
424 - "ia" : "Interlingua",
425 - "id" : "Bahasa Indonesia",
426 - "ie" : "Interlingue",
427 - "ig" : "Igbo",
428 - "ii" : "\ua187\ua259",
429 - "ik" : "I\u00f1upiak",
430 - "ike-cans" : "\u1403\u14c4\u1483\u144e\u1450\u1466",
431 - "ike-latn" : "inuktitut",
432 - "ilo" : "Ilokano",
433 - "inh" : "\u0413\u0406\u0430\u043b\u0433\u0406\u0430\u0439 \u011eal\u011faj",
434 - "io" : "Ido",
435 - "is" : "\u00cdslenska",
436 - "it" : "Italiano",
437 - "iu" : "\u1403\u14c4\u1483\u144e\u1450\u1466\/inuktitut",
438 - "ja" : "\u65e5\u672c\u8a9e",
439 - "jbo" : "Lojban",
440 - "jut" : "Jysk",
441 - "jv" : "Basa Jawa",
442 - "ka" : "\u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8",
443 - "kaa" : "Qaraqalpaqsha",
444 - "kab" : "Taqbaylit",
445 - "kg" : "Kongo",
446 - "ki" : "G\u0129k\u0169y\u0169",
447 - "kiu" : "Kurmanc\u00ee",
448 - "kj" : "Kwanyama",
449 - "kk" : "\u049a\u0430\u0437\u0430\u049b\u0448\u0430",
450 - "kk-arab" : "\u202b\u0642\u0627\u0632\u0627\u0642\u0634\u0627 (\u062a\u0674\u0648\u062a\u06d5)\u202c",
451 - "kk-cyrl" : "\u202a\u049a\u0430\u0437\u0430\u049b\u0448\u0430 (\u043a\u0438\u0440\u0438\u043b)\u202c",
452 - "kk-latn" : "\u202aQazaq\u015fa (lat\u0131n)\u202c",
453 - "kk-cn" : "\u202b\u0642\u0627\u0632\u0627\u0642\u0634\u0627 (\u062c\u06c7\u0646\u06af\u0648)\u202c",
454 - "kk-kz" : "\u202a\u049a\u0430\u0437\u0430\u049b\u0448\u0430 (\u049a\u0430\u0437\u0430\u049b\u0441\u0442\u0430\u043d)\u202c",
455 - "kk-tr" : "\u202aQazaq\u015fa (T\u00fcrk\u00efya)\u202c",
456 - "kl" : "Kalaallisut",
457 - "km" : "\u1797\u17b6\u179f\u17b6\u1781\u17d2\u1798\u17c2\u179a",
458 - "kn" : "\u0c95\u0ca8\u0ccd\u0ca8\u0ca1",
459 - "ko" : "\ud55c\uad6d\uc5b4",
460 - "ko-kp" : "\ud55c\uad6d\uc5b4 (\uc870\uc120)",
461 - "kr" : "Kanuri",
462 - "kri" : "Krio",
463 - "krj" : "Kinaray-a",
464 - "ks" : "\u0915\u0936\u094d\u092e\u0940\u0930\u0940 - (\u0643\u0634\u0645\u064a\u0631\u064a)",
465 - "ksh" : "Ripoarisch",
466 - "ku" : "Kurd\u00ee \/ \u0643\u0648\u0631\u062f\u06cc",
467 - "ku-latn" : "\u202aKurd\u00ee (lat\u00een\u00ee)\u202c",
468 - "ku-arab" : "\u202b\u0643\u0648\u0631\u062f\u064a (\u0639\u06d5\u0631\u06d5\u0628\u06cc)\u202c",
469 - "kv" : "\u041a\u043e\u043c\u0438",
470 - "kw" : "Kernowek",
471 - "ky" : "\u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430",
472 - "la" : "Latina",
473 - "lad" : "Ladino",
474 - "lb" : "L\u00ebtzebuergesch",
475 - "lbe" : "\u041b\u0430\u043a\u043a\u0443",
476 - "lez" : "\u041b\u0435\u0437\u0433\u0438",
477 - "lfn" : "Lingua Franca Nova",
478 - "lg" : "Luganda",
479 - "li" : "Limburgs",
480 - "lij" : "L\u00edguru",
481 - "lmo" : "Lumbaart",
482 - "ln" : "Ling\u00e1la",
483 - "lo" : "\u0ea5\u0eb2\u0ea7",
484 - "loz" : "Silozi",
485 - "lt" : "Lietuvi\u0173",
486 - "lv" : "Latvie\u0161u",
487 - "lzh" : "\u6587\u8a00",
488 - "mai" : "\u092e\u0948\u0925\u093f\u0932\u0940",
489 - "map-bms" : "Basa Banyumasan",
490 - "mdf" : "\u041c\u043e\u043a\u0448\u0435\u043d\u044c",
491 - "mg" : "Malagasy",
492 - "mh" : "Ebon",
493 - "mhr" : "\u041e\u043b\u044b\u043a \u041c\u0430\u0440\u0438\u0439",
494 - "mi" : "M\u0101ori",
495 - "mk" : "\u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438",
496 - "ml" : "\u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02",
497 - "mn" : "\u041c\u043e\u043d\u0433\u043e\u043b",
498 - "mo" : "\u041c\u043e\u043b\u0434\u043e\u0432\u0435\u043d\u044f\u0441\u043a\u044d",
499 - "mr" : "\u092e\u0930\u093e\u0920\u0940",
500 - "ms" : "Bahasa Melayu",
501 - "mt" : "Malti",
502 - "mus" : "Mvskoke",
503 - "mwl" : "Mirand\u00e9s",
504 - "my" : "\u1019\u103c\u1014\u103a\u1019\u102c\u1018\u102c\u101e\u102c",
505 - "myv" : "\u042d\u0440\u0437\u044f\u043d\u044c",
506 - "mzn" : "\u0645\u064e\u0632\u0650\u0631\u0648\u0646\u064a",
507 - "na" : "Dorerin Naoero",
508 - "nah" : "N\u0101huatl",
509 - "nan" : "B\u00e2n-l\u00e2m-g\u00fa",
510 - "nap" : "Nnapulitano",
511 - "nb" : "\u202aNorsk (bokm\u00e5l)\u202c",
512 - "nds" : "Plattd\u00fc\u00fctsch",
513 - "nds-nl" : "Nedersaksisch",
514 - "ne" : "\u0928\u0947\u092a\u093e\u0932\u0940",
515 - "new" : "\u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e",
516 - "ng" : "Oshiwambo",
517 - "niu" : "Niu\u0113",
518 - "nl" : "Nederlands",
519 - "nn" : "\u202aNorsk (nynorsk)\u202c",
520 - "no" : "\u202aNorsk (bokm\u00e5l)\u202c",
521 - "nov" : "Novial",
522 - "nrm" : "Nouormand",
523 - "nso" : "Sesotho sa Leboa",
524 - "nv" : "Din\u00e9 bizaad",
525 - "ny" : "Chi-Chewa",
526 - "oc" : "Occitan",
527 - "om" : "Oromoo",
528 - "or" : "\u0b13\u0b21\u0b3c\u0b3f\u0b06",
529 - "os" : "\u0418\u0440\u043e\u043d\u0430\u0443",
530 - "pa" : "\u0a2a\u0a70\u0a1c\u0a3e\u0a2c\u0a40",
531 - "pag" : "Pangasinan",
532 - "pam" : "Kapampangan",
533 - "pap" : "Papiamentu",
534 - "pcd" : "Picard",
535 - "pdc" : "Deitsch",
536 - "pdt" : "Plautdietsch",
537 - "pfl" : "Pf\u00e4lzisch",
538 - "pi" : "\u092a\u093e\u093f\u0934",
539 - "pih" : "Norfuk \/ Pitkern",
540 - "pl" : "Polski",
541 - "pms" : "Piemont\u00e8is",
542 - "pnb" : "\u067e\u0646\u062c\u0627\u0628\u06cc",
543 - "pnt" : "\u03a0\u03bf\u03bd\u03c4\u03b9\u03b1\u03ba\u03ac",
544 - "ps" : "\u067e\u069a\u062a\u0648",
545 - "pt" : "Portugu\u00eas",
546 - "pt-br" : "Portugu\u00eas do Brasil",
547 - "qu" : "Runa Simi",
548 - "rif" : "Tarifit",
549 - "rm" : "Rumantsch",
550 - "rmy" : "Romani",
551 - "rn" : "Kirundi",
552 - "ro" : "Rom\u00e2n\u0103",
553 - "roa-rup" : "Arm\u00e3neashce",
554 - "roa-tara" : "Tarand\u00edne",
555 - "ru" : "\u0420\u0443\u0441\u0441\u043a\u0438\u0439",
556 - "ruq" : "Vl\u0103he\u015fte",
557 - "ruq-cyrl" : "\u0412\u043b\u0430\u0445\u0435\u0441\u0442\u0435",
558 - "ruq-latn" : "Vl\u0103he\u015fte",
559 - "rw" : "Kinyarwanda",
560 - "sa" : "\u0938\u0902\u0938\u094d\u0915\u0943\u0924",
561 - "sah" : "\u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430",
562 - "sc" : "Sardu",
563 - "scn" : "Sicilianu",
564 - "sco" : "Scots",
565 - "sd" : "\u0633\u0646\u068c\u064a",
566 - "sdc" : "Sassaresu",
567 - "se" : "S\u00e1megiella",
568 - "sei" : "Cmique Itom",
569 - "sg" : "S\u00e4ng\u00f6",
570 - "sh" : "Srpskohrvatski \/ \u0421\u0440\u043f\u0441\u043a\u043e\u0445\u0440\u0432\u0430\u0442\u0441\u043a\u0438",
571 - "shi" : "Ta\u0161l\u1e25iyt",
572 - "si" : "\u0dc3\u0dd2\u0d82\u0dc4\u0dbd",
573 - "simple" : "Simple English",
574 - "sk" : "Sloven\u010dina",
575 - "sl" : "Sloven\u0161\u010dina",
576 - "sli" : "Schl\u00e4sch",
577 - "sm" : "Gagana Samoa",
578 - "sma" : "\u00c5arjelsaemien",
579 - "sn" : "chiShona",
580 - "so" : "Soomaaliga",
581 - "sq" : "Shqip",
582 - "sr" : "\u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski",
583 - "sr-ec" : "\u0421\u0440\u043f\u0441\u043a\u0438 (\u045b\u0438\u0440\u0438\u043b\u0438\u0446\u0430)",
584 - "sr-el" : "Srpski (latinica)",
585 - "srn" : "Sranantongo",
586 - "ss" : "SiSwati",
587 - "st" : "Sesotho",
588 - "stq" : "Seeltersk",
589 - "su" : "Basa Sunda",
590 - "sv" : "Svenska",
591 - "sw" : "Kiswahili",
592 - "szl" : "\u015al\u016fnski",
593 - "ta" : "\u0ba4\u0bae\u0bbf\u0bb4\u0bcd",
594 - "tcy" : "\u0ca4\u0cc1\u0cb3\u0cc1",
595 - "te" : "\u0c24\u0c46\u0c32\u0c41\u0c17\u0c41",
596 - "tet" : "Tetun",
597 - "tg" : "\u0422\u043e\u04b7\u0438\u043a\u04e3",
598 - "tg-cyrl" : "\u0422\u043e\u04b7\u0438\u043a\u04e3",
599 - "tg-latn" : "tojik\u012b",
600 - "th" : "\u0e44\u0e17\u0e22",
601 - "ti" : "\u1275\u130d\u122d\u129b",
602 - "tk" : "T\u00fcrkmen\u00e7e",
603 - "tl" : "Tagalog",
604 - "tn" : "Setswana",
605 - "to" : "lea faka-Tonga",
606 - "tokipona" : "Toki Pona",
607 - "tp" : "Toki Pona (deprecated:tokipona)",
608 - "tpi" : "Tok Pisin",
609 - "tr" : "T\u00fcrk\u00e7e",
610 - "ts" : "Xitsonga",
611 - "tt" : "\u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a",
612 - "tt-cyrl" : "\u0422\u0430\u0442\u0430\u0440\u0447\u0430",
613 - "tt-latn" : "Tatar\u00e7a",
614 - "tum" : "chiTumbuka",
615 - "tw" : "Twi",
616 - "ty" : "Reo M\u0101`ohi",
617 - "tyv" : "\u0422\u044b\u0432\u0430 \u0434\u044b\u043b",
618 - "udm" : "\u0423\u0434\u043c\u0443\u0440\u0442",
619 - "ug" : "Uyghurche\u200e \/ \u0626\u06c7\u064a\u063a\u06c7\u0631\u0686\u06d5",
620 - "ug-arab" : "\u0626\u06c7\u064a\u063a\u06c7\u0631\u0686\u06d5",
621 - "ug-latn" : "Uyghurche\u200e",
622 - "uk" : "\u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430",
623 - "ur" : "\u0627\u0631\u062f\u0648",
624 - "uz" : "O'zbek",
625 - "ve" : "Tshivenda",
626 - "vec" : "V\u00e8neto",
627 - "vep" : "Vepsan kel'",
628 - "vi" : "Ti\u1ebfng Vi\u1ec7t",
629 - "vls" : "West-Vlams",
630 - "vo" : "Volap\u00fck",
631 - "vro" : "V\u00f5ro",
632 - "wa" : "Walon",
633 - "war" : "Winaray",
634 - "wo" : "Wolof",
635 - "wuu" : "\u5434\u8bed",
636 - "xal" : "\u0425\u0430\u043b\u044c\u043c\u0433",
637 - "xh" : "isiXhosa",
638 - "xmf" : "\u10db\u10d0\u10e0\u10d2\u10d0\u10da\u10e3\u10e0\u10d8",
639 - "yi" : "\u05d9\u05d9\u05b4\u05d3\u05d9\u05e9",
640 - "yo" : "Yor\u00f9b\u00e1",
641 - "yue" : "\u7cb5\u8a9e",
642 - "za" : "Vahcuengh",
643 - "zea" : "Ze\u00eauws",
644 - "zh" : "\u4e2d\u6587",
645 - "zh-classical" : "\u6587\u8a00",
646 - "zh-cn" : "\u202a\u4e2d\u6587(\u4e2d\u56fd\u5927\u9646)\u202c",
647 - "zh-hans" : "\u202a\u4e2d\u6587(\u7b80\u4f53)\u202c",
648 - "zh-hant" : "\u202a\u4e2d\u6587(\u7e41\u9ad4)\u202c",
649 - "zh-hk" : "\u202a\u4e2d\u6587(\u9999\u6e2f)\u202c",
650 - "zh-min-nan" : "B\u00e2n-l\u00e2m-g\u00fa",
651 - "zh-mo" : "\u202a\u4e2d\u6587(\u6fb3\u9580)\u202c",
652 - "zh-my" : "\u202a\u4e2d\u6587(\u9a6c\u6765\u897f\u4e9a)\u202c",
653 - "zh-sg" : "\u202a\u4e2d\u6587(\u65b0\u52a0\u5761)\u202c",
654 - "zh-tw" : "\u202a\u4e2d\u6587(\u53f0\u7063)\u202c",
655 - "zh-yue" : "\u7cb5\u8a9e",
656 - "zu" : "isiZulu"
657 - };
658 -
659 - // Language classes ( has a file in /languages/classes/Language{code}.js )
660 - // ( for languages that override default transforms )
661 - mw.Language.transformClass = ['am', 'ar', 'bat_smg', 'be_tarak', 'be', 'bh',
662 - 'bs', 'cs', 'cu', 'cy', 'dsb', 'fr', 'ga', 'gd', 'gv', 'he', 'hi',
663 - 'hr', 'hsb', 'hy', 'ksh', 'ln', 'lt', 'lv', 'mg', 'mk', 'mo', 'mt',
664 - 'nso', 'pl', 'pt_br', 'ro', 'ru', 'se', 'sh', 'sk', 'sl', 'sma',
665 - 'sr_ec', 'sr_el', 'sr', 'ti', 'tl', 'uk', 'wa'
666 - ];
667 -
668 - // Language fallbacks listed from language -> fallback language
669 - mw.Language.fallbackTransformMap = {
670 - 'mwl' : 'pt',
671 - 'ace' : 'id',
672 - 'hsb' : 'de',
673 - 'frr' : 'de',
674 - 'pms' : 'it',
675 - 'dsb' : 'de',
676 - 'gan' : 'gan-hant',
677 - 'lzz' : 'tr',
678 - 'ksh' : 'de',
679 - 'kl' : 'da',
680 - 'fur' : 'it',
681 - 'zh-hk' : 'zh-hant',
682 - 'kk' : 'kk-cyrl',
683 - 'zh-my' : 'zh-sg',
684 - 'nah' : 'es',
685 - 'sr' : 'sr-ec',
686 - 'mo' : 'ro',
687 - 'ay' : 'es',
688 - 'gl' : 'pt',
689 - 'gag' : 'tr',
690 - 'mzn' : 'fa',
691 - 'ruq-cyrl' : 'mk',
692 - 'kk-arab' : 'kk-cyrl',
693 - 'pfl' : 'de',
694 - 'zh-yue' : 'yue',
695 - 'ug' : 'ug-latn',
696 - 'ltg' : 'lv',
697 - 'nds' : 'de',
698 - 'sli' : 'de',
699 - 'mhr' : 'ru',
700 - 'sah' : 'ru',
701 - 'ff' : 'fr',
702 - 'ab' : 'ru',
703 - 'ko-kp' : 'ko',
704 - 'sg' : 'fr',
705 - 'zh-tw' : 'zh-hant',
706 - 'map-bms' : 'jv',
707 - 'av' : 'ru',
708 - 'nds-nl' : 'nl',
709 - 'pt-br' : 'pt',
710 - 'ce' : 'ru',
711 - 'vep' : 'et',
712 - 'wuu' : 'zh-hans',
713 - 'pdt' : 'de',
714 - 'krc' : 'ru',
715 - 'gan-hant' : 'zh-hant',
716 - 'bqi' : 'fa',
717 - 'as' : 'bn',
718 - 'bm' : 'fr',
719 - 'gn' : 'es',
720 - 'tt' : 'ru',
721 - 'zh-hant' : 'zh-hans',
722 - 'hif' : 'hif-latn',
723 - 'zh' : 'zh-hans',
724 - 'kaa' : 'kk-latn',
725 - 'lij' : 'it',
726 - 'vot' : 'fi',
727 - 'ii' : 'zh-cn',
728 - 'ku-arab' : 'ckb',
729 - 'xmf' : 'ka',
730 - 'vmf' : 'de',
731 - 'zh-min-nan' : 'nan',
732 - 'bcc' : 'fa',
733 - 'an' : 'es',
734 - 'rgn' : 'it',
735 - 'qu' : 'es',
736 - 'nb' : 'no',
737 - 'bar' : 'de',
738 - 'lbe' : 'ru',
739 - 'su' : 'id',
740 - 'pcd' : 'fr',
741 - 'glk' : 'fa',
742 - 'lb' : 'de',
743 - 'kk-kz' : 'kk-cyrl',
744 - 'kk-tr' : 'kk-latn',
745 - 'inh' : 'ru',
746 - 'mai' : 'hi',
747 - 'tp' : 'tokipona',
748 - 'kk-latn' : 'kk-cyrl',
749 - 'ba' : 'ru',
750 - 'nap' : 'it',
751 - 'ruq' : 'ruq-latn',
752 - 'tt-cyrl' : 'ru',
753 - 'lad' : 'es',
754 - 'dk' : 'da',
755 - 'de-ch' : 'de',
756 - 'be-x-old' : 'be-tarask',
757 - 'za' : 'zh-hans',
758 - 'kk-cn' : 'kk-arab',
759 - 'shi' : 'ar',
760 - 'crh' : 'crh-latn',
761 - 'yi' : 'he',
762 - 'pdc' : 'de',
763 - 'eml' : 'it',
764 - 'uk' : 'ru',
765 - 'kv' : 'ru',
766 - 'koi' : 'ru',
767 - 'cv' : 'ru',
768 - 'zh-cn' : 'zh-hans',
769 - 'de-at' : 'de',
770 - 'jut' : 'da',
771 - 'vec' : 'it',
772 - 'zh-mo' : 'zh-hk',
773 - 'fiu-vro' : 'vro',
774 - 'frp' : 'fr',
775 - 'mg' : 'fr',
776 - 'ruq-latn' : 'ro',
777 - 'sa' : 'hi',
778 - 'lmo' : 'it',
779 - 'kiu' : 'tr',
780 - 'tcy' : 'kn',
781 - 'srn' : 'nl',
782 - 'jv' : 'id',
783 - 'vls' : 'nl',
784 - 'zea' : 'nl',
785 - 'ty' : 'fr',
786 - 'szl' : 'pl',
787 - 'rmy' : 'ro',
788 - 'wo' : 'fr',
789 - 'vro' : 'et',
790 - 'udm' : 'ru',
791 - 'bpy' : 'bn',
792 - 'mrj' : 'ru',
793 - 'xal' : 'ru',
794 - 'de-formal' : 'de',
795 - 'myv' : 'ru',
796 - 'ku' : 'ku-latn',
797 - 'crh-cyrl' : 'ru',
798 - 'gsw' : 'de',
799 - 'rue' : 'uk',
800 - 'iu' : 'ike-cans',
801 - 'stq' : 'de',
802 - 'gan-hans' : 'zh-hans',
803 - 'scn' : 'it',
804 - 'arn' : 'es',
805 - 'ht' : 'fr',
806 - 'zh-sg' : 'zh-hans',
807 - 'bat-smg' : 'lt',
808 - 'aln' : 'sq',
809 - 'tg' : 'tg-cyrl',
810 - 'li' : 'nl',
811 - 'simple' : 'en',
812 - 'os' : 'ru',
813 - 'ln' : 'fr',
814 - 'als' : 'gsw',
815 - 'zh-classical' : 'lzh',
816 - 'arz' : 'ar',
817 - 'wa' : 'fr'
818 - };
819 -
820 - /**
821 - * Plural form transformations, needed for some languages.
822 - * For example, there are 3 form of plural in Russian and Polish,
823 - * depending on "count mod 10". See [[w:Plural]]
824 - * For English it is pretty simple.
825 - *
826 - * Invoked by putting {{plural:count|wordform1|wordform2}}
827 - * or {{plural:count|wordform1|wordform2|wordform3}}
828 - *
829 - * Example: {{plural:{{NUMBEROFARTICLES}}|article|articles}}
830 - *
831 - * @param count Integer: non-localized number
832 - * @param forms Array: different plural forms
833 - * @return string Correct form of plural for count in this language
834 - */
835 -
836 - /**
837 - * Base gender transform function
838 - */
839 - mw.Language.gender = function( gender, forms ) {
840 - if ( ! forms.length ) {
841 - return '';
842 - }
843 - forms = mw.Language.preConvertPlural( forms, 2 );
844 - if ( gender === 'male' ) return forms[0];
845 - if ( gender === 'female' ) return forms[1];
846 - return ( forms[2] ) ? forms[2] : forms[0];
847 - };
848 -
849 - /**
850 - * Process the PLURAL template substitution
851 - * @param {Object} template Template object
852 - *
853 - * {{Template:argument|params}}
854 - *
855 - * Template object should include:
856 - * [arg] The argument sent to the template
857 - * [params] The template parameters
858 - */
859 - mw.Language.procPLURAL = function( templateObject ) {
860 - // Setup shortcuts
861 - // ( gRuleSet is loaded from script-loader to contains local ruleset )
862 - var rs = gRuleSet[ 'PLURAL' ];
863 -
864 - if( templateObject.arg && templateObject.param && mw.Language.convertPlural) {
865 - // Check if we have forms to replace
866 - if ( templateObject.param.length == 0 ) {
867 - return '';
868 - }
869 - // Restore the count into a Number ( if it got converted earlier )
870 - var count = mw.Language.convertNumber( templateObject.arg, true );
871 -
872 - // Do convertPlural call
873 - return mw.Language.convertPlural( parseInt( count ), templateObject.param );
874 -
875 - }
876 - // Could not process plural return first form or nothing
877 - if( templateObject.param[0] ) {
878 - return templateObject.param[0];
879 - }
880 - return '';
881 - };
882 -
883 - // NOTE:: add gender support here
884 - mw.Language.procGENDER = function( templateObject ){
885 - return 'gender-not-supported-in-js-yet';
886 - }
887 - /*
888 - * Base convertPlural function:
889 - */
890 - mw.Language.convertPlural = function( count, forms ){
891 - if ( !forms || forms.length == 0 ) {
892 - return '';
893 - }
894 - return ( parseInt( count ) == 1 ) ? forms[0] : forms[1];
895 - };
896 - /**
897 - * Checks that convertPlural was given an array and pads it to requested
898 - * amount of forms by copying the last one.
899 - *
900 - * @param {Array} forms Forms given to convertPlural
901 - * @param {Integer} count How many forms should there be at least
902 - * @return {Array} Padded array of forms or an exception if not an array
903 - */
904 - mw.Language.preConvertPlural = function( forms, count ) {
905 - while ( forms.length < count ) {
906 - forms.push( forms[ forms.length-1 ] );
907 - }
908 - return forms;
909 - };
910 -
911 - /**
912 - * Init the digitTransformTable ( populated by language classes where applicable )
913 - */
914 - mw.Language.digitTransformTable = null;
915 -
916 - /**
917 - * Convert a number using the digitTransformTable
918 - * @param Number number to be converted
919 - * @param Bollean typeInt if we should return a number of type int
920 - */
921 - mw.Language.convertNumber = function( number, typeInt ) {
922 - if( !mw.Language.digitTransformTable )
923 - return number;
924 -
925 - // Set the target Transform table:
926 - var transformTable = mw.Language.digitTransformTable;
927 -
928 - // Check if the "restore" to latin number flag is set:
929 - if( typeInt ) {
930 - if( parseInt( number ) == number )
931 - return number;
932 - var tmp = [];
933 - for( var i in transformTable ) {
934 - tmp[ transformTable[ i ] ] = i;
935 - }
936 - transformTable = tmp;
937 - }
938 -
939 - var numberString = '' + number;
940 - var convertedNumber = '';
941 - for( var i =0; i < numberString.length; i++) {
942 - if( transformTable[ numberString[i] ] ) {
943 - convertedNumber += transformTable[ numberString[i] ];
944 - }else{
945 - convertedNumber += numberString[i];
946 - }
947 - }
948 - return ( typeInt )? parseInt( convertedNumber) : convertedNumber;
949 - }
950 -
951 - /**
952 - * Checks if a language key is valid ( is part of languageCodeList )
953 - * @param {String} langKey Language key to be checked
954 - * @return true if valid language, false if not
955 - */
956 - mw.isValidLang = function( langKey ) {
957 - return ( mw.Language.names[ langKey ] )? true : false;
958 - }
959 -
960 - /**
961 - * Get a language transform key
962 - * returns default "en" fallback if none found
963 - * @param String langKey The language key to be checked
964 - */
965 - mw.getLangTransformKey = function( langKey ) {
966 - if( mw.Language.fallbackTransformMap[ langKey ] ) {
967 - langKey = mw.Language.fallbackTransformMap[ langKey ];
968 - }
969 - // Make sure the langKey has a transformClass:
970 - for( var i = 0; i < mw.Language.transformClass.length ; i++ ) {
971 - if( langKey == mw.Language.transformClass[i] ){
972 - return langKey
973 - }
974 - }
975 - // By default return the base 'en' class
976 - return 'en';
977 - }
978 -
979 - /**
980 - * getRemoteMsg loads remote msg strings
981 - *
982 - * @param {Mixed} msgSet the set of msg to load remotely
983 - * @param function callback the callback to issue once string is ready
984 - */
985 - mw.getRemoteMsg = function( msgSet, callback ) {
986 - var ammessages = '';
987 - if ( typeof msgSet == 'object' ) {
988 - for ( var i in msgSet ) {
989 - if( !messageCache[ i ] ) {
990 - ammessages += msgSet[i] + '|';
991 - }
992 - }
993 - } else if ( typeof msgSet == 'string' ) {
994 - if( !messageCache[ i ] ) {
995 - ammessages += msgSet;
996 - }
997 - }
998 - if ( ammessages == '' ) {
999 - mw.log( 'no remote msgs to get' );
1000 - callback();
1001 - return false;
1002 - }
1003 - var request = {
1004 - 'meta': 'allmessages',
1005 - 'ammessages': ammessages
1006 - }
1007 - mw.getJSON( request, function( data ) {
1008 - if ( data.query.allmessages ) {
1009 - var msgs = data.query.allmessages;
1010 - for ( var i in msgs ) {
1011 - var ld = { };
1012 - ld[ msgs[i]['name'] ] = msgs[i]['*'];
1013 - mw.addMessages( ld );
1014 - }
1015 - }
1016 - callback();
1017 - } );
1018 - }
1019 -
1020 - /**
1021 - * Format a size in bytes for output, using an appropriate
1022 - * unit (B, KB, MB or GB) according to the magnitude in question
1023 - *
1024 - * @param size Size to format
1025 - * @return string Plain text (not HTML)
1026 - */
1027 - mw.Language.formatSize = function ( size ) {
1028 - // For small sizes no decimal places are necessary
1029 - var round = 0;
1030 - var msg = '';
1031 - if ( size > 1024 ) {
1032 - size = size / 1024;
1033 - if ( size > 1024 ) {
1034 - size = size / 1024;
1035 - // For MB and bigger two decimal places are smarter
1036 - round = 2;
1037 - if ( size > 1024 ) {
1038 - size = size / 1024;
1039 - msg = 'mwe-size-gigabytes';
1040 - } else {
1041 - msg = 'mwe-size-megabytes';
1042 - }
1043 - } else {
1044 - msg = 'mwe-size-kilobytes';
1045 - }
1046 - } else {
1047 - msg = 'mwe-size-bytes';
1048 - }
1049 - // JavaScript does not let you choose the precision when rounding
1050 - var p = Math.pow( 10, round );
1051 - size = Math.round( size * p ) / p;
1052 - return gM( msg , size );
1053 - };
1054 -
1055 - /**
1056 - * Format a number
1057 - * @param {Number} num Number to be formated
1058 - * NOTE: add il8n support to lanuages/class/Language{langCode}.js
1059 - */
1060 - mw.Language.formatNumber = function( num ) {
1061 - /*
1062 - * addSeparatorsNF
1063 - * @param Str: The number to be formatted, as a string or number.
1064 - * @param outD: The decimal character for the output, such as ',' for the number 100,2
1065 - * @param sep: The separator character for the output, such as ',' for the number 1,000.2
1066 - */
1067 - function addSeparatorsNF( nStr, outD, sep ) {
1068 - nStr += '';
1069 - var dpos = nStr.indexOf( '.' );
1070 - var nStrEnd = '';
1071 - if ( dpos != -1 ) {
1072 - nStrEnd = outD + nStr.substring( dpos + 1, nStr.length );
1073 - nStr = nStr.substring( 0, dpos );
1074 - }
1075 - var rgx = /(\d+)(\d{3})/;
1076 - while ( rgx.test( nStr ) ) {
1077 - nStr = nStr.replace( rgx, '$1' + sep + '$2' );
1078 - }
1079 - return nStr + nStrEnd;
1080 - }
1081 - // @@todo read language code and give periods or comas:
1082 - return addSeparatorsNF( num, '.', ',' );
1083 - }
1084 -
1085 -}) ( window.mw );
1086 -
1087 -
1088 -// Load in js2 stopgap global msgs into proper location:
1089 -if ( typeof gMsg != 'undefined' ) {
1090 - mw.addMessages( gMsg )
1091 -}
1092 -
1093 -// Set global gM shortcut:
1094 -window[ 'gM' ] = mw.getMsg;
1095 -
1096 -
1097 -/**
1098 -* Add the core mvEmbed Messages ( will be localized by script server )
1099 -*/
1100 -mw.addMessages( {
1101 - "mwe-loading_txt" : "Loading ...",
1102 - "mwe-size-gigabytes" : "$1 GB",
1103 - "mwe-size-megabytes" : "$1 MB",
1104 - "mwe-size-kilobytes" : "$1 K",
1105 - "mwe-size-bytes" : "$1 B",
1106 - "mwe-error_load_lib" : "Error: JavaScript $1 was not retrievable or does not define $2",
1107 - "mwe-apiproxy-setup" : "Setting up API proxy",
1108 - "mwe-load-drag-item" : "Loading dragged item",
1109 - "mwe-ok" : "OK",
1110 - "mwe-cancel" : "Cancel",
1111 - "mwe-enable-gadget" : "Enable multimedia beta ( mwEmbed ) for all pages",
1112 - "mwe-enable-gadget-done" : "multimedia beta gadget has been enabled",
1113 - "mwe-must-login-gadget" : "To enable gadget you must <a target=\"_new\" href=\"$1\">login</a>",
1114 - "mwe-test-plural" : "I ran {{PLURAL:$1|$1 test|$1 tests}}"
1115 -} );
\ No newline at end of file
Index: trunk/extensions/JS2Support/mwEmbed/languages/mw.Parser.js
@@ -1,323 +0,0 @@
2 -/**
3 -* Mediawiki language text parser
4 -*/
5 -
6 -// Setup swap string constants
7 -var JQUERY_SWAP_STRING = 'ZjQuerySwapZ';
8 -var LINK_SWAP_STRING = 'ZreplaceZ';
9 -
10 -( function( mw ) {
11 -
12 - // The parser magic global
13 - var pMagicSet = { };
14 -
15 - /**
16 - * addTemplateTransform to the parser
17 - *
18 - * Lets you add a set template key to be transformed by a callback function
19 - *
20 - * @param {Object} magicSet key:callback
21 - */
22 - mw.addTemplateTransform = function( magicSet ) {
23 - for ( var i in magicSet ) {
24 - pMagicSet[ i ] = magicSet[i];
25 - }
26 - };
27 -
28 - /**
29 - * MediaWiki wikitext "Parser" constructor
30 - *
31 - * @param {String} wikiText the wikitext to be parsed
32 - * @return {Object} parserObj returns a parser object that has methods for getting at
33 - * things you would want
34 - */
35 - mw.Parser = function( wikiText, options) {
36 - // return the parserObj
37 - this.init( wikiText, options ) ;
38 - };
39 -
40 - mw.Parser.prototype = {
41 -
42 - // the parser output string container
43 - pOut: false,
44 -
45 - init: function( wikiText, parserOptions ) {
46 - this.wikiText = wikiText;
47 - },
48 -
49 - // Update the text value
50 - updateText : function( wikiText ) {
51 - this.wikiText = wikiText;
52 -
53 - // invalidate the output ( will force a re-parse )
54 - this.pOut = false;
55 - },
56 -
57 - /**
58 - * Quickly recursive / parse out templates:
59 - */
60 - parse: function() {
61 - function recurseTokenizeNodes ( text ) {
62 - var node = { };
63 - // Inspect each char
64 - for ( var a = 0; a < text.length; a++ ) {
65 - if ( text[a] == '{' && text[a + 1] == '{' ) {
66 - a = a + 2;
67 - node['parent'] = node;
68 - if ( !node['child'] ) {
69 - node['child'] = new Array();
70 - }
71 -
72 - node['child'].push( recurseTokenizeNodes( text.substr( a ) ) );
73 - } else if ( text[a] == '}' && text[a + 1] == '}' ) {
74 - a++;
75 - if ( !node['parent'] ) {
76 - return node;
77 - }
78 - node = node['parent'];
79 - }
80 - if ( !node['text'] ) {
81 - node['text'] = '';
82 - }
83 - // Don't put }} closures into output:
84 - if ( text[a] && text[a] != '}' ) {
85 - node['text'] += text[a];
86 - }
87 - }
88 - return node;
89 - }
90 -
91 - /**
92 - * Parse template text as template name and named params
93 - * @param {String} templateString Template String to be parsed
94 - */
95 - function parseTmplTxt( templateString ) {
96 - var templateObject = { };
97 -
98 - // Get template name:
99 - templateName = templateString.split( '\|' ).shift() ;
100 - templateName = templateName.split( '\{' ).shift() ;
101 - templateName = templateName.replace( /^\s+|\s+$/g, "" ); //trim
102 -
103 - // Check for arguments:
104 - if ( templateName.split( ':' ).length == 1 ) {
105 - templateObject["name"] = templateName;
106 - } else {
107 - templateObject["name"] = templateName.split( ':' ).shift();
108 - templateObject["arg"] = templateName.split( ':' ).pop();
109 - }
110 -
111 - var paramSet = templateString.split( '\|' );
112 - paramSet.splice( 0, 1 );
113 - if ( paramSet.length ) {
114 - templateObject.param = new Array();
115 - for ( var pInx in paramSet ) {
116 - var paramString = paramSet[ pInx ];
117 - // check for empty param
118 - if ( paramString == '' ) {
119 - templateObject.param[ pInx ] = '';
120 - continue;
121 - }
122 - for ( var b = 0 ; b < paramString.length ; b++ ) {
123 - if ( paramString[b] == '=' && b > 0 && b < paramString.length && paramString[b - 1] != '\\' ) {
124 - // named param
125 - templateObject.param[ paramString.split( '=' ).shift() ] = paramString.split( '=' ).pop();
126 - } else {
127 - // indexed param
128 - templateObject.param[ pInx ] = paramString;
129 - }
130 - }
131 - }
132 - }
133 - return templateObject;
134 - }
135 -
136 - /**
137 - * Get the Magic text from a template node
138 - */
139 - function getMagicTxtFromTempNode( node ) {
140 - node.templateObject = parseTmplTxt ( node.text );
141 - // Do magic swap if template key found in pMagicSet
142 - if ( node.templateObject.name in pMagicSet ) {
143 - var nodeText = pMagicSet[ node.templateObject.name ]( node.templateObject );
144 - return nodeText;
145 - } else {
146 - // don't swap just return text
147 - return node.text;
148 - }
149 - }
150 -
151 - /**
152 - * swap links of form [ ] for html a links or jquery helper spans
153 - * NOTE: this could be integrated into the tokenizer but for now
154 - * is a staged process.
155 - *
156 - * @param text to swapped
157 - */
158 - function linkSwapText( text ) {
159 - //mw.log( "linkSwapText::" + text );
160 - var re = new RegExp( /\[([^\s]+[\s]+[^\]]*)\]/g );
161 - var matchSet = text.match( re );
162 -
163 - if( !matchSet ){
164 - return text;
165 - }
166 -
167 - text = text.replace( re , LINK_SWAP_STRING );
168 -
169 - for( var i=0; i < matchSet.length; i++ ) {
170 - // Strip the leading [ and trailing ]
171 - var matchParts = matchSet[i].substr(1, matchSet[i].length-2);
172 -
173 - // Check for special jQuery type swap and replace inner JQUERY_SWAP_STRING not value
174 - if( matchParts.indexOf( JQUERY_SWAP_STRING ) !== -1 ) {
175 - // parse the link as html
176 - var $matchParts = $j('<span>' + matchParts + '</span>' );
177 -
178 - $jQuerySpan = $matchParts.find('#' +JQUERY_SWAP_STRING + i );
179 -
180 - var linkText = $matchParts.text();
181 - //mw.log(" going to swap in linktext: " + linkText );
182 - $jQuerySpan.text( linkText );
183 -
184 - text = text.replace( LINK_SWAP_STRING, $j('<span />' ).append( $jQuerySpan ).html() );
185 - } else {
186 - // do text string replace
187 - matchParts = matchParts.split(/ /);
188 - var link = matchParts[0];
189 - matchParts.shift();
190 - var linkText = matchParts.join(' ');
191 -
192 - text = text.replace( LINK_SWAP_STRING, '<a href="' + link + '">' + linkText + '</a>' );
193 - }
194 - }
195 - return text;
196 - }
197 -
198 - /**
199 - * recurse_magic_swap
200 - *
201 - * Go last child first swap upward:
202 - */
203 - var pNode = null;
204 - function recurse_magic_swap( node ) {
205 - if ( !pNode )
206 - pNode = node;
207 -
208 - if ( node['child'] ) {
209 - // swap all the kids:
210 - for ( var i in node['child'] ) {
211 - var nodeText = recurse_magic_swap( node['child'][i] );
212 - // swap it into current
213 - if ( node.text ) {
214 - node.text = node.text.replace( node['child'][i].text, nodeText );
215 - }
216 - // swap into parent
217 - pNode.text = pNode.text.replace( node['child'][i].text, nodeText );
218 - }
219 - // Get the updated node text
220 - var nodeText = getMagicTxtFromTempNode( node );
221 - pNode.text = pNode.text.replace( node.text , nodeText );
222 - // return the node text
223 - return node.text;
224 - } else {
225 - return getMagicTxtFromTempNode( node );
226 - }
227 - }
228 -
229 - // Parse out the template node structure:
230 - this.pNode = recurseTokenizeNodes ( this.wikiText );
231 -
232 - // Strip out the parent from the root
233 - this.pNode['parent'] = null;
234 -
235 - // Do the recursive magic swap text:
236 - this.pOut = recurse_magic_swap( this.pNode );
237 -
238 - // Do link swap
239 - this.pOut = linkSwapText( this.pOut );
240 - },
241 -
242 - /**
243 - * templates
244 - *
245 - * Get a requested template from the wikitext (if available)
246 - * @param templateName
247 - */
248 - templates: function( templateName ) {
249 - this.parse();
250 - var tmplSet = new Array();
251 - function getMatchingTmpl( node ) {
252 - if ( node['child'] ) {
253 - for ( var i in node['child'] ) {
254 - getMatchingTmpl( node['child'] );
255 - }
256 - }
257 - if ( templateName && node.templateObject ) {
258 - if ( node.templateObject['name'] == templateName )
259 - tmplSet.push( node.templateObject );
260 - } else if ( node.templateObject ) {
261 - tmplSet.push( node.templateObject );
262 - }
263 - }
264 - getMatchingTmpl( this.pNode );
265 - return tmplSet;
266 - },
267 -
268 - /**
269 - * getTemplateVars
270 - * returns a set of template values in a given wikitext page
271 - *
272 - * NOTE: should be integrated with the usability wikitext parser
273 - */
274 - getTemplateVars: function() {
275 - //mw.log('matching against: ' + wikiText);
276 - templateVars = new Array();
277 - var tempVars = wikiText.match(/\{\{\{([^\}]*)\}\}\}/gi);
278 -
279 - // Clean up results:
280 - for(var i=0; i < tempVars.length; i++) {
281 - //match
282 - var tvar = tempVars[i].replace('{{{','').replace('}}}','');
283 -
284 - // Strip anything after a |
285 - if(tvar.indexOf('|') != -1) {
286 - tvar = tvar.substr(0, tvar.indexOf('|'));
287 - }
288 -
289 - // Check for duplicates:
290 - var do_add=true;
291 - for(var j=0; j < templateVars.length; j++) {
292 - if( templateVars[j] == tvar)
293 - do_add=false;
294 - }
295 -
296 - // Add the template vars to the output obj
297 - if(do_add)
298 - templateVars.push( tvar );
299 - }
300 - return templateVars;
301 - },
302 -
303 - /**
304 - * Returns the transformed wikitext
305 - *
306 - * Build output from swappable index
307 - * (all transforms must be expanded in parse stage and linearly rebuilt)
308 - * Alternatively we could build output using a place-holder & replace system
309 - * (this lets us be slightly more sloppy with ordering and indexes, but probably slower)
310 - *
311 - * Ideal: we build a 'wiki DOM'
312 - * When editing you update the data structure directly
313 - * Then in output time you just go DOM->html-ish output without re-parsing anything
314 - */
315 - getHTML: function() {
316 - // wikiText updates should invalidate pOut
317 - if ( ! this.pOut ) {
318 - this.parse();
319 - }
320 - return this.pOut;
321 - }
322 - };
323 -
324 -}) ( window.mw );
\ No newline at end of file

Status & tagging log