r63852 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r63851‎ | r63852 | r63853 >
Date:01:24, 17 March 2010
Author:neilk
Status:deferred
Tags:
Comment:
Much more metadata -- parses and adds to the form
Filename and title mutually change each other
Date picker a la jQuery.
Modified paths:
  • /branches/js2-work/phase3/js/mwEmbed/modules/UploadWizard/css/uploadWizard.css (modified) (history)
  • /branches/js2-work/phase3/js/mwEmbed/modules/UploadWizard/mw.UploadWizard.js (modified) (history)
  • /branches/js2-work/phase3/js/mwEmbed/skins/common/images/calendar.gif (added) (history)
  • /branches/js2-work/phase3/js/uploadWizardPage.js (modified) (history)

Diff [purge]

Index: branches/js2-work/phase3/js/mwEmbed/skins/common/images/calendar.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/js2-work/phase3/js/mwEmbed/skins/common/images/calendar.gif
___________________________________________________________________
Name: svn:mime-type
11 + application/octet-stream
Index: branches/js2-work/phase3/js/mwEmbed/modules/UploadWizard/mw.UploadWizard.js
@@ -36,6 +36,7 @@
3737 'mwe-upwiz-date-created': 'Date created',
3838 'mwe-upwiz-geotag': 'Location',
3939 'mwe-upwiz-copyright-info': 'Copyright information',
 40+ 'mwe-upwiz-source': 'Source',
4041 'mwe-upwiz-author': 'Author',
4142 'mwe-upwiz-license': 'License',
4243 'mwe-upwiz-about-format': 'About the file',
@@ -51,16 +52,6 @@
5253 'mwe-upwiz-ok': 'OK',
5354 'mwe-upwiz-cancel': 'Cancel',
5455
55 -
56 - // available licenses should be a configuration of the MediaWiki instance,
57 - // not hardcoded here.
58 - // but, MediaWiki has no real concept of a License as a first class object -- there are templates and then specially - parsed
59 - // texts to create menus -- hack on top of hacks -- a bit too much to deal with ATM
60 - 'mwe-lic-pd': 'Public domain',
61 - 'mwe-lic-cc-0': 'Creative Commons Zero waiver',
62 - 'mwe-lic-cc-by-3.0': 'Creative Commons Attribution 3.0',
63 - 'mwe-lic-cc-by-sa-3.0': 'Creative Commons Attribution ShareAlike 3.0',
64 - 'mwe-lic-gfdl': 'GFDL'
6556 } );
6657
6758
@@ -72,6 +63,9 @@
7364 var _this = this;
7465 _this._thumbnails = {};
7566 _this.imageinfo = {};
 67+ _this.title = undefined;
 68+ _this.filename = undefined;
 69+ _this.originalFilename = undefined;
7670 };
7771
7872 mw.UploadWizardUpload.prototype = {
@@ -91,7 +85,7 @@
9286 if ( key === 'metadata' ) {
9387 _this.imageinfo.metadata = {};
9488 $j.each( result.upload.imageinfo.metadata, function( i, pair ) {
95 - _this.imageinfo.metadata[pair['name']] = pair['value'];
 89+ _this.imageinfo.metadata[pair['name'].toLowerCase()] = pair['value'];
9690 });
9791 } else {
9892 _this.imageinfo[key] = result.upload.imageinfo[key];
@@ -160,9 +154,10 @@
161155 * Create an interface fragment corresponding to a file input, suitable for Upload Wizard.
162156 * @param filenameAcceptedCb Execute if good filename entered into this interface; useful for knowing if we're ready to upload
163157 */
164 -mw.UploadWizardUploadInterface = function( filenameAcceptedCb ) {
 158+mw.UploadWizardUploadInterface = function( upload, filenameAcceptedCb ) {
165159 var _this = this;
166160
 161+ _this.upload = upload;
167162 _this.filenameAcceptedCb = filenameAcceptedCb;
168163
169164 // may need to collaborate with the particular upload type sometimes
@@ -270,12 +265,14 @@
271266 updateFilename: function() {
272267 var _this = this;
273268 var path = $j(_this.fileInputCtrl).attr('value');
 269+
274270
275271 // visible filename
276272 $j( _this.visibleFilename ).removeClass( 'helper' ).html( path );
277273
278274 // desired filename
279275 var filename = _this.convertPathToFilename( path );
 276+ _this.upload.originalFilename = filename;
280277 // this is a hack to get a filename guaranteed unique.
281278 uniqueFilename = mw.getConfig( 'userName' ) + "_" + ( new Date() ).getTime() + "_" + filename;
282279 $j(_this.filenameCtrl).attr( 'value', uniqueFilename );
@@ -335,12 +332,11 @@
336333 // lastFileSeparatorIdx is now -1 if no separator found, or some index in the string.
337334 // so, +1, that is either 0 ( beginning of string ) or the character after last separator.
338335 // caution! could go past end of string... need to be more careful
339 - var filename = path.substring( lastFileSeparatorIdx + 1, 10000 );
 336+ var filename = path.substr( lastFileSeparatorIdx + 1 );
 337+ return mw.UploadWizardUtil.pathToTitle( filename );
340338
341 - // Capitalise first letter and replace spaces by underscores
342 - filename = filename.charAt( 0 ).toUpperCase() + filename.substring( 1, 10000 );
343 - filename.replace(/ /g, '_' );
344 - return filename;
 339+
 340+
345341 },
346342
347343 /**
@@ -399,13 +395,23 @@
400396 */
401397 getWikiText: function() {
402398 var _this = this;
403 - return '{{' + _this.languageMenu.value + '|' + _this.description.value + '}}'
 399+ var language = $j( _this.languageMenu ).trim().val();
 400+ var fix = mw.getConfig("languageTemplateFixups");
 401+ if (fix[language]) {
 402+ language = fix[language];
 403+ }
 404+ return '{{' + language + '|' + $j( _this.description ).trim().val() + '}}'
404405 }
405406 };
406407
407408 /**
408409 * Object that represents the Details (step 2) portion of the UploadWizard
409410 * n.b. each upload gets its own details.
 411+ *
 412+ * XXX a lot of this construction is not really the jQuery way.
 413+ * The correct thing would be to have some hidden static HTML
 414+ * on the page which we clone and slice up with selectors. Inputs can still be members of the object
 415+ * but they'll be found by selectors, not by creating them as members and then adding them to a DOM structure.
410416 *
411417 * @param UploadWizardUpload
412418 * @param containerDiv The div to put the interface into
@@ -428,6 +434,7 @@
429435
430436 _this.dataDiv = $j( '<div class="mwe-upwiz-details-data"></div>' );
431437
 438+ // descriptions
432439 _this.descriptionsDiv = $j( '<div class="mwe-upwiz-details-descriptions"></div>' );
433440
434441
@@ -435,44 +442,123 @@
436443 .attr( 'href', '#' )
437444 .html( gM( 'mwe-upwiz-desc-add-0' ) )
438445 .click( function( ) { _this.addDescription( ) } );
439 -
 446+
440447 _this.descriptionsContainerDiv =
441448 $j( '<div class="mwe-upwiz-details-descriptions-container"></div>' )
442 - .append( $j( '<div class="mwe-upwiz-details-descriptions-title">' + gM( 'mwe-upwiz-desc' ) + '</div>' ) )
 449+ .append( $j( '<div class="mwe-details-label">' + gM( 'mwe-upwiz-desc' ) + '</div>' ) )
443450 .append( _this.descriptionsDiv )
444451 .append( $j( '<div class="mwe-upwiz-details-descriptions-add"></div>' )
445452 .append( _this.descriptionAdder ) );
446 -
 453+ // title
 454+ _this.titleInput = $j( '<input type="text" class="mwe-title" size="40"/>' )
 455+ .keydown( function() {
 456+ $j( _this.filenameInput ).val( _this.titleToFilename( $j(_this.titleInput).val() ) );
 457+ });
 458+
 459+ _this.titleContainerDiv = $j('<div></div>')
 460+ .append( $j( '<div class="mwe-details-label"></div>' ).append( gM( 'mwe-upwiz-title' ) ) )
 461+ .append( $j( '<div class="mwe-details-title"></div>' ).append( _this.titleInput ) );
 462+
 463+ _this.moreDetailsDiv = $j('<div class="mwe-more-details"></div>');
 464+
 465+ // more details ctrl
 466+ // XXX change class of button to have arrow pointing in different directions
 467+ // XXX standard jQuery "blind" effect seems to cause a jQuery error, why?
 468+ _this.moreDetailsCtrl = $j('<a class=".mwe-upwiz-more"/>')
 469+ .append( gM( 'mwe-upwiz-more-options' ) ).click( function() {
 470+ _this.moreDetailsOpen = !_this.moreDetailsOpen;
 471+ _this.moreDetailsOpen ? $j( _this.moreDetailsDiv ).show()
 472+ : $j( _this.moreDetailsDiv ).hide();
 473+ } );
 474+ _this.moreDetailsOpen = false;
 475+ _this.moreDetailsDiv.hide();
 476+
 477+ _this.moreDetailsCtrlDiv = $j( '<div class="mwe-details-more-options"></div>' )
 478+ .append( _this.moreDetailsCtrl );
 479+
 480+
447481 _this.dateInput = $j( '<input type="text" class="mwe-date" size="20"/>' );
448 - $j( _this.dateInput ).datepicker( { dateFormat: 'yyyy-mm-dd' } );
 482+ $j( _this.dateInput ).datepicker( {
 483+ dateFormat: 'yyyy-mm-dd',
 484+ buttonImage: '/js/mwEmbed/skins/common/images/calendar.gif',
 485+ buttonImageOnly: false // XXX determine what this does, docs are confusing
 486+ } );
449487
450 - $j( _this.div )
451 - .append( _this.macroDiv )
452 - .append( _this.thumbnailDiv )
453 - .append( _this.errorDiv )
454 - .append( $j( _this.dataDiv )
455 - .append( _this.descriptionsContainerDiv )
456 - .append( _this.dateInput )
 488+ var aboutThisWorkDiv = $j('<div></div>')
 489+ .append( $j( '<h5 class="mwe-details-more-subhead">' ).append( gM( 'mwe-upwiz-about-this-work' ) ) )
 490+ .append( $j( '<div class="mwe-details-more-subdiv">' )
 491+ .append( $j( '<div></div>' )
 492+ .append( $j( '<div class="mwe-details-more-label"></div>' ).append( gM( 'mwe-upwiz-date-created' ) ) )
 493+ .append( $j( '<div class="mwe-details-more-input"></div>' ).append( _this.dateInput ) )
 494+ )
 495+ .append( $j ( '<div></div>' )
 496+ .append( $j( '<div class="mwe-details-more-label"></div>' ).append( gM( 'mwe-upwiz-geotag' ) ) )
 497+ .append( $j( '<div class="mwe-details-more-input"></div>' ).append( "(map widget tba)" ) )
 498+ )
457499 );
458 -
459500
 501+ _this.sourceInput = $j('<input type="text" class="mwe-source" size="30" />' );
 502+ _this.authorInput = $j('<input type="text" class="mwe-author" size="30" />' );
 503+ _this.licenseInput = $j('<input type="text" class="mwe-license" size="30" />' );
 504+ var sourceDiv = $j( '<div></div>' )
 505+ .append( $j( '<div class="mwe-details-more-label"></div>' ).append( gM( 'mwe-upwiz-source' ) ) )
 506+ .append( $j( '<div class="mwe-details-more-input"></div>' ).append( _this.sourceInput ) );
460507
461 - // create the basic HTML
462 - // thumbnail
463508
464 - // about this work
465 - // media type
466 - // date created
467 - // location widget
 509+ var copyrightInfoDiv = $j('<div></div>')
 510+ .append( $j( '<h5 class="mwe-details-more-subhead">' ).append( gM( 'mwe-upwiz-copyright-info' ) ) )
 511+ .append( $j( '<div class="mwe-details-more-subdiv">' )
 512+ .append( sourceDiv )
 513+ .append( $j( '<div></div>' )
 514+ .append( $j( '<div class="mwe-details-more-label"></div>' ).append( gM( 'mwe-upwiz-author' ) ) )
 515+ .append( $j( '<div class="mwe-details-more-input"></div>' ).append( _this.authorInput ) )
 516+ )
 517+ .append( $j( '<div></div>' )
 518+ .append( $j( '<div class="mwe-details-more-label"></div>' ).append( gM( 'mwe-upwiz-license' ) ) )
 519+ .append( $j( '<div class="mwe-details-more-input"></div>' ).append( _this.licenseInput ) )
 520+ )
 521+ );
468522
469 - // copyright info <--- THIS IS THE IMPORTANT BIT
470 - // Author
471 - // License
 523+
 524+ _this.filenameInput = $j('<input type="text" class="mwe-filename" size="30" />' )
 525+ .keydown( function() {
 526+ $j( _this.titleInput ).val( _this.filenameToTitle( $j(_this.filenameInput).val() ) );
 527+ });
472528
473 - // About the file...
 529+ var aboutTheFileDiv = $j('<div></div>')
 530+ .append( $j( '<h5 class="mwe-details-more-subhead">' ).append( gM( 'mwe-upwiz-about-format' ) ) )
 531+ .append( $j( '<div class="mwe-details-more-subdiv">' )
 532+ .append( $j( '<div></div>' )
 533+ .append( $j( '<div class="mwe-details-more-label"></div>' ).append( gM( 'mwe-upwiz-filename-tag' ) ) )
 534+ .append( $j( '<div class="mwe-details-more-input"></div>' )
 535+ .append( "File:" ) // this is the constant NS_FILE, defined in Namespaces.php. Usually unchangeable?
 536+ .append( _this.filenameInput )
 537+ )
 538+ )
 539+ );
474540
475 - // Other info
 541+ var otherInformationInput = $j( '<textarea class="mwe-upwiz-other-textarea" rows="3" cols="40"></textarea>' );
 542+ var otherInformationDiv = $j('<div></div>')
 543+ .append( $j( '<h5 class="mwe-details-more-subhead">' ).append( gM( 'mwe-upwiz-other' ) ) )
 544+ .append( otherInformationInput );
476545
 546+
 547+ $j( _this.div )
 548+ .append( _this.macroDiv ) // XXX this is wrong; it's not part of a file's details
 549+ .append( _this.thumbnailDiv )
 550+ .append( _this.errorDiv )
 551+ .append( $j( _this.dataDiv )
 552+ .append( _this.descriptionsContainerDiv )
 553+ .append( _this.titleContainerDiv )
 554+ .append( _this.moreDetailsCtrlDiv )
 555+ .append( $j( _this.moreDetailsDiv )
 556+ .append( aboutThisWorkDiv )
 557+ .append( copyrightInfoDiv )
 558+ .append( aboutTheFileDiv )
 559+ .append( otherInformationDiv )
 560+ )
 561+ );
 562+
477563 _this.addDescription();
478564 $j( containerDiv ).append( _this.div );
479565
@@ -574,15 +660,13 @@
575661 populate: function() {
576662 var _this = this;
577663 mw.log( "populating details from upload" );
578 - _this.setThumbnail( mw.getConfig( 'thumbnailWidth' ) );
579 - _this.setDate();
580 -
581 - //_this.setSource();
582 -
583 - //_this.setFilename();
584 -
585 - //_this.setLocation(); // we could be VERY clever with location sensing...
586 - //_this.setAuthor();
 664+ _this.setThumbnailFromImageInfo( mw.getConfig( 'thumbnailWidth' ) );
 665+ _this.setDateFromImageInfo();
 666+ _this.setSourceFromImageInfo();
 667+ _this.setAuthorFromImageInfo();
 668+ _this.setTitleFromImageInfo();
 669+ _this.setFilenameFromImageInfo();
 670+ _this.setLocationFromImageInfo();
587671 },
588672
589673 /**
@@ -590,7 +674,7 @@
591675 *
592676 * @param width
593677 */
594 - setThumbnail: function( width ) {
 678+ setThumbnailFromImageInfo: function( width ) {
595679 var _this = this;
596680
597681 var callback = function( thumbnail ) {
@@ -617,39 +701,89 @@
618702 * EXIF examples tend to be in ISO 8601, but the separators are sometimes things like colons, and they have lots of trailing info
619703 * (which we should actually be using, such as time and timezone)
620704 */
621 - setDate: function() {
 705+ setDateFromImageInfo: function() {
622706 var _this = this;
623 - var iso8601regex = /^(\d\d\d\d)[:\/-](\d\d)[:\/-](\d\d)\D.*/;
 707+ var yyyyMmDdRegex = /^(\d\d\d\d)[:\/-](\d\d)[:\/-](\d\d)\D.*/;
624708 var dateStr;
625709 var metadata = _this.upload.imageinfo.metadata;
626 - $j.each([metadata.DateTimeOriginal, metadata.DateTimeDigitized, metadata.DateTime],
 710+ $j.each([metadata.datetimeoriginal, metadata.datetimedigitized, metadata.datetime, metadata['date']],
627711 function( i, imageinfoDate ) {
628712 if ( imageinfoDate !== undefined ) {
629713 var d = imageinfoDate.trim();
630 - if ( d.match( iso8601regex ) ) {
631 - dateStr = d.replace( iso8601regex, "$1-$2-$3" );
 714+ if ( d.match( yyyyMmDdRegex ) ) {
 715+ dateStr = d.replace( yyyyMmDdRegex, "$1-$2-$3" );
632716 return false; // break from $j.each
633717 }
634718 }
635719 }
636720 );
637721 // if we don't have EXIF or other metadata, let's use "now"
638 - // XXX if we have FileAPI, it might be clever to look at time created of the file. Save that in the
639 - // upload object for use here later, perhaps
 722+ // XXX if we have FileAPI, it might be clever to look at file attrs, saved
 723+ // in the upload object for use here later, perhaps
640724 function pad( n ) {
641725 return n < 10 ? "0" + n : n;
642726 }
643727
644728 if (dateStr === undefined) {
645729 d = new Date();
646 - dateStr = d.getUTCFullYear() + '-' + pad(d.getUTCMonth()) + pad(d.getUTCDate());
 730+ dateStr = d.getUTCFullYear() + '-' + pad(d.getUTCMonth()) + '-' + pad(d.getUTCDate());
647731 }
648732
649733 // ok by now we should definitely have a date string formatted in YYYY-MM-DD
650 - $j(_this.dateInput).val(dateStr);
 734+ $j( _this.dateInput ).val( dateStr );
651735 },
652736
653737 /**
 738+ * Set the title of the thing we just uploaded, visibly
 739+ * Note: the interface's notion of "filename" versus "title" is the opposite of MediaWiki
 740+ */
 741+ setTitleFromImageInfo: function() {
 742+ var _this = this;
 743+ $j( _this.titleInput ).val( mw.UploadWizardUtil.pathToTitle( _this.upload.originalFilename ) );
 744+ },
 745+
 746+ /**
 747+ * Set the title of the thing we just uploaded, visibly
 748+ * Note: the interface's notion of "filename" versus "title" is the opposite of MediaWiki
 749+ */
 750+ setFilenameFromImageInfo: function() {
 751+ var _this = this;
 752+ $j( _this.filenameInput ).val( mw.UploadWizardUtil.titleToPath( _this.upload.title ) );
 753+ },
 754+
 755+
 756+ setSourceFromImageInfo: function() {
 757+ // we have no idea, as far as I can tell
 758+ },
 759+
 760+ setAuthorFromImageInfo: function() {
 761+ var _this = this;
 762+ if (_this.upload.metadata.artist !== undefined) {
 763+ $j( _this.authorInput ).val( _this.upload.metadata.artist );
 764+ }
 765+
 766+ },
 767+
 768+ setLicenseFromImageInfo: function() {
 769+ var _this = this;
 770+ if (_this.upload.metadata.copyright !== undefined) {
 771+ var copyright = _this.upload.metadata.copyright;
 772+ if (copyright.match(/\<cc-by-sa\>/i) {
 773+ // set license to be that CC-BY-SA
 774+ } else if (copyright.match(/\<cc-by\>/i) {
 775+ // set license to be that
 776+ } else if (copyright.match(/\<cc-zero\>/i) {
 777+ // set license to be that
 778+ // XXX any other licenses we could pick up from copyright
 779+ } else {
 780+ $j( _this.licenseInput ).val( _this.upload.metadata.copyright );
 781+ }
 782+ }
 783+ },
 784+
 785+
 786+
 787+ /**
654788 * Convert entire details for this file into wikiText, which will then be posted to the file
655789 * @return wikitext representing all details
656790 */
@@ -666,7 +800,7 @@
667801 'date' : '', // YYYY, YYYY-MM, or YYYY-MM-DD required - use jquery but allow editing, then double check for sane date.
668802 'source' : '', // {{own}} or wikitext optional
669803 'author' : '', // any wikitext, but particularly {{Creator:Name Surname}} required
670 - 'permission' : '', // leave blank; by default will be "see below" optional
 804+ 'permission' : '', // leave blank unless OTRS pending; by default will be "see below" optional
671805 'other_versions' : '', // pipe separated list, other versions optional
672806 'other_fields' : '' // ??? additional table fields
673807 };
@@ -680,10 +814,14 @@
681815 $j.each( _this.descriptions, function( i, desc ) {
682816 information['description'] += desc.getWikiText();
683817 } )
 818+
684819
685820 // XXX add a sanity check here for good date
686 - information['date'] = $j(_this.dateInput).val();
687 -
 821+ information['date'] = $j( _this.dateInput ).trim().val();
 822+
 823+ information['source'] = $j( _this.sourceInput ).trim().val();
 824+ information['author'] = $j( _this.authorInput ).trim().val();
 825+
688826 var info = '';
689827 for ( var key in information ) {
690828 info += '|' + key + '=' + information[key] + "\n";
@@ -698,6 +836,11 @@
699837 //wikiText += "{{cc-by-sa-3.0}}\n";
700838 // http://commons.wikimedia.org / wiki / Template:Information
701839
 840+ // add a location template
 841+
 842+ // add an "anything else" template
 843+ wikiText += $j( _this.otherInformationInput ).trim().val();
 844+
702845 return wikiText;
703846 },
704847
@@ -930,7 +1073,7 @@
9311074 var filenameAcceptedCb = function() {
9321075 _this.updateFileCounts();
9331076 };
934 - var ui = new mw.UploadWizardUploadInterface( filenameAcceptedCb );
 1077+ var ui = new mw.UploadWizardUploadInterface( upload, filenameAcceptedCb );
9351078 ui.removeCtrl = $j( '<a title="' + gM( 'mwe-upwiz-remove-upload' )
9361079 + '" href="#" class="mwe-upwiz-remove">x</a>' )
9371080 .click( function() { _this.removeUpload( upload ) } )
@@ -1281,7 +1424,36 @@
12821425 break;
12831426 }
12841427 }
 1428+ },
 1429+
 1430+ /**
 1431+ * Capitalise first letter and replace spaces by underscores
 1432+ * @param filename (basename, without directories)
 1433+ * @return typical title as would appear on MediaWiki
 1434+ */
 1435+ pathToTitle: function ( filename ) {
 1436+ return mw.ucfirst( filename.replace(/ /g, '_' ) );
 1437+ },
 1438+
 1439+ /**
 1440+ * Capitalise first letter and replace underscores by spaces
 1441+ * @param title typical title as would appear on MediaWiki
 1442+ * @return plausible local filename, with spaces changed to underscores.
 1443+ */
 1444+ titleToPath: function ( title ) {
 1445+ return mw.ucfirst( title.replace(/_/g, ' ' ) );
12851446 }
 1447+
12861448 };
12871449
 1450+/**
 1451+ * Upper-case the first letter of a string. XXX move to common library
 1452+ * @param string
 1453+ * @return string with first letter uppercased.
 1454+ */
 1455+mw.ucfirst = function( s ) {
 1456+ return s.substring(0,1).toUpperCase() + s.substr(1);
 1457+};
12881458
 1459+
 1460+
Index: branches/js2-work/phase3/js/mwEmbed/modules/UploadWizard/css/uploadWizard.css
@@ -52,7 +52,7 @@
5353 }
5454
5555 /* perhaps a general class for links that are actually "buttons" */
56 -#mwe-upwiz-add-file, .mwe-upwiz-remove {
 56+#mwe-upwiz-add-file, .mwe-upwiz-remove, .mwe-upwiz-more-options {
5757 cursor: pointer;
5858 }
5959
Index: branches/js2-work/phase3/js/uploadWizardPage.js
@@ -31,6 +31,12 @@
3232 mw.setConfig('token', token);
3333 mw.setConfig('thumbnailWidth', 220); // new standard size
3434
 35+ // not for use with all wikis.
 36+ // The ISO 639 code for the language tagalog is "tl".
 37+ // Normally we name templates for languages by the ISO 639 code.
 38+ // Commons already had a template called 'tl', though.
 39+ // so, this workaround will cause tagalog descriptions to be saved with this template instead.
 40+ mw.setConfig('languageTemplateFixups', { tl: 'tgl' });
3541
3642 var uploadWizard = new mw.UploadWizard();
3743 uploadWizard.createInterface(wizardDiv);

Status & tagging log