( function () { 'use strict'; var noOfSourceUnits, noOfTranslationUnits, pageName = '', langCode = '', sourceUnits = []; /** * Create translation pages using content of right hand side blocks * and identifiers from left hand side blocks. Create pages only if * content is not empty. * * @param {number} i Array index to sourceUnits. * @param {string} content * @return {Function} Returns a function which returns a jQuery.Promise */ function createTranslationPage( i, content ) { return function () { var identifier, title, summary, api = new mw.Api(); identifier = sourceUnits[ i ].identifier; title = 'Translations:' + pageName + '/' + identifier + '/' + langCode; summary = $( '#pm-summary' ).val(); return api.postWithToken( 'csrf', { action: 'edit', watchlist: 'nochange', title: title, text: content, summary: summary } ); }; } /** * Get the old translations of a given page at given time. * * @param {string} fuzzyTimestamp Timestamp in MediaWiki format * @param {string} pageTitle * @return {jQuery.Promise} * @return {Function} return.done * @return {Array} return.done.data Array of old translations */ function splitTranslationPage( fuzzyTimestamp, pageTitle ) { var api = new mw.Api(); return api.get( { action: 'query', prop: 'revisions', rvprop: 'content', rvstart: fuzzyTimestamp, titles: pageTitle } ).then( function ( data ) { var pageContent, oldTranslationUnits, obj, page, errorBox = $( '.mw-tpm-sp-error__message' ); for ( page in data.query.pages ) { obj = data.query.pages[ page ]; } if ( typeof obj === undefined ) { // obj was not initialized errorBox.text( mw.msg( 'pm-page-does-not-exist', pageTitle ) ).show( 'fast' ); return $.Deferred().reject(); } if ( obj.revisions === undefined ) { // the case of /en subpage where first edit is by FuzzyBot errorBox.text( mw.msg( 'pm-old-translations-missing', pageTitle ) ).show( 'fast' ); return $.Deferred().reject(); } pageContent = obj.revisions[ 0 ][ '*' ]; oldTranslationUnits = pageContent.split( '\n\n' ); return oldTranslationUnits; } ); } /** * Get the timestamp before FuzzyBot's first edit on page. * * @param {string} pageTitle * @return {jQuery.Promise} * @return {Function} return.done * @return {string} return.done.data */ function getFuzzyTimestamp( pageTitle ) { var api = new mw.Api(); // This api call returns the timestamp of FuzzyBot's edit return api.get( { action: 'query', prop: 'revisions', rvprop: 'timestamp', rvuser: 'FuzzyBot', rvdir: 'newer', titles: pageTitle } ).then( function ( data ) { var timestampFB, dateFB, timestampOld, page, obj, errorBox = $( '.mw-tpm-sp-error__message' ); for ( page in data.query.pages ) { obj = data.query.pages[ page ]; } // Page does not exist if missing field is present if ( obj.missing === '' ) { errorBox.text( mw.msg( 'pm-page-does-not-exist', pageTitle ) ).show( 'fast' ); return $.Deferred().reject(); } // Page exists, but no edit by FuzzyBot if ( obj.revisions === undefined ) { errorBox.text( mw.msg( 'pm-old-translations-missing', pageTitle ) ).show( 'fast' ); return $.Deferred().reject(); } else { // FB over here refers to FuzzyBot timestampFB = obj.revisions[ 0 ].timestamp; dateFB = new Date( timestampFB ); dateFB.setSeconds( dateFB.getSeconds() - 1 ); timestampOld = dateFB.toISOString(); mw.log( 'New Timestamp: ' + timestampOld ); return timestampOld; } } ); } /** * Get the translation units created by Translate extension. * * @param {string} pageName * @return {jQuery.Promise} * @return {Function} return.done * @return {Object[]} return.done.data Array of sUnit Objects */ function getSourceUnits( pageName ) { var api = new mw.Api(); return api.get( { action: 'query', list: 'messagecollection', mcgroup: 'page-' + pageName, mclanguage: 'en', mcprop: 'definition' } ).then( function ( data ) { var result, i, sUnit, key; sourceUnits = []; result = data.query.messagecollection; for ( i = 1; i < result.length; i++ ) { sUnit = {}; key = result[ i ].key; sUnit.identifier = key.slice( key.lastIndexOf( '/' ) + 1 ); sUnit.definition = result[ i ].definition; sourceUnits.push( sUnit ); } return sourceUnits; } ); } /** * Shift rows up by one unit. This is called after a unit is deleted. * * @param {jQuery} $start The starting node */ function shiftRowsUp( $start ) { var nextVal, $current = $start, $next = $start.next(); while ( $next.length ) { nextVal = $next.find( '.mw-tpm-sp-unit__target' ).val(); $current.find( '.mw-tpm-sp-unit__target' ).val( nextVal ); $current = $next; $next = $current.next(); } if ( $current.find( '.mw-tpm-sp-unit__source' ).val() ) { $current.find( '.mw-tpm-sp-unit__target' ).val( '' ); } else { $current.remove(); } } /** * Shift rows down by one unit. This is called after a new empty unit is * added. * * @param {jQuery} $nextRow The next row to start with * @param {string} text The text of the next row * @return {string} text The text of the last row */ function shiftRowsDown( $nextRow, text ) { var oldText; while ( $nextRow.length ) { oldText = $nextRow.find( '.mw-tpm-sp-unit__target' ).val(); $nextRow.find( '.mw-tpm-sp-unit__target' ).val( text ); $nextRow = $nextRow.next(); text = oldText; } return text; } /** * Create a new row of source text and target text with action icons. * * @param {string} sourceText * @param {string} targetText * @return {jQuery} newUnit The new row unit object */ function createNewUnit( sourceText, targetText ) { var newUnit, sourceUnit, targetUnit, actionUnit; newUnit = $( '
' ).addClass( 'mw-tpm-sp-unit row' ); sourceUnit = $( '